summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/area_2d.cpp12
-rw-r--r--scene/2d/navigation_obstacle_2d.cpp65
-rw-r--r--scene/2d/navigation_obstacle_2d.h17
-rw-r--r--scene/2d/physics_body_2d.cpp29
-rw-r--r--scene/2d/physics_body_2d.h20
-rw-r--r--scene/2d/tile_map.cpp17
-rw-r--r--scene/3d/area_3d.cpp11
-rw-r--r--scene/3d/fog_volume.cpp1
-rw-r--r--scene/3d/navigation_obstacle_3d.cpp65
-rw-r--r--scene/3d/navigation_obstacle_3d.h17
-rw-r--r--scene/3d/physics_body_3d.cpp76
-rw-r--r--scene/3d/physics_body_3d.h40
-rw-r--r--scene/animation/tween.cpp2
-rw-r--r--scene/main/viewport.cpp3
-rw-r--r--scene/resources/mesh_data_tool.cpp2
-rw-r--r--scene/resources/tile_set.cpp112
-rw-r--r--scene/resources/tile_set.h27
-rw-r--r--scene/resources/world_3d.cpp4
18 files changed, 437 insertions, 83 deletions
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index fff9c47d4d..75a1723e04 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -369,12 +369,11 @@ void Area2D::set_monitoring(bool p_enable) {
monitoring = p_enable;
if (monitoring) {
- PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_inout);
- PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_area_inout);
-
+ PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), callable_mp(this, &Area2D::_body_inout));
+ PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), callable_mp(this, &Area2D::_area_inout));
} else {
- PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), nullptr, StringName());
- PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), nullptr, StringName());
+ PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), Callable());
+ PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), Callable());
_clear_monitoring();
}
}
@@ -530,9 +529,6 @@ void Area2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area2D::set_audio_bus_override);
ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area2D::is_overriding_audio_bus);
- ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout);
- ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout);
-
ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D")));
diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp
index 0a105826c0..4cfc7fe89e 100644
--- a/scene/2d/navigation_obstacle_2d.cpp
+++ b/scene/2d/navigation_obstacle_2d.cpp
@@ -34,19 +34,41 @@
#include "servers/navigation_server_2d.h"
void NavigationObstacle2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_estimate_radius", "estimate_radius"), &NavigationObstacle2D::set_estimate_radius);
+ ClassDB::bind_method(D_METHOD("is_radius_estimated"), &NavigationObstacle2D::is_radius_estimated);
+ ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationObstacle2D::set_radius);
+ ClassDB::bind_method(D_METHOD("get_radius"), &NavigationObstacle2D::get_radius);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "estimate_radius"), "set_estimate_radius", "is_radius_estimated");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,500,0.01"), "set_radius", "get_radius");
+}
+
+void NavigationObstacle2D::_validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "radius") {
+ if (estimate_radius) {
+ p_property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+ }
}
void NavigationObstacle2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
+ initialize_agent();
+ parent_node2d = Object::cast_to<Node2D>(get_parent());
+ if (parent_node2d != nullptr) {
+ // place agent on navigation map first or else the RVO agent callback creation fails silently later
+ NavigationServer2D::get_singleton()->agent_set_map(get_rid(), parent_node2d->get_world_2d()->get_navigation_map());
+ }
set_physics_process_internal(true);
} break;
case NOTIFICATION_EXIT_TREE: {
+ parent_node2d = nullptr;
set_physics_process_internal(false);
} break;
case NOTIFICATION_PARENTED: {
parent_node2d = Object::cast_to<Node2D>(get_parent());
- update_agent_shape();
+ reevaluate_agent_radius();
} break;
case NOTIFICATION_UNPARENTED: {
parent_node2d = nullptr;
@@ -78,7 +100,22 @@ TypedArray<String> NavigationObstacle2D::get_configuration_warnings() const {
return warnings;
}
-void NavigationObstacle2D::update_agent_shape() {
+void NavigationObstacle2D::initialize_agent() {
+ NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
+ NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, 0);
+ NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, 0.0);
+ NavigationServer2D::get_singleton()->agent_set_max_speed(agent, 0.0);
+}
+
+void NavigationObstacle2D::reevaluate_agent_radius() {
+ if (!estimate_radius) {
+ NavigationServer2D::get_singleton()->agent_set_radius(agent, radius);
+ } else if (parent_node2d) {
+ NavigationServer2D::get_singleton()->agent_set_radius(agent, estimate_agent_radius());
+ }
+}
+
+real_t NavigationObstacle2D::estimate_agent_radius() const {
if (parent_node2d) {
// Estimate the radius of this physics body
real_t radius = 0.0;
@@ -101,15 +138,21 @@ void NavigationObstacle2D::update_agent_shape() {
Vector2 s = parent_node2d->get_global_scale();
radius *= MAX(s.x, s.y);
- if (radius == 0.0) {
- radius = 1.0; // Never a 0 radius
+ if (radius > 0.0) {
+ return radius;
}
-
- // Initialize the Agent as an object
- NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
- NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, 0);
- NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, 0.0);
- NavigationServer2D::get_singleton()->agent_set_radius(agent, radius);
- NavigationServer2D::get_singleton()->agent_set_max_speed(agent, 0.0);
}
+ return 1.0; // Never a 0 radius
+}
+
+void NavigationObstacle2D::set_estimate_radius(bool p_estimate_radius) {
+ estimate_radius = p_estimate_radius;
+ notify_property_list_changed();
+ reevaluate_agent_radius();
+}
+
+void NavigationObstacle2D::set_radius(real_t p_radius) {
+ ERR_FAIL_COND_MSG(p_radius <= 0.0, "Radius must be greater than 0.");
+ radius = p_radius;
+ reevaluate_agent_radius();
}
diff --git a/scene/2d/navigation_obstacle_2d.h b/scene/2d/navigation_obstacle_2d.h
index 9cffc2c0c3..a5603f059f 100644
--- a/scene/2d/navigation_obstacle_2d.h
+++ b/scene/2d/navigation_obstacle_2d.h
@@ -40,8 +40,12 @@ class NavigationObstacle2D : public Node {
Node2D *parent_node2d = nullptr;
RID agent;
+ bool estimate_radius = true;
+ real_t radius = 1.0;
+
protected:
static void _bind_methods();
+ void _validate_property(PropertyInfo &p_property) const override;
void _notification(int p_what);
public:
@@ -52,10 +56,21 @@ public:
return agent;
}
+ void set_estimate_radius(bool p_estimate_radius);
+ bool is_radius_estimated() const {
+ return estimate_radius;
+ }
+ void set_radius(real_t p_radius);
+ real_t get_radius() const {
+ return radius;
+ }
+
TypedArray<String> get_configuration_warnings() const override;
private:
- void update_agent_shape();
+ void initialize_agent();
+ void reevaluate_agent_radius();
+ real_t estimate_agent_radius() const;
};
#endif
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 4d4d21bad7..11790b4cda 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -684,6 +684,24 @@ real_t RigidDynamicBody2D::get_gravity_scale() const {
return gravity_scale;
}
+void RigidDynamicBody2D::set_linear_damp_mode(DampMode p_mode) {
+ linear_damp_mode = p_mode;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
+}
+
+RigidDynamicBody2D::DampMode RigidDynamicBody2D::get_linear_damp_mode() const {
+ return linear_damp_mode;
+}
+
+void RigidDynamicBody2D::set_angular_damp_mode(DampMode p_mode) {
+ angular_damp_mode = p_mode;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
+}
+
+RigidDynamicBody2D::DampMode RigidDynamicBody2D::get_angular_damp_mode() const {
+ return angular_damp_mode;
+}
+
void RigidDynamicBody2D::set_linear_damp(real_t p_linear_damp) {
ERR_FAIL_COND(p_linear_damp < -1);
linear_damp = p_linear_damp;
@@ -916,6 +934,12 @@ void RigidDynamicBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidDynamicBody2D::set_gravity_scale);
ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidDynamicBody2D::get_gravity_scale);
+ ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidDynamicBody2D::set_linear_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidDynamicBody2D::get_linear_damp_mode);
+
+ ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidDynamicBody2D::set_angular_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidDynamicBody2D::get_angular_damp_mode);
+
ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidDynamicBody2D::set_linear_damp);
ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidDynamicBody2D::get_linear_damp);
@@ -992,9 +1016,11 @@ void RigidDynamicBody2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "freeze_mode", PROPERTY_HINT_ENUM, "Static,Kinematic"), "set_freeze_mode", "get_freeze_mode");
ADD_GROUP("Linear", "linear_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
ADD_GROUP("Angular", "angular_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
ADD_GROUP("Applied Forces", "applied_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "applied_force"), "set_applied_force", "get_applied_force");
@@ -1012,6 +1038,9 @@ void RigidDynamicBody2D::_bind_methods() {
BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_AUTO);
BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_CUSTOM);
+ BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
+ BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
+
BIND_ENUM_CONSTANT(CCD_MODE_DISABLED);
BIND_ENUM_CONSTANT(CCD_MODE_CAST_RAY);
BIND_ENUM_CONSTANT(CCD_MODE_CAST_SHAPE);
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 15e8469bb4..2abce4b0a5 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -127,6 +127,11 @@ public:
CENTER_OF_MASS_MODE_CUSTOM,
};
+ enum DampMode {
+ DAMP_MODE_COMBINE,
+ DAMP_MODE_REPLACE,
+ };
+
enum CCDMode {
CCD_MODE_DISABLED,
CCD_MODE_CAST_RAY,
@@ -146,8 +151,12 @@ private:
Ref<PhysicsMaterial> physics_material_override;
real_t gravity_scale = 1.0;
- real_t linear_damp = -1.0;
- real_t angular_damp = -1.0;
+
+ DampMode linear_damp_mode = DAMP_MODE_COMBINE;
+ DampMode angular_damp_mode = DAMP_MODE_COMBINE;
+
+ real_t linear_damp = 0.0;
+ real_t angular_damp = 0.0;
Vector2 linear_velocity;
real_t angular_velocity = 0.0;
@@ -241,6 +250,12 @@ public:
void set_gravity_scale(real_t p_gravity_scale);
real_t get_gravity_scale() const;
+ void set_linear_damp_mode(DampMode p_mode);
+ DampMode get_linear_damp_mode() const;
+
+ void set_angular_damp_mode(DampMode p_mode);
+ DampMode get_angular_damp_mode() const;
+
void set_linear_damp(real_t p_linear_damp);
real_t get_linear_damp() const;
@@ -300,6 +315,7 @@ private:
VARIANT_ENUM_CAST(RigidDynamicBody2D::FreezeMode);
VARIANT_ENUM_CAST(RigidDynamicBody2D::CenterOfMassMode);
+VARIANT_ENUM_CAST(RigidDynamicBody2D::DampMode);
VARIANT_ENUM_CAST(RigidDynamicBody2D::CCDMode);
class CharacterBody2D : public PhysicsBody2D {
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index c11262e0c9..770cb75bab 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -2146,18 +2146,16 @@ Set<TileSet::TerrainsPattern> TileMap::_get_valid_terrains_patterns_for_constrai
Set<TileSet::TerrainsPattern> compatible_terrain_tile_patterns;
for (TileSet::TerrainsPattern &terrain_pattern : tile_set->get_terrains_pattern_set(p_terrain_set)) {
int valid = true;
- int in_pattern_count = 0;
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor bit = TileSet::CellNeighbor(i);
if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, bit)) {
// Check if the bit is compatible with the constraints.
- TerrainConstraint terrain_bit_constraint = TerrainConstraint(this, p_position, bit, terrain_pattern[in_pattern_count]);
+ TerrainConstraint terrain_bit_constraint = TerrainConstraint(this, p_position, bit, terrain_pattern.get_terrain(bit));
Set<TerrainConstraint>::Element *in_set_constraint_element = p_constraints.find(terrain_bit_constraint);
if (in_set_constraint_element && in_set_constraint_element->get().get_terrain() != terrain_bit_constraint.get_terrain()) {
valid = false;
break;
}
- in_pattern_count++;
}
}
@@ -2249,13 +2247,11 @@ Set<TileMap::TerrainConstraint> TileMap::get_terrain_constraints_from_added_tile
// Compute the constraints needed from the surrounding tiles.
Set<TerrainConstraint> output;
- int in_pattern_count = 0;
for (uint32_t i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
TileSet::CellNeighbor side = TileSet::CellNeighbor(i);
if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, side)) {
- TerrainConstraint c = TerrainConstraint(this, p_position, side, p_terrains_pattern[in_pattern_count]);
+ TerrainConstraint c = TerrainConstraint(this, p_position, side, p_terrains_pattern.get_terrain(side));
output.insert(c);
- in_pattern_count++;
}
}
@@ -2312,8 +2308,11 @@ Map<Vector2i, TileSet::TerrainsPattern> TileMap::terrain_wave_function_collapse(
int pattern_index = 0;
for (const TileSet::TerrainsPattern &pattern : valid_tiles) {
Set<int> terrains;
- for (int i = 0; i < pattern.size(); i++) {
- terrains.insert(pattern[i]);
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ TileSet::CellNeighbor side = TileSet::CellNeighbor(i);
+ if (tile_set->is_valid_peering_bit_terrain(p_terrain_set, side)) {
+ terrains.insert(pattern.get_terrain(side));
+ }
}
min_terrain_count = MIN(min_terrain_count, terrains.size());
terrains_counts.push_back(terrains.size());
@@ -2369,7 +2368,7 @@ void TileMap::set_cells_from_surrounding_terrains(int p_layer, TypedArray<Vector
Map<Vector2i, TileSet::TerrainsPattern> wfc_output = terrain_wave_function_collapse(coords_set, p_terrain_set, constraints);
for (const KeyValue<Vector2i, TileSet::TerrainsPattern> &kv : wfc_output) {
- TileMapCell cell = tile_set->get_random_tile_from_pattern(p_terrain_set, kv.value);
+ TileMapCell cell = tile_set->get_random_tile_from_terrains_pattern(p_terrain_set, kv.value);
set_cell(p_layer, kv.key, cell.source_id, cell.get_atlas_coords(), cell.alternative_tile);
}
}
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp
index 9179983220..e459c42e8c 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -334,11 +334,11 @@ void Area3D::set_monitoring(bool p_enable) {
monitoring = p_enable;
if (monitoring) {
- PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_inout);
- PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_area_inout);
+ PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), callable_mp(this, &Area3D::_body_inout));
+ PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), callable_mp(this, &Area3D::_area_inout));
} else {
- PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), nullptr, StringName());
- PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), nullptr, StringName());
+ PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), Callable());
+ PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), Callable());
_clear_monitoring();
}
}
@@ -630,9 +630,6 @@ void Area3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("overlaps_body", "body"), &Area3D::overlaps_body);
ClassDB::bind_method(D_METHOD("overlaps_area", "area"), &Area3D::overlaps_area);
- ClassDB::bind_method(D_METHOD("_body_inout"), &Area3D::_body_inout);
- ClassDB::bind_method(D_METHOD("_area_inout"), &Area3D::_area_inout);
-
ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area3D::set_audio_bus_override);
ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area3D::is_overriding_audio_bus);
diff --git a/scene/3d/fog_volume.cpp b/scene/3d/fog_volume.cpp
index cc4fbbb41b..694defd7dc 100644
--- a/scene/3d/fog_volume.cpp
+++ b/scene/3d/fog_volume.cpp
@@ -50,6 +50,7 @@ void FogVolume::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NONE;
return;
}
+ VisualInstance3D::_validate_property(property);
}
void FogVolume::set_extents(const Vector3 &p_extents) {
diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp
index 20ffc3b00e..ef15a6319e 100644
--- a/scene/3d/navigation_obstacle_3d.cpp
+++ b/scene/3d/navigation_obstacle_3d.cpp
@@ -35,19 +35,41 @@
#include "servers/navigation_server_3d.h"
void NavigationObstacle3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_estimate_radius", "estimate_radius"), &NavigationObstacle3D::set_estimate_radius);
+ ClassDB::bind_method(D_METHOD("is_radius_estimated"), &NavigationObstacle3D::is_radius_estimated);
+ ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationObstacle3D::set_radius);
+ ClassDB::bind_method(D_METHOD("get_radius"), &NavigationObstacle3D::get_radius);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "estimate_radius"), "set_estimate_radius", "is_radius_estimated");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_radius", "get_radius");
+}
+
+void NavigationObstacle3D::_validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "radius") {
+ if (estimate_radius) {
+ p_property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+ }
}
void NavigationObstacle3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
+ initialize_agent();
+ parent_node3d = Object::cast_to<Node3D>(get_parent());
+ if (parent_node3d != nullptr) {
+ // place agent on navigation map first or else the RVO agent callback creation fails silently later
+ NavigationServer3D::get_singleton()->agent_set_map(get_rid(), parent_node3d->get_world_3d()->get_navigation_map());
+ }
set_physics_process_internal(true);
} break;
case NOTIFICATION_EXIT_TREE: {
+ parent_node3d = nullptr;
set_physics_process_internal(false);
} break;
case NOTIFICATION_PARENTED: {
parent_node3d = Object::cast_to<Node3D>(get_parent());
- update_agent_shape();
+ reevaluate_agent_radius();
} break;
case NOTIFICATION_UNPARENTED: {
parent_node3d = nullptr;
@@ -86,7 +108,22 @@ TypedArray<String> NavigationObstacle3D::get_configuration_warnings() const {
return warnings;
}
-void NavigationObstacle3D::update_agent_shape() {
+void NavigationObstacle3D::initialize_agent() {
+ NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
+ NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0);
+ NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0);
+ NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0);
+}
+
+void NavigationObstacle3D::reevaluate_agent_radius() {
+ if (!estimate_radius) {
+ NavigationServer3D::get_singleton()->agent_set_radius(agent, radius);
+ } else if (parent_node3d) {
+ NavigationServer3D::get_singleton()->agent_set_radius(agent, estimate_agent_radius());
+ }
+}
+
+real_t NavigationObstacle3D::estimate_agent_radius() const {
if (parent_node3d) {
// Estimate the radius of this physics body
real_t radius = 0.0;
@@ -110,15 +147,21 @@ void NavigationObstacle3D::update_agent_shape() {
Vector3 s = parent_node3d->get_global_transform().basis.get_scale();
radius *= MAX(s.x, MAX(s.y, s.z));
- if (radius == 0.0) {
- radius = 1.0; // Never a 0 radius
+ if (radius > 0.0) {
+ return radius;
}
-
- // Initialize the Agent as an object
- NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
- NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0);
- NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0);
- NavigationServer3D::get_singleton()->agent_set_radius(agent, radius);
- NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0);
}
+ return 1.0; // Never a 0 radius
+}
+
+void NavigationObstacle3D::set_estimate_radius(bool p_estimate_radius) {
+ estimate_radius = p_estimate_radius;
+ notify_property_list_changed();
+ reevaluate_agent_radius();
+}
+
+void NavigationObstacle3D::set_radius(real_t p_radius) {
+ ERR_FAIL_COND_MSG(p_radius <= 0.0, "Radius must be greater than 0.");
+ radius = p_radius;
+ reevaluate_agent_radius();
}
diff --git a/scene/3d/navigation_obstacle_3d.h b/scene/3d/navigation_obstacle_3d.h
index ab0b158303..12c813ab08 100644
--- a/scene/3d/navigation_obstacle_3d.h
+++ b/scene/3d/navigation_obstacle_3d.h
@@ -39,8 +39,12 @@ class NavigationObstacle3D : public Node {
Node3D *parent_node3d = nullptr;
RID agent;
+ bool estimate_radius = true;
+ real_t radius = 1.0;
+
protected:
static void _bind_methods();
+ void _validate_property(PropertyInfo &p_property) const override;
void _notification(int p_what);
public:
@@ -51,10 +55,21 @@ public:
return agent;
}
+ void set_estimate_radius(bool p_estimate_radius);
+ bool is_radius_estimated() const {
+ return estimate_radius;
+ }
+ void set_radius(real_t p_radius);
+ real_t get_radius() const {
+ return radius;
+ }
+
TypedArray<String> get_configuration_warnings() const override;
private:
- void update_agent_shape();
+ void initialize_agent();
+ void reevaluate_agent_radius();
+ real_t estimate_agent_radius() const;
};
#endif
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 4f1003839e..edd720117a 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -758,8 +758,26 @@ real_t RigidDynamicBody3D::get_gravity_scale() const {
return gravity_scale;
}
+void RigidDynamicBody3D::set_linear_damp_mode(DampMode p_mode) {
+ linear_damp_mode = p_mode;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
+}
+
+RigidDynamicBody3D::DampMode RigidDynamicBody3D::get_linear_damp_mode() const {
+ return linear_damp_mode;
+}
+
+void RigidDynamicBody3D::set_angular_damp_mode(DampMode p_mode) {
+ angular_damp_mode = p_mode;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
+}
+
+RigidDynamicBody3D::DampMode RigidDynamicBody3D::get_angular_damp_mode() const {
+ return angular_damp_mode;
+}
+
void RigidDynamicBody3D::set_linear_damp(real_t p_linear_damp) {
- ERR_FAIL_COND(p_linear_damp < -1);
+ ERR_FAIL_COND(p_linear_damp < 0.0);
linear_damp = p_linear_damp;
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP, linear_damp);
}
@@ -769,7 +787,7 @@ real_t RigidDynamicBody3D::get_linear_damp() const {
}
void RigidDynamicBody3D::set_angular_damp(real_t p_angular_damp) {
- ERR_FAIL_COND(p_angular_damp < -1);
+ ERR_FAIL_COND(p_angular_damp < 0.0);
angular_damp = p_angular_damp;
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP, angular_damp);
}
@@ -970,6 +988,12 @@ void RigidDynamicBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidDynamicBody3D::set_gravity_scale);
ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidDynamicBody3D::get_gravity_scale);
+ ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidDynamicBody3D::set_linear_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidDynamicBody3D::get_linear_damp_mode);
+
+ ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidDynamicBody3D::set_angular_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidDynamicBody3D::get_angular_damp_mode);
+
ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidDynamicBody3D::set_linear_damp);
ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidDynamicBody3D::get_linear_damp);
@@ -1035,10 +1059,12 @@ void RigidDynamicBody3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "freeze_mode", PROPERTY_HINT_ENUM, "Static,Kinematic"), "set_freeze_mode", "get_freeze_mode");
ADD_GROUP("Linear", "linear_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
ADD_GROUP("Angular", "angular_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::RID, "body_rid"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape_index"), PropertyInfo(Variant::INT, "local_shape_index")));
@@ -1051,6 +1077,9 @@ void RigidDynamicBody3D::_bind_methods() {
BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_AUTO);
BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_CUSTOM);
+
+ BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
+ BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
}
void RigidDynamicBody3D::_validate_property(PropertyInfo &property) const {
@@ -2825,6 +2854,12 @@ void PhysicalBone3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &PhysicalBone3D::set_gravity_scale);
ClassDB::bind_method(D_METHOD("get_gravity_scale"), &PhysicalBone3D::get_gravity_scale);
+ ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &PhysicalBone3D::set_linear_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &PhysicalBone3D::get_linear_damp_mode);
+
+ ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &PhysicalBone3D::set_angular_damp_mode);
+ ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &PhysicalBone3D::get_angular_damp_mode);
+
ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &PhysicalBone3D::set_linear_damp);
ClassDB::bind_method(D_METHOD("get_linear_damp"), &PhysicalBone3D::get_linear_damp);
@@ -2845,10 +2880,15 @@ void PhysicalBone3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-10,10,0.01"), "set_gravity_scale", "get_gravity_scale");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "linear_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_linear_damp_mode", "get_linear_damp_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "angular_damp_mode", PROPERTY_HINT_ENUM, "Combine,Replace"), "set_angular_damp_mode", "get_angular_damp_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
+ BIND_ENUM_CONSTANT(DAMP_MODE_COMBINE);
+ BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE);
+
BIND_ENUM_CONSTANT(JOINT_TYPE_NONE);
BIND_ENUM_CONSTANT(JOINT_TYPE_PIN);
BIND_ENUM_CONSTANT(JOINT_TYPE_CONE);
@@ -3146,8 +3186,27 @@ real_t PhysicalBone3D::get_gravity_scale() const {
return gravity_scale;
}
+void PhysicalBone3D::set_linear_damp_mode(DampMode p_mode) {
+ linear_damp_mode = p_mode;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode);
+}
+
+PhysicalBone3D::DampMode PhysicalBone3D::get_linear_damp_mode() const {
+ return linear_damp_mode;
+}
+
+void PhysicalBone3D::set_angular_damp_mode(DampMode p_mode) {
+ angular_damp_mode = p_mode;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode);
+}
+
+PhysicalBone3D::DampMode PhysicalBone3D::get_angular_damp_mode() const {
+ return angular_damp_mode;
+}
+
void PhysicalBone3D::set_linear_damp(real_t p_linear_damp) {
- ERR_FAIL_COND(p_linear_damp < -1);
+ ERR_FAIL_COND(p_linear_damp < 0);
+
linear_damp = p_linear_damp;
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP, linear_damp);
}
@@ -3157,7 +3216,8 @@ real_t PhysicalBone3D::get_linear_damp() const {
}
void PhysicalBone3D::set_angular_damp(real_t p_angular_damp) {
- ERR_FAIL_COND(p_angular_damp < -1);
+ ERR_FAIL_COND(p_angular_damp < 0);
+
angular_damp = p_angular_damp;
PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP, angular_damp);
}
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 5677df730c..2ea796d335 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -143,6 +143,11 @@ public:
CENTER_OF_MASS_MODE_CUSTOM,
};
+ enum DampMode {
+ DAMP_MODE_COMBINE,
+ DAMP_MODE_REPLACE,
+ };
+
private:
bool can_sleep = true;
bool lock_rotation = false;
@@ -160,8 +165,12 @@ private:
Vector3 angular_velocity;
Basis inverse_inertia_tensor;
real_t gravity_scale = 1.0;
- real_t linear_damp = -1.0;
- real_t angular_damp = -1.0;
+
+ DampMode linear_damp_mode = DAMP_MODE_COMBINE;
+ DampMode angular_damp_mode = DAMP_MODE_COMBINE;
+
+ real_t linear_damp = 0.0;
+ real_t angular_damp = 0.0;
bool sleeping = false;
bool ccd = false;
@@ -265,6 +274,12 @@ public:
void set_gravity_scale(real_t p_gravity_scale);
real_t get_gravity_scale() const;
+ void set_linear_damp_mode(DampMode p_mode);
+ DampMode get_linear_damp_mode() const;
+
+ void set_angular_damp_mode(DampMode p_mode);
+ DampMode get_angular_damp_mode() const;
+
void set_linear_damp(real_t p_linear_damp);
real_t get_linear_damp() const;
@@ -310,6 +325,7 @@ private:
VARIANT_ENUM_CAST(RigidDynamicBody3D::FreezeMode);
VARIANT_ENUM_CAST(RigidDynamicBody3D::CenterOfMassMode);
+VARIANT_ENUM_CAST(RigidDynamicBody3D::DampMode);
class KinematicCollision3D;
@@ -494,6 +510,11 @@ class PhysicalBone3D : public PhysicsBody3D {
GDCLASS(PhysicalBone3D, PhysicsBody3D);
public:
+ enum DampMode {
+ DAMP_MODE_COMBINE,
+ DAMP_MODE_REPLACE,
+ };
+
enum JointType {
JOINT_TYPE_NONE,
JOINT_TYPE_PIN,
@@ -632,10 +653,14 @@ private:
real_t mass = 1.0;
real_t friction = 1.0;
real_t gravity_scale = 1.0;
- real_t linear_damp = -1.0;
- real_t angular_damp = -1.0;
bool can_sleep = true;
+ DampMode linear_damp_mode = DAMP_MODE_COMBINE;
+ DampMode angular_damp_mode = DAMP_MODE_COMBINE;
+
+ real_t linear_damp = 0.0;
+ real_t angular_damp = 0.0;
+
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -698,6 +723,12 @@ public:
void set_gravity_scale(real_t p_gravity_scale);
real_t get_gravity_scale() const;
+ void set_linear_damp_mode(DampMode p_mode);
+ DampMode get_linear_damp_mode() const;
+
+ void set_angular_damp_mode(DampMode p_mode);
+ DampMode get_angular_damp_mode() const;
+
void set_linear_damp(real_t p_linear_damp);
real_t get_linear_damp() const;
@@ -725,5 +756,6 @@ private:
};
VARIANT_ENUM_CAST(PhysicalBone3D::JointType);
+VARIANT_ENUM_CAST(PhysicalBone3D::DampMode);
#endif // PHYSICS_BODY__H
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 47e290beb3..da933ae02d 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -626,7 +626,7 @@ void Tween::_bind_methods() {
ClassDB::bind_method(D_METHOD("parallel"), &Tween::parallel);
ClassDB::bind_method(D_METHOD("chain"), &Tween::chain);
- ClassDB::bind_method(D_METHOD("interpolate_value", "trans_type", "ease_type", "elapsed_time", "initial_value", "delta_value", "duration"), &Tween::interpolate_variant);
+ ClassDB::bind_method(D_METHOD("interpolate_value", "initial_value", "delta_value", "elapsed_time", "duration", "trans_type", "ease_type"), &Tween::interpolate_variant);
ADD_SIGNAL(MethodInfo("step_finished", PropertyInfo(Variant::INT, "idx")));
ADD_SIGNAL(MethodInfo("loop_finished", PropertyInfo(Variant::INT, "loop_count")));
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 6388b375d9..cdf1f495e4 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -715,10 +715,11 @@ void Viewport::_process_picking() {
if (camera_3d) {
Vector3 from = camera_3d->project_ray_origin(pos);
Vector3 dir = camera_3d->project_ray_normal(pos);
+ real_t far = camera_3d->far;
PhysicsDirectSpaceState3D *space = PhysicsServer3D::get_singleton()->space_get_direct_state(find_world_3d()->get_space());
if (space) {
- bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true, true, true);
+ bool col = space->intersect_ray(from, from + dir * far, result, Set<RID>(), 0xFFFFFFFF, true, true, true);
ObjectID new_collider;
if (col) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(result.collider);
diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp
index 04b2437ae8..9ecd8ec2f3 100644
--- a/scene/resources/mesh_data_tool.cpp
+++ b/scene/resources/mesh_data_tool.cpp
@@ -421,6 +421,7 @@ Vector<int> MeshDataTool::get_vertex_bones(int p_idx) const {
void MeshDataTool::set_vertex_bones(int p_idx, const Vector<int> &p_bones) {
ERR_FAIL_INDEX(p_idx, vertices.size());
+ ERR_FAIL_COND(p_bones.size() != 4);
vertices.write[p_idx].bones = p_bones;
format |= Mesh::ARRAY_FORMAT_BONES;
}
@@ -432,6 +433,7 @@ Vector<float> MeshDataTool::get_vertex_weights(int p_idx) const {
void MeshDataTool::set_vertex_weights(int p_idx, const Vector<float> &p_weights) {
ERR_FAIL_INDEX(p_idx, vertices.size());
+ ERR_FAIL_COND(p_weights.size() != 4);
vertices.write[p_idx].weights = p_weights;
format |= Mesh::ARRAY_FORMAT_WEIGHTS;
}
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 141e9e1b0e..9306d19520 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -225,6 +225,90 @@ void TileMapPattern::_bind_methods() {
/////////////////////////////// TileSet //////////////////////////////////////
+bool TileSet::TerrainsPattern::is_valid() const {
+ return valid;
+}
+
+bool TileSet::TerrainsPattern::is_erase_pattern() const {
+ return not_empty_terrains_count == 0;
+}
+
+bool TileSet::TerrainsPattern::operator<(const TerrainsPattern &p_terrains_pattern) const {
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ if (is_valid_bit[i] != p_terrains_pattern.is_valid_bit[i]) {
+ return is_valid_bit[i] < p_terrains_pattern.is_valid_bit[i];
+ }
+ }
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ if (is_valid_bit[i] && bits[i] != p_terrains_pattern.bits[i]) {
+ return bits[i] < p_terrains_pattern.bits[i];
+ }
+ }
+ return false;
+}
+
+bool TileSet::TerrainsPattern::operator==(const TerrainsPattern &p_terrains_pattern) const {
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ if (is_valid_bit[i] != p_terrains_pattern.is_valid_bit[i]) {
+ return false;
+ }
+ if (is_valid_bit[i] && bits[i] != p_terrains_pattern.bits[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void TileSet::TerrainsPattern::set_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain) {
+ ERR_FAIL_COND(p_peering_bit == TileSet::CELL_NEIGHBOR_MAX);
+ ERR_FAIL_COND(!is_valid_bit[p_peering_bit]);
+ ERR_FAIL_COND(p_terrain < -1);
+
+ // Update the "is_erase_pattern" status.
+ if (p_terrain >= 0 && bits[p_peering_bit] < 0) {
+ not_empty_terrains_count++;
+ } else if (p_terrain < 0 && bits[p_peering_bit] >= 0) {
+ not_empty_terrains_count--;
+ }
+
+ bits[p_peering_bit] = p_terrain;
+}
+
+int TileSet::TerrainsPattern::get_terrain(TileSet::CellNeighbor p_peering_bit) const {
+ ERR_FAIL_COND_V(p_peering_bit == TileSet::CELL_NEIGHBOR_MAX, -1);
+ ERR_FAIL_COND_V(!is_valid_bit[p_peering_bit], -1);
+ return bits[p_peering_bit];
+}
+
+void TileSet::TerrainsPattern::set_terrains_from_array(Array p_terrains) {
+ int in_array_index = 0;
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ if (is_valid_bit[i]) {
+ ERR_FAIL_COND(in_array_index >= p_terrains.size());
+ set_terrain(TileSet::CellNeighbor(i), p_terrains[in_array_index]);
+ in_array_index++;
+ }
+ }
+}
+
+Array TileSet::TerrainsPattern::get_terrains_as_array() const {
+ Array output;
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ if (is_valid_bit[i]) {
+ output.push_back(bits[i]);
+ }
+ }
+ return output;
+}
+TileSet::TerrainsPattern::TerrainsPattern(const TileSet *p_tile_set, int p_terrain_set) {
+ ERR_FAIL_COND(p_terrain_set < 0);
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ is_valid_bit[i] = (p_tile_set->is_valid_peering_bit_terrain(p_terrain_set, TileSet::CellNeighbor(i)));
+ bits[i] = -1;
+ }
+ valid = true;
+}
+
const int TileSet::INVALID_SOURCE = -1;
const char *TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[] = {
@@ -330,10 +414,13 @@ void TileSet::_update_terrains_cache() {
TileSet::TerrainsPattern terrains_pattern = tile_data->get_terrains_pattern();
// Terrain bits.
- for (int i = 0; i < terrains_pattern.size(); i++) {
- int terrain = terrains_pattern[i];
- if (terrain >= 0) {
- per_terrain_pattern_tiles[terrain_set][terrains_pattern].insert(cell);
+ for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
+ CellNeighbor bit = CellNeighbor(i);
+ if (is_valid_peering_bit_terrain(terrain_set, bit)) {
+ int terrain = terrains_pattern.get_terrain(bit);
+ if (terrain >= 0) {
+ per_terrain_pattern_tiles[terrain_set][terrains_pattern].insert(cell);
+ }
}
}
}
@@ -344,12 +431,7 @@ void TileSet::_update_terrains_cache() {
// Add the empty cell in the possible patterns and cells.
for (int i = 0; i < terrain_sets.size(); i++) {
- TileSet::TerrainsPattern empty_pattern;
- for (int j = 0; j < TileSet::CELL_NEIGHBOR_MAX; j++) {
- if (is_valid_peering_bit_terrain(i, TileSet::CellNeighbor(j))) {
- empty_pattern.push_back(-1);
- }
- }
+ TileSet::TerrainsPattern empty_pattern(this, i);
TileMapCell empty_cell;
empty_cell.source_id = TileSet::INVALID_SOURCE;
@@ -1283,7 +1365,7 @@ Set<TileMapCell> TileSet::get_tiles_for_terrains_pattern(int p_terrain_set, Terr
return per_terrain_pattern_tiles[p_terrain_set][p_terrain_tile_pattern];
}
-TileMapCell TileSet::get_random_tile_from_pattern(int p_terrain_set, TileSet::TerrainsPattern p_terrain_tile_pattern) {
+TileMapCell TileSet::get_random_tile_from_terrains_pattern(int p_terrain_set, TileSet::TerrainsPattern p_terrain_tile_pattern) {
ERR_FAIL_INDEX_V(p_terrain_set, terrain_sets.size(), TileMapCell());
_update_terrains_cache();
@@ -4864,8 +4946,8 @@ int TileData::get_collision_polygon_shapes_count(int p_layer_id, int p_polygon_i
Ref<ConvexPolygonShape2D> TileData::get_collision_polygon_shape(int p_layer_id, int p_polygon_index, int shape_index) const {
ERR_FAIL_INDEX_V(p_layer_id, physics.size(), 0);
ERR_FAIL_INDEX_V(p_polygon_index, physics[p_layer_id].polygons.size(), Ref<ConvexPolygonShape2D>());
- ERR_FAIL_INDEX_V(shape_index, (int)physics[p_layer_id].polygons[shape_index].shapes.size(), Ref<ConvexPolygonShape2D>());
- return physics[p_layer_id].polygons[shape_index].shapes[shape_index];
+ ERR_FAIL_INDEX_V(shape_index, (int)physics[p_layer_id].polygons[p_polygon_index].shapes.size(), Ref<ConvexPolygonShape2D>());
+ return physics[p_layer_id].polygons[p_polygon_index].shapes[shape_index];
}
// Terrain
@@ -4915,10 +4997,10 @@ bool TileData::is_valid_peering_bit_terrain(TileSet::CellNeighbor p_peering_bit)
TileSet::TerrainsPattern TileData::get_terrains_pattern() const {
ERR_FAIL_COND_V(!tile_set, TileSet::TerrainsPattern());
- TileSet::TerrainsPattern output;
+ TileSet::TerrainsPattern output(tile_set, terrain_set);
for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) {
if (tile_set->is_valid_peering_bit_terrain(terrain_set, TileSet::CellNeighbor(i))) {
- output.push_back(get_peering_bit_terrain(TileSet::CellNeighbor(i)));
+ output.set_terrain(TileSet::CellNeighbor(i), get_peering_bit_terrain(TileSet::CellNeighbor(i)));
}
}
return output;
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 077315e58d..71559074e7 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -253,7 +253,30 @@ public:
Ref<PackedScene> scene;
Vector2 offset;
};
- typedef Array TerrainsPattern;
+
+ class TerrainsPattern {
+ bool valid = false;
+ int bits[TileSet::CELL_NEIGHBOR_MAX];
+ bool is_valid_bit[TileSet::CELL_NEIGHBOR_MAX];
+
+ int not_empty_terrains_count = 0;
+
+ public:
+ bool is_valid() const;
+ bool is_erase_pattern() const;
+
+ bool operator<(const TerrainsPattern &p_terrains_pattern) const;
+ bool operator==(const TerrainsPattern &p_terrains_pattern) const;
+
+ void set_terrain(TileSet::CellNeighbor p_peering_bit, int p_terrain);
+ int get_terrain(TileSet::CellNeighbor p_peering_bit) const;
+
+ void set_terrains_from_array(Array p_terrains);
+ Array get_terrains_as_array() const;
+
+ TerrainsPattern(const TileSet *p_tile_set, int p_terrain_set);
+ TerrainsPattern() {}
+ };
protected:
bool _set(const StringName &p_name, const Variant &p_value);
@@ -478,7 +501,7 @@ public:
// Terrains.
Set<TerrainsPattern> get_terrains_pattern_set(int p_terrain_set);
Set<TileMapCell> get_tiles_for_terrains_pattern(int p_terrain_set, TerrainsPattern p_terrain_tile_pattern);
- TileMapCell get_random_tile_from_pattern(int p_terrain_set, TerrainsPattern p_terrain_tile_pattern);
+ TileMapCell get_random_tile_from_terrains_pattern(int p_terrain_set, TerrainsPattern p_terrain_tile_pattern);
// Helpers
Vector<Vector2> get_tile_shape_polygon();
diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp
index 42047f104f..0e1b343eac 100644
--- a/scene/resources/world_3d.cpp
+++ b/scene/resources/world_3d.cpp
@@ -144,9 +144,9 @@ World3D::World3D() {
PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/3d/default_gravity", 9.8));
PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/3d/default_gravity_vector", Vector3(0, -1, 0)));
PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/3d/default_linear_damp", 0.1));
- ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"));
PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/3d/default_angular_damp", 0.1));
- ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"));
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"));
navigation_map = NavigationServer3D::get_singleton()->map_create();
NavigationServer3D::get_singleton()->map_set_active(navigation_map, true);