Remove Navigation2D/3D nodes, and move the navigation map to the world resource

This commit is contained in:
Gilles Roudière 2021-03-08 09:47:18 +01:00
parent 469ac1e415
commit a9dc53d152
39 changed files with 233 additions and 1012 deletions

View file

@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Navigation2D" inherits="Node2D" version="4.0">
<brief_description>
2D navigation and pathfinding node.
</brief_description>
<description>
Navigation2D provides navigation and pathfinding within a 2D area, specified as a collection of [NavigationPolygon] resources. These are automatically collected from child [NavigationRegion2D] nodes.
</description>
<tutorials>
<link title="2D Navigation Demo">https://godotengine.org/asset-library/asset/117</link>
</tutorials>
<methods>
<method name="get_closest_point" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="to_point" type="Vector2">
</argument>
<description>
Returns the point closest to the provided [code]to_point[/code] on the navigation mesh surface.
</description>
</method>
<method name="get_closest_point_owner" qualifiers="const">
<return type="RID">
</return>
<argument index="0" name="to_point" type="Vector2">
</argument>
<description>
Returns the owner region RID for the point returned by [method get_closest_point].
</description>
</method>
<method name="get_rid" qualifiers="const">
<return type="RID">
</return>
<description>
</description>
</method>
<method name="get_simple_path" qualifiers="const">
<return type="PackedVector2Array">
</return>
<argument index="0" name="start" type="Vector2">
</argument>
<argument index="1" name="end" type="Vector2">
</argument>
<argument index="2" name="optimize" type="bool" default="true">
</argument>
<description>
Returns the path between two given points. Points are in local coordinate space. If [code]optimize[/code] is [code]true[/code] (the default), the path is smoothed by merging path segments where possible.
</description>
</method>
</methods>
<members>
<member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size" default="10.0">
</member>
<member name="edge_connection_margin" type="float" setter="set_edge_connection_margin" getter="get_edge_connection_margin" default="100.0">
</member>
</members>
<constants>
</constants>
</class>

View file

@ -1,84 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Navigation3D" inherits="Node3D" version="4.0">
<brief_description>
Mesh-based navigation and pathfinding node.
</brief_description>
<description>
Provides navigation and pathfinding within a collection of [NavigationMesh]es. These will be automatically collected from child [NavigationRegion3D] nodes. In addition to basic pathfinding, this class also assists with aligning navigation agents with the meshes they are navigating on.
</description>
<tutorials>
<link title="3D Navmesh Demo">https://godotengine.org/asset-library/asset/124</link>
</tutorials>
<methods>
<method name="get_closest_point" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="to_point" type="Vector3">
</argument>
<description>
Returns the point closest to the provided [code]to_point[/code] on the navigation mesh surface.
</description>
</method>
<method name="get_closest_point_normal" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="to_point" type="Vector3">
</argument>
<description>
Returns the normal for the point returned by [method get_closest_point].
</description>
</method>
<method name="get_closest_point_owner" qualifiers="const">
<return type="RID">
</return>
<argument index="0" name="to_point" type="Vector3">
</argument>
<description>
Returns the owner region RID for the point returned by [method get_closest_point].
</description>
</method>
<method name="get_closest_point_to_segment" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="start" type="Vector3">
</argument>
<argument index="1" name="end" type="Vector3">
</argument>
<argument index="2" name="use_collision" type="bool" default="false">
</argument>
<description>
Returns the closest point between the navigation surface and the segment.
</description>
</method>
<method name="get_rid" qualifiers="const">
<return type="RID">
</return>
<description>
</description>
</method>
<method name="get_simple_path" qualifiers="const">
<return type="PackedVector3Array">
</return>
<argument index="0" name="start" type="Vector3">
</argument>
<argument index="1" name="end" type="Vector3">
</argument>
<argument index="2" name="optimize" type="bool" default="true">
</argument>
<description>
Returns the path between two given points. Points are in local coordinate space. If [code]optimize[/code] is [code]true[/code] (the default), the agent properties associated with each [NavigationMesh] (radius, height, etc.) are considered in the path calculation, otherwise they are ignored.
</description>
</method>
</methods>
<members>
<member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size" default="0.3">
</member>
<member name="edge_connection_margin" type="float" setter="set_edge_connection_margin" getter="get_edge_connection_margin" default="5.0">
</member>
<member name="up_vector" type="Vector3" setter="set_up_vector" getter="get_up_vector" default="Vector3( 0, 1, 0 )">
Defines which direction is up. By default, this is [code](0, 1, 0)[/code], which is the world's "up" direction.
</member>
</members>
<constants>
</constants>
</class>

View file

@ -4,7 +4,7 @@
2D Agent used in navigation for collision avoidance.
</brief_description>
<description>
2D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. This can be done by having the agent as a child of a [Navigation2D] node, or using [method set_navigation]. [NavigationAgent2D] is physics safe.
2D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. [NavigationAgent2D] is physics safe.
</description>
<tutorials>
</tutorials>
@ -37,13 +37,6 @@
Returns which index the agent is currently on in the navigation path's [PackedVector2Array].
</description>
</method>
<method name="get_navigation" qualifiers="const">
<return type="Node">
</return>
<description>
Returns the [Navigation2D] node that the agent is using for its navigation system.
</description>
</method>
<method name="get_next_location">
<return type="Vector2">
</return>
@ -79,15 +72,6 @@
Returns true if the target location is reached. The target location is set using [method set_target_location]. It may not always be possible to reach the target location. It should always be possible to reach the final location though. See [method get_final_location].
</description>
</method>
<method name="set_navigation">
<return type="void">
</return>
<argument index="0" name="navigation" type="Node">
</argument>
<description>
Sets the [Navigation2D] node used by the agent. Useful when you don't want to make the agent a child of a [Navigation2D] node.
</description>
</method>
<method name="set_target_location">
<return type="void">
</return>

View file

@ -4,7 +4,7 @@
3D Agent used in navigation for collision avoidance.
</brief_description>
<description>
3D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. This can be done by having the agent as a child of a [Navigation3D] node, or using [method set_navigation]. [NavigationAgent3D] is physics safe.
3D Agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO collision avoidance. The agent needs navigation data to work correctly. [NavigationAgent3D] is physics safe.
</description>
<tutorials>
</tutorials>
@ -37,13 +37,6 @@
Returns which index the agent is currently on in the navigation path's [PackedVector3Array].
</description>
</method>
<method name="get_navigation" qualifiers="const">
<return type="Node">
</return>
<description>
Returns the [Navigation3D] node that the agent is using for its navigation system.
</description>
</method>
<method name="get_next_location">
<return type="Vector3">
</return>
@ -79,15 +72,6 @@
Returns true if the target location is reached. The target location is set using [method set_target_location]. It may not always be possible to reach the target location. It should always be possible to reach the final location though. See [method get_final_location].
</description>
</method>
<method name="set_navigation">
<return type="void">
</return>
<argument index="0" name="navigation" type="Node">
</argument>
<description>
Sets the [Navigation3D] node used by the agent. Useful when you don't want to make the agent a child of a [Navigation3D] node.
</description>
</method>
<method name="set_target_location">
<return type="void">
</return>

View file

@ -4,27 +4,11 @@
2D Obstacle used in navigation for collision avoidance.
</brief_description>
<description>
2D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. This can be done by having the obstacle as a child of a [Navigation2D] node, or using [method set_navigation]. [NavigationObstacle2D] is physics safe.
2D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. [NavigationObstacle2D] is physics safe.
</description>
<tutorials>
</tutorials>
<methods>
<method name="get_navigation" qualifiers="const">
<return type="Node">
</return>
<description>
Returns the [Navigation2D] node that the obstacle is using for its navigation system.
</description>
</method>
<method name="set_navigation">
<return type="void">
</return>
<argument index="0" name="navigation" type="Node">
</argument>
<description>
Sets the [Navigation2D] node used by the obstacle. Useful when you don't want to make the obstacle a child of a [Navigation2D] node.
</description>
</method>
</methods>
<constants>
</constants>

