Path: blob/master/scene/resources/2d/navigation_polygon.cpp
9898 views
/**************************************************************************/1/* navigation_polygon.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "navigation_polygon.h"3132#include "core/math/geometry_2d.h"33#include "core/os/mutex.h"3435#include "thirdparty/misc/polypartition.h"3637#ifdef DEBUG_ENABLED38Rect2 NavigationPolygon::_edit_get_rect() const {39RWLockRead read_lock(rwlock);40if (rect_cache_dirty) {41item_rect = Rect2();42bool first = true;4344for (int i = 0; i < outlines.size(); i++) {45const Vector<Vector2> &outline = outlines[i];46const int outline_size = outline.size();47if (outline_size < 3) {48continue;49}50const Vector2 *p = outline.ptr();51for (int j = 0; j < outline_size; j++) {52if (first) {53item_rect = Rect2(p[j], Vector2(0, 0));54first = false;55} else {56item_rect.expand_to(p[j]);57}58}59}6061rect_cache_dirty = false;62}63return item_rect;64}6566bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {67RWLockRead read_lock(rwlock);68for (int i = 0; i < outlines.size(); i++) {69const Vector<Vector2> &outline = outlines[i];70const int outline_size = outline.size();71if (outline_size < 3) {72continue;73}74if (Geometry2D::is_point_in_polygon(p_point, Variant(outline))) {75return true;76}77}78return false;79}80#endif // DEBUG_ENABLED8182void NavigationPolygon::set_vertices(const Vector<Vector2> &p_vertices) {83RWLockWrite write_lock(rwlock);84{85MutexLock lock(navigation_mesh_generation);86navigation_mesh.unref();87}88vertices = p_vertices;89rect_cache_dirty = true;90}9192Vector<Vector2> NavigationPolygon::get_vertices() const {93RWLockRead read_lock(rwlock);94return vertices;95}9697void NavigationPolygon::_set_polygons(const TypedArray<Vector<int32_t>> &p_array) {98RWLockWrite write_lock(rwlock);99{100MutexLock lock(navigation_mesh_generation);101navigation_mesh.unref();102}103polygons.resize(p_array.size());104for (int i = 0; i < p_array.size(); i++) {105polygons.write[i] = p_array[i];106}107}108109TypedArray<Vector<int32_t>> NavigationPolygon::_get_polygons() const {110RWLockRead read_lock(rwlock);111TypedArray<Vector<int32_t>> ret;112ret.resize(polygons.size());113for (int i = 0; i < ret.size(); i++) {114ret[i] = polygons[i];115}116117return ret;118}119120void NavigationPolygon::_set_outlines(const TypedArray<Vector<Vector2>> &p_array) {121RWLockWrite write_lock(rwlock);122outlines.resize(p_array.size());123for (int i = 0; i < p_array.size(); i++) {124outlines.write[i] = p_array[i];125}126rect_cache_dirty = true;127}128129TypedArray<Vector<Vector2>> NavigationPolygon::_get_outlines() const {130RWLockRead read_lock(rwlock);131TypedArray<Vector<Vector2>> ret;132ret.resize(outlines.size());133for (int i = 0; i < ret.size(); i++) {134ret[i] = outlines[i];135}136137return ret;138}139140void NavigationPolygon::add_polygon(const Vector<int> &p_polygon) {141RWLockWrite write_lock(rwlock);142polygons.push_back(p_polygon);143{144MutexLock lock(navigation_mesh_generation);145navigation_mesh.unref();146}147}148149void NavigationPolygon::add_outline_at_index(const Vector<Vector2> &p_outline, int p_index) {150RWLockWrite write_lock(rwlock);151outlines.insert(p_index, p_outline);152rect_cache_dirty = true;153}154155int NavigationPolygon::get_polygon_count() const {156RWLockRead read_lock(rwlock);157return polygons.size();158}159160Vector<int> NavigationPolygon::get_polygon(int p_idx) {161RWLockRead read_lock(rwlock);162ERR_FAIL_INDEX_V(p_idx, polygons.size(), Vector<int>());163return polygons[p_idx];164}165166void NavigationPolygon::clear_polygons() {167RWLockWrite write_lock(rwlock);168polygons.clear();169{170MutexLock lock(navigation_mesh_generation);171navigation_mesh.unref();172}173}174175void NavigationPolygon::clear() {176RWLockWrite write_lock(rwlock);177polygons.clear();178vertices.clear();179{180MutexLock lock(navigation_mesh_generation);181navigation_mesh.unref();182}183}184185void NavigationPolygon::set_data(const Vector<Vector2> &p_vertices, const Vector<Vector<int>> &p_polygons) {186RWLockWrite write_lock(rwlock);187vertices = p_vertices;188polygons = p_polygons;189{190MutexLock lock(navigation_mesh_generation);191navigation_mesh.unref();192}193}194195void NavigationPolygon::set_data(const Vector<Vector2> &p_vertices, const Vector<Vector<int>> &p_polygons, const Vector<Vector<Vector2>> &p_outlines) {196RWLockWrite write_lock(rwlock);197vertices = p_vertices;198polygons = p_polygons;199outlines = p_outlines;200rect_cache_dirty = true;201{202MutexLock lock(navigation_mesh_generation);203navigation_mesh.unref();204}205}206207void NavigationPolygon::get_data(Vector<Vector2> &r_vertices, Vector<Vector<int>> &r_polygons) {208RWLockRead read_lock(rwlock);209r_vertices = vertices;210r_polygons = polygons;211}212213void NavigationPolygon::get_data(Vector<Vector2> &r_vertices, Vector<Vector<int>> &r_polygons, Vector<Vector<Vector2>> &r_outlines) {214RWLockRead read_lock(rwlock);215r_vertices = vertices;216r_polygons = polygons;217r_outlines = outlines;218}219220Ref<NavigationMesh> NavigationPolygon::get_navigation_mesh() {221MutexLock lock(navigation_mesh_generation);222223if (navigation_mesh.is_null()) {224navigation_mesh.instantiate();225Vector<Vector3> verts;226Vector<Vector<int>> polys;227{228verts.resize(get_vertices().size());229Vector3 *w = verts.ptrw();230231const Vector2 *r = get_vertices().ptr();232233for (int i(0); i < get_vertices().size(); i++) {234w[i] = Vector3(r[i].x, 0.0, r[i].y);235}236}237238for (int i(0); i < get_polygon_count(); i++) {239polys.push_back(get_polygon(i));240}241242navigation_mesh->set_data(verts, polys);243navigation_mesh->set_cell_size(cell_size); // Needed to not fail the cell size check on the server244}245246return navigation_mesh;247}248249void NavigationPolygon::set_outlines(const Vector<Vector<Vector2>> &p_outlines) {250RWLockWrite write_lock(rwlock);251outlines = p_outlines;252rect_cache_dirty = true;253}254255Vector<Vector<Vector2>> NavigationPolygon::get_outlines() const {256RWLockRead read_lock(rwlock);257return outlines;258}259260void NavigationPolygon::set_polygons(const Vector<Vector<int>> &p_polygons) {261RWLockWrite write_lock(rwlock);262polygons = p_polygons;263{264MutexLock lock(navigation_mesh_generation);265navigation_mesh.unref();266}267}268269Vector<Vector<int>> NavigationPolygon::get_polygons() const {270RWLockRead read_lock(rwlock);271return polygons;272}273274void NavigationPolygon::add_outline(const Vector<Vector2> &p_outline) {275RWLockWrite write_lock(rwlock);276outlines.push_back(p_outline);277rect_cache_dirty = true;278}279280int NavigationPolygon::get_outline_count() const {281RWLockRead read_lock(rwlock);282return outlines.size();283}284285void NavigationPolygon::set_outline(int p_idx, const Vector<Vector2> &p_outline) {286RWLockWrite write_lock(rwlock);287ERR_FAIL_INDEX(p_idx, outlines.size());288outlines.write[p_idx] = p_outline;289rect_cache_dirty = true;290}291292void NavigationPolygon::remove_outline(int p_idx) {293RWLockWrite write_lock(rwlock);294ERR_FAIL_INDEX(p_idx, outlines.size());295outlines.remove_at(p_idx);296rect_cache_dirty = true;297}298299Vector<Vector2> NavigationPolygon::get_outline(int p_idx) const {300RWLockRead read_lock(rwlock);301ERR_FAIL_INDEX_V(p_idx, outlines.size(), Vector<Vector2>());302return outlines[p_idx];303}304305void NavigationPolygon::clear_outlines() {306RWLockWrite write_lock(rwlock);307outlines.clear();308rect_cache_dirty = true;309}310311#ifndef DISABLE_DEPRECATED312void NavigationPolygon::make_polygons_from_outlines() {313RWLockWrite write_lock(rwlock);314WARN_PRINT("Function make_polygons_from_outlines() is deprecated."315"\nUse NavigationServer2D.parse_source_geometry_data() and NavigationServer2D.bake_from_source_geometry_data() instead.");316317{318MutexLock lock(navigation_mesh_generation);319navigation_mesh.unref();320}321List<TPPLPoly> in_poly, out_poly;322323Vector2 outside_point(-1e10, -1e10);324325for (int i = 0; i < outlines.size(); i++) {326Vector<Vector2> ol = outlines[i];327int olsize = ol.size();328if (olsize < 3) {329continue;330}331const Vector2 *r = ol.ptr();332for (int j = 0; j < olsize; j++) {333outside_point = outside_point.max(r[j]);334}335}336337outside_point += Vector2(0.7239784, 0.819238); //avoid precision issues338339for (int i = 0; i < outlines.size(); i++) {340Vector<Vector2> ol = outlines[i];341int olsize = ol.size();342if (olsize < 3) {343continue;344}345const Vector2 *r = ol.ptr();346347int interscount = 0;348//test if this is an outer outline349for (int k = 0; k < outlines.size(); k++) {350if (i == k) {351continue; //no self intersect352}353354Vector<Vector2> ol2 = outlines[k];355int olsize2 = ol2.size();356if (olsize2 < 3) {357continue;358}359const Vector2 *r2 = ol2.ptr();360361for (int l = 0; l < olsize2; l++) {362if (Geometry2D::segment_intersects_segment(r[0], outside_point, r2[l], r2[(l + 1) % olsize2], nullptr)) {363interscount++;364}365}366}367368bool outer = (interscount % 2) == 0;369370TPPLPoly tp;371tp.Init(olsize);372for (int j = 0; j < olsize; j++) {373tp[j] = r[j];374}375376if (outer) {377tp.SetOrientation(TPPL_ORIENTATION_CCW);378} else {379tp.SetOrientation(TPPL_ORIENTATION_CW);380tp.SetHole(true);381}382383in_poly.push_back(tp);384}385386TPPLPartition tpart;387if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed!388ERR_PRINT("NavigationPolygon: Convex partition failed! Failed to convert outlines to a valid NavigationPolygon."389"\nNavigationPolygon outlines can not overlap vertices or edges inside same outline or with other outlines or have any intersections."390"\nAdd the outmost and largest outline first. To add holes inside this outline add the smaller outlines with same winding order.");391return;392}393394polygons.clear();395vertices.clear();396397HashMap<Vector2, int> points;398for (const TPPLPoly &tp : out_poly) {399Vector<int> p;400401for (int64_t i = 0; i < tp.GetNumPoints(); i++) {402HashMap<Vector2, int>::Iterator E = points.find(tp[i]);403if (!E) {404E = points.insert(tp[i], vertices.size());405vertices.push_back(tp[i]);406}407p.push_back(E->value);408}409410polygons.push_back(p);411}412413emit_changed();414}415#endif // DISABLE_DEPRECATED416417void NavigationPolygon::set_cell_size(real_t p_cell_size) {418cell_size = p_cell_size;419get_navigation_mesh()->set_cell_size(cell_size);420}421422real_t NavigationPolygon::get_cell_size() const {423return cell_size;424}425426void NavigationPolygon::set_border_size(real_t p_value) {427ERR_FAIL_COND(p_value < 0.0);428border_size = p_value;429}430431real_t NavigationPolygon::get_border_size() const {432return border_size;433}434435void NavigationPolygon::set_sample_partition_type(SamplePartitionType p_value) {436ERR_FAIL_INDEX(p_value, SAMPLE_PARTITION_MAX);437partition_type = p_value;438}439440NavigationPolygon::SamplePartitionType NavigationPolygon::get_sample_partition_type() const {441return partition_type;442}443444void NavigationPolygon::set_parsed_geometry_type(ParsedGeometryType p_geometry_type) {445ERR_FAIL_INDEX(p_geometry_type, PARSED_GEOMETRY_MAX);446parsed_geometry_type = p_geometry_type;447notify_property_list_changed();448}449450NavigationPolygon::ParsedGeometryType NavigationPolygon::get_parsed_geometry_type() const {451return parsed_geometry_type;452}453454void NavigationPolygon::set_parsed_collision_mask(uint32_t p_mask) {455parsed_collision_mask = p_mask;456}457458uint32_t NavigationPolygon::get_parsed_collision_mask() const {459return parsed_collision_mask;460}461462void NavigationPolygon::set_parsed_collision_mask_value(int p_layer_number, bool p_value) {463ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive.");464ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive.");465uint32_t mask = get_parsed_collision_mask();466if (p_value) {467mask |= 1 << (p_layer_number - 1);468} else {469mask &= ~(1 << (p_layer_number - 1));470}471set_parsed_collision_mask(mask);472}473474bool NavigationPolygon::get_parsed_collision_mask_value(int p_layer_number) const {475ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive.");476ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive.");477return get_parsed_collision_mask() & (1 << (p_layer_number - 1));478}479480void NavigationPolygon::set_source_geometry_mode(SourceGeometryMode p_geometry_mode) {481ERR_FAIL_INDEX(p_geometry_mode, SOURCE_GEOMETRY_MAX);482source_geometry_mode = p_geometry_mode;483notify_property_list_changed();484}485486NavigationPolygon::SourceGeometryMode NavigationPolygon::get_source_geometry_mode() const {487return source_geometry_mode;488}489490void NavigationPolygon::set_source_geometry_group_name(const StringName &p_group_name) {491source_geometry_group_name = p_group_name;492}493494StringName NavigationPolygon::get_source_geometry_group_name() const {495return source_geometry_group_name;496}497498void NavigationPolygon::set_agent_radius(real_t p_value) {499ERR_FAIL_COND(p_value < 0);500agent_radius = p_value;501}502503real_t NavigationPolygon::get_agent_radius() const {504return agent_radius;505}506507void NavigationPolygon::set_baking_rect(const Rect2 &p_rect) {508baking_rect = p_rect;509emit_changed();510}511512Rect2 NavigationPolygon::get_baking_rect() const {513return baking_rect;514}515516void NavigationPolygon::set_baking_rect_offset(const Vector2 &p_rect_offset) {517baking_rect_offset = p_rect_offset;518emit_changed();519}520521Vector2 NavigationPolygon::get_baking_rect_offset() const {522return baking_rect_offset;523}524525void NavigationPolygon::_bind_methods() {526ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationPolygon::set_vertices);527ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationPolygon::get_vertices);528529ClassDB::bind_method(D_METHOD("add_polygon", "polygon"), &NavigationPolygon::add_polygon);530ClassDB::bind_method(D_METHOD("get_polygon_count"), &NavigationPolygon::get_polygon_count);531ClassDB::bind_method(D_METHOD("get_polygon", "idx"), &NavigationPolygon::get_polygon);532ClassDB::bind_method(D_METHOD("clear_polygons"), &NavigationPolygon::clear_polygons);533ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationPolygon::get_navigation_mesh);534535ClassDB::bind_method(D_METHOD("add_outline", "outline"), &NavigationPolygon::add_outline);536ClassDB::bind_method(D_METHOD("add_outline_at_index", "outline", "index"), &NavigationPolygon::add_outline_at_index);537ClassDB::bind_method(D_METHOD("get_outline_count"), &NavigationPolygon::get_outline_count);538ClassDB::bind_method(D_METHOD("set_outline", "idx", "outline"), &NavigationPolygon::set_outline);539ClassDB::bind_method(D_METHOD("get_outline", "idx"), &NavigationPolygon::get_outline);540ClassDB::bind_method(D_METHOD("remove_outline", "idx"), &NavigationPolygon::remove_outline);541ClassDB::bind_method(D_METHOD("clear_outlines"), &NavigationPolygon::clear_outlines);542#ifndef DISABLE_DEPRECATED543ClassDB::bind_method(D_METHOD("make_polygons_from_outlines"), &NavigationPolygon::make_polygons_from_outlines);544#endif // DISABLE_DEPRECATED545546ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationPolygon::_set_polygons);547ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationPolygon::_get_polygons);548549ClassDB::bind_method(D_METHOD("_set_outlines", "outlines"), &NavigationPolygon::_set_outlines);550ClassDB::bind_method(D_METHOD("_get_outlines"), &NavigationPolygon::_get_outlines);551552ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &NavigationPolygon::set_cell_size);553ClassDB::bind_method(D_METHOD("get_cell_size"), &NavigationPolygon::get_cell_size);554555ClassDB::bind_method(D_METHOD("set_border_size", "border_size"), &NavigationPolygon::set_border_size);556ClassDB::bind_method(D_METHOD("get_border_size"), &NavigationPolygon::get_border_size);557558ClassDB::bind_method(D_METHOD("set_sample_partition_type", "sample_partition_type"), &NavigationPolygon::set_sample_partition_type);559ClassDB::bind_method(D_METHOD("get_sample_partition_type"), &NavigationPolygon::get_sample_partition_type);560561ClassDB::bind_method(D_METHOD("set_parsed_geometry_type", "geometry_type"), &NavigationPolygon::set_parsed_geometry_type);562ClassDB::bind_method(D_METHOD("get_parsed_geometry_type"), &NavigationPolygon::get_parsed_geometry_type);563564ClassDB::bind_method(D_METHOD("set_parsed_collision_mask", "mask"), &NavigationPolygon::set_parsed_collision_mask);565ClassDB::bind_method(D_METHOD("get_parsed_collision_mask"), &NavigationPolygon::get_parsed_collision_mask);566567ClassDB::bind_method(D_METHOD("set_parsed_collision_mask_value", "layer_number", "value"), &NavigationPolygon::set_parsed_collision_mask_value);568ClassDB::bind_method(D_METHOD("get_parsed_collision_mask_value", "layer_number"), &NavigationPolygon::get_parsed_collision_mask_value);569570ClassDB::bind_method(D_METHOD("set_source_geometry_mode", "geometry_mode"), &NavigationPolygon::set_source_geometry_mode);571ClassDB::bind_method(D_METHOD("get_source_geometry_mode"), &NavigationPolygon::get_source_geometry_mode);572573ClassDB::bind_method(D_METHOD("set_source_geometry_group_name", "group_name"), &NavigationPolygon::set_source_geometry_group_name);574ClassDB::bind_method(D_METHOD("get_source_geometry_group_name"), &NavigationPolygon::get_source_geometry_group_name);575576ClassDB::bind_method(D_METHOD("set_agent_radius", "agent_radius"), &NavigationPolygon::set_agent_radius);577ClassDB::bind_method(D_METHOD("get_agent_radius"), &NavigationPolygon::get_agent_radius);578579ClassDB::bind_method(D_METHOD("set_baking_rect", "rect"), &NavigationPolygon::set_baking_rect);580ClassDB::bind_method(D_METHOD("get_baking_rect"), &NavigationPolygon::get_baking_rect);581ClassDB::bind_method(D_METHOD("set_baking_rect_offset", "rect_offset"), &NavigationPolygon::set_baking_rect_offset);582ClassDB::bind_method(D_METHOD("get_baking_rect_offset"), &NavigationPolygon::get_baking_rect_offset);583584ClassDB::bind_method(D_METHOD("clear"), &NavigationPolygon::clear);585586ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");587ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons");588ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines");589590ADD_GROUP("Sampling", "sample_");591ADD_PROPERTY(PropertyInfo(Variant::INT, "sample_partition_type", PROPERTY_HINT_ENUM, "Convex Partition,Triangulate"), "set_sample_partition_type", "get_sample_partition_type");592ADD_GROUP("Geometry", "");593ADD_PROPERTY(PropertyInfo(Variant::INT, "parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Meshes and Static Colliders"), "set_parsed_geometry_type", "get_parsed_geometry_type");594ADD_PROPERTY(PropertyInfo(Variant::INT, "parsed_collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_parsed_collision_mask", "get_parsed_collision_mask");595ADD_PROPERTY_DEFAULT("parsed_collision_mask", 0xFFFFFFFF);596ADD_PROPERTY(PropertyInfo(Variant::INT, "source_geometry_mode", PROPERTY_HINT_ENUM, "Root Node Children,Group With Children,Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode");597ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_geometry_group_name"), "set_source_geometry_group_name", "get_source_geometry_group_name");598ADD_PROPERTY_DEFAULT("source_geometry_group_name", StringName("navigation_polygon_source_geometry_group"));599ADD_GROUP("Cells", "");600ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "1.0,50.0,1.0,or_greater,suffix:px"), "set_cell_size", "get_cell_size");601ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "border_size", PROPERTY_HINT_RANGE, "0.0,500.0,1.0,or_greater,suffix:px"), "set_border_size", "get_border_size");602ADD_GROUP("Agents", "agent_");603ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_radius", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater,suffix:px"), "set_agent_radius", "get_agent_radius");604ADD_GROUP("Filters", "");605ADD_PROPERTY(PropertyInfo(Variant::RECT2, "baking_rect"), "set_baking_rect", "get_baking_rect");606ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "baking_rect_offset"), "set_baking_rect_offset", "get_baking_rect_offset");607608BIND_ENUM_CONSTANT(SAMPLE_PARTITION_CONVEX_PARTITION);609BIND_ENUM_CONSTANT(SAMPLE_PARTITION_TRIANGULATE);610BIND_ENUM_CONSTANT(SAMPLE_PARTITION_MAX);611612BIND_ENUM_CONSTANT(PARSED_GEOMETRY_MESH_INSTANCES);613BIND_ENUM_CONSTANT(PARSED_GEOMETRY_STATIC_COLLIDERS);614BIND_ENUM_CONSTANT(PARSED_GEOMETRY_BOTH);615BIND_ENUM_CONSTANT(PARSED_GEOMETRY_MAX);616617BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_ROOT_NODE_CHILDREN);618BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN);619BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_GROUPS_EXPLICIT);620BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_MAX);621}622623void NavigationPolygon::_validate_property(PropertyInfo &p_property) const {624if (p_property.name == "parsed_collision_mask") {625if (parsed_geometry_type == PARSED_GEOMETRY_MESH_INSTANCES) {626p_property.usage = PROPERTY_USAGE_NONE;627return;628}629}630631if (p_property.name == "parsed_source_group_name") {632if (source_geometry_mode == SOURCE_GEOMETRY_ROOT_NODE_CHILDREN) {633p_property.usage = PROPERTY_USAGE_NONE;634return;635}636}637}638639640