feat: updated engine version to 4.4-rc1

This commit is contained in:
Sara 2025-02-23 14:38:14 +01:00
parent ee00efde1f
commit 21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View file

@ -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;

View file

@ -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();
}

View file

@ -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");

View file

@ -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(); }
};

View file

@ -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);

View file

@ -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);

View file

@ -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();
}

View file

@ -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();
}

View file

@ -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();
}

View file

@ -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"

View file

@ -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

View file

@ -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 {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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() {

View file

@ -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);

View file

@ -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;