View file

@ -4,27 +4,11 @@
3D Obstacle used in navigation for collision avoidance.
</brief_description>
<description>
3D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. This can be done by having the obstacle as a child of a [Navigation3D] node, or using [method set_navigation]. [NavigationObstacle3D] is physics safe.
3D Obstacle used in navigation for collision avoidance. The obstacle needs navigation data to work correctly. [NavigationObstacle3D] is physics safe.
</description>
<tutorials>
</tutorials>
<methods>
<method name="get_navigation" qualifiers="const">
<return type="Node">
</return>
<description>
Returns the [Navigation3D] node that the obstacle is using for its navigation system.
</description>
</method>
<method name="set_navigation">
<return type="void">
</return>
<argument index="0" name="navigation" type="Node">
</argument>
<description>
Sets the [Navigation3D] node used by the obstacle. Useful when you don't want to make the obstacle a child of a [Navigation3D] node.
</description>
</method>
</methods>
<constants>
</constants>

View file

@ -4,7 +4,7 @@
A region of the navigation map.
</brief_description>
<description>
A region of the navigation map. It tells the [Navigation3D] node what can be navigated and what cannot, based on the [NavigationMesh] resource. This should be a child of a [Navigation3D] node (even not a direct child).
A region of the navigation map. It tells the [NavigationServer3D] what can be navigated and what cannot, based on its [NavigationMesh] resource.
</description>
<tutorials>
</tutorials>

View file

@ -1020,6 +1020,14 @@
</member>
<member name="mono/unhandled_exception_policy" type="int" setter="" getter="" default="0">
</member>
<member name="navigation/2d/default_cell_size" type="int" setter="" getter="" default="10">
</member>
<member name="navigation/2d/default_edge_connection_margin" type="int" setter="" getter="" default="100">
</member>
<member name="navigation/3d/default_cell_size" type="float" setter="" getter="" default="0.3">
</member>
<member name="navigation/3d/default_edge_connection_margin" type="float" setter="" getter="" default="5.0">
</member>
<member name="network/limits/debugger/max_chars_per_second" type="int" setter="" getter="" default="32768">
Maximum amount of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
</member>

View file

@ -272,6 +272,9 @@
</method>
</methods>
<members>
<member name="bake_navigation" type="bool" setter="set_bake_navigation" getter="is_baking_navigation" default="false">
If [code]true[/code], this TileMap bakes a navigation region.
</member>
<member name="cell_clip_uv" type="bool" setter="set_clip_uv" getter="get_clip_uv" default="false">
If [code]true[/code], the cell's UVs will be clipped.
</member>

View file

@ -18,6 +18,9 @@
<member name="direct_space_state" type="PhysicsDirectSpaceState2D" setter="" getter="get_direct_space_state">
Direct access to the world's physics 2D space state. Used for querying current and potential collisions. When using multi-threaded physics, access is limited to [code]_physics_process(delta)[/code] in the main thread.
</member>
<member name="navigation_map" type="RID" setter="" getter="get_navigation_map">
The [RID] of this world's navigation map. Used by the [NavigationServer2D].
</member>
<member name="space" type="RID" setter="" getter="get_space">
The [RID] of this world's physics space resource. Used by the [PhysicsServer2D] for 2D physics, treating it as both a space and an area.
</member>

View file

@ -23,6 +23,9 @@
<member name="fallback_environment" type="Environment" setter="set_fallback_environment" getter="get_fallback_environment">
The World3D's fallback_environment will be used if the World3D's [Environment] fails or is missing.
</member>
<member name="navigation_map" type="RID" setter="" getter="get_navigation_map">
The [RID] of this world's navigation map. Used by the [NavigationServer3D].
</member>
<member name="scenario" type="RID" setter="" getter="get_scenario">
The World3D's visual scenario.
</member>

View file

@ -35,7 +35,7 @@
#include "editor/import/scene_importer_mesh_node_3d.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/navigation_3d.h"
#include "scene/3d/navigation_region_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/3d/vehicle_body_3d.h"
#include "scene/animation/animation_player.h"

View file

