feat: updated engine version to 4.4-rc1
This commit is contained in:
parent
ee00efde1f
commit
21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ void CapsuleShape2D::_update_shape() {
|
|||
|
||||
void CapsuleShape2D::set_radius(real_t p_radius) {
|
||||
ERR_FAIL_COND_MSG(p_radius < 0, "CapsuleShape2D radius cannot be negative.");
|
||||
if (radius == p_radius) {
|
||||
return;
|
||||
}
|
||||
radius = p_radius;
|
||||
if (radius > height * 0.5) {
|
||||
height = radius * 2.0;
|
||||
|
|
@ -73,6 +76,9 @@ real_t CapsuleShape2D::get_radius() const {
|
|||
|
||||
void CapsuleShape2D::set_height(real_t p_height) {
|
||||
ERR_FAIL_COND_MSG(p_height < 0, "CapsuleShape2D height cannot be negative.");
|
||||
if (height == p_height) {
|
||||
return;
|
||||
}
|
||||
height = p_height;
|
||||
if (radius > height * 0.5) {
|
||||
radius = height * 0.5;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@ void CircleShape2D::_update_shape() {
|
|||
|
||||
void CircleShape2D::set_radius(real_t p_radius) {
|
||||
ERR_FAIL_COND_MSG(p_radius < 0, "CircleShape2D radius cannot be negative.");
|
||||
if (radius == p_radius) {
|
||||
return;
|
||||
}
|
||||
radius = p_radius;
|
||||
_update_shape();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,33 +30,37 @@
|
|||
|
||||
#include "navigation_mesh_source_geometry_data_2d.h"
|
||||
|
||||
#include "scene/resources/mesh.h"
|
||||
#include "core/variant/typed_array.h"
|
||||
|
||||
void NavigationMeshSourceGeometryData2D::clear() {
|
||||
RWLockWrite write_lock(geometry_rwlock);
|
||||
traversable_outlines.clear();
|
||||
obstruction_outlines.clear();
|
||||
_projected_obstructions.clear();
|
||||
bounds_dirty = true;
|
||||
}
|
||||
|
||||
bool NavigationMeshSourceGeometryData2D::has_data() {
|
||||
RWLockRead read_lock(geometry_rwlock);
|
||||
return traversable_outlines.size();
|
||||
};
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData2D::clear_projected_obstructions() {
|
||||
RWLockWrite write_lock(geometry_rwlock);
|
||||
_projected_obstructions.clear();
|
||||
bounds_dirty = true;
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData2D::_set_traversable_outlines(const Vector<Vector<Vector2>> &p_traversable_outlines) {
|
||||
RWLockWrite write_lock(geometry_rwlock);
|
||||
traversable_outlines = p_traversable_outlines;
|
||||
bounds_dirty = true;
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData2D::_set_obstruction_outlines(const Vector<Vector<Vector2>> &p_obstruction_outlines) {
|
||||
RWLockWrite write_lock(geometry_rwlock);
|
||||
obstruction_outlines = p_obstruction_outlines;
|
||||
bounds_dirty = true;
|
||||
}
|
||||
|
||||
const Vector<Vector<Vector2>> &NavigationMeshSourceGeometryData2D::_get_traversable_outlines() const {
|
||||
|
|
@ -73,6 +77,7 @@ void NavigationMeshSourceGeometryData2D::_add_traversable_outline(const Vector<V
|
|||
if (p_shape_outline.size() > 1) {
|
||||
RWLockWrite write_lock(geometry_rwlock);
|
||||
traversable_outlines.push_back(p_shape_outline);
|
||||
bounds_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,6 +85,7 @@ void NavigationMeshSourceGeometryData2D::_add_obstruction_outline(const Vector<V
|
|||
if (p_shape_outline.size() > 1) {
|
||||
RWLockWrite write_lock(geometry_rwlock);
|
||||
obstruction_outlines.push_back(p_shape_outline);
|
||||
bounds_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -89,6 +95,7 @@ void NavigationMeshSourceGeometryData2D::set_traversable_outlines(const TypedArr
|
|||
for (int i = 0; i < p_traversable_outlines.size(); i++) {
|
||||
traversable_outlines.write[i] = p_traversable_outlines[i];
|
||||
}
|
||||
bounds_dirty = true;
|
||||
}
|
||||
|
||||
TypedArray<Vector<Vector2>> NavigationMeshSourceGeometryData2D::get_traversable_outlines() const {
|
||||
|
|
@ -108,6 +115,7 @@ void NavigationMeshSourceGeometryData2D::set_obstruction_outlines(const TypedArr
|
|||
for (int i = 0; i < p_obstruction_outlines.size(); i++) {
|
||||
obstruction_outlines.write[i] = p_obstruction_outlines[i];
|
||||
}
|
||||
bounds_dirty = true;
|
||||
}
|
||||
|
||||
TypedArray<Vector<Vector2>> NavigationMeshSourceGeometryData2D::get_obstruction_outlines() const {
|
||||
|
|
@ -128,6 +136,7 @@ void NavigationMeshSourceGeometryData2D::append_traversable_outlines(const Typed
|
|||
for (int i = traversable_outlines_size; i < p_traversable_outlines.size(); i++) {
|
||||
traversable_outlines.write[i] = p_traversable_outlines[i];
|
||||
}
|
||||
bounds_dirty = true;
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData2D::append_obstruction_outlines(const TypedArray<Vector<Vector2>> &p_obstruction_outlines) {
|
||||
|
|
@ -137,6 +146,7 @@ void NavigationMeshSourceGeometryData2D::append_obstruction_outlines(const Typed
|
|||
for (int i = obstruction_outlines_size; i < p_obstruction_outlines.size(); i++) {
|
||||
obstruction_outlines.write[i] = p_obstruction_outlines[i];
|
||||
}
|
||||
bounds_dirty = true;
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData2D::add_traversable_outline(const PackedVector2Array &p_shape_outline) {
|
||||
|
|
@ -148,6 +158,7 @@ void NavigationMeshSourceGeometryData2D::add_traversable_outline(const PackedVec
|
|||
traversable_outline.write[i] = p_shape_outline[i];
|
||||
}
|
||||
traversable_outlines.push_back(traversable_outline);
|
||||
bounds_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,11 +171,12 @@ void NavigationMeshSourceGeometryData2D::add_obstruction_outline(const PackedVec
|
|||
obstruction_outline.write[i] = p_shape_outline[i];
|
||||
}
|
||||
obstruction_outlines.push_back(obstruction_outline);
|
||||
bounds_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData2D::merge(const Ref<NavigationMeshSourceGeometryData2D> &p_other_geometry) {
|
||||
ERR_FAIL_NULL(p_other_geometry);
|
||||
ERR_FAIL_COND(p_other_geometry.is_null());
|
||||
|
||||
Vector<Vector<Vector2>> other_traversable_outlines;
|
||||
Vector<Vector<Vector2>> other_obstruction_outlines;
|
||||
|
|
@ -176,6 +188,7 @@ void NavigationMeshSourceGeometryData2D::merge(const Ref<NavigationMeshSourceGeo
|
|||
traversable_outlines.append_array(other_traversable_outlines);
|
||||
obstruction_outlines.append_array(other_obstruction_outlines);
|
||||
_projected_obstructions.append_array(other_projected_obstructions);
|
||||
bounds_dirty = true;
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData2D::add_projected_obstruction(const Vector<Vector2> &p_vertices, bool p_carve) {
|
||||
|
|
@ -195,6 +208,7 @@ void NavigationMeshSourceGeometryData2D::add_projected_obstruction(const Vector<
|
|||
|
||||
RWLockWrite write_lock(geometry_rwlock);
|
||||
_projected_obstructions.push_back(projected_obstruction);
|
||||
bounds_dirty = true;
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData2D::set_projected_obstructions(const Array &p_array) {
|
||||
|
|
@ -217,6 +231,7 @@ void NavigationMeshSourceGeometryData2D::set_projected_obstructions(const Array
|
|||
|
||||
RWLockWrite write_lock(geometry_rwlock);
|
||||
_projected_obstructions.push_back(projected_obstruction);
|
||||
bounds_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -266,6 +281,7 @@ void NavigationMeshSourceGeometryData2D::set_data(const Vector<Vector<Vector2>>
|
|||
traversable_outlines = p_traversable_outlines;
|
||||
obstruction_outlines = p_obstruction_outlines;
|
||||
_projected_obstructions = p_projected_obstructions;
|
||||
bounds_dirty = true;
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData2D::get_data(Vector<Vector<Vector2>> &r_traversable_outlines, Vector<Vector<Vector2>> &r_obstruction_outlines, Vector<ProjectedObstruction> &r_projected_obstructions) {
|
||||
|
|
@ -275,6 +291,58 @@ void NavigationMeshSourceGeometryData2D::get_data(Vector<Vector<Vector2>> &r_tra
|
|||
r_projected_obstructions = _projected_obstructions;
|
||||
}
|
||||
|
||||
Rect2 NavigationMeshSourceGeometryData2D::get_bounds() {
|
||||
geometry_rwlock.read_lock();
|
||||
|
||||
if (bounds_dirty) {
|
||||
geometry_rwlock.read_unlock();
|
||||
RWLockWrite write_lock(geometry_rwlock);
|
||||
|
||||
bounds_dirty = false;
|
||||
bounds = Rect2();
|
||||
bool first_vertex = true;
|
||||
|
||||
for (const Vector<Vector2> &traversable_outline : traversable_outlines) {
|
||||
for (const Vector2 &traversable_point : traversable_outline) {
|
||||
if (first_vertex) {
|
||||
first_vertex = false;
|
||||
bounds.position = traversable_point;
|
||||
} else {
|
||||
bounds.expand_to(traversable_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const Vector<Vector2> &obstruction_outline : obstruction_outlines) {
|
||||
for (const Vector2 &obstruction_point : obstruction_outline) {
|
||||
if (first_vertex) {
|
||||
first_vertex = false;
|
||||
bounds.position = obstruction_point;
|
||||
} else {
|
||||
bounds.expand_to(obstruction_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const ProjectedObstruction &projected_obstruction : _projected_obstructions) {
|
||||
for (int i = 0; i < projected_obstruction.vertices.size() / 2; i++) {
|
||||
const Vector2 vertex = Vector2(projected_obstruction.vertices[i * 2], projected_obstruction.vertices[i * 2 + 1]);
|
||||
if (first_vertex) {
|
||||
first_vertex = false;
|
||||
bounds.position = vertex;
|
||||
} else {
|
||||
bounds.expand_to(vertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
geometry_rwlock.read_unlock();
|
||||
}
|
||||
|
||||
RWLockRead read_lock(geometry_rwlock);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
void NavigationMeshSourceGeometryData2D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("clear"), &NavigationMeshSourceGeometryData2D::clear);
|
||||
ClassDB::bind_method(D_METHOD("has_data"), &NavigationMeshSourceGeometryData2D::has_data);
|
||||
|
|
@ -298,6 +366,8 @@ void NavigationMeshSourceGeometryData2D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_projected_obstructions", "projected_obstructions"), &NavigationMeshSourceGeometryData2D::set_projected_obstructions);
|
||||
ClassDB::bind_method(D_METHOD("get_projected_obstructions"), &NavigationMeshSourceGeometryData2D::get_projected_obstructions);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_bounds"), &NavigationMeshSourceGeometryData2D::get_bounds);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "traversable_outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_traversable_outlines", "get_traversable_outlines");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "obstruction_outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_obstruction_outlines", "get_obstruction_outlines");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "projected_obstructions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_projected_obstructions", "get_projected_obstructions");
|
||||
|
|
|
|||
|
|
@ -31,17 +31,21 @@
|
|||
#ifndef NAVIGATION_MESH_SOURCE_GEOMETRY_DATA_2D_H
|
||||
#define NAVIGATION_MESH_SOURCE_GEOMETRY_DATA_2D_H
|
||||
|
||||
#include "core/io/resource.h"
|
||||
#include "core/os/rw_lock.h"
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/2d/navigation_polygon.h"
|
||||
|
||||
class NavigationMeshSourceGeometryData2D : public Resource {
|
||||
friend class NavMeshGenerator2D;
|
||||
|
||||
GDCLASS(NavigationMeshSourceGeometryData2D, Resource);
|
||||
RWLock geometry_rwlock;
|
||||
|
||||
Vector<Vector<Vector2>> traversable_outlines;
|
||||
Vector<Vector<Vector2>> obstruction_outlines;
|
||||
|
||||
Rect2 bounds;
|
||||
bool bounds_dirty = true;
|
||||
|
||||
public:
|
||||
struct ProjectedObstruction;
|
||||
|
||||
|
|
@ -103,6 +107,8 @@ public:
|
|||
void set_data(const Vector<Vector<Vector2>> &p_traversable_outlines, const Vector<Vector<Vector2>> &p_obstruction_outlines, Vector<ProjectedObstruction> &p_projected_obstructions);
|
||||
void get_data(Vector<Vector<Vector2>> &r_traversable_outlines, Vector<Vector<Vector2>> &r_obstruction_outlines, Vector<ProjectedObstruction> &r_projected_obstructions);
|
||||
|
||||
Rect2 get_bounds();
|
||||
|
||||
NavigationMeshSourceGeometryData2D() {}
|
||||
~NavigationMeshSourceGeometryData2D() { clear(); }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -32,11 +32,10 @@
|
|||
|
||||
#include "core/math/geometry_2d.h"
|
||||
#include "core/os/mutex.h"
|
||||
#include "servers/navigation_server_2d.h"
|
||||
|
||||
#include "thirdparty/misc/polypartition.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#ifdef DEBUG_ENABLED
|
||||
Rect2 NavigationPolygon::_edit_get_rect() const {
|
||||
RWLockRead read_lock(rwlock);
|
||||
if (rect_cache_dirty) {
|
||||
|
|
@ -79,7 +78,7 @@ bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double
|
|||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
void NavigationPolygon::set_vertices(const Vector<Vector2> &p_vertices) {
|
||||
RWLockWrite write_lock(rwlock);
|
||||
|
|
@ -104,7 +103,7 @@ void NavigationPolygon::_set_polygons(const TypedArray<Vector<int32_t>> &p_array
|
|||
}
|
||||
polygons.resize(p_array.size());
|
||||
for (int i = 0; i < p_array.size(); i++) {
|
||||
polygons.write[i].indices = p_array[i];
|
||||
polygons.write[i] = p_array[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +112,7 @@ TypedArray<Vector<int32_t>> NavigationPolygon::_get_polygons() const {
|
|||
TypedArray<Vector<int32_t>> ret;
|
||||
ret.resize(polygons.size());
|
||||
for (int i = 0; i < ret.size(); i++) {
|
||||
ret[i] = polygons[i].indices;
|
||||
ret[i] = polygons[i];
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -141,9 +140,7 @@ TypedArray<Vector<Vector2>> NavigationPolygon::_get_outlines() const {
|
|||
|
||||
void NavigationPolygon::add_polygon(const Vector<int> &p_polygon) {
|
||||
RWLockWrite write_lock(rwlock);
|
||||
Polygon polygon;
|
||||
polygon.indices = p_polygon;
|
||||
polygons.push_back(polygon);
|
||||
polygons.push_back(p_polygon);
|
||||
{
|
||||
MutexLock lock(navigation_mesh_generation);
|
||||
navigation_mesh.unref();
|
||||
|
|
@ -164,7 +161,7 @@ int NavigationPolygon::get_polygon_count() const {
|
|||
Vector<int> NavigationPolygon::get_polygon(int p_idx) {
|
||||
RWLockRead read_lock(rwlock);
|
||||
ERR_FAIL_INDEX_V(p_idx, polygons.size(), Vector<int>());
|
||||
return polygons[p_idx].indices;
|
||||
return polygons[p_idx];
|
||||
}
|
||||
|
||||
void NavigationPolygon::clear_polygons() {
|
||||
|
|
@ -189,10 +186,19 @@ void NavigationPolygon::clear() {
|
|||
void NavigationPolygon::set_data(const Vector<Vector2> &p_vertices, const Vector<Vector<int>> &p_polygons) {
|
||||
RWLockWrite write_lock(rwlock);
|
||||
vertices = p_vertices;
|
||||
polygons.resize(p_polygons.size());
|
||||
for (int i = 0; i < p_polygons.size(); i++) {
|
||||
polygons.write[i].indices = p_polygons[i];
|
||||
polygons = p_polygons;
|
||||
{
|
||||
MutexLock lock(navigation_mesh_generation);
|
||||
navigation_mesh.unref();
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationPolygon::set_data(const Vector<Vector2> &p_vertices, const Vector<Vector<int>> &p_polygons, const Vector<Vector<Vector2>> &p_outlines) {
|
||||
RWLockWrite write_lock(rwlock);
|
||||
vertices = p_vertices;
|
||||
polygons = p_polygons;
|
||||
outlines = p_outlines;
|
||||
rect_cache_dirty = true;
|
||||
{
|
||||
MutexLock lock(navigation_mesh_generation);
|
||||
navigation_mesh.unref();
|
||||
|
|
@ -202,10 +208,14 @@ void NavigationPolygon::set_data(const Vector<Vector2> &p_vertices, const Vector
|
|||
void NavigationPolygon::get_data(Vector<Vector2> &r_vertices, Vector<Vector<int>> &r_polygons) {
|
||||
RWLockRead read_lock(rwlock);
|
||||
r_vertices = vertices;
|
||||
r_polygons.resize(polygons.size());
|
||||
for (int i = 0; i < polygons.size(); i++) {
|
||||
r_polygons.write[i] = polygons[i].indices;
|
||||
}
|
||||
r_polygons = polygons;
|
||||
}
|
||||
|
||||
void NavigationPolygon::get_data(Vector<Vector2> &r_vertices, Vector<Vector<int>> &r_polygons, Vector<Vector<Vector2>> &r_outlines) {
|
||||
RWLockRead read_lock(rwlock);
|
||||
r_vertices = vertices;
|
||||
r_polygons = polygons;
|
||||
r_outlines = outlines;
|
||||
}
|
||||
|
||||
Ref<NavigationMesh> NavigationPolygon::get_navigation_mesh() {
|
||||
|
|
@ -237,6 +247,31 @@ Ref<NavigationMesh> NavigationPolygon::get_navigation_mesh() {
|
|||
return navigation_mesh;
|
||||
}
|
||||
|
||||
void NavigationPolygon::set_outlines(const Vector<Vector<Vector2>> &p_outlines) {
|
||||
RWLockWrite write_lock(rwlock);
|
||||
outlines = p_outlines;
|
||||
rect_cache_dirty = true;
|
||||
}
|
||||
|
||||
Vector<Vector<Vector2>> NavigationPolygon::get_outlines() const {
|
||||
RWLockRead read_lock(rwlock);
|
||||
return outlines;
|
||||
}
|
||||
|
||||
void NavigationPolygon::set_polygons(const Vector<Vector<int>> &p_polygons) {
|
||||
RWLockWrite write_lock(rwlock);
|
||||
polygons = p_polygons;
|
||||
{
|
||||
MutexLock lock(navigation_mesh_generation);
|
||||
navigation_mesh.unref();
|
||||
}
|
||||
}
|
||||
|
||||
Vector<Vector<int>> NavigationPolygon::get_polygons() const {
|
||||
RWLockRead read_lock(rwlock);
|
||||
return polygons;
|
||||
}
|
||||
|
||||
void NavigationPolygon::add_outline(const Vector<Vector2> &p_outline) {
|
||||
RWLockWrite write_lock(rwlock);
|
||||
outlines.push_back(p_outline);
|
||||
|
|
@ -364,7 +399,7 @@ void NavigationPolygon::make_polygons_from_outlines() {
|
|||
for (List<TPPLPoly>::Element *I = out_poly.front(); I; I = I->next()) {
|
||||
TPPLPoly &tp = I->get();
|
||||
|
||||
struct Polygon p;
|
||||
Vector<int> p;
|
||||
|
||||
for (int64_t i = 0; i < tp.GetNumPoints(); i++) {
|
||||
HashMap<Vector2, int>::Iterator E = points.find(tp[i]);
|
||||
|
|
@ -372,7 +407,7 @@ void NavigationPolygon::make_polygons_from_outlines() {
|
|||
E = points.insert(tp[i], vertices.size());
|
||||
vertices.push_back(tp[i]);
|
||||
}
|
||||
p.indices.push_back(E->value);
|
||||
p.push_back(E->value);
|
||||
}
|
||||
|
||||
polygons.push_back(p);
|
||||
|
|
@ -400,6 +435,15 @@ real_t NavigationPolygon::get_border_size() const {
|
|||
return border_size;
|
||||
}
|
||||
|
||||
void NavigationPolygon::set_sample_partition_type(SamplePartitionType p_value) {
|
||||
ERR_FAIL_INDEX(p_value, SAMPLE_PARTITION_MAX);
|
||||
partition_type = p_value;
|
||||
}
|
||||
|
||||
NavigationPolygon::SamplePartitionType NavigationPolygon::get_sample_partition_type() const {
|
||||
return partition_type;
|
||||
}
|
||||
|
||||
void NavigationPolygon::set_parsed_geometry_type(ParsedGeometryType p_geometry_type) {
|
||||
ERR_FAIL_INDEX(p_geometry_type, PARSED_GEOMETRY_MAX);
|
||||
parsed_geometry_type = p_geometry_type;
|
||||
|
|
@ -514,6 +558,9 @@ void NavigationPolygon::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_border_size", "border_size"), &NavigationPolygon::set_border_size);
|
||||
ClassDB::bind_method(D_METHOD("get_border_size"), &NavigationPolygon::get_border_size);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_sample_partition_type", "sample_partition_type"), &NavigationPolygon::set_sample_partition_type);
|
||||
ClassDB::bind_method(D_METHOD("get_sample_partition_type"), &NavigationPolygon::get_sample_partition_type);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_parsed_geometry_type", "geometry_type"), &NavigationPolygon::set_parsed_geometry_type);
|
||||
ClassDB::bind_method(D_METHOD("get_parsed_geometry_type"), &NavigationPolygon::get_parsed_geometry_type);
|
||||
|
||||
|
|
@ -543,6 +590,8 @@ void NavigationPolygon::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines");
|
||||
|
||||
ADD_GROUP("Sampling", "sample_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "sample_partition_type", PROPERTY_HINT_ENUM, "Convex Partition,Triangulate"), "set_sample_partition_type", "get_sample_partition_type");
|
||||
ADD_GROUP("Geometry", "");
|
||||
ADD_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");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "parsed_collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_parsed_collision_mask", "get_parsed_collision_mask");
|
||||
|
|
@ -559,6 +608,10 @@ void NavigationPolygon::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "baking_rect"), "set_baking_rect", "get_baking_rect");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "baking_rect_offset"), "set_baking_rect_offset", "get_baking_rect_offset");
|
||||
|
||||
BIND_ENUM_CONSTANT(SAMPLE_PARTITION_CONVEX_PARTITION);
|
||||
BIND_ENUM_CONSTANT(SAMPLE_PARTITION_TRIANGULATE);
|
||||
BIND_ENUM_CONSTANT(SAMPLE_PARTITION_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_MESH_INSTANCES);
|
||||
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_STATIC_COLLIDERS);
|
||||
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_BOTH);
|
||||
|
|
|
|||
|
|
@ -33,16 +33,14 @@
|
|||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/navigation_mesh.h"
|
||||
#include "servers/navigation/navigation_globals.h"
|
||||
|
||||
class NavigationPolygon : public Resource {
|
||||
GDCLASS(NavigationPolygon, Resource);
|
||||
RWLock rwlock;
|
||||
|
||||
Vector<Vector2> vertices;
|
||||
struct Polygon {
|
||||
Vector<int> indices;
|
||||
};
|
||||
Vector<Polygon> polygons;
|
||||
Vector<Vector<int>> polygons;
|
||||
Vector<Vector<Vector2>> outlines;
|
||||
Vector<Vector<Vector2>> baked_outlines;
|
||||
|
||||
|
|
@ -53,7 +51,7 @@ class NavigationPolygon : public Resource {
|
|||
// Navigation mesh
|
||||
Ref<NavigationMesh> navigation_mesh;
|
||||
|
||||
real_t cell_size = 1.0f; // Must match ProjectSettings default 2D cell_size.
|
||||
real_t cell_size = NavigationDefaults2D::navmesh_cell_size;
|
||||
real_t border_size = 0.0f;
|
||||
|
||||
Rect2 baking_rect;
|
||||
|
|
@ -70,10 +68,16 @@ protected:
|
|||
TypedArray<Vector<Vector2>> _get_outlines() const;
|
||||
|
||||
public:
|
||||
#ifdef TOOLS_ENABLED
|
||||
#ifdef DEBUG_ENABLED
|
||||
Rect2 _edit_get_rect() const;
|
||||
bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
|
||||
#endif
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
enum SamplePartitionType {
|
||||
SAMPLE_PARTITION_CONVEX_PARTITION = 0,
|
||||
SAMPLE_PARTITION_TRIANGULATE,
|
||||
SAMPLE_PARTITION_MAX
|
||||
};
|
||||
|
||||
enum ParsedGeometryType {
|
||||
PARSED_GEOMETRY_MESH_INSTANCES = 0,
|
||||
|
|
@ -91,6 +95,7 @@ public:
|
|||
|
||||
real_t agent_radius = 10.0f;
|
||||
|
||||
SamplePartitionType partition_type = SAMPLE_PARTITION_CONVEX_PARTITION;
|
||||
ParsedGeometryType parsed_geometry_type = PARSED_GEOMETRY_BOTH;
|
||||
uint32_t parsed_collision_mask = 0xFFFFFFFF;
|
||||
|
||||
|
|
@ -109,6 +114,8 @@ public:
|
|||
Vector<Vector2> get_outline(int p_idx) const;
|
||||
void remove_outline(int p_idx);
|
||||
int get_outline_count() const;
|
||||
void set_outlines(const Vector<Vector<Vector2>> &p_outlines);
|
||||
Vector<Vector<Vector2>> get_outlines() const;
|
||||
|
||||
void clear_outlines();
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
|
|
@ -116,10 +123,13 @@ public:
|
|||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
void set_polygons(const Vector<Vector<int>> &p_polygons);
|
||||
const Vector<Vector<int>> &get_polygons() const;
|
||||
Vector<Vector<int>> get_polygons() const;
|
||||
Vector<int> get_polygon(int p_idx);
|
||||
void clear_polygons();
|
||||
|
||||
void set_sample_partition_type(SamplePartitionType p_value);
|
||||
SamplePartitionType get_sample_partition_type() const;
|
||||
|
||||
void set_parsed_geometry_type(ParsedGeometryType p_geometry_type);
|
||||
ParsedGeometryType get_parsed_geometry_type() const;
|
||||
|
||||
|
|
@ -155,12 +165,15 @@ public:
|
|||
void clear();
|
||||
|
||||
void set_data(const Vector<Vector2> &p_vertices, const Vector<Vector<int>> &p_polygons);
|
||||
void set_data(const Vector<Vector2> &p_vertices, const Vector<Vector<int>> &p_polygons, const Vector<Vector<Vector2>> &p_outlines);
|
||||
void get_data(Vector<Vector2> &r_vertices, Vector<Vector<int>> &r_polygons);
|
||||
void get_data(Vector<Vector2> &r_vertices, Vector<Vector<int>> &r_polygons, Vector<Vector<Vector2>> &r_outlines);
|
||||
|
||||
NavigationPolygon() {}
|
||||
~NavigationPolygon() {}
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(NavigationPolygon::SamplePartitionType);
|
||||
VARIANT_ENUM_CAST(NavigationPolygon::ParsedGeometryType);
|
||||
VARIANT_ENUM_CAST(NavigationPolygon::SourceGeometryMode);
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ bool RectangleShape2D::_get(const StringName &p_name, Variant &r_property) const
|
|||
|
||||
void RectangleShape2D::set_size(const Size2 &p_size) {
|
||||
ERR_FAIL_COND_MSG(p_size.x < 0 || p_size.y < 0, "RectangleShape2D size cannot be negative.");
|
||||
if (size == p_size) {
|
||||
return;
|
||||
}
|
||||
size = p_size;
|
||||
_update_shape();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ void SegmentShape2D::_update_shape() {
|
|||
}
|
||||
|
||||
void SegmentShape2D::set_a(const Vector2 &p_a) {
|
||||
if (a == p_a) {
|
||||
return;
|
||||
}
|
||||
a = p_a;
|
||||
_update_shape();
|
||||
}
|
||||
|
|
@ -58,6 +61,9 @@ Vector2 SegmentShape2D::get_a() const {
|
|||
}
|
||||
|
||||
void SegmentShape2D::set_b(const Vector2 &p_b) {
|
||||
if (b == p_b) {
|
||||
return;
|
||||
}
|
||||
b = p_b;
|
||||
_update_shape();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ void SeparationRayShape2D::_bind_methods() {
|
|||
}
|
||||
|
||||
void SeparationRayShape2D::set_length(real_t p_length) {
|
||||
if (length == p_length) {
|
||||
return;
|
||||
}
|
||||
length = p_length;
|
||||
_update_shape();
|
||||
}
|
||||
|
|
@ -103,6 +106,9 @@ real_t SeparationRayShape2D::get_length() const {
|
|||
}
|
||||
|
||||
void SeparationRayShape2D::set_slide_on_slope(bool p_active) {
|
||||
if (slide_on_slope == p_active) {
|
||||
return;
|
||||
}
|
||||
slide_on_slope = p_active;
|
||||
_update_shape();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include "shape_2d.h"
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "servers/physics_server_2d.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -31,10 +31,6 @@
|
|||
#include "skeleton_modification_2d.h"
|
||||
#include "scene/2d/skeleton_2d.h"
|
||||
|
||||
#include "scene/2d/physics/collision_object_2d.h"
|
||||
#include "scene/2d/physics/collision_shape_2d.h"
|
||||
#include "scene/2d/physics/physical_bone_2d.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#include "editor/editor_settings.h"
|
||||
#endif // TOOLS_ENABLED
|
||||
|
|
|
|||
|
|
@ -31,14 +31,12 @@
|
|||
#ifndef SKELETON_MODIFICATION_2D_H
|
||||
#define SKELETON_MODIFICATION_2D_H
|
||||
|
||||
#include "scene/2d/skeleton_2d.h"
|
||||
#include "scene/resources/2d/skeleton/skeleton_modification_stack_2d.h"
|
||||
|
||||
///////////////////////////////////////
|
||||
// SkeletonModification2D
|
||||
///////////////////////////////////////
|
||||
|
||||
class SkeletonModificationStack2D;
|
||||
class Bone2D;
|
||||
|
||||
class SkeletonModification2D : public Resource {
|
||||
|
|
|
|||
|
|
@ -31,10 +31,6 @@
|
|||
#include "skeleton_modification_2d_ccdik.h"
|
||||
#include "scene/2d/skeleton_2d.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#include "editor/editor_settings.h"
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
bool SkeletonModification2DCCDIK::_set(const StringName &p_path, const Variant &p_value) {
|
||||
String path = p_path;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,10 +31,6 @@
|
|||
#include "skeleton_modification_2d_fabrik.h"
|
||||
#include "scene/2d/skeleton_2d.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#include "editor/editor_settings.h"
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
bool SkeletonModification2DFABRIK::_set(const StringName &p_path, const Variant &p_value) {
|
||||
String path = p_path;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,10 +31,6 @@
|
|||
#include "skeleton_modification_2d_lookat.h"
|
||||
#include "scene/2d/skeleton_2d.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#include "editor/editor_settings.h"
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
bool SkeletonModification2DLookAt::_set(const StringName &p_path, const Variant &p_value) {
|
||||
String path = p_path;
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ void SkeletonModificationStack2D::setup() {
|
|||
if (skeleton != nullptr) {
|
||||
is_setup = true;
|
||||
for (int i = 0; i < modifications.size(); i++) {
|
||||
if (!modifications[i].is_valid()) {
|
||||
if (modifications[i].is_null()) {
|
||||
continue;
|
||||
}
|
||||
modifications.get(i)->_setup_modification(this);
|
||||
|
|
@ -100,7 +100,7 @@ void SkeletonModificationStack2D::execute(float p_delta, int p_execution_mode) {
|
|||
}
|
||||
|
||||
for (int i = 0; i < modifications.size(); i++) {
|
||||
if (!modifications[i].is_valid()) {
|
||||
if (modifications[i].is_null()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ void SkeletonModificationStack2D::draw_editor_gizmos() {
|
|||
|
||||
if (editor_gizmo_dirty) {
|
||||
for (int i = 0; i < modifications.size(); i++) {
|
||||
if (!modifications[i].is_valid()) {
|
||||
if (modifications[i].is_null()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ void SkeletonModificationStack2D::set_editor_gizmos_dirty(bool p_dirty) {
|
|||
|
||||
void SkeletonModificationStack2D::enable_all_modifications(bool p_enabled) {
|
||||
for (int i = 0; i < modifications.size(); i++) {
|
||||
if (!modifications[i].is_valid()) {
|
||||
if (modifications[i].is_null()) {
|
||||
continue;
|
||||
}
|
||||
modifications.get(i)->set_enabled(p_enabled);
|
||||
|
|
@ -160,7 +160,7 @@ Ref<SkeletonModification2D> SkeletonModificationStack2D::get_modification(int p_
|
|||
}
|
||||
|
||||
void SkeletonModificationStack2D::add_modification(Ref<SkeletonModification2D> p_mod) {
|
||||
ERR_FAIL_COND(!p_mod.is_valid());
|
||||
ERR_FAIL_COND(p_mod.is_null());
|
||||
|
||||
p_mod->_setup_modification(this);
|
||||
modifications.push_back(p_mod);
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@
|
|||
#ifndef SKELETON_MODIFICATION_STACK_2D_H
|
||||
#define SKELETON_MODIFICATION_STACK_2D_H
|
||||
|
||||
#include "scene/2d/skeleton_2d.h"
|
||||
#include "scene/resources/2d/skeleton/skeleton_modification_2d.h"
|
||||
#include "core/io/resource.h"
|
||||
|
||||
///////////////////////////////////////
|
||||
// SkeletonModificationStack2D
|
||||
|
|
@ -64,7 +63,7 @@ public:
|
|||
execution_mode_physics_process
|
||||
};
|
||||
|
||||
Vector<Ref<SkeletonModification2D>> modifications = Vector<Ref<SkeletonModification2D>>();
|
||||
Vector<Ref<SkeletonModification2D>> modifications;
|
||||
|
||||
void setup();
|
||||
void execute(float p_delta, int p_execution_mode);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ Ref<NavigationPolygon> TileData::_get_navigation_polygon_bind_compat_84660(int p
|
|||
}
|
||||
|
||||
Ref<OccluderPolygon2D> TileData::_get_occluder_bind_compat_84660(int p_layer_id) const {
|
||||
return get_occluder(p_layer_id, false, false, false);
|
||||
return get_occluder_polygon(p_layer_id, 0, false, false, false);
|
||||
}
|
||||
|
||||
void TileData::_bind_compatibility_methods() {
|
||||
|
|
|
|||
|
|
@ -174,13 +174,13 @@ void TileMapPattern::set_size(const Size2i &p_size) {
|
|||
|
||||
bool TileMapPattern::is_empty() const {
|
||||
return pattern.is_empty();
|
||||
};
|
||||
}
|
||||
|
||||
void TileMapPattern::clear() {
|
||||
size = Size2i();
|
||||
pattern.clear();
|
||||
emit_changed();
|
||||
};
|
||||
}
|
||||
|
||||
bool TileMapPattern::_set(const StringName &p_name, const Variant &p_value) {
|
||||
if (p_name == "tile_data") {
|
||||
|
|
@ -471,7 +471,7 @@ void TileSet::_compute_next_source_id() {
|
|||
|
||||
// Sources management
|
||||
int TileSet::add_source(Ref<TileSetSource> p_tile_set_source, int p_atlas_source_id_override) {
|
||||
ERR_FAIL_COND_V(!p_tile_set_source.is_valid(), TileSet::INVALID_SOURCE);
|
||||
ERR_FAIL_COND_V(p_tile_set_source.is_null(), TileSet::INVALID_SOURCE);
|
||||
ERR_FAIL_COND_V_MSG(p_atlas_source_id_override >= 0 && (sources.has(p_atlas_source_id_override)), TileSet::INVALID_SOURCE, vformat("Cannot create TileSet atlas source. Another atlas source exists with id %d.", p_atlas_source_id_override));
|
||||
ERR_FAIL_COND_V_MSG(p_atlas_source_id_override < 0 && p_atlas_source_id_override != TileSet::INVALID_SOURCE, TileSet::INVALID_SOURCE, vformat("Provided source ID %d is not valid. Negative source IDs are not allowed.", p_atlas_source_id_override));
|
||||
|
||||
|
|
@ -571,11 +571,11 @@ void TileSet::set_uv_clipping(bool p_uv_clipping) {
|
|||
|
||||
bool TileSet::is_uv_clipping() const {
|
||||
return uv_clipping;
|
||||
};
|
||||
}
|
||||
|
||||
int TileSet::get_occlusion_layers_count() const {
|
||||
return occlusion_layers.size();
|
||||
};
|
||||
}
|
||||
|
||||
void TileSet::add_occlusion_layer(int p_index) {
|
||||
if (p_index < 0) {
|
||||
|
|
@ -699,6 +699,17 @@ uint32_t TileSet::get_physics_layer_collision_mask(int p_layer_index) const {
|
|||
return physics_layers[p_layer_index].collision_mask;
|
||||
}
|
||||
|
||||
void TileSet::set_physics_layer_collision_priority(int p_layer_index, real_t p_priority) {
|
||||
ERR_FAIL_INDEX(p_layer_index, physics_layers.size());
|
||||
physics_layers.write[p_layer_index].collision_priority = p_priority;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
real_t TileSet::get_physics_layer_collision_priority(int p_layer_index) const {
|
||||
ERR_FAIL_INDEX_V(p_layer_index, physics_layers.size(), 0);
|
||||
return physics_layers[p_layer_index].collision_priority;
|
||||
}
|
||||
|
||||
void TileSet::set_physics_layer_physics_material(int p_layer_index, Ref<PhysicsMaterial> p_physics_material) {
|
||||
ERR_FAIL_INDEX(p_layer_index, physics_layers.size());
|
||||
physics_layers.write[p_layer_index].physics_material = p_physics_material;
|
||||
|
|
@ -1111,6 +1122,10 @@ void TileSet::set_custom_data_layer_name(int p_layer_id, String p_value) {
|
|||
emit_changed();
|
||||
}
|
||||
|
||||
bool TileSet::has_custom_data_layer_by_name(const String &p_value) const {
|
||||
return custom_data_layers_by_name.has(p_value);
|
||||
}
|
||||
|
||||
String TileSet::get_custom_data_layer_name(int p_layer_id) const {
|
||||
ERR_FAIL_INDEX_V(p_layer_id, custom_data_layers.size(), "");
|
||||
return custom_data_layers[p_layer_id].name;
|
||||
|
|
@ -1381,7 +1396,7 @@ void TileSet::clear_tile_proxies() {
|
|||
}
|
||||
|
||||
int TileSet::add_pattern(Ref<TileMapPattern> p_pattern, int p_index) {
|
||||
ERR_FAIL_COND_V(!p_pattern.is_valid(), -1);
|
||||
ERR_FAIL_COND_V(p_pattern.is_null(), -1);
|
||||
ERR_FAIL_COND_V_MSG(p_pattern->is_empty(), -1, "Cannot add an empty pattern to the TileSet.");
|
||||
for (const Ref<TileMapPattern> &pattern : patterns) {
|
||||
ERR_FAIL_COND_V_MSG(pattern == p_pattern, -1, "TileSet has already this pattern.");
|
||||
|
|
@ -3444,7 +3459,8 @@ void TileSet::_compatibility_conversion() {
|
|||
polygon.write[index] = xform.xform(polygon[index] - ctd->region.get_size() / 2.0);
|
||||
}
|
||||
occluder->set_polygon(polygon);
|
||||
tile_data->set_occluder(0, occluder);
|
||||
tile_data->add_occluder_polygon(0);
|
||||
tile_data->set_occluder_polygon(0, 0, occluder);
|
||||
}
|
||||
if (ctd->navigation.is_valid()) {
|
||||
if (get_navigation_layers_count() < 1) {
|
||||
|
|
@ -3558,7 +3574,8 @@ void TileSet::_compatibility_conversion() {
|
|||
polygon.write[index] = xform.xform(polygon[index] - ctd->region.get_size() / 2.0);
|
||||
}
|
||||
occluder->set_polygon(polygon);
|
||||
tile_data->set_occluder(0, occluder);
|
||||
tile_data->add_occluder_polygon(0);
|
||||
tile_data->set_occluder_polygon(0, 0, occluder);
|
||||
}
|
||||
if (ctd->autotile_navpoly_map.has(coords)) {
|
||||
if (get_navigation_layers_count() < 1) {
|
||||
|
|
@ -3689,7 +3706,7 @@ Array TileSet::compatibility_tilemap_map(int p_tile_id, Vector2i p_coords, bool
|
|||
return cannot_convert_array;
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
|
|
@ -3898,6 +3915,13 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
|
|||
}
|
||||
set_physics_layer_collision_mask(index, p_value);
|
||||
return true;
|
||||
} else if (components[1] == "collision_priority") {
|
||||
ERR_FAIL_COND_V(p_value.get_type() != Variant::FLOAT, false);
|
||||
while (index >= physics_layers.size()) {
|
||||
add_physics_layer();
|
||||
}
|
||||
set_physics_layer_collision_priority(index, p_value);
|
||||
return true;
|
||||
} else if (components[1] == "physics_material") {
|
||||
Ref<PhysicsMaterial> physics_material = p_value;
|
||||
while (index >= physics_layers.size()) {
|
||||
|
|
@ -3920,7 +3944,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
|
|||
int terrain_index = components[1].trim_prefix("terrain_").to_int();
|
||||
ERR_FAIL_COND_V(terrain_index < 0, false);
|
||||
if (components[2] == "name") {
|
||||
ERR_FAIL_COND_V(p_value.get_type() != Variant::STRING, false);
|
||||
ERR_FAIL_COND_V(!p_value.is_string(), false);
|
||||
while (terrain_set_index >= terrain_sets.size()) {
|
||||
add_terrain_set();
|
||||
}
|
||||
|
|
@ -3958,7 +3982,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
|
|||
int index = components[0].trim_prefix("custom_data_layer_").to_int();
|
||||
ERR_FAIL_COND_V(index < 0, false);
|
||||
if (components[1] == "name") {
|
||||
ERR_FAIL_COND_V(p_value.get_type() != Variant::STRING, false);
|
||||
ERR_FAIL_COND_V(!p_value.is_string(), false);
|
||||
while (index >= custom_data_layers.size()) {
|
||||
add_custom_data_layer();
|
||||
}
|
||||
|
|
@ -4049,6 +4073,9 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
|
|||
} else if (components[1] == "collision_mask") {
|
||||
r_ret = get_physics_layer_collision_mask(index);
|
||||
return true;
|
||||
} else if (components[1] == "collision_priority") {
|
||||
r_ret = get_physics_layer_collision_priority(index);
|
||||
return true;
|
||||
} else if (components[1] == "physics_material") {
|
||||
r_ret = get_physics_layer_physics_material(index);
|
||||
return true;
|
||||
|
|
@ -4174,9 +4201,16 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
|
|||
}
|
||||
p_list->push_back(property_info);
|
||||
|
||||
// physics_layer_%d/collision_priority
|
||||
property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/collision_priority", i));
|
||||
if (physics_layers[i].collision_priority == 1.0) {
|
||||
property_info.usage ^= PROPERTY_USAGE_STORAGE;
|
||||
}
|
||||
p_list->push_back(property_info);
|
||||
|
||||
// physics_layer_%d/physics_material
|
||||
property_info = PropertyInfo(Variant::OBJECT, vformat("physics_layer_%d/physics_material", i), PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial");
|
||||
if (!physics_layers[i].physics_material.is_valid()) {
|
||||
if (physics_layers[i].physics_material.is_null()) {
|
||||
property_info.usage ^= PROPERTY_USAGE_STORAGE;
|
||||
}
|
||||
p_list->push_back(property_info);
|
||||
|
|
@ -4218,10 +4252,10 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
|
|||
|
||||
// Tile Proxies.
|
||||
// Note: proxies need to be set after sources are set.
|
||||
p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Tile Proxies", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
|
||||
p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/source_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
|
||||
p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/coords_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
|
||||
p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/alternative_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
|
||||
p_list->push_back(PropertyInfo(Variant::NIL, "Tile Proxies", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
|
||||
p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/source_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
|
||||
p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/coords_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
|
||||
p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/alternative_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
|
||||
|
||||
// Patterns.
|
||||
for (unsigned int pattern_index = 0; pattern_index < patterns.size(); pattern_index++) {
|
||||
|
|
@ -4285,6 +4319,8 @@ void TileSet::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_physics_layer_collision_layer", "layer_index"), &TileSet::get_physics_layer_collision_layer);
|
||||
ClassDB::bind_method(D_METHOD("set_physics_layer_collision_mask", "layer_index", "mask"), &TileSet::set_physics_layer_collision_mask);
|
||||
ClassDB::bind_method(D_METHOD("get_physics_layer_collision_mask", "layer_index"), &TileSet::get_physics_layer_collision_mask);
|
||||
ClassDB::bind_method(D_METHOD("set_physics_layer_collision_priority", "layer_index", "priority"), &TileSet::set_physics_layer_collision_priority);
|
||||
ClassDB::bind_method(D_METHOD("get_physics_layer_collision_priority", "layer_index"), &TileSet::get_physics_layer_collision_priority);
|
||||
ClassDB::bind_method(D_METHOD("set_physics_layer_physics_material", "layer_index", "physics_material"), &TileSet::set_physics_layer_physics_material);
|
||||
ClassDB::bind_method(D_METHOD("get_physics_layer_physics_material", "layer_index"), &TileSet::get_physics_layer_physics_material);
|
||||
|
||||
|
|
@ -4322,6 +4358,7 @@ void TileSet::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("remove_custom_data_layer", "layer_index"), &TileSet::remove_custom_data_layer);
|
||||
ClassDB::bind_method(D_METHOD("get_custom_data_layer_by_name", "layer_name"), &TileSet::get_custom_data_layer_by_name);
|
||||
ClassDB::bind_method(D_METHOD("set_custom_data_layer_name", "layer_index", "layer_name"), &TileSet::set_custom_data_layer_name);
|
||||
ClassDB::bind_method(D_METHOD("has_custom_data_layer_by_name", "layer_name"), &TileSet::has_custom_data_layer_by_name);
|
||||
ClassDB::bind_method(D_METHOD("get_custom_data_layer_name", "layer_index"), &TileSet::get_custom_data_layer_name);
|
||||
ClassDB::bind_method(D_METHOD("set_custom_data_layer_type", "layer_index", "layer_type"), &TileSet::set_custom_data_layer_type);
|
||||
ClassDB::bind_method(D_METHOD("get_custom_data_layer_type", "layer_index"), &TileSet::get_custom_data_layer_type);
|
||||
|
|
@ -4430,7 +4467,7 @@ TileSet *TileSetSource::get_tile_set() const {
|
|||
|
||||
void TileSetSource::reset_state() {
|
||||
tile_set = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
void TileSetSource::_bind_methods() {
|
||||
// Base tiles
|
||||
|
|
@ -4710,7 +4747,7 @@ bool TileSetAtlasSource::get_use_texture_padding() const {
|
|||
|
||||
Vector2i TileSetAtlasSource::get_atlas_grid_size() const {
|
||||
Ref<Texture2D> txt = get_texture();
|
||||
if (!txt.is_valid()) {
|
||||
if (txt.is_null()) {
|
||||
return Vector2i();
|
||||
}
|
||||
|
||||
|
|
@ -4929,10 +4966,13 @@ void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const {
|
|||
}
|
||||
|
||||
for (const KeyValue<int, TileData *> &E_alternative : E_tile.value.alternatives) {
|
||||
const String formatted_key = itos(E_alternative.key);
|
||||
|
||||
// Add a dummy property to show the alternative exists.
|
||||
tile_property_list.push_back(PropertyInfo(Variant::INT, vformat("%d", E_alternative.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
|
||||
tile_property_list.push_back(PropertyInfo(Variant::INT, formatted_key, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
|
||||
|
||||
// Get the alternative tile's properties and append them to the list of properties.
|
||||
const String alternative_property_info_prefix = formatted_key + '/';
|
||||
List<PropertyInfo> alternative_property_list;
|
||||
E_alternative.value->get_property_list(&alternative_property_list);
|
||||
for (PropertyInfo &alternative_property_info : alternative_property_list) {
|
||||
|
|
@ -4941,14 +4981,15 @@ void TileSetAtlasSource::_get_property_list(List<PropertyInfo> *p_list) const {
|
|||
if (default_value.get_type() != Variant::NIL && bool(Variant::evaluate(Variant::OP_EQUAL, value, default_value))) {
|
||||
alternative_property_info.usage ^= PROPERTY_USAGE_STORAGE;
|
||||
}
|
||||
alternative_property_info.name = vformat("%s/%s", vformat("%d", E_alternative.key), alternative_property_info.name);
|
||||
alternative_property_info.name = alternative_property_info_prefix + alternative_property_info.name;
|
||||
tile_property_list.push_back(alternative_property_info);
|
||||
}
|
||||
}
|
||||
|
||||
// Add all alternative.
|
||||
const String property_info_prefix = vformat("%d:%d/", E_tile.key.x, E_tile.key.y);
|
||||
for (PropertyInfo &tile_property_info : tile_property_list) {
|
||||
tile_property_info.name = vformat("%s/%s", vformat("%d:%d", E_tile.key.x, E_tile.key.y), tile_property_info.name);
|
||||
tile_property_info.name = property_info_prefix + tile_property_info.name;
|
||||
p_list->push_back(tile_property_info);
|
||||
}
|
||||
}
|
||||
|
|
@ -5275,11 +5316,26 @@ Rect2i TileSetAtlasSource::get_tile_texture_region(Vector2i p_atlas_coords, int
|
|||
|
||||
bool TileSetAtlasSource::is_position_in_tile_texture_region(const Vector2i p_atlas_coords, int p_alternative_tile, Vector2 p_position) const {
|
||||
Size2 size = get_tile_texture_region(p_atlas_coords).size;
|
||||
Rect2 rect = Rect2(-size / 2 - get_tile_data(p_atlas_coords, p_alternative_tile)->get_texture_origin(), size);
|
||||
TileData *tile_data = get_tile_data(p_atlas_coords, p_alternative_tile);
|
||||
if (tile_data->get_transpose()) {
|
||||
size = Size2(size.y, size.x);
|
||||
}
|
||||
Rect2 rect = Rect2(-size / 2 - tile_data->get_texture_origin(), size);
|
||||
|
||||
return rect.has_point(p_position);
|
||||
}
|
||||
|
||||
bool TileSetAtlasSource::is_rect_in_tile_texture_region(const Vector2i p_atlas_coords, int p_alternative_tile, Rect2 p_rect) const {
|
||||
Size2 size = get_tile_texture_region(p_atlas_coords).size;
|
||||
TileData *tile_data = get_tile_data(p_atlas_coords, p_alternative_tile);
|
||||
if (tile_data->get_transpose()) {
|
||||
size = Size2(size.y, size.x);
|
||||
}
|
||||
Rect2 rect = Rect2(-size / 2 - tile_data->get_texture_origin(), size);
|
||||
|
||||
return p_rect.intersection(rect) == p_rect;
|
||||
}
|
||||
|
||||
int TileSetAtlasSource::alternative_no_transform(int p_alternative_id) {
|
||||
return p_alternative_id & ~(TRANSFORM_FLIP_H | TRANSFORM_FLIP_V | TRANSFORM_TRANSPOSE);
|
||||
}
|
||||
|
|
@ -6205,33 +6261,86 @@ int TileData::get_y_sort_origin() const {
|
|||
return y_sort_origin;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void TileData::set_occluder(int p_layer_id, Ref<OccluderPolygon2D> p_occluder_polygon) {
|
||||
ERR_FAIL_INDEX(p_layer_id, occluders.size());
|
||||
occluders.write[p_layer_id].occluder = p_occluder_polygon;
|
||||
occluders.write[p_layer_id].transformed_occluders.clear();
|
||||
if (get_occluder_polygons_count(p_layer_id) == 0) {
|
||||
add_occluder_polygon(p_layer_id);
|
||||
}
|
||||
set_occluder_polygon(p_layer_id, 0, p_occluder_polygon);
|
||||
emit_signal(CoreStringName(changed));
|
||||
}
|
||||
|
||||
Ref<OccluderPolygon2D> TileData::get_occluder(int p_layer_id, bool p_flip_h, bool p_flip_v, bool p_transpose) const {
|
||||
ERR_FAIL_INDEX_V(p_layer_id, occluders.size(), Ref<OccluderPolygon2D>());
|
||||
if (get_occluder_polygons_count(p_layer_id) == 0) {
|
||||
return Ref<OccluderPolygon2D>();
|
||||
}
|
||||
return get_occluder_polygon(p_layer_id, 0, p_flip_h, p_flip_v, p_transpose);
|
||||
}
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
void TileData::set_occluder_polygons_count(int p_layer_id, int p_polygons_count) {
|
||||
ERR_FAIL_INDEX(p_layer_id, occluders.size());
|
||||
ERR_FAIL_COND(p_polygons_count < 0);
|
||||
if (p_polygons_count == occluders.write[p_layer_id].polygons.size()) {
|
||||
return;
|
||||
}
|
||||
occluders.write[p_layer_id].polygons.resize(p_polygons_count);
|
||||
notify_property_list_changed();
|
||||
emit_signal(CoreStringName(changed));
|
||||
}
|
||||
|
||||
int TileData::get_occluder_polygons_count(int p_layer_id) const {
|
||||
ERR_FAIL_INDEX_V(p_layer_id, occluders.size(), 0);
|
||||
return occluders[p_layer_id].polygons.size();
|
||||
}
|
||||
|
||||
void TileData::add_occluder_polygon(int p_layer_id) {
|
||||
ERR_FAIL_INDEX(p_layer_id, occluders.size());
|
||||
occluders.write[p_layer_id].polygons.push_back(OcclusionLayerTileData::PolygonOccluderTileData());
|
||||
emit_signal(CoreStringName(changed));
|
||||
}
|
||||
|
||||
void TileData::remove_occluder_polygon(int p_layer_id, int p_polygon_index) {
|
||||
ERR_FAIL_INDEX(p_layer_id, occluders.size());
|
||||
ERR_FAIL_INDEX(p_polygon_index, occluders[p_layer_id].polygons.size());
|
||||
occluders.write[p_layer_id].polygons.remove_at(p_polygon_index);
|
||||
emit_signal(CoreStringName(changed));
|
||||
}
|
||||
|
||||
void TileData::set_occluder_polygon(int p_layer_id, int p_polygon_index, const Ref<OccluderPolygon2D> &p_occluder_polygon) {
|
||||
ERR_FAIL_INDEX(p_layer_id, occluders.size());
|
||||
ERR_FAIL_INDEX(p_polygon_index, occluders[p_layer_id].polygons.size());
|
||||
|
||||
OcclusionLayerTileData::PolygonOccluderTileData &polygon_occluder_tile_data = occluders.write[p_layer_id].polygons.write[p_polygon_index];
|
||||
polygon_occluder_tile_data.occluder_polygon = p_occluder_polygon;
|
||||
polygon_occluder_tile_data.transformed_polygon_occluders.clear();
|
||||
emit_signal(CoreStringName(changed));
|
||||
}
|
||||
|
||||
Ref<OccluderPolygon2D> TileData::get_occluder_polygon(int p_layer_id, int p_polygon_index, bool p_flip_h, bool p_flip_v, bool p_transpose) const {
|
||||
ERR_FAIL_INDEX_V(p_layer_id, occluders.size(), Ref<OccluderPolygon2D>());
|
||||
ERR_FAIL_INDEX_V(p_polygon_index, occluders[p_layer_id].polygons.size(), Ref<OccluderPolygon2D>());
|
||||
|
||||
const OcclusionLayerTileData &layer_tile_data = occluders[p_layer_id];
|
||||
const Ref<OccluderPolygon2D> &occluder_polygon = layer_tile_data.polygons[p_polygon_index].occluder_polygon;
|
||||
|
||||
int key = int(p_flip_h) | int(p_flip_v) << 1 | int(p_transpose) << 2;
|
||||
if (key == 0) {
|
||||
return layer_tile_data.occluder;
|
||||
return occluder_polygon;
|
||||
}
|
||||
|
||||
if (layer_tile_data.occluder.is_null()) {
|
||||
if (occluder_polygon.is_null()) {
|
||||
return Ref<OccluderPolygon2D>();
|
||||
}
|
||||
|
||||
HashMap<int, Ref<OccluderPolygon2D>>::Iterator I = layer_tile_data.transformed_occluders.find(key);
|
||||
HashMap<int, Ref<OccluderPolygon2D>>::Iterator I = layer_tile_data.polygons[p_polygon_index].transformed_polygon_occluders.find(key);
|
||||
if (!I) {
|
||||
Ref<OccluderPolygon2D> transformed_polygon;
|
||||
transformed_polygon.instantiate();
|
||||
transformed_polygon->set_polygon(get_transformed_vertices(layer_tile_data.occluder->get_polygon(), p_flip_h, p_flip_v, p_transpose));
|
||||
layer_tile_data.transformed_occluders[key] = transformed_polygon;
|
||||
transformed_polygon->set_polygon(get_transformed_vertices(occluder_polygon->get_polygon(), p_flip_h, p_flip_v, p_transpose));
|
||||
layer_tile_data.polygons[p_polygon_index].transformed_polygon_occluders[key] = transformed_polygon;
|
||||
return transformed_polygon;
|
||||
} else {
|
||||
return I->value;
|
||||
|
|
@ -6410,9 +6519,9 @@ int TileData::get_terrain_set() const {
|
|||
}
|
||||
|
||||
void TileData::set_terrain(int p_terrain) {
|
||||
ERR_FAIL_COND(terrain_set < 0);
|
||||
ERR_FAIL_COND(p_terrain < -1);
|
||||
if (tile_set) {
|
||||
ERR_FAIL_COND(terrain_set < 0 && p_terrain != -1);
|
||||
if (tile_set && terrain_set >= 0) {
|
||||
ERR_FAIL_COND(p_terrain >= tile_set->get_terrains_count(terrain_set));
|
||||
}
|
||||
terrain = p_terrain;
|
||||
|
|
@ -6425,9 +6534,9 @@ int TileData::get_terrain() const {
|
|||
|
||||
void TileData::set_terrain_peering_bit(TileSet::CellNeighbor p_peering_bit, int p_terrain_index) {
|
||||
ERR_FAIL_INDEX(p_peering_bit, TileSet::CellNeighbor::CELL_NEIGHBOR_MAX);
|
||||
ERR_FAIL_COND(terrain_set < 0);
|
||||
ERR_FAIL_COND(p_terrain_index < -1);
|
||||
if (tile_set) {
|
||||
ERR_FAIL_COND(terrain_set < 0 && p_terrain_index != -1);
|
||||
if (tile_set && terrain_set >= 0) {
|
||||
ERR_FAIL_COND(p_terrain_index >= tile_set->get_terrains_count(terrain_set));
|
||||
ERR_FAIL_COND(!is_valid_terrain_peering_bit(p_peering_bit));
|
||||
}
|
||||
|
|
@ -6487,17 +6596,18 @@ Ref<NavigationPolygon> TileData::get_navigation_polygon(int p_layer_id, bool p_f
|
|||
transformed_polygon.instantiate();
|
||||
|
||||
PackedVector2Array new_points = get_transformed_vertices(layer_tile_data.navigation_polygon->get_vertices(), p_flip_h, p_flip_v, p_transpose);
|
||||
transformed_polygon->set_vertices(new_points);
|
||||
|
||||
int num_polygons = layer_tile_data.navigation_polygon->get_polygon_count();
|
||||
for (int i = 0; i < num_polygons; ++i) {
|
||||
transformed_polygon->add_polygon(layer_tile_data.navigation_polygon->get_polygon(i));
|
||||
const Vector<Vector<Vector2>> outlines = layer_tile_data.navigation_polygon->get_outlines();
|
||||
int outline_count = outlines.size();
|
||||
|
||||
Vector<Vector<Vector2>> new_outlines;
|
||||
new_outlines.resize(outline_count);
|
||||
|
||||
for (int i = 0; i < outline_count; i++) {
|
||||
new_outlines.write[i] = get_transformed_vertices(outlines[i], p_flip_h, p_flip_v, p_transpose);
|
||||
}
|
||||
|
||||
for (int i = 0; i < layer_tile_data.navigation_polygon->get_outline_count(); i++) {
|
||||
PackedVector2Array new_outline = get_transformed_vertices(layer_tile_data.navigation_polygon->get_outline(i), p_flip_h, p_flip_v, p_transpose);
|
||||
transformed_polygon->add_outline(new_outline);
|
||||
}
|
||||
transformed_polygon->set_data(new_points, layer_tile_data.navigation_polygon->get_polygons(), new_outlines);
|
||||
|
||||
layer_tile_data.transformed_navigation_polygon[key] = transformed_polygon;
|
||||
return transformed_polygon;
|
||||
|
|
@ -6531,6 +6641,11 @@ Variant TileData::get_custom_data(String p_layer_name) const {
|
|||
return get_custom_data_by_layer_id(p_layer_id);
|
||||
}
|
||||
|
||||
bool TileData::has_custom_data(const String &p_layer_name) const {
|
||||
ERR_FAIL_NULL_V(tile_set, false);
|
||||
return tile_set->has_custom_data_layer_by_name(p_layer_name);
|
||||
}
|
||||
|
||||
void TileData::set_custom_data_by_layer_id(int p_layer_id, Variant p_value) {
|
||||
ERR_FAIL_INDEX(p_layer_id, custom_data.size());
|
||||
custom_data.write[p_layer_id] = p_value;
|
||||
|
|
@ -6578,13 +6693,37 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) {
|
|||
#endif
|
||||
|
||||
Vector<String> components = String(p_name).split("/", true, 2);
|
||||
|
||||
if (components.size() == 2 && components[0].begins_with("occlusion_layer_") && components[0].trim_prefix("occlusion_layer_").is_valid_int()) {
|
||||
if (components.size() >= 2 && components[0].begins_with("occlusion_layer_") && components[0].trim_prefix("occlusion_layer_").is_valid_int()) {
|
||||
// Occlusion layers.
|
||||
int layer_index = components[0].trim_prefix("occlusion_layer_").to_int();
|
||||
ERR_FAIL_COND_V(layer_index < 0, false);
|
||||
if (components[1] == "polygon") {
|
||||
Ref<OccluderPolygon2D> polygon = p_value;
|
||||
if (components.size() == 2) {
|
||||
if (components[1] == "polygon") {
|
||||
// Kept for compatibility.
|
||||
Ref<OccluderPolygon2D> polygon = p_value;
|
||||
if (layer_index >= occluders.size()) {
|
||||
if (tile_set) {
|
||||
return false;
|
||||
} else {
|
||||
occluders.resize(layer_index + 1);
|
||||
}
|
||||
}
|
||||
if (get_occluder_polygons_count(layer_index) == 0) {
|
||||
add_occluder_polygon(layer_index);
|
||||
}
|
||||
set_occluder_polygon(layer_index, 0, polygon);
|
||||
return true;
|
||||
} else if (components[1] == "polygons_count") {
|
||||
if (p_value.get_type() != Variant::INT) {
|
||||
return false;
|
||||
}
|
||||
set_occluder_polygons_count(layer_index, p_value);
|
||||
return true;
|
||||
}
|
||||
} else if (components.size() == 3 && components[1].begins_with("polygon_") && components[1].trim_prefix("polygon_").is_valid_int()) {
|
||||
// Polygons.
|
||||
int polygon_index = components[1].trim_prefix("polygon_").to_int();
|
||||
ERR_FAIL_COND_V(polygon_index < 0, false);
|
||||
|
||||
if (layer_index >= occluders.size()) {
|
||||
if (tile_set) {
|
||||
|
|
@ -6593,8 +6732,16 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) {
|
|||
occluders.resize(layer_index + 1);
|
||||
}
|
||||
}
|
||||
set_occluder(layer_index, polygon);
|
||||
return true;
|
||||
|
||||
if (polygon_index >= occluders[layer_index].polygons.size()) {
|
||||
occluders.write[layer_index].polygons.resize(polygon_index + 1);
|
||||
}
|
||||
|
||||
if (components[2] == "polygon") {
|
||||
Ref<OccluderPolygon2D> polygon = p_value;
|
||||
set_occluder_polygon(layer_index, polygon_index, polygon);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (components.size() >= 2 && components[0].begins_with("physics_layer_") && components[0].trim_prefix("physics_layer_").is_valid_int()) {
|
||||
// Physics layers.
|
||||
|
|
@ -6622,6 +6769,7 @@ bool TileData::_set(const StringName &p_name, const Variant &p_value) {
|
|||
return true;
|
||||
}
|
||||
} else if (components.size() == 3 && components[1].begins_with("polygon_") && components[1].trim_prefix("polygon_").is_valid_int()) {
|
||||
// Polygons.
|
||||
int polygon_index = components[1].trim_prefix("polygon_").to_int();
|
||||
ERR_FAIL_COND_V(polygon_index < 0, false);
|
||||
|
||||
|
|
@ -6708,16 +6856,36 @@ bool TileData::_get(const StringName &p_name, Variant &r_ret) const {
|
|||
Vector<String> components = String(p_name).split("/", true, 2);
|
||||
|
||||
if (tile_set) {
|
||||
if (components.size() == 2 && components[0].begins_with("occlusion_layer") && components[0].trim_prefix("occlusion_layer_").is_valid_int()) {
|
||||
if (components.size() >= 2 && components[0].begins_with("occlusion_layer") && components[0].trim_prefix("occlusion_layer_").is_valid_int()) {
|
||||
// Occlusion layers.
|
||||
int layer_index = components[0].trim_prefix("occlusion_layer_").to_int();
|
||||
ERR_FAIL_COND_V(layer_index < 0, false);
|
||||
if (layer_index >= occluders.size()) {
|
||||
return false;
|
||||
}
|
||||
if (components[1] == "polygon") {
|
||||
r_ret = get_occluder(layer_index);
|
||||
return true;
|
||||
if (components.size() == 2) {
|
||||
if (components[1] == "polygon") {
|
||||
// Kept for compatibility.
|
||||
if (occluders[layer_index].polygons.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
r_ret = get_occluder_polygon(layer_index, 0);
|
||||
return true;
|
||||
} else if (components[1] == "polygons_count") {
|
||||
r_ret = get_occluder_polygons_count(layer_index);
|
||||
return true;
|
||||
}
|
||||
} else if (components.size() == 3 && components[1].begins_with("polygon_") && components[1].trim_prefix("polygon_").is_valid_int()) {
|
||||
// Polygons.
|
||||
int polygon_index = components[1].trim_prefix("polygon_").to_int();
|
||||
ERR_FAIL_COND_V(polygon_index < 0, false);
|
||||
if (polygon_index >= occluders[layer_index].polygons.size()) {
|
||||
return false;
|
||||
}
|
||||
if (components[2] == "polygon") {
|
||||
r_ret = get_occluder_polygon(layer_index, polygon_index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (components.size() >= 2 && components[0].begins_with("physics_layer_") && components[0].trim_prefix("physics_layer_").is_valid_int()) {
|
||||
// Physics layers.
|
||||
|
|
@ -6797,12 +6965,15 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const {
|
|||
// Occlusion layers.
|
||||
p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Rendering", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
|
||||
for (int i = 0; i < occluders.size(); i++) {
|
||||
// occlusion_layer_%d/polygon
|
||||
property_info = PropertyInfo(Variant::OBJECT, vformat("occlusion_layer_%d/%s", i, PNAME("polygon")), PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_DEFAULT);
|
||||
if (occluders[i].occluder.is_null()) {
|
||||
property_info.usage ^= PROPERTY_USAGE_STORAGE;
|
||||
p_list->push_back(PropertyInfo(Variant::INT, vformat("occlusion_layer_%d/%s", i, PNAME("polygons_count")), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
|
||||
for (int j = 0; j < occluders[i].polygons.size(); j++) {
|
||||
// occlusion_layer_%d/polygon_%d/polygon
|
||||
property_info = PropertyInfo(Variant::OBJECT, vformat("occlusion_layer_%d/polygon_%d/%s", i, j, PNAME("polygon")), PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_DEFAULT);
|
||||
if (occluders[i].polygons[j].occluder_polygon.is_null()) {
|
||||
property_info.usage ^= PROPERTY_USAGE_STORAGE;
|
||||
}
|
||||
p_list->push_back(property_info);
|
||||
}
|
||||
p_list->push_back(property_info);
|
||||
}
|
||||
|
||||
// Physics layers.
|
||||
|
|
@ -6907,8 +7078,17 @@ void TileData::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_y_sort_origin", "y_sort_origin"), &TileData::set_y_sort_origin);
|
||||
ClassDB::bind_method(D_METHOD("get_y_sort_origin"), &TileData::get_y_sort_origin);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_occluder_polygons_count", "layer_id", "polygons_count"), &TileData::set_occluder_polygons_count);
|
||||
ClassDB::bind_method(D_METHOD("get_occluder_polygons_count", "layer_id"), &TileData::get_occluder_polygons_count);
|
||||
ClassDB::bind_method(D_METHOD("add_occluder_polygon", "layer_id"), &TileData::add_occluder_polygon);
|
||||
ClassDB::bind_method(D_METHOD("remove_occluder_polygon", "layer_id", "polygon_index"), &TileData::remove_occluder_polygon);
|
||||
ClassDB::bind_method(D_METHOD("set_occluder_polygon", "layer_id", "polygon_index", "polygon"), &TileData::set_occluder_polygon);
|
||||
ClassDB::bind_method(D_METHOD("get_occluder_polygon", "layer_id", "polygon_index", "flip_h", "flip_v", "transpose"), &TileData::get_occluder_polygon, DEFVAL(false), DEFVAL(false), DEFVAL(false));
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
ClassDB::bind_method(D_METHOD("set_occluder", "layer_id", "occluder_polygon"), &TileData::set_occluder);
|
||||
ClassDB::bind_method(D_METHOD("get_occluder", "layer_id", "flip_h", "flip_v", "transpose"), &TileData::get_occluder, DEFVAL(false), DEFVAL(false), DEFVAL(false));
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
// Physics.
|
||||
ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "layer_id", "velocity"), &TileData::set_constant_linear_velocity);
|
||||
|
|
@ -6946,6 +7126,7 @@ void TileData::_bind_methods() {
|
|||
// Custom data.
|
||||
ClassDB::bind_method(D_METHOD("set_custom_data", "layer_name", "value"), &TileData::set_custom_data);
|
||||
ClassDB::bind_method(D_METHOD("get_custom_data", "layer_name"), &TileData::get_custom_data);
|
||||
ClassDB::bind_method(D_METHOD("has_custom_data", "layer_name"), &TileData::has_custom_data);
|
||||
ClassDB::bind_method(D_METHOD("set_custom_data_by_layer_id", "layer_id", "value"), &TileData::set_custom_data_by_layer_id);
|
||||
ClassDB::bind_method(D_METHOD("get_custom_data_by_layer_id", "layer_id"), &TileData::get_custom_data_by_layer_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ public:
|
|||
bool operator==(const TerrainsPattern &p_terrains_pattern) const;
|
||||
bool operator!=(const TerrainsPattern &p_terrains_pattern) const {
|
||||
return !operator==(p_terrains_pattern);
|
||||
};
|
||||
}
|
||||
|
||||
void set_terrain(int p_terrain);
|
||||
int get_terrain() const;
|
||||
|
|
@ -327,6 +327,7 @@ private:
|
|||
struct PhysicsLayer {
|
||||
uint32_t collision_layer = 1;
|
||||
uint32_t collision_mask = 1;
|
||||
real_t collision_priority = 1.0;
|
||||
Ref<PhysicsMaterial> physics_material;
|
||||
};
|
||||
Vector<PhysicsLayer> physics_layers;
|
||||
|
|
@ -448,6 +449,8 @@ public:
|
|||
uint32_t get_physics_layer_collision_layer(int p_layer_index) const;
|
||||
void set_physics_layer_collision_mask(int p_layer_index, uint32_t p_mask);
|
||||
uint32_t get_physics_layer_collision_mask(int p_layer_index) const;
|
||||
void set_physics_layer_collision_priority(int p_layer_index, real_t p_priority);
|
||||
real_t get_physics_layer_collision_priority(int p_layer_index) const;
|
||||
void set_physics_layer_physics_material(int p_layer_index, Ref<PhysicsMaterial> p_physics_material);
|
||||
Ref<PhysicsMaterial> get_physics_layer_physics_material(int p_layer_index) const;
|
||||
|
||||
|
|
@ -488,6 +491,7 @@ public:
|
|||
void remove_custom_data_layer(int p_index);
|
||||
int get_custom_data_layer_by_name(String p_value) const;
|
||||
void set_custom_data_layer_name(int p_layer_id, String p_value);
|
||||
bool has_custom_data_layer_by_name(const String &p_value) const;
|
||||
String get_custom_data_layer_name(int p_layer_id) const;
|
||||
void set_custom_data_layer_type(int p_layer_id, Variant::Type p_value);
|
||||
Variant::Type get_custom_data_layer_type(int p_layer_id) const;
|
||||
|
|
@ -571,25 +575,25 @@ public:
|
|||
// Not exposed.
|
||||
virtual void set_tile_set(const TileSet *p_tile_set);
|
||||
TileSet *get_tile_set() const;
|
||||
virtual void notify_tile_data_properties_should_change(){};
|
||||
virtual void add_occlusion_layer(int p_index){};
|
||||
virtual void move_occlusion_layer(int p_from_index, int p_to_pos){};
|
||||
virtual void remove_occlusion_layer(int p_index){};
|
||||
virtual void add_physics_layer(int p_index){};
|
||||
virtual void move_physics_layer(int p_from_index, int p_to_pos){};
|
||||
virtual void remove_physics_layer(int p_index){};
|
||||
virtual void add_terrain_set(int p_index){};
|
||||
virtual void move_terrain_set(int p_from_index, int p_to_pos){};
|
||||
virtual void remove_terrain_set(int p_index){};
|
||||
virtual void add_terrain(int p_terrain_set, int p_index){};
|
||||
virtual void move_terrain(int p_terrain_set, int p_from_index, int p_to_pos){};
|
||||
virtual void remove_terrain(int p_terrain_set, int p_index){};
|
||||
virtual void add_navigation_layer(int p_index){};
|
||||
virtual void move_navigation_layer(int p_from_index, int p_to_pos){};
|
||||
virtual void remove_navigation_layer(int p_index){};
|
||||
virtual void add_custom_data_layer(int p_index){};
|
||||
virtual void move_custom_data_layer(int p_from_index, int p_to_pos){};
|
||||
virtual void remove_custom_data_layer(int p_index){};
|
||||
virtual void notify_tile_data_properties_should_change() {}
|
||||
virtual void add_occlusion_layer(int p_index) {}
|
||||
virtual void move_occlusion_layer(int p_from_index, int p_to_pos) {}
|
||||
virtual void remove_occlusion_layer(int p_index) {}
|
||||
virtual void add_physics_layer(int p_index) {}
|
||||
virtual void move_physics_layer(int p_from_index, int p_to_pos) {}
|
||||
virtual void remove_physics_layer(int p_index) {}
|
||||
virtual void add_terrain_set(int p_index) {}
|
||||
virtual void move_terrain_set(int p_from_index, int p_to_pos) {}
|
||||
virtual void remove_terrain_set(int p_index) {}
|
||||
virtual void add_terrain(int p_terrain_set, int p_index) {}
|
||||
virtual void move_terrain(int p_terrain_set, int p_from_index, int p_to_pos) {}
|
||||
virtual void remove_terrain(int p_terrain_set, int p_index) {}
|
||||
virtual void add_navigation_layer(int p_index) {}
|
||||
virtual void move_navigation_layer(int p_from_index, int p_to_pos) {}
|
||||
virtual void remove_navigation_layer(int p_index) {}
|
||||
virtual void add_custom_data_layer(int p_index) {}
|
||||
virtual void move_custom_data_layer(int p_from_index, int p_to_pos) {}
|
||||
virtual void remove_custom_data_layer(int p_index) {}
|
||||
virtual void reset_state() override;
|
||||
|
||||
// Tiles.
|
||||
|
|
@ -763,6 +767,7 @@ public:
|
|||
Vector2i get_atlas_grid_size() const;
|
||||
Rect2i get_tile_texture_region(Vector2i p_atlas_coords, int p_frame = 0) const;
|
||||
bool is_position_in_tile_texture_region(const Vector2i p_atlas_coords, int p_alternative_tile, Vector2 p_position) const;
|
||||
bool is_rect_in_tile_texture_region(const Vector2i p_atlas_coords, int p_alternative_tile, Rect2 p_rect) const;
|
||||
|
||||
static int alternative_no_transform(int p_alternative_id);
|
||||
|
||||
|
|
@ -811,8 +816,8 @@ public:
|
|||
|
||||
// Scenes accessors. Lot are similar to "Alternative tiles".
|
||||
int get_scene_tiles_count() { return get_alternative_tiles_count(Vector2i()); }
|
||||
int get_scene_tile_id(int p_index) { return get_alternative_tile_id(Vector2i(), p_index); };
|
||||
bool has_scene_tile_id(int p_id) { return has_alternative_tile(Vector2i(), p_id); };
|
||||
int get_scene_tile_id(int p_index) { return get_alternative_tile_id(Vector2i(), p_index); }
|
||||
bool has_scene_tile_id(int p_id) { return has_alternative_tile(Vector2i(), p_id); }
|
||||
int create_scene_tile(Ref<PackedScene> p_packed_scene = Ref<PackedScene>(), int p_id_override = -1);
|
||||
void set_scene_tile_id(int p_id, int p_new_id);
|
||||
void set_scene_tile_scene(int p_id, Ref<PackedScene> p_packed_scene);
|
||||
|
|
@ -835,13 +840,16 @@ private:
|
|||
bool flip_v = false;
|
||||
bool transpose = false;
|
||||
Vector2i texture_origin;
|
||||
Ref<Material> material = Ref<Material>();
|
||||
Ref<Material> material;
|
||||
Color modulate = Color(1.0, 1.0, 1.0, 1.0);
|
||||
int z_index = 0;
|
||||
int y_sort_origin = 0;
|
||||
struct OcclusionLayerTileData {
|
||||
Ref<OccluderPolygon2D> occluder;
|
||||
mutable HashMap<int, Ref<OccluderPolygon2D>> transformed_occluders;
|
||||
struct PolygonOccluderTileData {
|
||||
Ref<OccluderPolygon2D> occluder_polygon;
|
||||
mutable HashMap<int, Ref<OccluderPolygon2D>> transformed_polygon_occluders;
|
||||
};
|
||||
Vector<PolygonOccluderTileData> polygons;
|
||||
};
|
||||
Vector<OcclusionLayerTileData> occluders;
|
||||
|
||||
|
|
@ -940,8 +948,17 @@ public:
|
|||
void set_y_sort_origin(int p_y_sort_origin);
|
||||
int get_y_sort_origin() const;
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void set_occluder(int p_layer_id, Ref<OccluderPolygon2D> p_occluder_polygon);
|
||||
Ref<OccluderPolygon2D> get_occluder(int p_layer_id, bool p_flip_h = false, bool p_flip_v = false, bool p_transpose = false) const;
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
void set_occluder_polygons_count(int p_layer_id, int p_polygons_count);
|
||||
int get_occluder_polygons_count(int p_layer_id) const;
|
||||
void add_occluder_polygon(int p_layer_id);
|
||||
void remove_occluder_polygon(int p_layer_id, int p_polygon_index);
|
||||
void set_occluder_polygon(int p_layer_id, int p_polygon_index, const Ref<OccluderPolygon2D> &p_occluder_polygon);
|
||||
Ref<OccluderPolygon2D> get_occluder_polygon(int p_layer_id, int p_polygon_index, bool p_flip_h = false, bool p_flip_v = false, bool p_transpose = false) const;
|
||||
|
||||
// Physics
|
||||
void set_constant_linear_velocity(int p_layer_id, const Vector2 &p_velocity);
|
||||
|
|
@ -983,6 +1000,7 @@ public:
|
|||
// Custom data.
|
||||
void set_custom_data(String p_layer_name, Variant p_value);
|
||||
Variant get_custom_data(String p_layer_name) const;
|
||||
bool has_custom_data(const String &p_layer_name) const;
|
||||
void set_custom_data_by_layer_id(int p_layer_id, Variant p_value);
|
||||
Variant get_custom_data_by_layer_id(int p_layer_id) const;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue