summaryrefslogtreecommitdiff
path: root/scene/2d/navigation_polygon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d/navigation_polygon.cpp')
-rw-r--r--scene/2d/navigation_polygon.cpp171
1 files changed, 105 insertions, 66 deletions
diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp
index 883fb37668..9159ef21c5 100644
--- a/scene/2d/navigation_polygon.cpp
+++ b/scene/2d/navigation_polygon.cpp
@@ -32,7 +32,9 @@
#include "core/core_string_names.h"
#include "core/engine.h"
+#include "core/os/mutex.h"
#include "navigation_2d.h"
+#include "servers/navigation_2d_server.h"
#include "thirdparty/misc/triangulator.h"
@@ -44,11 +46,11 @@ Rect2 NavigationPolygon::_edit_get_rect() const {
bool first = true;
for (int i = 0; i < outlines.size(); i++) {
- const PoolVector<Vector2> &outline = outlines[i];
+ const Vector<Vector2> &outline = outlines[i];
const int outline_size = outline.size();
if (outline_size < 3)
continue;
- PoolVector<Vector2>::Read p = outline.read();
+ const Vector2 *p = outline.ptr();
for (int j = 0; j < outline_size; j++) {
if (first) {
item_rect = Rect2(p[j], Vector2(0, 0));
@@ -67,7 +69,7 @@ Rect2 NavigationPolygon::_edit_get_rect() const {
bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
for (int i = 0; i < outlines.size(); i++) {
- const PoolVector<Vector2> &outline = outlines[i];
+ const Vector<Vector2> &outline = outlines[i];
const int outline_size = outline.size();
if (outline_size < 3)
continue;
@@ -78,19 +80,27 @@ bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double
}
#endif
-void NavigationPolygon::set_vertices(const PoolVector<Vector2> &p_vertices) {
+void NavigationPolygon::set_vertices(const Vector<Vector2> &p_vertices) {
+ {
+ MutexLock lock(navmesh_generation);
+ navmesh.unref();
+ }
vertices = p_vertices;
rect_cache_dirty = true;
}
-PoolVector<Vector2> NavigationPolygon::get_vertices() const {
+Vector<Vector2> NavigationPolygon::get_vertices() const {
return vertices;
}
void NavigationPolygon::_set_polygons(const Array &p_array) {
+ {
+ MutexLock lock(navmesh_generation);
+ navmesh.unref();
+ }
polygons.resize(p_array.size());
for (int i = 0; i < p_array.size(); i++) {
polygons.write[i].indices = p_array[i];
@@ -133,9 +143,13 @@ void NavigationPolygon::add_polygon(const Vector<int> &p_polygon) {
Polygon polygon;
polygon.indices = p_polygon;
polygons.push_back(polygon);
+ {
+ MutexLock lock(navmesh_generation);
+ navmesh.unref();
+ }
}
-void NavigationPolygon::add_outline_at_index(const PoolVector<Vector2> &p_outline, int p_index) {
+void NavigationPolygon::add_outline_at_index(const Vector<Vector2> &p_outline, int p_index) {
outlines.insert(p_index, p_outline);
rect_cache_dirty = true;
@@ -153,9 +167,39 @@ Vector<int> NavigationPolygon::get_polygon(int p_idx) {
void NavigationPolygon::clear_polygons() {
polygons.clear();
+ {
+ MutexLock lock(navmesh_generation);
+ navmesh.unref();
+ }
}
-void NavigationPolygon::add_outline(const PoolVector<Vector2> &p_outline) {
+Ref<NavigationMesh> NavigationPolygon::get_mesh() {
+ MutexLock lock(navmesh_generation);
+
+ if (navmesh.is_null()) {
+ navmesh.instance();
+ Vector<Vector3> verts;
+ {
+ verts.resize(get_vertices().size());
+ Vector3 *w = verts.ptrw();
+
+ const Vector2 *r = get_vertices().ptr();
+
+ for (int i(0); i < get_vertices().size(); i++) {
+ w[i] = Vector3(r[i].x, 0.0, r[i].y);
+ }
+ }
+ navmesh->set_vertices(verts);
+
+ for (int i(0); i < get_polygon_count(); i++) {
+ navmesh->add_polygon(get_polygon(i));
+ }
+ }
+
+ return navmesh;
+}
+
+void NavigationPolygon::add_outline(const Vector<Vector2> &p_outline) {
outlines.push_back(p_outline);
rect_cache_dirty = true;
@@ -166,7 +210,7 @@ int NavigationPolygon::get_outline_count() const {
return outlines.size();
}
-void NavigationPolygon::set_outline(int p_idx, const PoolVector<Vector2> &p_outline) {
+void NavigationPolygon::set_outline(int p_idx, const Vector<Vector2> &p_outline) {
ERR_FAIL_INDEX(p_idx, outlines.size());
outlines.write[p_idx] = p_outline;
rect_cache_dirty = true;
@@ -179,8 +223,8 @@ void NavigationPolygon::remove_outline(int p_idx) {
rect_cache_dirty = true;
}
-PoolVector<Vector2> NavigationPolygon::get_outline(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, outlines.size(), PoolVector<Vector2>());
+Vector<Vector2> NavigationPolygon::get_outline(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, outlines.size(), Vector<Vector2>());
return outlines[p_idx];
}
@@ -191,17 +235,21 @@ void NavigationPolygon::clear_outlines() {
}
void NavigationPolygon::make_polygons_from_outlines() {
+ {
+ MutexLock lock(navmesh_generation);
+ navmesh.unref();
+ }
List<TriangulatorPoly> in_poly, out_poly;
Vector2 outside_point(-1e10, -1e10);
for (int i = 0; i < outlines.size(); i++) {
- PoolVector<Vector2> ol = outlines[i];
+ Vector<Vector2> ol = outlines[i];
int olsize = ol.size();
if (olsize < 3)
continue;
- PoolVector<Vector2>::Read r = ol.read();
+ const Vector2 *r = ol.ptr();
for (int j = 0; j < olsize; j++) {
outside_point.x = MAX(r[j].x, outside_point.x);
outside_point.y = MAX(r[j].y, outside_point.y);
@@ -212,11 +260,11 @@ void NavigationPolygon::make_polygons_from_outlines() {
for (int i = 0; i < outlines.size(); i++) {
- PoolVector<Vector2> ol = outlines[i];
+ Vector<Vector2> ol = outlines[i];
int olsize = ol.size();
if (olsize < 3)
continue;
- PoolVector<Vector2>::Read r = ol.read();
+ const Vector2 *r = ol.ptr();
int interscount = 0;
//test if this is an outer outline
@@ -225,11 +273,11 @@ void NavigationPolygon::make_polygons_from_outlines() {
if (i == k)
continue; //no self intersect
- PoolVector<Vector2> ol2 = outlines[k];
+ Vector<Vector2> ol2 = outlines[k];
int olsize2 = ol2.size();
if (olsize2 < 3)
continue;
- PoolVector<Vector2>::Read r2 = ol2.read();
+ const Vector2 *r2 = ol2.ptr();
for (int l = 0; l < olsize2; l++) {
@@ -314,7 +362,7 @@ void NavigationPolygon::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_outlines", "outlines"), &NavigationPolygon::_set_outlines);
ClassDB::bind_method(D_METHOD("_get_outlines"), &NavigationPolygon::_get_outlines);
- ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines");
}
@@ -323,7 +371,10 @@ NavigationPolygon::NavigationPolygon() :
rect_cache_dirty(true) {
}
-void NavigationPolygonInstance::set_enabled(bool p_enabled) {
+NavigationPolygon::~NavigationPolygon() {
+}
+
+void NavigationRegion2D::set_enabled(bool p_enabled) {
if (enabled == p_enabled)
return;
@@ -334,18 +385,12 @@ void NavigationPolygonInstance::set_enabled(bool p_enabled) {
if (!enabled) {
- if (nav_id != -1) {
- navigation->navpoly_remove(nav_id);
- nav_id = -1;
- }
+ Navigation2DServer::get_singleton()->region_set_map(region, RID());
} else {
if (navigation) {
- if (navpoly.is_valid()) {
-
- nav_id = navigation->navpoly_add(navpoly, get_relative_transform_to_parent(navigation), this);
- }
+ Navigation2DServer::get_singleton()->region_set_map(region, navigation->get_rid());
}
}
@@ -353,25 +398,25 @@ void NavigationPolygonInstance::set_enabled(bool p_enabled) {
update();
}
-bool NavigationPolygonInstance::is_enabled() const {
+bool NavigationRegion2D::is_enabled() const {
return enabled;
}
/////////////////////////////
#ifdef TOOLS_ENABLED
-Rect2 NavigationPolygonInstance::_edit_get_rect() const {
+Rect2 NavigationRegion2D::_edit_get_rect() const {
return navpoly.is_valid() ? navpoly->_edit_get_rect() : Rect2();
}
-bool NavigationPolygonInstance::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+bool NavigationRegion2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
return navpoly.is_valid() ? navpoly->_edit_is_selected_on_click(p_point, p_tolerance) : false;
}
#endif
-void NavigationPolygonInstance::_notification(int p_what) {
+void NavigationRegion2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -382,9 +427,9 @@ void NavigationPolygonInstance::_notification(int p_what) {
navigation = Object::cast_to<Navigation2D>(c);
if (navigation) {
- if (enabled && navpoly.is_valid()) {
+ if (enabled) {
- nav_id = navigation->navpoly_add(navpoly, get_relative_transform_to_parent(navigation), this);
+ Navigation2DServer::get_singleton()->region_set_map(region, navigation->get_rid());
}
break;
}
@@ -395,19 +440,14 @@ void NavigationPolygonInstance::_notification(int p_what) {
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
- if (navigation && nav_id != -1) {
- navigation->navpoly_set_transform(nav_id, get_relative_transform_to_parent(navigation));
- }
+ Navigation2DServer::get_singleton()->region_set_transform(region, get_global_transform());
} break;
case NOTIFICATION_EXIT_TREE: {
if (navigation) {
- if (nav_id != -1) {
- navigation->navpoly_remove(nav_id);
- nav_id = -1;
- }
+ Navigation2DServer::get_singleton()->region_set_map(region, RID());
}
navigation = NULL;
} break;
@@ -415,7 +455,7 @@ void NavigationPolygonInstance::_notification(int p_what) {
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) && navpoly.is_valid()) {
- PoolVector<Vector2> verts = navpoly->get_vertices();
+ Vector<Vector2> verts = navpoly->get_vertices();
int vsize = verts.size();
if (vsize < 3)
return;
@@ -431,7 +471,7 @@ void NavigationPolygonInstance::_notification(int p_what) {
vertices.resize(vsize);
colors.resize(vsize);
{
- PoolVector<Vector2>::Read vr = verts.read();
+ const Vector2 *vr = verts.ptr();
for (int i = 0; i < vsize; i++) {
vertices.write[i] = vr[i];
colors.write[i] = color;
@@ -460,46 +500,40 @@ void NavigationPolygonInstance::_notification(int p_what) {
}
}
-void NavigationPolygonInstance::set_navigation_polygon(const Ref<NavigationPolygon> &p_navpoly) {
+void NavigationRegion2D::set_navigation_polygon(const Ref<NavigationPolygon> &p_navpoly) {
if (p_navpoly == navpoly) {
return;
}
- if (navigation && nav_id != -1) {
- navigation->navpoly_remove(nav_id);
- nav_id = -1;
- }
-
if (navpoly.is_valid()) {
- navpoly->disconnect(CoreStringNames::get_singleton()->changed, this, "_navpoly_changed");
+ navpoly->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NavigationRegion2D::_navpoly_changed));
}
+
navpoly = p_navpoly;
+ Navigation2DServer::get_singleton()->region_set_navpoly(region, p_navpoly);
+
if (navpoly.is_valid()) {
- navpoly->connect(CoreStringNames::get_singleton()->changed, this, "_navpoly_changed");
+ navpoly->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NavigationRegion2D::_navpoly_changed));
}
_navpoly_changed();
- if (navigation && navpoly.is_valid() && enabled) {
- nav_id = navigation->navpoly_add(navpoly, get_relative_transform_to_parent(navigation), this);
- }
-
_change_notify("navpoly");
update_configuration_warning();
}
-Ref<NavigationPolygon> NavigationPolygonInstance::get_navigation_polygon() const {
+Ref<NavigationPolygon> NavigationRegion2D::get_navigation_polygon() const {
return navpoly;
}
-void NavigationPolygonInstance::_navpoly_changed() {
+void NavigationRegion2D::_navpoly_changed() {
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()))
update();
}
-String NavigationPolygonInstance::get_configuration_warning() const {
+String NavigationRegion2D::get_configuration_warning() const {
if (!is_visible_in_tree() || !is_inside_tree())
return String();
@@ -517,27 +551,32 @@ String NavigationPolygonInstance::get_configuration_warning() const {
c = Object::cast_to<Node2D>(c->get_parent());
}
- return TTR("NavigationPolygonInstance must be a child or grandchild to a Navigation2D node. It only provides navigation data.");
+ return TTR("NavigationRegion2D must be a child or grandchild to a Navigation2D node. It only provides navigation data.");
}
-void NavigationPolygonInstance::_bind_methods() {
+void NavigationRegion2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_navigation_polygon", "navpoly"), &NavigationPolygonInstance::set_navigation_polygon);
- ClassDB::bind_method(D_METHOD("get_navigation_polygon"), &NavigationPolygonInstance::get_navigation_polygon);
+ ClassDB::bind_method(D_METHOD("set_navigation_polygon", "navpoly"), &NavigationRegion2D::set_navigation_polygon);
+ ClassDB::bind_method(D_METHOD("get_navigation_polygon"), &NavigationRegion2D::get_navigation_polygon);
- ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationPolygonInstance::set_enabled);
- ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationPolygonInstance::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion2D::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion2D::is_enabled);
- ClassDB::bind_method(D_METHOD("_navpoly_changed"), &NavigationPolygonInstance::_navpoly_changed);
+ ClassDB::bind_method(D_METHOD("_navpoly_changed"), &NavigationRegion2D::_navpoly_changed);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navpoly", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon"), "set_navigation_polygon", "get_navigation_polygon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
}
-NavigationPolygonInstance::NavigationPolygonInstance() {
+NavigationRegion2D::NavigationRegion2D() {
- navigation = NULL;
- nav_id = -1;
enabled = true;
set_notify_transform(true);
+ region = Navigation2DServer::get_singleton()->region_create();
+
+ navigation = NULL;
+}
+
+NavigationRegion2D::~NavigationRegion2D() {
+ Navigation2DServer::get_singleton()->free(region);
}