@ -31,10 +31,10 @@
#ifndef NAV_REGION_H
#define NAV_REGION_H
#include "nav_rid.h"
#include "scene/resources/navigation_mesh.h"
#include "nav_rid.h"
#include "nav_utils.h"
#include "scene/3d/navigation_3d.h"
#include <vector>
/**

View file

@ -184,6 +184,9 @@
</method>
</methods>
<members>
<member name="bake_navigation" type="bool" setter="set_bake_navigation" getter="is_baking_navigation" default="false">
If [code]true[/code], this GridMap bakes a navigation region.
</member>
<member name="cell_center_x" type="bool" setter="set_center_x" getter="get_center_x" default="true">
If [code]true[/code], grid items are centered on the X axis.
</member>

View file

@ -179,6 +179,15 @@ bool GridMap::get_collision_layer_bit(int p_bit) const {
return get_collision_layer() & (1 << p_bit);
}
void GridMap::set_bake_navigation(bool p_bake_navigation) {
bake_navigation = p_bake_navigation;
_recreate_octant_data();
}
bool GridMap::is_baking_navigation() {
return bake_navigation;
}
void GridMap::set_mesh_library(const Ref<MeshLibrary> &p_mesh_library) {
if (!mesh_library.is_null()) {
mesh_library->unregister_owner(this);
@ -474,13 +483,14 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
Octant::NavMesh nm;
nm.xform = xform * mesh_library->get_item_navmesh_transform(c.item);
if (navigation) {
if (bake_navigation) {
RID region = NavigationServer3D::get_singleton()->region_create();
NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh);
NavigationServer3D::get_singleton()->region_set_transform(region, navigation->get_global_transform() * nm.xform);
NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid());
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * mesh_library->get_item_navmesh_transform(c.item));
NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
nm.region = region;
}
g.navmesh_ids[E->get()] = nm;
}
}
@ -564,15 +574,16 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
RS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform());
}
if (navigation && mesh_library.is_valid()) {
if (bake_navigation && mesh_library.is_valid()) {
for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) {
if (cell_map.has(F->key()) && F->get().region.is_valid() == false) {
Ref<NavigationMesh> nm = mesh_library->get_item_navmesh(cell_map[F->key()].item);
if (nm.is_valid()) {
RID region = NavigationServer3D::get_singleton()->region_create();
NavigationServer3D::get_singleton()->region_set_navmesh(region, nm);
NavigationServer3D::get_singleton()->region_set_transform(region, navigation->get_global_transform() * F->get().xform);
NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid());
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * F->get().xform);
NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
F->get().region = region;
}
}
@ -594,12 +605,10 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
RS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, RID());
}
if (navigation) {
for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) {
if (F->get().region.is_valid()) {
NavigationServer3D::get_singleton()->free(F->get().region);
F->get().region = RID();
}
for (Map<IndexKey, Octant::NavMesh>::Element *F = g.navmesh_ids.front(); F; F = F->next()) {
if (F->get().region.is_valid()) {
NavigationServer3D::get_singleton()->free(F->get().region);
F->get().region = RID();
}
}
}
@ -635,16 +644,6 @@ void GridMap::_octant_clean_up(const OctantKey &p_key) {
void GridMap::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_WORLD: {
Node3D *c = this;
while (c) {
navigation = Object::cast_to<Navigation3D>(c);
if (navigation) {
break;
}
c = Object::cast_to<Node3D>(c->get_parent());
}
last_transform = get_global_transform();
for (Map<OctantKey, Octant *>::Element *E = octant_map.front(); E; E = E->next()) {
@ -679,8 +678,6 @@ void GridMap::_notification(int p_what) {
_octant_exit_world(E->key());
}
navigation = nullptr;
//_queue_octants_dirty(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS);
//_update_octants_callback();
//_update_area_instances();
@ -785,6 +782,9 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &GridMap::set_collision_layer_bit);
ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &GridMap::get_collision_layer_bit);
ClassDB::bind_method(D_METHOD("set_bake_navigation", "bake_navigation"), &GridMap::set_bake_navigation);
ClassDB::bind_method(D_METHOD("is_baking_navigation"), &GridMap::is_baking_navigation);
ClassDB::bind_method(D_METHOD("set_mesh_library", "mesh_library"), &GridMap::set_mesh_library);
ClassDB::bind_method(D_METHOD("get_mesh_library"), &GridMap::get_mesh_library);
@ -838,6 +838,8 @@ void GridMap::_bind_methods() {
ADD_GROUP("Collision", "collision_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_GROUP("Navigation", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_navigation"), "set_bake_navigation", "is_baking_navigation");
BIND_CONSTANT(INVALID_CELL_ITEM);

View file

@ -31,7 +31,6 @@
#ifndef GRID_MAP_H
#define GRID_MAP_H
#include "scene/3d/navigation_3d.h"
#include "scene/3d/node_3d.h"
#include "scene/resources/mesh_library.h"
#include "scene/resources/multimesh.h"
@ -135,6 +134,7 @@ class GridMap : public Node3D {
uint32_t collision_layer = 1;
uint32_t collision_mask = 1;
bool bake_navigation = false;
Transform last_transform;
@ -145,7 +145,6 @@ class GridMap : public Node3D {
bool center_y = true;
bool center_z = true;
float cell_scale = 1.0;
Navigation3D *navigation = nullptr;
bool clip = false;
bool clip_above = true;
@ -223,6 +222,9 @@ public:
void set_collision_mask_bit(int p_bit, bool p_value);
bool get_collision_mask_bit(int p_bit) const;
void set_bake_navigation(bool p_bake_navigation);
bool is_baking_navigation();
void set_mesh_library(const Ref<MeshLibrary> &p_mesh_library);
Ref<MeshLibrary> get_mesh_library() const;

View file

@ -1,92 +0,0 @@
/*************************************************************************/
/* navigation_2d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 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_2d.h"
#include "servers/navigation_server_2d.h"
void Navigation2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rid"), &Navigation2D::get_rid);
ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation2D::get_simple_path, DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Navigation2D::get_closest_point);
ClassDB::bind_method(D_METHOD("get_closest_point_owner", "to_point"), &Navigation2D::get_closest_point_owner);
ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation2D::set_cell_size);
ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation2D::get_cell_size);
ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation2D::set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation2D::get_edge_connection_margin);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin");
}
void Navigation2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
NavigationServer2D::get_singleton()->map_set_active(map, true);
} break;
case NOTIFICATION_EXIT_TREE: {
NavigationServer2D::get_singleton()->map_set_active(map, false);
} break;
}
}
void Navigation2D::set_cell_size(float p_cell_size) {
cell_size = p_cell_size;
NavigationServer2D::get_singleton()->map_set_cell_size(map, cell_size);
}
void Navigation2D::set_edge_connection_margin(float p_edge_connection_margin) {
edge_connection_margin = p_edge_connection_margin;
NavigationServer2D::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin);
}
Vector<Vector2> Navigation2D::get_simple_path(const Vector2 &p_start, const Vector2 &p_end, bool p_optimize) const {
return NavigationServer2D::get_singleton()->map_get_path(map, p_start, p_end, p_optimize);
}
Vector2 Navigation2D::get_closest_point(const Vector2 &p_point) const {
return NavigationServer2D::get_singleton()->map_get_closest_point(map, p_point);
}
RID Navigation2D::get_closest_point_owner(const Vector2 &p_point) const {
return NavigationServer2D::get_singleton()->map_get_closest_point_owner(map, p_point);
}
Navigation2D::Navigation2D() {
map = NavigationServer2D::get_singleton()->map_create();
set_cell_size(10); // Ten pixels
set_edge_connection_margin(100);
}
Navigation2D::~Navigation2D() {
NavigationServer2D::get_singleton()->free(map);
}

View file

@ -1,71 +0,0 @@
/*************************************************************************/
/* navigation_2d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 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_2D_H
#define NAVIGATION_2D_H
#include "scene/2d/navigation_region_2d.h"
#include "scene/2d/node_2d.h"
class Navigation2D : public Node2D {
GDCLASS(Navigation2D, Node2D);
RID map;
real_t cell_size;
real_t edge_connection_margin;
protected:
static void _bind_methods();
void _notification(int p_what);
public:
RID get_rid() const {
return map;
}
void set_cell_size(float p_cell_size);
float get_cell_size() const {
return cell_size;
}
void set_edge_connection_margin(float p_edge_connection_margin);
float get_edge_connection_margin() const {
return edge_connection_margin;
}
Vector<Vector2> get_simple_path(const Vector2 &p_start, const Vector2 &p_end, bool p_optimize = true) const;
Vector2 get_closest_point(const Vector2 &p_point) const;
RID get_closest_point_owner(const Vector2 &p_point) const;
Navigation2D();
~Navigation2D();
};
#endif // NAVIGATION_2D_H

View file

@ -32,7 +32,6 @@
#include "core/config/engine.h"
#include "core/math/geometry_2d.h"
#include "scene/2d/navigation_2d.h"
#include "servers/navigation_server_2d.h"
void NavigationAgent2D::_bind_methods() {
@ -42,9 +41,6 @@ void NavigationAgent2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationAgent2D::set_radius);
ClassDB::bind_method(D_METHOD("get_radius"), &NavigationAgent2D::get_radius);
ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationAgent2D::set_navigation_node);
ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationAgent2D::get_navigation_node);
ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent2D::set_neighbor_dist);
ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent2D::get_neighbor_dist);
@ -95,27 +91,10 @@ void NavigationAgent2D::_notification(int p_what) {
NavigationServer2D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
// Search the navigation node and set it
{
Navigation2D *nav = nullptr;
Node *p = get_parent();
while (p != nullptr) {
nav = Object::cast_to<Navigation2D>(p);
if (nav != nullptr) {
p = nullptr;
} else {
p = p->get_parent();
}
}
set_navigation(nav);
}
set_physics_process_internal(true);
} break;
case NOTIFICATION_EXIT_TREE: {
agent_parent = nullptr;
set_navigation(nullptr);
set_physics_process_internal(false);
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
@ -146,25 +125,6 @@ NavigationAgent2D::~NavigationAgent2D() {
agent = RID(); // Pointless
}
void NavigationAgent2D::set_navigation(Navigation2D *p_nav) {
if (navigation == p_nav) {
return; // Pointless
}
navigation = p_nav;
NavigationServer2D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid());
}
void NavigationAgent2D::set_navigation_node(Node *p_nav) {
Navigation2D *nav = Object::cast_to<Navigation2D>(p_nav);
ERR_FAIL_COND(nav == nullptr);
set_navigation(nav);
}
Node *NavigationAgent2D::get_navigation_node() const {
return Object::cast_to<Node>(navigation);
}
void NavigationAgent2D::set_target_desired_distance(real_t p_dd) {
target_desired_distance = p_dd;
}
@ -287,7 +247,7 @@ void NavigationAgent2D::update_navigation() {
if (agent_parent == nullptr) {
return;
}
if (navigation == nullptr) {
if (!agent_parent->is_inside_tree()) {
return;
}
if (update_frame_id == Engine::get_singleton()->get_physics_frames()) {
@ -319,7 +279,7 @@ void NavigationAgent2D::update_navigation() {
}
if (reload_path) {
navigation_path = NavigationServer2D::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true);
navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true);
navigation_finished = false;
nav_path_index = 0;
emit_signal("path_changed");

View file

@ -35,13 +35,11 @@
#include "scene/main/node.h"
class Node2D;
class Navigation2D;
class NavigationAgent2D : public Node {
GDCLASS(NavigationAgent2D, Node);
Node2D *agent_parent = nullptr;
Navigation2D *navigation = nullptr;
RID agent;
@ -74,14 +72,6 @@ public:
NavigationAgent2D();
virtual ~NavigationAgent2D();
void set_navigation(Navigation2D *p_nav);
const Navigation2D *get_navigation() const {
return navigation;
}
void set_navigation_node(Node *p_nav);
Node *get_navigation_node() const;
RID get_rid() const {
return agent;
}

View file

@ -31,48 +31,31 @@
#include "navigation_obstacle_2d.h"
#include "scene/2d/collision_shape_2d.h"
#include "scene/2d/navigation_2d.h"
#include "scene/2d/physics_body_2d.h"
#include "servers/navigation_server_2d.h"
void NavigationObstacle2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle2D::set_navigation_node);
ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle2D::get_navigation_node);
}
void NavigationObstacle2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
update_agent_shape();
// Search the navigation node and set it
{
Navigation2D *nav = nullptr;
Node *p = get_parent();
while (p != nullptr) {
nav = Object::cast_to<Navigation2D>(p);
if (nav != nullptr) {
p = nullptr;
} else {
p = p->get_parent();
}
}
set_navigation(nav);
}
set_physics_process_internal(true);
} break;
case NOTIFICATION_EXIT_TREE: {
set_navigation(nullptr);
set_physics_process_internal(false);
} break;
case NOTIFICATION_PARENTED: {
parent_node2d = Object::cast_to<Node2D>(get_parent());
update_agent_shape();
} break;
case NOTIFICATION_UNPARENTED: {
parent_node2d = nullptr;
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
Node2D *node = Object::cast_to<Node2D>(get_parent());
if (node) {
NavigationServer2D::get_singleton()->agent_set_position(agent, node->get_global_transform().get_origin());
if (parent_node2d) {
NavigationServer2D::get_singleton()->agent_set_position(agent, parent_node2d->get_global_transform().get_origin());
}
} break;
}
}
@ -86,25 +69,6 @@ NavigationObstacle2D::~NavigationObstacle2D() {
agent = RID(); // Pointless
}
void NavigationObstacle2D::set_navigation(Navigation2D *p_nav) {
if (navigation == p_nav) {
return; // Pointless
}
navigation = p_nav;
NavigationServer2D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid());
}
void NavigationObstacle2D::set_navigation_node(Node *p_nav) {
Navigation2D *nav = Object::cast_to<Navigation2D>(p_nav);
ERR_FAIL_COND(nav == nullptr);
set_navigation(nav);
}
Node *NavigationObstacle2D::get_navigation_node() const {
return Object::cast_to<Node>(navigation);
}
String NavigationObstacle2D::get_configuration_warning() const {
String warning = Node::get_configuration_warning();
@ -119,40 +83,37 @@ String NavigationObstacle2D::get_configuration_warning() const {
}
void NavigationObstacle2D::update_agent_shape() {
Node *node = get_parent();
// Estimate the radius of this physics body
real_t radius = 0.0;
for (int i(0); i < node->get_child_count(); i++) {
// For each collision shape
CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(node->get_child(i));
if (cs) {
// Take the distance between the Body center to the shape center
real_t r = cs->get_transform().get_origin().length();
if (cs->get_shape().is_valid()) {
// and add the enclosing shape radius
r += cs->get_shape()->get_enclosing_radius();
if (parent_node2d) {
// Estimate the radius of this physics body
real_t radius = 0.0;
for (int i(0); i < parent_node2d->get_child_count(); i++) {
// For each collision shape
CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(parent_node2d->get_child(i));
if (cs) {
// Take the distance between the Body center to the shape center
real_t r = cs->get_transform().get_origin().length();
if (cs->get_shape().is_valid()) {
// and add the enclosing shape radius
r += cs->get_shape()->get_enclosing_radius();
}
Size2 s = cs->get_global_transform().get_scale();
r *= MAX(s.x, s.y);
// Takes the biggest radius
radius = MAX(radius, r);
}
Size2 s = cs->get_global_transform().get_scale();
r *= MAX(s.x, s.y);
// Takes the biggest radius
radius = MAX(radius, r);
}
}
Node2D *node_2d = Object::cast_to<Node2D>(node);
if (node_2d) {
Vector2 s = node_2d->get_global_transform().get_scale();
Vector2 s = parent_node2d->get_global_transform().get_scale();
radius *= MAX(s.x, s.y);
}
if (radius == 0.0) {
radius = 1.0; // Never a 0 radius
}
if (radius == 0.0) {
radius = 1.0; // Never a 0 radius
}
// Initialize the Agent as an object
NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, 0);
NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, 0.0);
NavigationServer2D::get_singleton()->agent_set_radius(agent, radius);
NavigationServer2D::get_singleton()->agent_set_max_speed(agent, 0.0);
// Initialize the Agent as an object
NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, 0);
NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, 0.0);
NavigationServer2D::get_singleton()->agent_set_radius(agent, radius);
NavigationServer2D::get_singleton()->agent_set_max_speed(agent, 0.0);
}
}

View file

@ -31,15 +31,13 @@
#ifndef NAVIGATION_OBSTACLE_2D_H
#define NAVIGATION_OBSTACLE_2D_H
#include "scene/2d/node_2d.h"
#include "scene/main/node.h"
class Navigation2D;
class NavigationObstacle2D : public Node {
GDCLASS(NavigationObstacle2D, Node);
Navigation2D *navigation = nullptr;
Node2D *parent_node2d = nullptr;
RID agent;
protected:
@ -50,14 +48,6 @@ public:
NavigationObstacle2D();
virtual ~NavigationObstacle2D();
void set_navigation(Navigation2D *p_nav);
const Navigation2D *get_navigation() const {
return navigation;
}
void set_navigation_node(Node *p_nav);
Node *get_navigation_node() const;
RID get_rid() const {
return agent;
}

View file

@ -34,7 +34,6 @@
#include "core/core_string_names.h"
#include "core/math/geometry_2d.h"
#include "core/os/mutex.h"
#include "navigation_2d.h"
#include "servers/navigation_server_2d.h"
#include "thirdparty/misc/polypartition.h"
@ -366,9 +365,7 @@ void NavigationRegion2D::set_enabled(bool p_enabled) {
if (!enabled) {
NavigationServer2D::get_singleton()->region_set_map(region, RID());
} else {
if (navigation) {
NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid());
}
NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
}
if (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) {
@ -394,29 +391,15 @@ bool NavigationRegion2D::_edit_is_selected_on_click(const Point2 &p_point, doubl
void NavigationRegion2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
Node2D *c = this;
while (c) {
navigation = Object::cast_to<Navigation2D>(c);
if (navigation) {
if (enabled) {
NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid());
}
break;
}
c = Object::cast_to<Node2D>(c->get_parent());
if (enabled) {
NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
}
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
NavigationServer2D::get_singleton()->region_set_transform(region, get_global_transform());
} break;
case NOTIFICATION_EXIT_TREE: {
if (navigation) {
NavigationServer2D::get_singleton()->region_set_map(region, RID());
}
navigation = nullptr;
NavigationServer2D::get_singleton()->region_set_map(region, RID());
} break;
case NOTIFICATION_DRAW: {
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) && navpoly.is_valid()) {
@ -507,18 +490,8 @@ String NavigationRegion2D::get_configuration_warning() const {
}
warning += TTR("A NavigationPolygon resource must be set or created for this node to work. Please set a property or draw a polygon.");
}
const Node2D *c = this;
while (c) {
if (Object::cast_to<Navigation2D>(c)) {
return warning;
}
c = Object::cast_to<Node2D>(c->get_parent());
}
if (!warning.is_empty()) {
warning += "\n\n";
}
return warning + TTR("NavigationRegion2D must be a child or grandchild to a Navigation2D node. It only provides navigation data.");
return warning;
}
void NavigationRegion2D::_bind_methods() {

View file

@ -91,14 +91,11 @@ public:
~NavigationPolygon() {}
};
class Navigation2D;
class NavigationRegion2D : public Node2D {
GDCLASS(NavigationRegion2D, Node2D);
bool enabled = true;
RID region;
Navigation2D *navigation = nullptr;
Ref<NavigationPolygon> navpoly;
void _navpoly_changed();

View file

@ -48,16 +48,6 @@ int TileMap::_get_quadrant_size() const {
void TileMap::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
Node2D *c = this;
while (c) {
navigation = Object::cast_to<Navigation2D>(c);
if (navigation) {
break;
}
c = Object::cast_to<Node2D>(c->get_parent());
}
if (use_parent) {
_clear_quadrants();
collision_parent = Object::cast_to<CollisionObject2D>(get_parent());
@ -77,12 +67,10 @@ void TileMap::_notification(int p_what) {
_update_quadrant_space(RID());
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
Quadrant &q = E->get();
if (navigation) {
for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) {
NavigationServer2D::get_singleton()->region_set_map(F->get().region, RID());
}
q.navpoly_ids.clear();
for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) {
NavigationServer2D::get_singleton()->region_set_map(F->get().region, RID());
}
q.navpoly_ids.clear();
if (collision_parent) {
collision_parent->remove_shape_owner(q.shape_owner_id);
@ -96,8 +84,6 @@ void TileMap::_notification(int p_what) {
}
collision_parent = nullptr;
navigation = nullptr;
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
@ -135,11 +121,6 @@ void TileMap::_update_quadrant_transform() {
local_transform = get_transform();
}
Transform2D nav_rel;
if (navigation) {
nav_rel = get_relative_transform_to_parent(navigation);
}
for (Map<PosKey, Quadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
Quadrant &q = E->get();
Transform2D xform;
@ -150,9 +131,9 @@ void TileMap::_update_quadrant_transform() {
PhysicsServer2D::get_singleton()->body_set_state(q.body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
}
if (navigation) {
if (bake_navigation) {
for (Map<PosKey, Quadrant::NavPoly>::Element *F = q.navpoly_ids.front(); F; F = F->next()) {
NavigationServer2D::get_singleton()->region_set_transform(F->get().region, nav_rel * F->get().xform);
NavigationServer2D::get_singleton()->region_set_transform(F->get().region, F->get().xform);
}
}
@ -315,11 +296,6 @@ void TileMap::update_dirty_quadrants() {
RenderingServer *vs = RenderingServer::get_singleton();
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
Vector2 tofs = get_cell_draw_offset();
Transform2D nav_rel;
if (navigation) {
nav_rel = get_relative_transform_to_parent(navigation);
}
Vector2 qofs;
SceneTree *st = SceneTree::get_singleton();
@ -352,12 +328,10 @@ void TileMap::update_dirty_quadrants() {
}
int shape_idx = 0;
if (navigation) {
for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) {
NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID());
}
q.navpoly_ids.clear();
for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) {
NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID());
}
q.navpoly_ids.clear();
for (Map<PosKey, Quadrant::Occluder>::Element *E = q.occluder_instances.front(); E; E = E->next()) {
RS::get_singleton()->free(E->get().id);
@ -579,7 +553,7 @@ void TileMap::update_dirty_quadrants() {
vs->canvas_item_add_set_transform(debug_canvas_item, Transform2D());
}
if (navigation) {
if (bake_navigation) {
Ref<NavigationPolygon> navpoly;
Vector2 npoly_ofs;
if (tile_set->tile_get_tile_mode(c.id) == TileSet::AUTO_TILE || tile_set->tile_get_tile_mode(c.id) == TileSet::ATLAS_TILE) {
@ -596,8 +570,8 @@ void TileMap::update_dirty_quadrants() {
_fix_cell_transform(xform, c, npoly_ofs, s);
RID region = NavigationServer2D::get_singleton()->region_create();
NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid());
NavigationServer2D::get_singleton()->region_set_transform(region, nav_rel * xform);
NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
NavigationServer2D::get_singleton()->region_set_transform(region, xform);
NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly);
Quadrant::NavPoly np;
@ -787,12 +761,10 @@ void TileMap::_erase_quadrant(Map<PosKey, Quadrant>::Element *Q) {
dirty_quadrant_list.remove(&q.dirty_list);
}
if (navigation) {
for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) {
NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID());
}
q.navpoly_ids.clear();
for (Map<PosKey, Quadrant::NavPoly>::Element *E = q.navpoly_ids.front(); E; E = E->next()) {
NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID());
}
q.navpoly_ids.clear();
for (Map<PosKey, Quadrant::Occluder>::Element *E = q.occluder_instances.front(); E; E = E->next()) {
RS::get_singleton()->free(E->get().id);
@ -1360,6 +1332,17 @@ float TileMap::get_collision_bounce() const {
return bounce;
}
void TileMap::set_bake_navigation(bool p_bake_navigation) {
bake_navigation = p_bake_navigation;
for (Map<PosKey, Quadrant>::Element *F = quadrant_map.front(); F; F = F->next()) {
_make_quadrant_dirty(F);
}
}
bool TileMap::is_baking_navigation() {
return bake_navigation;
}
uint32_t TileMap::get_collision_layer() const {
return collision_layer;
}
@ -1784,6 +1767,9 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_bounce", "value"), &TileMap::set_collision_bounce);
ClassDB::bind_method(D_METHOD("get_collision_bounce"), &TileMap::get_collision_bounce);
ClassDB::bind_method(D_METHOD("set_bake_navigation", "bake_navigation"), &TileMap::set_bake_navigation);
ClassDB::bind_method(D_METHOD("is_baking_navigation"), &TileMap::is_baking_navigation);
ClassDB::bind_method(D_METHOD("set_occluder_light_mask", "mask"), &TileMap::set_occluder_light_mask);
ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &TileMap::get_occluder_light_mask);
@ -1842,6 +1828,9 @@ void TileMap::_bind_methods() {
ADD_GROUP("Occluder", "occluder_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "occluder_light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_occluder_light_mask", "get_occluder_light_mask");
ADD_GROUP("Navigation", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bake_navigation"), "set_bake_navigation", "is_baking_navigation");
ADD_PROPERTY_DEFAULT("format", FORMAT_1);
ADD_SIGNAL(MethodInfo("settings_changed"));

View file

@ -33,7 +33,6 @@
#include "core/templates/self_list.h"
#include "core/templates/vset.h"
#include "scene/2d/navigation_2d.h"
#include "scene/2d/node_2d.h"
#include "scene/resources/tile_set.h"
@ -78,7 +77,7 @@ private:
bool use_parent = false;
CollisionObject2D *collision_parent = nullptr;
bool use_kinematic = false;
Navigation2D *navigation = nullptr;
bool bake_navigation = false;
union PosKey {
struct {
@ -295,6 +294,9 @@ public:
void set_collision_bounce(float p_bounce);
float get_collision_bounce() const;
void set_bake_navigation(bool p_bake_navigation);
bool is_baking_navigation();
void set_mode(Mode p_mode);
Mode get_mode() const;

View file

@ -1,117 +0,0 @@
/*************************************************************************/
/* navigation_3d.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 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_3d.h"
#include "servers/navigation_server_3d.h"
Vector<Vector3> Navigation3D::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) const {
return NavigationServer3D::get_singleton()->map_get_path(map, p_start, p_end, p_optimize);
}
Vector3 Navigation3D::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision) const {
return NavigationServer3D::get_singleton()->map_get_closest_point_to_segment(map, p_from, p_to, p_use_collision);
}
Vector3 Navigation3D::get_closest_point(const Vector3 &p_point) const {
return NavigationServer3D::get_singleton()->map_get_closest_point(map, p_point);
}
Vector3 Navigation3D::get_closest_point_normal(const Vector3 &p_point) const {
return NavigationServer3D::get_singleton()->map_get_closest_point_normal(map, p_point);
}
RID Navigation3D::get_closest_point_owner(const Vector3 &p_point) const {
return NavigationServer3D::get_singleton()->map_get_closest_point_owner(map, p_point);
}
void Navigation3D::set_up_vector(const Vector3 &p_up) {
up = p_up;
NavigationServer3D::get_singleton()->map_set_up(map, up);
}
Vector3 Navigation3D::get_up_vector() const {
return up;
}
void Navigation3D::set_cell_size(float p_cell_size) {
cell_size = p_cell_size;
NavigationServer3D::get_singleton()->map_set_cell_size(map, cell_size);
}
void Navigation3D::set_edge_connection_margin(float p_edge_connection_margin) {
edge_connection_margin = p_edge_connection_margin;
NavigationServer3D::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin);
}
void Navigation3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rid"), &Navigation3D::get_rid);
ClassDB::bind_method(D_METHOD("get_simple_path", "start", "end", "optimize"), &Navigation3D::get_simple_path, DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "start", "end", "use_collision"), &Navigation3D::get_closest_point_to_segment, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Navigation3D::get_closest_point);
ClassDB::bind_method(D_METHOD("get_closest_point_normal", "to_point"), &Navigation3D::get_closest_point_normal);
ClassDB::bind_method(D_METHOD("get_closest_point_owner", "to_point"), &Navigation3D::get_closest_point_owner);
ClassDB::bind_method(D_METHOD("set_up_vector", "up"), &Navigation3D::set_up_vector);
ClassDB::bind_method(D_METHOD("get_up_vector"), &Navigation3D::get_up_vector);
ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation3D::set_cell_size);
ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation3D::get_cell_size);
ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation3D::set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation3D::get_edge_connection_margin);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_vector"), "set_up_vector", "get_up_vector");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size"), "set_cell_size", "get_cell_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin");
}
void Navigation3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
NavigationServer3D::get_singleton()->map_set_active(map, true);
} break;
case NOTIFICATION_EXIT_TREE: {
NavigationServer3D::get_singleton()->map_set_active(map, false);
} break;
}
}
Navigation3D::Navigation3D() {
map = NavigationServer3D::get_singleton()->map_create();
set_cell_size(0.3);
set_edge_connection_margin(5.0); // Five meters, depends a lot on the agent's radius
}
Navigation3D::~Navigation3D() {
NavigationServer3D::get_singleton()->free(map);
}

View file

@ -1,78 +0,0 @@
/*************************************************************************/
/* navigation_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 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_3D_H
#define NAVIGATION_3D_H
#include "scene/3d/navigation_region_3d.h"
#include "scene/3d/node_3d.h"
class Navigation3D : public Node3D {
GDCLASS(Navigation3D, Node3D);
RID map;
Vector3 up = Vector3(0, 1, 0);
real_t cell_size;
real_t edge_connection_margin;
protected:
static void _bind_methods();
void _notification(int p_what);
public:
RID get_rid() const {
return map;
}
void set_up_vector(const Vector3 &p_up);
Vector3 get_up_vector() const;
void set_cell_size(float p_cell_size);
float get_cell_size() const {
return cell_size;
}
void set_edge_connection_margin(float p_edge_connection_margin);
float get_edge_connection_margin() const {
return edge_connection_margin;
}
Vector<Vector3> get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize = true) const;
Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision = false) const;
Vector3 get_closest_point(const Vector3 &p_point) const;
Vector3 get_closest_point_normal(const Vector3 &p_point) const;
RID get_closest_point_owner(const Vector3 &p_point) const;
Navigation3D();
~Navigation3D();
};
#endif // NAVIGATION_H

View file

@ -31,7 +31,6 @@
#include "navigation_agent_3d.h"
#include "core/config/engine.h"
#include "scene/3d/navigation_3d.h"
#include "servers/navigation_server_3d.h"
void NavigationAgent3D::_bind_methods() {
@ -47,9 +46,6 @@ void NavigationAgent3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_ignore_y", "ignore"), &NavigationAgent3D::set_ignore_y);
ClassDB::bind_method(D_METHOD("get_ignore_y"), &NavigationAgent3D::get_ignore_y);
ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationAgent3D::set_navigation_node);
ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationAgent3D::get_navigation_node);
ClassDB::bind_method(D_METHOD("set_neighbor_dist", "neighbor_dist"), &NavigationAgent3D::set_neighbor_dist);
ClassDB::bind_method(D_METHOD("get_neighbor_dist"), &NavigationAgent3D::get_neighbor_dist);
@ -101,28 +97,10 @@ void NavigationAgent3D::_notification(int p_what) {
agent_parent = Object::cast_to<Node3D>(get_parent());
NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
// Search the navigation node and set it
{
Navigation3D *nav = nullptr;
Node *p = get_parent();
while (p != nullptr) {
nav = Object::cast_to<Navigation3D>(p);
if (nav != nullptr) {
p = nullptr;
} else {
p = p->get_parent();
}
}
set_navigation(nav);
}
set_physics_process_internal(true);
} break;
case NOTIFICATION_EXIT_TREE: {
agent_parent = nullptr;
set_navigation(nullptr);
set_physics_process_internal(false);
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
@ -154,25 +132,6 @@ NavigationAgent3D::~NavigationAgent3D() {
agent = RID(); // Pointless
}
void NavigationAgent3D::set_navigation(Navigation3D *p_nav) {
if (navigation == p_nav) {
return; // Pointless
}
navigation = p_nav;
NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid());
}
void NavigationAgent3D::set_navigation_node(Node *p_nav) {
Navigation3D *nav = Object::cast_to<Navigation3D>(p_nav);
ERR_FAIL_COND(nav == nullptr);
set_navigation(nav);
}
Node *NavigationAgent3D::get_navigation_node() const {
return Object::cast_to<Node>(navigation);
}
void NavigationAgent3D::set_target_desired_distance(real_t p_dd) {
target_desired_distance = p_dd;
}
@ -303,7 +262,7 @@ void NavigationAgent3D::update_navigation() {
if (agent_parent == nullptr) {
return;
}
if (navigation == nullptr) {
if (!agent_parent->is_inside_tree()) {
return;
}
if (update_frame_id == Engine::get_singleton()->get_physics_frames()) {
@ -337,7 +296,7 @@ void NavigationAgent3D::update_navigation() {
}
if (reload_path) {
navigation_path = NavigationServer3D::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true);
navigation_path = NavigationServer3D::get_singleton()->map_get_path(agent_parent->get_world_3d()->get_navigation_map(), o, target_location, true);
navigation_finished = false;
nav_path_index = 0;
emit_signal("path_changed");

View file

@ -35,13 +35,11 @@
#include "scene/main/node.h"
class Node3D;
class Navigation3D;
class NavigationAgent3D : public Node {
GDCLASS(NavigationAgent3D, Node);
Node3D *agent_parent = nullptr;
Navigation3D *navigation = nullptr;
RID agent;
@ -76,14 +74,6 @@ public:
NavigationAgent3D();
virtual ~NavigationAgent3D();
void set_navigation(Navigation3D *p_nav);
const Navigation3D *get_navigation() const {
return navigation;
}
void set_navigation_node(Node *p_nav);
Node *get_navigation_node() const;
RID get_rid() const {
return agent;
}

View file

@ -31,55 +31,38 @@
#include "navigation_obstacle_3d.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/navigation_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "servers/navigation_server_3d.h"
void NavigationObstacle3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle3D::set_navigation_node);
ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle3D::get_navigation_node);
}
void NavigationObstacle3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
update_agent_shape();
// Search the navigation node and set it
{
Navigation3D *nav = nullptr;
Node *p = get_parent();
while (p != nullptr) {
nav = Object::cast_to<Navigation3D>(p);
if (nav != nullptr) {
p = nullptr;
} else {
p = p->get_parent();
}
}
set_navigation(nav);
}
set_physics_process_internal(true);
} break;
case NOTIFICATION_EXIT_TREE: {
set_navigation(nullptr);
set_physics_process_internal(false);
} break;
case NOTIFICATION_PARENTED: {
parent_node3d = Object::cast_to<Node3D>(get_parent());
update_agent_shape();
} break;
case NOTIFICATION_UNPARENTED: {
parent_node3d = nullptr;
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
Node3D *spatial = Object::cast_to<Node3D>(get_parent());
if (spatial) {
NavigationServer3D::get_singleton()->agent_set_position(agent, spatial->get_global_transform().origin);
}
if (parent_node3d) {
NavigationServer3D::get_singleton()->agent_set_position(agent, parent_node3d->get_global_transform().origin);
PhysicsBody3D *rigid = Object::cast_to<PhysicsBody3D>(get_parent());
if (rigid) {
Vector3 v = rigid->get_linear_velocity();
NavigationServer3D::get_singleton()->agent_set_velocity(agent, v);
NavigationServer3D::get_singleton()->agent_set_target_velocity(agent, v);
PhysicsBody3D *rigid = Object::cast_to<PhysicsBody3D>(get_parent());
if (rigid) {
Vector3 v = rigid->get_linear_velocity();
NavigationServer3D::get_singleton()->agent_set_velocity(agent, v);
NavigationServer3D::get_singleton()->agent_set_target_velocity(agent, v);
}
}
} break;
}
}
@ -93,29 +76,10 @@ NavigationObstacle3D::~NavigationObstacle3D() {
agent = RID(); // Pointless
}
void NavigationObstacle3D::set_navigation(Navigation3D *p_nav) {
if (navigation == p_nav) {
return; // Pointless
}
navigation = p_nav;
NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == nullptr ? RID() : navigation->get_rid());
}
void NavigationObstacle3D::set_navigation_node(Node *p_nav) {
Navigation3D *nav = Object::cast_to<Navigation3D>(p_nav);
ERR_FAIL_COND(nav == nullptr);
set_navigation(nav);
}
Node *NavigationObstacle3D::get_navigation_node() const {
return Object::cast_to<Node>(navigation);
}
String NavigationObstacle3D::get_configuration_warning() const {
String warning = Node::get_configuration_warning();
if (!Object::cast_to<Node3D>(get_parent())) {
if (!parent_node3d) {
if (!warning.is_empty()) {
warning += "\n\n";
}
@ -126,40 +90,38 @@ String NavigationObstacle3D::get_configuration_warning() const {
}
void NavigationObstacle3D::update_agent_shape() {
Node *node = get_parent();
// Estimate the radius of this physics body
real_t radius = 0.0;
for (int i(0); i < node->get_child_count(); i++) {
// For each collision shape
CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(node->get_child(i));
if (cs) {
// Take the distance between the Body center to the shape center
real_t r = cs->get_transform().origin.length();
if (cs->get_shape().is_valid()) {
// and add the enclosing shape radius
r += cs->get_shape()->get_enclosing_radius();
if (parent_node3d) {
// Estimate the radius of this physics body
real_t radius = 0.0;
for (int i(0); i < parent_node3d->get_child_count(); i++) {
// For each collision shape
CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(parent_node3d->get_child(i));
if (cs) {
// Take the distance between the Body center to the shape center
real_t r = cs->get_transform().origin.length();
if (cs->get_shape().is_valid()) {
// and add the enclosing shape radius
r += cs->get_shape()->get_enclosing_radius();
}
Vector3 s = cs->get_global_transform().basis.get_scale();
r *= MAX(s.x, MAX(s.y, s.z));
// Takes the biggest radius
radius = MAX(radius, r);
}
Vector3 s = cs->get_global_transform().basis.get_scale();
r *= MAX(s.x, MAX(s.y, s.z));
// Takes the biggest radius
radius = MAX(radius, r);
}
}
Node3D *spa = Object::cast_to<Node3D>(node);
if (spa) {
Vector3 s = spa->get_global_transform().basis.get_scale();
Vector3 s = parent_node3d->get_global_transform().basis.get_scale();
radius *= MAX(s.x, MAX(s.y, s.z));
}
if (radius == 0.0) {
radius = 1.0; // Never a 0 radius
}
if (radius == 0.0) {
radius = 1.0; // Never a 0 radius
}
// Initialize the Agent as an object
NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0);
NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0);
NavigationServer3D::get_singleton()->agent_set_radius(agent, radius);
NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0);
// Initialize the Agent as an object
NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0);
NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0);
NavigationServer3D::get_singleton()->agent_set_radius(agent, radius);
NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0);
}
}

View file

@ -31,15 +31,13 @@
#ifndef NAVIGATION_OBSTACLE_H
#define NAVIGATION_OBSTACLE_H
#include "scene/3d/node_3d.h"
#include "scene/main/node.h"
class Navigation3D;
class NavigationObstacle3D : public Node {
GDCLASS(NavigationObstacle3D, Node);
Navigation3D *navigation = nullptr;
Node3D *parent_node3d = nullptr;
RID agent;
protected:
@ -50,14 +48,6 @@ public:
NavigationObstacle3D();
virtual ~NavigationObstacle3D();
void set_navigation(Navigation3D *p_nav);
const Navigation3D *get_navigation() const {
return navigation;
}
void set_navigation_node(Node *p_nav);
Node *get_navigation_node() const;
RID get_rid() const {
return agent;
}

View file

@ -32,7 +32,6 @@
#include "core/os/thread.h"
#include "mesh_instance_3d.h"
#include "navigation_3d.h"
#include "servers/navigation_server_3d.h"
void NavigationRegion3D::set_enabled(bool p_enabled) {
@ -48,9 +47,7 @@ void NavigationRegion3D::set_enabled(bool p_enabled) {
if (!enabled) {
NavigationServer3D::get_singleton()->region_set_map(region, RID());
} else {
if (navigation) {
NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid());
}
NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
}
if (debug_view) {
@ -74,17 +71,8 @@ bool NavigationRegion3D::is_enabled() const {
void NavigationRegion3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
Node3D *c = this;
while (c) {
navigation = Object::cast_to<Navigation3D>(c);
if (navigation) {
if (enabled) {
NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid());
}
break;
}
c = c->get_parent_spatial();
if (enabled) {
NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
}
if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) {
@ -105,15 +93,12 @@ void NavigationRegion3D::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
if (navigation) {
NavigationServer3D::get_singleton()->region_set_map(region, RID());
}
NavigationServer3D::get_singleton()->region_set_map(region, RID());
if (debug_view) {
debug_view->queue_delete();
debug_view = nullptr;
}
navigation = nullptr;
} break;
}
}
@ -198,19 +183,7 @@ String NavigationRegion3D::get_configuration_warning() const {
warning += TTR("A NavigationMesh resource must be set or created for this node to work.");
}
const Node3D *c = this;
while (c) {
if (Object::cast_to<Navigation3D>(c)) {
return warning;
}
c = Object::cast_to<Node3D>(c->get_parent());
}
if (!warning.is_empty()) {
warning += "\n\n";
}
return warning + TTR("NavigationRegion3D must be a child or grandchild to a Navigation3D node. It only provides navigation data.");
return warning;
}
void NavigationRegion3D::_bind_methods() {

View file

@ -35,8 +35,6 @@
#include "scene/resources/mesh.h"
#include "scene/resources/navigation_mesh.h"
class Navigation3D;
class NavigationRegion3D : public Node3D {
GDCLASS(NavigationRegion3D, Node3D);
@ -44,7 +42,6 @@ class NavigationRegion3D : public Node3D {
RID region;
Ref<NavigationMesh> navmesh;
Navigation3D *navigation = nullptr;
Node *debug_view = nullptr;
Thread bake_thread;

View file

@ -50,7 +50,6 @@
#include "scene/2d/line_2d.h"
#include "scene/2d/mesh_instance_2d.h"
#include "scene/2d/multimesh_instance_2d.h"
#include "scene/2d/navigation_2d.h"
#include "scene/2d/navigation_agent_2d.h"
#include "scene/2d/navigation_obstacle_2d.h"
#include "scene/2d/parallax_background.h"
@ -206,7 +205,6 @@
#include "scene/3d/listener_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/multimesh_instance_3d.h"
#include "scene/3d/navigation_3d.h"
#include "scene/3d/navigation_agent_3d.h"
#include "scene/3d/navigation_obstacle_3d.h"
#include "scene/3d/navigation_region_3d.h"
@ -516,7 +514,6 @@ void register_scene_types() {
ClassDB::register_class<ConeTwistJoint3D>();
ClassDB::register_class<Generic6DOFJoint3D>();
ClassDB::register_class<Navigation3D>();
ClassDB::register_class<NavigationRegion3D>();
ClassDB::register_class<NavigationAgent3D>();
ClassDB::register_class<NavigationObstacle3D>();
@ -793,7 +790,6 @@ void register_scene_types() {
ClassDB::register_class<PathFollow2D>();
ClassDB::register_class<NavigationMesh>();
ClassDB::register_class<Navigation2D>();
ClassDB::register_class<NavigationPolygon>();
ClassDB::register_class<NavigationRegion2D>();
ClassDB::register_class<NavigationAgent2D>();
@ -814,6 +810,8 @@ void register_scene_types() {
ClassDB::add_compatibility_class("DynamicFont", "Font");
ClassDB::add_compatibility_class("DynamicFontData", "FontData");
ClassDB::add_compatibility_class("ToolButton", "Button");
ClassDB::add_compatibility_class("Navigation3D", "Node3D");
ClassDB::add_compatibility_class("Navigation2D", "Node2D");
// Renamed in 4.0.
// Keep alphabetical ordering to easily locate classes and avoid duplicates.
@ -865,7 +863,6 @@ void register_scene_types() {
ClassDB::add_compatibility_class("Listener", "Listener3D");
ClassDB::add_compatibility_class("MeshInstance", "MeshInstance3D");
ClassDB::add_compatibility_class("MultiMeshInstance", "MultiMeshInstance3D");
ClassDB::add_compatibility_class("Navigation", "Navigation3D");
ClassDB::add_compatibility_class("NavigationAgent", "NavigationAgent3D");
ClassDB::add_compatibility_class("NavigationMeshInstance", "NavigationRegion3D");
ClassDB::add_compatibility_class("NavigationObstacle", "NavigationObstacle3D");

View file

@ -34,6 +34,7 @@
#include "scene/2d/camera_2d.h"
#include "scene/2d/visibility_notifier_2d.h"
#include "scene/main/window.h"
#include "servers/navigation_server_2d.h"
#include "servers/physics_server_2d.h"
#include "servers/rendering_server.h"
@ -315,14 +316,18 @@ void World2D::_update() {
indexer->_update();
}
RID World2D::get_canvas() {
RID World2D::get_canvas() const {
return canvas;
}
RID World2D::get_space() {
RID World2D::get_space() const {
return space;
}
RID World2D::get_navigation_map() const {
return navigation_map;
}
void World2D::get_viewport_list(List<Viewport *> *r_viewports) {
for (Map<Viewport *, SpatialIndexer2D::ViewportData>::Element *E = indexer->viewports.front(); E; E = E->next()) {
r_viewports->push_back(E->key());
@ -332,11 +337,13 @@ void World2D::get_viewport_list(List<Viewport *> *r_viewports) {
void World2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_canvas"), &World2D::get_canvas);
ClassDB::bind_method(D_METHOD("get_space"), &World2D::get_space);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &World2D::get_navigation_map);
ClassDB::bind_method(D_METHOD("get_direct_space_state"), &World2D::get_direct_space_state);
ADD_PROPERTY(PropertyInfo(Variant::RID, "canvas", PROPERTY_HINT_NONE, "", 0), "", "get_canvas");
ADD_PROPERTY(PropertyInfo(Variant::RID, "space", PROPERTY_HINT_NONE, "", 0), "", "get_space");
ADD_PROPERTY(PropertyInfo(Variant::RID, "navigation_map", PROPERTY_HINT_NONE, "", 0), "", "get_navigation_map");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectSpaceState2D", 0), "", "get_direct_space_state");
}
@ -346,9 +353,9 @@ PhysicsDirectSpaceState2D *World2D::get_direct_space_state() {
World2D::World2D() {
canvas = RenderingServer::get_singleton()->canvas_create();
space = PhysicsServer2D::get_singleton()->space_create();
//set space2D to be more friendly with pixels than meters, by adjusting some constants
// Create and configure space2D to be more friendly with pixels than meters
space = PhysicsServer2D::get_singleton()->space_create();
PhysicsServer2D::get_singleton()->space_set_active(space, true);
PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 98));
PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/2d/default_gravity_vector", Vector2(0, 1)));
@ -356,11 +363,19 @@ World2D::World2D() {
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/2d/default_angular_damp", 1.0));
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
// Create and configure the navigation_map to be more friendly with pixels than meters.
navigation_map = NavigationServer2D::get_singleton()->map_create();
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", 10));
NavigationServer2D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/2d/default_edge_connection_margin", 100));
indexer = memnew(SpatialIndexer2D);
}
World2D::~World2D() {
RenderingServer::get_singleton()->free(canvas);
PhysicsServer2D::get_singleton()->free(space);
NavigationServer2D::get_singleton()->free(navigation_map);
memdelete(indexer);
}

View file

@ -44,6 +44,7 @@ class World2D : public Resource {
RID canvas;
RID space;
RID navigation_map;
SpatialIndexer2D *indexer;
@ -63,8 +64,9 @@ protected:
void _update();
public:
RID get_canvas();
RID get_space();
RID get_canvas() const;
RID get_space() const;
RID get_navigation_map() const;
PhysicsDirectSpaceState2D *get_direct_space_state();

View file

@ -35,6 +35,7 @@
#include "scene/3d/camera_3d.h"
#include "scene/3d/visibility_notifier_3d.h"
#include "scene/scene_string_names.h"
#include "servers/navigation_server_3d.h"
struct SpatialIndexer {
Octree<VisibilityNotifier3D> octree;
@ -243,6 +244,10 @@ RID World3D::get_space() const {
return space;
}
RID World3D::get_navigation_map() const {
return navigation_map;
}
RID World3D::get_scenario() const {
return scenario;
}
@ -310,6 +315,7 @@ void World3D::get_camera_list(List<Camera3D *> *r_cameras) {
void World3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_space"), &World3D::get_space);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &World3D::get_navigation_map);
ClassDB::bind_method(D_METHOD("get_scenario"), &World3D::get_scenario);
ClassDB::bind_method(D_METHOD("set_environment", "env"), &World3D::set_environment);
ClassDB::bind_method(D_METHOD("get_environment"), &World3D::get_environment);
@ -322,6 +328,7 @@ void World3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_fallback_environment", "get_fallback_environment");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_camera_effects", "get_camera_effects");
ADD_PROPERTY(PropertyInfo(Variant::RID, "space", PROPERTY_HINT_NONE, "", 0), "", "get_space");
ADD_PROPERTY(PropertyInfo(Variant::RID, "navigation_map", PROPERTY_HINT_NONE, "", 0), "", "get_navigation_map");
ADD_PROPERTY(PropertyInfo(Variant::RID, "scenario", PROPERTY_HINT_NONE, "", 0), "", "get_scenario");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectSpaceState3D", 0), "", "get_direct_space_state");
}
@ -338,6 +345,11 @@ World3D::World3D() {
PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/3d/default_angular_damp", 0.1));
ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
navigation_map = NavigationServer3D::get_singleton()->map_create();
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.3));
NavigationServer3D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/3d/default_edge_connection_margin", 5.0)); // Five meters, depends a lot on the agent's radius
#ifdef _3D_DISABLED
indexer = nullptr;
#else
@ -348,6 +360,7 @@ World3D::World3D() {
World3D::~World3D() {
PhysicsServer3D::get_singleton()->free(space);
RenderingServer::get_singleton()->free(scenario);
NavigationServer3D::get_singleton()->free(navigation_map);
#ifndef _3D_DISABLED
memdelete(indexer);

View file

@ -46,6 +46,7 @@ class World3D : public Resource {
private:
RID space;
RID navigation_map;
RID scenario;
SpatialIndexer *indexer;
Ref<Environment> environment;
@ -70,6 +71,7 @@ protected:
public:
RID get_space() const;
RID get_navigation_map() const;
RID get_scenario() const;
void set_environment(const Ref<Environment> &p_environment);