Path: blob/master/scene/resources/2d/navigation_mesh_source_geometry_data_2d.cpp
9903 views
/**************************************************************************/1/* navigation_mesh_source_geometry_data_2d.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_mesh_source_geometry_data_2d.h"3132#include "core/variant/typed_array.h"3334void NavigationMeshSourceGeometryData2D::clear() {35RWLockWrite write_lock(geometry_rwlock);36traversable_outlines.clear();37obstruction_outlines.clear();38_projected_obstructions.clear();39bounds_dirty = true;40}4142bool NavigationMeshSourceGeometryData2D::has_data() {43RWLockRead read_lock(geometry_rwlock);44return traversable_outlines.size();45}4647void NavigationMeshSourceGeometryData2D::clear_projected_obstructions() {48RWLockWrite write_lock(geometry_rwlock);49_projected_obstructions.clear();50bounds_dirty = true;51}5253void NavigationMeshSourceGeometryData2D::_set_traversable_outlines(const Vector<Vector<Vector2>> &p_traversable_outlines) {54RWLockWrite write_lock(geometry_rwlock);55traversable_outlines = p_traversable_outlines;56bounds_dirty = true;57}5859void NavigationMeshSourceGeometryData2D::_set_obstruction_outlines(const Vector<Vector<Vector2>> &p_obstruction_outlines) {60RWLockWrite write_lock(geometry_rwlock);61obstruction_outlines = p_obstruction_outlines;62bounds_dirty = true;63}6465const Vector<Vector<Vector2>> &NavigationMeshSourceGeometryData2D::_get_traversable_outlines() const {66RWLockRead read_lock(geometry_rwlock);67return traversable_outlines;68}6970const Vector<Vector<Vector2>> &NavigationMeshSourceGeometryData2D::_get_obstruction_outlines() const {71RWLockRead read_lock(geometry_rwlock);72return obstruction_outlines;73}7475void NavigationMeshSourceGeometryData2D::_add_traversable_outline(const Vector<Vector2> &p_shape_outline) {76if (p_shape_outline.size() > 1) {77RWLockWrite write_lock(geometry_rwlock);78traversable_outlines.push_back(p_shape_outline);79bounds_dirty = true;80}81}8283void NavigationMeshSourceGeometryData2D::_add_obstruction_outline(const Vector<Vector2> &p_shape_outline) {84if (p_shape_outline.size() > 1) {85RWLockWrite write_lock(geometry_rwlock);86obstruction_outlines.push_back(p_shape_outline);87bounds_dirty = true;88}89}9091void NavigationMeshSourceGeometryData2D::set_traversable_outlines(const TypedArray<Vector<Vector2>> &p_traversable_outlines) {92RWLockWrite write_lock(geometry_rwlock);93traversable_outlines.resize(p_traversable_outlines.size());94for (int i = 0; i < p_traversable_outlines.size(); i++) {95traversable_outlines.write[i] = p_traversable_outlines[i];96}97bounds_dirty = true;98}99100TypedArray<Vector<Vector2>> NavigationMeshSourceGeometryData2D::get_traversable_outlines() const {101RWLockRead read_lock(geometry_rwlock);102TypedArray<Vector<Vector2>> typed_array_traversable_outlines;103typed_array_traversable_outlines.resize(traversable_outlines.size());104for (int i = 0; i < typed_array_traversable_outlines.size(); i++) {105typed_array_traversable_outlines[i] = traversable_outlines[i];106}107108return typed_array_traversable_outlines;109}110111void NavigationMeshSourceGeometryData2D::set_obstruction_outlines(const TypedArray<Vector<Vector2>> &p_obstruction_outlines) {112RWLockWrite write_lock(geometry_rwlock);113obstruction_outlines.resize(p_obstruction_outlines.size());114for (int i = 0; i < p_obstruction_outlines.size(); i++) {115obstruction_outlines.write[i] = p_obstruction_outlines[i];116}117bounds_dirty = true;118}119120TypedArray<Vector<Vector2>> NavigationMeshSourceGeometryData2D::get_obstruction_outlines() const {121RWLockRead read_lock(geometry_rwlock);122TypedArray<Vector<Vector2>> typed_array_obstruction_outlines;123typed_array_obstruction_outlines.resize(obstruction_outlines.size());124for (int i = 0; i < typed_array_obstruction_outlines.size(); i++) {125typed_array_obstruction_outlines[i] = obstruction_outlines[i];126}127128return typed_array_obstruction_outlines;129}130131void NavigationMeshSourceGeometryData2D::append_traversable_outlines(const TypedArray<Vector<Vector2>> &p_traversable_outlines) {132RWLockWrite write_lock(geometry_rwlock);133int traversable_outlines_size = traversable_outlines.size();134traversable_outlines.resize(traversable_outlines_size + p_traversable_outlines.size());135for (int i = traversable_outlines_size; i < p_traversable_outlines.size(); i++) {136traversable_outlines.write[i] = p_traversable_outlines[i];137}138bounds_dirty = true;139}140141void NavigationMeshSourceGeometryData2D::append_obstruction_outlines(const TypedArray<Vector<Vector2>> &p_obstruction_outlines) {142RWLockWrite write_lock(geometry_rwlock);143int obstruction_outlines_size = obstruction_outlines.size();144obstruction_outlines.resize(obstruction_outlines_size + p_obstruction_outlines.size());145for (int i = obstruction_outlines_size; i < p_obstruction_outlines.size(); i++) {146obstruction_outlines.write[i] = p_obstruction_outlines[i];147}148bounds_dirty = true;149}150151void NavigationMeshSourceGeometryData2D::add_traversable_outline(const PackedVector2Array &p_shape_outline) {152if (p_shape_outline.size() > 1) {153RWLockWrite write_lock(geometry_rwlock);154Vector<Vector2> traversable_outline;155traversable_outline.resize(p_shape_outline.size());156for (int i = 0; i < p_shape_outline.size(); i++) {157traversable_outline.write[i] = p_shape_outline[i];158}159traversable_outlines.push_back(traversable_outline);160bounds_dirty = true;161}162}163164void NavigationMeshSourceGeometryData2D::add_obstruction_outline(const PackedVector2Array &p_shape_outline) {165if (p_shape_outline.size() > 1) {166RWLockWrite write_lock(geometry_rwlock);167Vector<Vector2> obstruction_outline;168obstruction_outline.resize(p_shape_outline.size());169for (int i = 0; i < p_shape_outline.size(); i++) {170obstruction_outline.write[i] = p_shape_outline[i];171}172obstruction_outlines.push_back(obstruction_outline);173bounds_dirty = true;174}175}176177void NavigationMeshSourceGeometryData2D::merge(const Ref<NavigationMeshSourceGeometryData2D> &p_other_geometry) {178ERR_FAIL_COND(p_other_geometry.is_null());179180Vector<Vector<Vector2>> other_traversable_outlines;181Vector<Vector<Vector2>> other_obstruction_outlines;182Vector<ProjectedObstruction> other_projected_obstructions;183184p_other_geometry->get_data(other_traversable_outlines, other_obstruction_outlines, other_projected_obstructions);185186RWLockWrite write_lock(geometry_rwlock);187traversable_outlines.append_array(other_traversable_outlines);188obstruction_outlines.append_array(other_obstruction_outlines);189_projected_obstructions.append_array(other_projected_obstructions);190bounds_dirty = true;191}192193void NavigationMeshSourceGeometryData2D::add_projected_obstruction(const Vector<Vector2> &p_vertices, bool p_carve) {194ERR_FAIL_COND(p_vertices.size() < 2);195196ProjectedObstruction projected_obstruction;197projected_obstruction.vertices.resize(p_vertices.size() * 2);198projected_obstruction.carve = p_carve;199200float *obstruction_vertices_ptrw = projected_obstruction.vertices.ptrw();201202int vertex_index = 0;203for (const Vector2 &vertex : p_vertices) {204obstruction_vertices_ptrw[vertex_index++] = vertex.x;205obstruction_vertices_ptrw[vertex_index++] = vertex.y;206}207208RWLockWrite write_lock(geometry_rwlock);209_projected_obstructions.push_back(projected_obstruction);210bounds_dirty = true;211}212213void NavigationMeshSourceGeometryData2D::set_projected_obstructions(const Array &p_array) {214clear_projected_obstructions();215216for (int i = 0; i < p_array.size(); i++) {217Dictionary data = p_array[i];218ERR_FAIL_COND(!data.has("version"));219220uint32_t po_version = data["version"];221222if (po_version == 1) {223ERR_FAIL_COND(!data.has("vertices"));224ERR_FAIL_COND(!data.has("carve"));225}226227ProjectedObstruction projected_obstruction;228projected_obstruction.vertices = Vector<float>(data["vertices"]);229projected_obstruction.carve = data["carve"];230231RWLockWrite write_lock(geometry_rwlock);232_projected_obstructions.push_back(projected_obstruction);233bounds_dirty = true;234}235}236237Vector<NavigationMeshSourceGeometryData2D::ProjectedObstruction> NavigationMeshSourceGeometryData2D::_get_projected_obstructions() const {238RWLockRead read_lock(geometry_rwlock);239return _projected_obstructions;240}241242Array NavigationMeshSourceGeometryData2D::get_projected_obstructions() const {243RWLockRead read_lock(geometry_rwlock);244245Array ret;246ret.resize(_projected_obstructions.size());247248for (int i = 0; i < _projected_obstructions.size(); i++) {249const ProjectedObstruction &projected_obstruction = _projected_obstructions[i];250251Dictionary data;252data["version"] = (int)ProjectedObstruction::VERSION;253data["vertices"] = projected_obstruction.vertices;254data["carve"] = projected_obstruction.carve;255256ret[i] = data;257}258259return ret;260}261262bool NavigationMeshSourceGeometryData2D::_set(const StringName &p_name, const Variant &p_value) {263if (p_name == "projected_obstructions") {264set_projected_obstructions(p_value);265return true;266}267return false;268}269270bool NavigationMeshSourceGeometryData2D::_get(const StringName &p_name, Variant &r_ret) const {271if (p_name == "projected_obstructions") {272r_ret = get_projected_obstructions();273return true;274}275return false;276}277278void NavigationMeshSourceGeometryData2D::set_data(const Vector<Vector<Vector2>> &p_traversable_outlines, const Vector<Vector<Vector2>> &p_obstruction_outlines, Vector<ProjectedObstruction> &p_projected_obstructions) {279RWLockWrite write_lock(geometry_rwlock);280traversable_outlines = p_traversable_outlines;281obstruction_outlines = p_obstruction_outlines;282_projected_obstructions = p_projected_obstructions;283bounds_dirty = true;284}285286void NavigationMeshSourceGeometryData2D::get_data(Vector<Vector<Vector2>> &r_traversable_outlines, Vector<Vector<Vector2>> &r_obstruction_outlines, Vector<ProjectedObstruction> &r_projected_obstructions) {287RWLockRead read_lock(geometry_rwlock);288r_traversable_outlines = traversable_outlines;289r_obstruction_outlines = obstruction_outlines;290r_projected_obstructions = _projected_obstructions;291}292293Rect2 NavigationMeshSourceGeometryData2D::get_bounds() {294geometry_rwlock.read_lock();295296if (bounds_dirty) {297geometry_rwlock.read_unlock();298RWLockWrite write_lock(geometry_rwlock);299300bounds_dirty = false;301bounds = Rect2();302bool first_vertex = true;303304for (const Vector<Vector2> &traversable_outline : traversable_outlines) {305for (const Vector2 &traversable_point : traversable_outline) {306if (first_vertex) {307first_vertex = false;308bounds.position = traversable_point;309} else {310bounds.expand_to(traversable_point);311}312}313}314315for (const Vector<Vector2> &obstruction_outline : obstruction_outlines) {316for (const Vector2 &obstruction_point : obstruction_outline) {317if (first_vertex) {318first_vertex = false;319bounds.position = obstruction_point;320} else {321bounds.expand_to(obstruction_point);322}323}324}325326for (const ProjectedObstruction &projected_obstruction : _projected_obstructions) {327for (int i = 0; i < projected_obstruction.vertices.size() / 2; i++) {328const Vector2 vertex = Vector2(projected_obstruction.vertices[i * 2], projected_obstruction.vertices[i * 2 + 1]);329if (first_vertex) {330first_vertex = false;331bounds.position = vertex;332} else {333bounds.expand_to(vertex);334}335}336}337} else {338geometry_rwlock.read_unlock();339}340341RWLockRead read_lock(geometry_rwlock);342return bounds;343}344345void NavigationMeshSourceGeometryData2D::_bind_methods() {346ClassDB::bind_method(D_METHOD("clear"), &NavigationMeshSourceGeometryData2D::clear);347ClassDB::bind_method(D_METHOD("has_data"), &NavigationMeshSourceGeometryData2D::has_data);348349ClassDB::bind_method(D_METHOD("set_traversable_outlines", "traversable_outlines"), &NavigationMeshSourceGeometryData2D::set_traversable_outlines);350ClassDB::bind_method(D_METHOD("get_traversable_outlines"), &NavigationMeshSourceGeometryData2D::get_traversable_outlines);351352ClassDB::bind_method(D_METHOD("set_obstruction_outlines", "obstruction_outlines"), &NavigationMeshSourceGeometryData2D::set_obstruction_outlines);353ClassDB::bind_method(D_METHOD("get_obstruction_outlines"), &NavigationMeshSourceGeometryData2D::get_obstruction_outlines);354355ClassDB::bind_method(D_METHOD("append_traversable_outlines", "traversable_outlines"), &NavigationMeshSourceGeometryData2D::append_traversable_outlines);356ClassDB::bind_method(D_METHOD("append_obstruction_outlines", "obstruction_outlines"), &NavigationMeshSourceGeometryData2D::append_obstruction_outlines);357358ClassDB::bind_method(D_METHOD("add_traversable_outline", "shape_outline"), &NavigationMeshSourceGeometryData2D::add_traversable_outline);359ClassDB::bind_method(D_METHOD("add_obstruction_outline", "shape_outline"), &NavigationMeshSourceGeometryData2D::add_obstruction_outline);360361ClassDB::bind_method(D_METHOD("merge", "other_geometry"), &NavigationMeshSourceGeometryData2D::merge);362363ClassDB::bind_method(D_METHOD("add_projected_obstruction", "vertices", "carve"), &NavigationMeshSourceGeometryData2D::add_projected_obstruction);364ClassDB::bind_method(D_METHOD("clear_projected_obstructions"), &NavigationMeshSourceGeometryData2D::clear_projected_obstructions);365ClassDB::bind_method(D_METHOD("set_projected_obstructions", "projected_obstructions"), &NavigationMeshSourceGeometryData2D::set_projected_obstructions);366ClassDB::bind_method(D_METHOD("get_projected_obstructions"), &NavigationMeshSourceGeometryData2D::get_projected_obstructions);367368ClassDB::bind_method(D_METHOD("get_bounds"), &NavigationMeshSourceGeometryData2D::get_bounds);369370ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "traversable_outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_traversable_outlines", "get_traversable_outlines");371ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "obstruction_outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_obstruction_outlines", "get_obstruction_outlines");372ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "projected_obstructions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_projected_obstructions", "get_projected_obstructions");373}374375376