summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/physics_body_2d.cpp261
-rw-r--r--scene/2d/physics_body_2d.h55
-rw-r--r--scene/2d/tile_map.cpp60
-rw-r--r--scene/2d/tile_map.h4
-rw-r--r--scene/3d/physics_body_3d.cpp332
-rw-r--r--scene/3d/physics_body_3d.h68
-rw-r--r--scene/gui/check_box.cpp18
-rw-r--r--scene/gui/code_edit.cpp4
-rw-r--r--scene/gui/control.cpp29
-rw-r--r--scene/gui/control.h3
-rw-r--r--scene/gui/line_edit.cpp2
-rw-r--r--scene/gui/tab_container.cpp1
-rw-r--r--scene/gui/text_edit.cpp47
-rw-r--r--scene/gui/text_edit.h2
-rw-r--r--scene/main/node.cpp47
-rw-r--r--scene/main/node.h6
-rw-r--r--scene/main/scene_tree.h2
-rw-r--r--scene/register_scene_types.cpp2
-rw-r--r--scene/resources/tile_set.cpp689
-rw-r--r--scene/resources/tile_set.h88
20 files changed, 1173 insertions, 547 deletions
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 3518d434c3..30f012c7aa 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -165,21 +165,13 @@ void PhysicsBody2D::remove_collision_exception_with(Node *p_node) {
void StaticBody2D::set_constant_linear_velocity(const Vector2 &p_vel) {
constant_linear_velocity = p_vel;
- if (kinematic_motion) {
- _update_kinematic_motion();
- } else {
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
- }
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
}
void StaticBody2D::set_constant_angular_velocity(real_t p_vel) {
constant_angular_velocity = p_vel;
- if (kinematic_motion) {
- _update_kinematic_motion();
- } else {
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
- }
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
}
Vector2 StaticBody2D::get_constant_linear_velocity() const {
@@ -209,62 +201,72 @@ Ref<PhysicsMaterial> StaticBody2D::get_physics_material_override() const {
return physics_material_override;
}
-void StaticBody2D::set_kinematic_motion_enabled(bool p_enabled) {
- if (p_enabled == kinematic_motion) {
- return;
- }
-
- kinematic_motion = p_enabled;
+void StaticBody2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody2D::set_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody2D::set_constant_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody2D::get_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody2D::get_constant_angular_velocity);
- if (kinematic_motion) {
- set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
- } else {
- set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
- }
+ ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override);
+ ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override);
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- update_configuration_warnings();
- return;
- }
-#endif
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
+}
- _update_kinematic_motion();
+StaticBody2D::StaticBody2D(PhysicsServer2D::BodyMode p_mode) :
+ PhysicsBody2D(p_mode) {
}
-bool StaticBody2D::is_kinematic_motion_enabled() const {
- return kinematic_motion;
+void StaticBody2D::_reload_physics_characteristics() {
+ if (physics_material_override.is_null()) {
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
+ }
}
-void StaticBody2D::set_sync_to_physics(bool p_enable) {
+void AnimatableBody2D::set_sync_to_physics(bool p_enable) {
if (sync_to_physics == p_enable) {
return;
}
sync_to_physics = p_enable;
+ _update_kinematic_motion();
+}
+
+bool AnimatableBody2D::is_sync_to_physics_enabled() const {
+ return sync_to_physics;
+}
+
+void AnimatableBody2D::_update_kinematic_motion() {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- update_configuration_warnings();
return;
}
#endif
- if (kinematic_motion) {
- _update_kinematic_motion();
+ if (sync_to_physics) {
+ PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
+ set_only_update_transform_changes(true);
+ set_notify_local_transform(true);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), nullptr, nullptr);
+ set_only_update_transform_changes(false);
+ set_notify_local_transform(false);
}
}
-bool StaticBody2D::is_sync_to_physics_enabled() const {
- return sync_to_physics;
-}
-
-void StaticBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) {
- StaticBody2D *body = (StaticBody2D *)p_instance;
+void AnimatableBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) {
+ AnimatableBody2D *body = (AnimatableBody2D *)p_instance;
body->_body_state_changed(p_state);
}
-void StaticBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
+void AnimatableBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
if (!sync_to_physics) {
return;
}
@@ -275,17 +277,7 @@ void StaticBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
set_notify_local_transform(true);
}
-TypedArray<String> StaticBody2D::get_configuration_warnings() const {
- TypedArray<String> warnings = PhysicsBody2D::get_configuration_warnings();
-
- if (sync_to_physics && !kinematic_motion) {
- warnings.push_back(TTR("Sync to physics works only when kinematic motion is enabled."));
- }
-
- return warnings;
-}
-
-void StaticBody2D::_notification(int p_what) {
+void AnimatableBody2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
last_valid_transform = get_global_transform();
@@ -295,10 +287,6 @@ void StaticBody2D::_notification(int p_what) {
// Used by sync to physics, send the new transform to the physics...
Transform2D new_transform = get_global_transform();
- double delta_time = get_physics_process_delta_time();
- new_transform.translate(constant_linear_velocity * delta_time);
- new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time);
-
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
// ... but then revert changes.
@@ -306,98 +294,19 @@ void StaticBody2D::_notification(int p_what) {
set_global_transform(last_valid_transform);
set_notify_local_transform(true);
} break;
-
- case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
-#endif
-
- ERR_FAIL_COND(!kinematic_motion);
-
- Transform2D new_transform = get_global_transform();
-
- double delta_time = get_physics_process_delta_time();
- new_transform.translate(constant_linear_velocity * delta_time);
- new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time);
-
- if (sync_to_physics) {
- // Propagate transform change to node.
- set_global_transform(new_transform);
- } else {
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
-
- // Propagate transform change to node.
- set_block_transform_notify(true);
- set_global_transform(new_transform);
- set_block_transform_notify(false);
- }
- } break;
}
}
-void StaticBody2D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody2D::set_constant_linear_velocity);
- ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody2D::set_constant_angular_velocity);
- ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody2D::get_constant_linear_velocity);
- ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody2D::get_constant_angular_velocity);
-
- ClassDB::bind_method(D_METHOD("set_kinematic_motion_enabled", "enabled"), &StaticBody2D::set_kinematic_motion_enabled);
- ClassDB::bind_method(D_METHOD("is_kinematic_motion_enabled"), &StaticBody2D::is_kinematic_motion_enabled);
-
- ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override);
- ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override);
-
- ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &StaticBody2D::set_sync_to_physics);
- ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &StaticBody2D::is_sync_to_physics_enabled);
+void AnimatableBody2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &AnimatableBody2D::set_sync_to_physics);
+ ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &AnimatableBody2D::is_sync_to_physics_enabled);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "kinematic_motion"), "set_kinematic_motion_enabled", "is_kinematic_motion_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
}
-StaticBody2D::StaticBody2D() :
- PhysicsBody2D(PhysicsServer2D::BODY_MODE_STATIC) {
-}
-
-void StaticBody2D::_reload_physics_characteristics() {
- if (physics_material_override.is_null()) {
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1);
- } else {
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
- }
-}
-
-void StaticBody2D::_update_kinematic_motion() {
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
-#endif
-
- if (kinematic_motion && sync_to_physics) {
- PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
- set_only_update_transform_changes(true);
- set_notify_local_transform(true);
- } else {
- PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), nullptr, nullptr);
- set_only_update_transform_changes(false);
- set_notify_local_transform(false);
- }
-
- bool needs_physics_process = false;
- if (kinematic_motion) {
- if (!Math::is_zero_approx(constant_angular_velocity) || !constant_linear_velocity.is_equal_approx(Vector2())) {
- needs_physics_process = true;
- }
- }
-
- set_physics_process_internal(needs_physics_process);
+AnimatableBody2D::AnimatableBody2D() :
+ StaticBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) {
+ _update_kinematic_motion();
}
void RigidBody2D::_body_enter_tree(ObjectID p_id) {
@@ -651,11 +560,53 @@ real_t RigidBody2D::get_mass() const {
void RigidBody2D::set_inertia(real_t p_inertia) {
ERR_FAIL_COND(p_inertia < 0);
- PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, p_inertia);
+ inertia = p_inertia;
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia);
}
real_t RigidBody2D::get_inertia() const {
- return PhysicsServer2D::get_singleton()->body_get_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA);
+ return inertia;
+}
+
+void RigidBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) {
+ if (center_of_mass_mode == p_mode) {
+ return;
+ }
+
+ center_of_mass_mode = p_mode;
+
+ switch (center_of_mass_mode) {
+ case CENTER_OF_MASS_MODE_AUTO: {
+ center_of_mass = Vector2();
+ PhysicsServer2D::get_singleton()->body_reset_mass_properties(get_rid());
+ if (inertia != 0.0) {
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia);
+ }
+ } break;
+
+ case CENTER_OF_MASS_MODE_CUSTOM: {
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
+ } break;
+ }
+}
+
+RigidBody2D::CenterOfMassMode RigidBody2D::get_center_of_mass_mode() const {
+ return center_of_mass_mode;
+}
+
+void RigidBody2D::set_center_of_mass(const Vector2 &p_center_of_mass) {
+ if (center_of_mass == p_center_of_mass) {
+ return;
+ }
+
+ ERR_FAIL_COND(center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM);
+ center_of_mass = p_center_of_mass;
+
+ PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
+}
+
+const Vector2 &RigidBody2D::get_center_of_mass() const {
+ return center_of_mass;
}
void RigidBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
@@ -909,6 +860,12 @@ void RigidBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody2D::get_inertia);
ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody2D::set_inertia);
+ ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody2D::set_center_of_mass_mode);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody2D::get_center_of_mass_mode);
+
+ ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody2D::set_center_of_mass);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody2D::get_center_of_mass);
+
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody2D::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody2D::get_physics_material_override);
@@ -965,8 +922,11 @@ void RigidBody2D::_bind_methods() {
GDVIRTUAL_BIND(_integrate_forces, "state");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Dynamic,Static,DynamicLocked,Kinematic"), "set_mode", "get_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,65535,0.01,exp"), "set_mass", "get_mass");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inertia", PROPERTY_HINT_RANGE, "0.01,65535,0.01,exp", PROPERTY_USAGE_NONE), "set_inertia", "get_inertia");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inertia", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater,exp"), "set_inertia", "get_inertia");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_center_of_mass_mode", "get_center_of_mass_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass", PROPERTY_HINT_RANGE, "-10,10,0.01,or_lesser,or_greater"), "set_center_of_mass", "get_center_of_mass");
+ ADD_LINKED_PROPERTY("center_of_mass_mode", "center_of_mass");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
@@ -996,11 +956,22 @@ void RigidBody2D::_bind_methods() {
BIND_ENUM_CONSTANT(MODE_DYNAMIC_LOCKED);
BIND_ENUM_CONSTANT(MODE_KINEMATIC);
+ BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_AUTO);
+ BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_CUSTOM);
+
BIND_ENUM_CONSTANT(CCD_MODE_DISABLED);
BIND_ENUM_CONSTANT(CCD_MODE_CAST_RAY);
BIND_ENUM_CONSTANT(CCD_MODE_CAST_SHAPE);
}
+void RigidBody2D::_validate_property(PropertyInfo &property) const {
+ if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) {
+ if (property.name == "center_of_mass") {
+ property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+ }
+ }
+}
+
RigidBody2D::RigidBody2D() :
PhysicsBody2D(PhysicsServer2D::BODY_MODE_DYNAMIC) {
PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 1bf53ea53c..1d6437a3ad 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -63,21 +63,13 @@ public:
class StaticBody2D : public PhysicsBody2D {
GDCLASS(StaticBody2D, PhysicsBody2D);
+private:
Vector2 constant_linear_velocity;
real_t constant_angular_velocity = 0.0;
Ref<PhysicsMaterial> physics_material_override;
- bool kinematic_motion = false;
- bool sync_to_physics = false;
-
- Transform2D last_valid_transform;
-
- static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state);
- void _body_state_changed(PhysicsDirectBodyState2D *p_state);
-
protected:
- void _notification(int p_what);
static void _bind_methods();
public:
@@ -90,17 +82,32 @@ public:
Vector2 get_constant_linear_velocity() const;
real_t get_constant_angular_velocity() const;
- virtual TypedArray<String> get_configuration_warnings() const override;
-
- StaticBody2D();
+ StaticBody2D(PhysicsServer2D::BodyMode p_mode = PhysicsServer2D::BODY_MODE_STATIC);
private:
void _reload_physics_characteristics();
+};
- void _update_kinematic_motion();
+class AnimatableBody2D : public StaticBody2D {
+ GDCLASS(AnimatableBody2D, StaticBody2D);
+
+private:
+ bool sync_to_physics = false;
+
+ Transform2D last_valid_transform;
- void set_kinematic_motion_enabled(bool p_enabled);
- bool is_kinematic_motion_enabled() const;
+ static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state);
+ void _body_state_changed(PhysicsDirectBodyState2D *p_state);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ AnimatableBody2D();
+
+private:
+ void _update_kinematic_motion();
void set_sync_to_physics(bool p_enable);
bool is_sync_to_physics_enabled() const;
@@ -117,6 +124,11 @@ public:
MODE_KINEMATIC,
};
+ enum CenterOfMassMode {
+ CENTER_OF_MASS_MODE_AUTO,
+ CENTER_OF_MASS_MODE_CUSTOM,
+ };
+
enum CCDMode {
CCD_MODE_DISABLED,
CCD_MODE_CAST_RAY,
@@ -128,6 +140,10 @@ private:
Mode mode = MODE_DYNAMIC;
real_t mass = 1.0;
+ real_t inertia = 0.0;
+ CenterOfMassMode center_of_mass_mode = CENTER_OF_MASS_MODE_AUTO;
+ Vector2 center_of_mass;
+
Ref<PhysicsMaterial> physics_material_override;
real_t gravity_scale = 1.0;
real_t linear_damp = -1.0;
@@ -191,6 +207,8 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual void _validate_property(PropertyInfo &property) const override;
+
GDVIRTUAL1(_integrate_forces, PhysicsDirectBodyState2D *)
public:
@@ -203,6 +221,12 @@ public:
void set_inertia(real_t p_inertia);
real_t get_inertia() const;
+ void set_center_of_mass_mode(CenterOfMassMode p_mode);
+ CenterOfMassMode get_center_of_mass_mode() const;
+
+ void set_center_of_mass(const Vector2 &p_center_of_mass);
+ const Vector2 &get_center_of_mass() const;
+
void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
Ref<PhysicsMaterial> get_physics_material_override() const;
@@ -267,6 +291,7 @@ private:
};
VARIANT_ENUM_CAST(RigidBody2D::Mode);
+VARIANT_ENUM_CAST(RigidBody2D::CenterOfMassMode);
VARIANT_ENUM_CAST(RigidBody2D::CCDMode);
class CharacterBody2D : public PhysicsBody2D {
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 13f1d258a8..e1552b3b60 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -314,16 +314,38 @@ int TileMap::get_quadrant_size() const {
return quadrant_size;
}
-void TileMap::set_layers_count(int p_layers_count) {
- ERR_FAIL_COND(p_layers_count < 0);
- _clear_internals();
+int TileMap::get_layers_count() const {
+ return layers.size();
+}
- layers.resize(p_layers_count);
+void TileMap::add_layer(int p_to_pos) {
+ if (p_to_pos < 0) {
+ p_to_pos = layers.size();
+ }
+
+ ERR_FAIL_INDEX(p_to_pos, (int)layers.size() + 1);
+
+ layers.insert(p_to_pos, TileMapLayer());
_recreate_internals();
notify_property_list_changed();
- if (selected_layer >= p_layers_count) {
- selected_layer = -1;
+ emit_signal(SNAME("changed"));
+
+ update_configuration_warnings();
+}
+
+void TileMap::move_layer(int p_layer, int p_to_pos) {
+ ERR_FAIL_INDEX(p_layer, (int)layers.size());
+ ERR_FAIL_INDEX(p_to_pos, (int)layers.size() + 1);
+
+ TileMapLayer tl = layers[p_layer];
+ layers.insert(p_to_pos, tl);
+ layers.remove(p_to_pos < p_layer ? p_layer + 1 : p_layer);
+ _recreate_internals();
+ notify_property_list_changed();
+
+ if (selected_layer == p_layer) {
+ selected_layer = p_to_pos < p_layer ? p_to_pos - 1 : p_to_pos;
}
emit_signal(SNAME("changed"));
@@ -331,8 +353,20 @@ void TileMap::set_layers_count(int p_layers_count) {
update_configuration_warnings();
}
-int TileMap::get_layers_count() const {
- return layers.size();
+void TileMap::remove_layer(int p_layer) {
+ ERR_FAIL_INDEX(p_layer, (int)layers.size());
+
+ layers.remove(p_layer);
+ _recreate_internals();
+ notify_property_list_changed();
+
+ if (selected_layer >= p_layer) {
+ selected_layer -= 1;
+ }
+
+ emit_signal(SNAME("changed"));
+
+ update_configuration_warnings();
}
void TileMap::set_layer_name(int p_layer, String p_name) {
@@ -1147,7 +1181,7 @@ void TileMap::_physics_create_quadrant(TileMapQuadrant *p_quadrant) {
PhysicsServer2D::get_singleton()->body_set_space(body, space);
Transform2D xform;
- xform.set_origin(map_to_world(p_quadrant->coords * get_effective_quadrant_size(layer)));
+ xform.set_origin(map_to_world(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)));
xform = global_transform * xform;
PhysicsServer2D::get_singleton()->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
}
@@ -2896,8 +2930,10 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_quadrant_size", "size"), &TileMap::set_quadrant_size);
ClassDB::bind_method(D_METHOD("get_quadrant_size"), &TileMap::get_quadrant_size);
- ClassDB::bind_method(D_METHOD("set_layers_count", "layers_count"), &TileMap::set_layers_count);
ClassDB::bind_method(D_METHOD("get_layers_count"), &TileMap::get_layers_count);
+ ClassDB::bind_method(D_METHOD("add_layer"), &TileMap::add_layer);
+ ClassDB::bind_method(D_METHOD("move_layer"), &TileMap::move_layer);
+ ClassDB::bind_method(D_METHOD("remove_layer"), &TileMap::remove_layer);
ClassDB::bind_method(D_METHOD("set_layer_name", "layer", "name"), &TileMap::set_layer_name);
ClassDB::bind_method(D_METHOD("get_layer_name", "layer"), &TileMap::get_layer_name);
ClassDB::bind_method(D_METHOD("set_layer_enabled", "layer", "enabled"), &TileMap::set_layer_enabled);
@@ -2942,9 +2978,7 @@ void TileMap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_collision_visibility_mode", "get_collision_visibility_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_navigation_visibility_mode", "get_navigation_visibility_mode");
- ADD_GROUP("Layers", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "layers_count"), "set_layers_count", "get_layers_count");
- ADD_PROPERTY_DEFAULT("layers_count", 1);
+ ADD_ARRAY("layers", "layer_");
ADD_PROPERTY_DEFAULT("format", FORMAT_1);
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 4e2d76a7b7..3ac50fc7cc 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -308,8 +308,10 @@ public:
static void draw_tile(RID p_canvas_item, Vector2i p_position, const Ref<TileSet> p_tile_set, int p_atlas_source_id, Vector2i p_atlas_coords, int p_alternative_tile, Color p_modulation = Color(1.0, 1.0, 1.0, 1.0));
// Layers management.
- void set_layers_count(int p_layers_count);
int get_layers_count() const;
+ void add_layer(int p_to_pos);
+ void move_layer(int p_layer, int p_to_pos);
+ void remove_layer(int p_layer);
void set_layer_name(int p_layer, String p_name);
String get_layer_name(int p_layer) const;
void set_layer_enabled(int p_layer, bool p_visible);
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 0356994cdb..00c6664e65 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -223,72 +223,98 @@ Ref<PhysicsMaterial> StaticBody3D::get_physics_material_override() const {
return physics_material_override;
}
-void StaticBody3D::set_kinematic_motion_enabled(bool p_enabled) {
- if (p_enabled == kinematic_motion) {
- return;
- }
+void StaticBody3D::set_constant_linear_velocity(const Vector3 &p_vel) {
+ constant_linear_velocity = p_vel;
- kinematic_motion = p_enabled;
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
+}
- if (kinematic_motion) {
- set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
- } else {
- set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
- }
+void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) {
+ constant_angular_velocity = p_vel;
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- update_configuration_warnings();
- return;
- }
-#endif
+ PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
+}
- _update_kinematic_motion();
+Vector3 StaticBody3D::get_constant_linear_velocity() const {
+ return constant_linear_velocity;
}
-bool StaticBody3D::is_kinematic_motion_enabled() const {
- return kinematic_motion;
+Vector3 StaticBody3D::get_constant_angular_velocity() const {
+ return constant_angular_velocity;
}
-void StaticBody3D::set_constant_linear_velocity(const Vector3 &p_vel) {
- constant_linear_velocity = p_vel;
+void StaticBody3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody3D::set_constant_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody3D::get_constant_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody3D::get_constant_angular_velocity);
+
+ ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody3D::set_physics_material_override);
+ ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody3D::get_physics_material_override);
+
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
+}
+
+StaticBody3D::StaticBody3D(PhysicsServer3D::BodyMode p_mode) :
+ PhysicsBody3D(p_mode) {
+}
- if (kinematic_motion) {
- _update_kinematic_motion();
+void StaticBody3D::_reload_physics_characteristics() {
+ if (physics_material_override.is_null()) {
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0);
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1);
} else {
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
}
}
-void StaticBody3D::set_sync_to_physics(bool p_enable) {
+Vector3 AnimatableBody3D::get_linear_velocity() const {
+ return linear_velocity;
+}
+
+Vector3 AnimatableBody3D::get_angular_velocity() const {
+ return angular_velocity;
+}
+
+void AnimatableBody3D::set_sync_to_physics(bool p_enable) {
if (sync_to_physics == p_enable) {
return;
}
sync_to_physics = p_enable;
+ _update_kinematic_motion();
+}
+
+bool AnimatableBody3D::is_sync_to_physics_enabled() const {
+ return sync_to_physics;
+}
+
+void AnimatableBody3D::_update_kinematic_motion() {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- update_configuration_warnings();
return;
}
#endif
- if (kinematic_motion) {
- _update_kinematic_motion();
+ if (sync_to_physics) {
+ set_only_update_transform_changes(true);
+ set_notify_local_transform(true);
+ } else {
+ set_only_update_transform_changes(false);
+ set_notify_local_transform(false);
}
}
-bool StaticBody3D::is_sync_to_physics_enabled() const {
- return sync_to_physics;
-}
-
-void StaticBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) {
- StaticBody3D *body = (StaticBody3D *)p_instance;
+void AnimatableBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) {
+ AnimatableBody3D *body = (AnimatableBody3D *)p_instance;
body->_body_state_changed(p_state);
}
-void StaticBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
+void AnimatableBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
linear_velocity = p_state->get_linear_velocity();
angular_velocity = p_state->get_angular_velocity();
@@ -303,43 +329,7 @@ void StaticBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) {
_on_transform_changed();
}
-TypedArray<String> StaticBody3D::get_configuration_warnings() const {
- TypedArray<String> warnings = PhysicsBody3D::get_configuration_warnings();
-
- if (sync_to_physics && !kinematic_motion) {
- warnings.push_back(TTR("Sync to physics works only when kinematic motion is enabled."));
- }
-
- return warnings;
-}
-
-void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) {
- constant_angular_velocity = p_vel;
-
- if (kinematic_motion) {
- _update_kinematic_motion();
- } else {
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
- }
-}
-
-Vector3 StaticBody3D::get_constant_linear_velocity() const {
- return constant_linear_velocity;
-}
-
-Vector3 StaticBody3D::get_constant_angular_velocity() const {
- return constant_angular_velocity;
-}
-
-Vector3 StaticBody3D::get_linear_velocity() const {
- return linear_velocity;
-}
-
-Vector3 StaticBody3D::get_angular_velocity() const {
- return angular_velocity;
-}
-
-void StaticBody3D::_notification(int p_what) {
+void AnimatableBody3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
last_valid_transform = get_global_transform();
@@ -349,17 +339,6 @@ void StaticBody3D::_notification(int p_what) {
// Used by sync to physics, send the new transform to the physics...
Transform3D new_transform = get_global_transform();
- double delta_time = get_physics_process_delta_time();
- new_transform.origin += constant_linear_velocity * delta_time;
-
- real_t ang_vel = constant_angular_velocity.length();
- if (!Math::is_zero_approx(ang_vel)) {
- Vector3 ang_vel_axis = constant_angular_velocity / ang_vel;
- Basis rot(ang_vel_axis, ang_vel * delta_time);
- new_transform.basis = rot * new_transform.basis;
- new_transform.orthonormalize();
- }
-
PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
// ... but then revert changes.
@@ -368,108 +347,21 @@ void StaticBody3D::_notification(int p_what) {
set_notify_local_transform(true);
_on_transform_changed();
} break;
-
- case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
-#endif
-
- ERR_FAIL_COND(!kinematic_motion);
-
- Transform3D new_transform = get_global_transform();
-
- double delta_time = get_physics_process_delta_time();
- new_transform.origin += constant_linear_velocity * delta_time;
-
- real_t ang_vel = constant_angular_velocity.length();
- if (!Math::is_zero_approx(ang_vel)) {
- Vector3 ang_vel_axis = constant_angular_velocity / ang_vel;
- Basis rot(ang_vel_axis, ang_vel * delta_time);
- new_transform.basis = rot * new_transform.basis;
- new_transform.orthonormalize();
- }
-
- if (sync_to_physics) {
- // Propagate transform change to node.
- set_global_transform(new_transform);
- } else {
- PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_TRANSFORM, new_transform);
-
- // Propagate transform change to node.
- set_ignore_transform_notification(true);
- set_global_transform(new_transform);
- set_ignore_transform_notification(false);
- _on_transform_changed();
- }
- } break;
}
}
-void StaticBody3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity);
- ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody3D::set_constant_angular_velocity);
- ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody3D::get_constant_linear_velocity);
- ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody3D::get_constant_angular_velocity);
-
- ClassDB::bind_method(D_METHOD("set_kinematic_motion_enabled", "enabled"), &StaticBody3D::set_kinematic_motion_enabled);
- ClassDB::bind_method(D_METHOD("is_kinematic_motion_enabled"), &StaticBody3D::is_kinematic_motion_enabled);
-
- ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody3D::set_physics_material_override);
- ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody3D::get_physics_material_override);
-
- ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &StaticBody3D::set_sync_to_physics);
- ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &StaticBody3D::is_sync_to_physics_enabled);
+void AnimatableBody3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &AnimatableBody3D::set_sync_to_physics);
+ ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &AnimatableBody3D::is_sync_to_physics_enabled);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "kinematic_motion"), "set_kinematic_motion_enabled", "is_kinematic_motion_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
}
-StaticBody3D::StaticBody3D() :
- PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC) {
-}
-
-void StaticBody3D::_reload_physics_characteristics() {
- if (physics_material_override.is_null()) {
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0);
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1);
- } else {
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
- PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
- }
-}
-
-void StaticBody3D::_update_kinematic_motion() {
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
-#endif
+AnimatableBody3D::AnimatableBody3D() :
+ StaticBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) {
+ PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
- if (kinematic_motion && sync_to_physics) {
- set_only_update_transform_changes(true);
- set_notify_local_transform(true);
- } else {
- set_only_update_transform_changes(false);
- set_notify_local_transform(false);
- }
-
- bool needs_physics_process = false;
- if (kinematic_motion) {
- PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, &StaticBody3D::_body_state_changed_callback);
-
- if (!constant_angular_velocity.is_equal_approx(Vector3()) || !constant_linear_velocity.is_equal_approx(Vector3())) {
- needs_physics_process = true;
- }
- } else {
- PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), nullptr, nullptr);
- }
-
- set_physics_process_internal(needs_physics_process);
+ _update_kinematic_motion();
}
void RigidBody3D::_body_enter_tree(ObjectID p_id) {
@@ -739,6 +631,60 @@ real_t RigidBody3D::get_mass() const {
return mass;
}
+void RigidBody3D::set_inertia(const Vector3 &p_inertia) {
+ ERR_FAIL_COND(p_inertia.x < 0);
+ ERR_FAIL_COND(p_inertia.y < 0);
+ ERR_FAIL_COND(p_inertia.z < 0);
+
+ inertia = p_inertia;
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_INERTIA, inertia);
+}
+
+const Vector3 &RigidBody3D::get_inertia() const {
+ return inertia;
+}
+
+void RigidBody3D::set_center_of_mass_mode(CenterOfMassMode p_mode) {
+ if (center_of_mass_mode == p_mode) {
+ return;
+ }
+
+ center_of_mass_mode = p_mode;
+
+ switch (center_of_mass_mode) {
+ case CENTER_OF_MASS_MODE_AUTO: {
+ center_of_mass = Vector3();
+ PhysicsServer3D::get_singleton()->body_reset_mass_properties(get_rid());
+ if (inertia != Vector3()) {
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_INERTIA, inertia);
+ }
+ } break;
+
+ case CENTER_OF_MASS_MODE_CUSTOM: {
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
+ } break;
+ }
+}
+
+RigidBody3D::CenterOfMassMode RigidBody3D::get_center_of_mass_mode() const {
+ return center_of_mass_mode;
+}
+
+void RigidBody3D::set_center_of_mass(const Vector3 &p_center_of_mass) {
+ if (center_of_mass == p_center_of_mass) {
+ return;
+ }
+
+ ERR_FAIL_COND(center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM);
+ center_of_mass = p_center_of_mass;
+
+ PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS, center_of_mass);
+}
+
+const Vector3 &RigidBody3D::get_center_of_mass() const {
+ return center_of_mass;
+}
+
void RigidBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
if (physics_material_override.is_valid()) {
if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody3D::_reload_physics_characteristics))) {
@@ -959,6 +905,15 @@ void RigidBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody3D::set_mass);
ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody3D::get_mass);
+ ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody3D::set_inertia);
+ ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody3D::get_inertia);
+
+ ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody3D::set_center_of_mass_mode);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody3D::get_center_of_mass_mode);
+
+ ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody3D::set_center_of_mass);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody3D::get_center_of_mass);
+
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody3D::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody3D::get_physics_material_override);
@@ -1012,7 +967,11 @@ void RigidBody3D::_bind_methods() {
GDVIRTUAL_BIND(_integrate_forces, "state");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Dynamic,Static,DynamicLocked,Kinematic"), "set_mode", "get_mode");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,65535,0.01,exp"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "inertia", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater,exp"), "set_inertia", "get_inertia");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "center_of_mass_mode", PROPERTY_HINT_ENUM, "Auto,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_center_of_mass_mode", "get_center_of_mass_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass", PROPERTY_HINT_RANGE, "-10,10,0.01,or_lesser,or_greater"), "set_center_of_mass", "get_center_of_mass");
+ ADD_LINKED_PROPERTY("center_of_mass_mode", "center_of_mass");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
@@ -1038,11 +997,22 @@ void RigidBody3D::_bind_methods() {
BIND_ENUM_CONSTANT(MODE_STATIC);
BIND_ENUM_CONSTANT(MODE_DYNAMIC_LOCKED);
BIND_ENUM_CONSTANT(MODE_KINEMATIC);
+
+ BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_AUTO);
+ BIND_ENUM_CONSTANT(CENTER_OF_MASS_MODE_CUSTOM);
+}
+
+void RigidBody3D::_validate_property(PropertyInfo &property) const {
+ if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) {
+ if (property.name == "center_of_mass") {
+ property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+ }
+ }
}
RigidBody3D::RigidBody3D() :
PhysicsBody3D(PhysicsServer3D::BODY_MODE_DYNAMIC) {
- PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, &RigidBody3D::_body_state_changed_callback);
+ PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
}
RigidBody3D::~RigidBody3D() {
@@ -2315,7 +2285,7 @@ void PhysicalBone3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "body_offset"), "set_body_offset", "get_body_offset");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,65535,0.01,exp"), "set_mass", "get_mass");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_RANGE, "0.01,1000,0.01,or_greater,exp"), "set_mass", "get_mass");
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");
@@ -2713,7 +2683,7 @@ void PhysicalBone3D::_start_physics_simulation() {
set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC);
PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
- PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, &PhysicalBone3D::_body_state_changed_callback);
+ PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
set_as_top_level(true);
_internal_simulate_physics = true;
}
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 8c09f77846..8e6463f838 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -73,24 +73,13 @@ public:
class StaticBody3D : public PhysicsBody3D {
GDCLASS(StaticBody3D, PhysicsBody3D);
+private:
Vector3 constant_linear_velocity;
Vector3 constant_angular_velocity;
- Vector3 linear_velocity;
- Vector3 angular_velocity;
-
Ref<PhysicsMaterial> physics_material_override;
- bool kinematic_motion = false;
- bool sync_to_physics = false;
-
- Transform3D last_valid_transform;
-
- static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state);
- void _body_state_changed(PhysicsDirectBodyState3D *p_state);
-
protected:
- void _notification(int p_what);
static void _bind_methods();
public:
@@ -103,20 +92,38 @@ public:
Vector3 get_constant_linear_velocity() const;
Vector3 get_constant_angular_velocity() const;
- virtual Vector3 get_linear_velocity() const override;
- virtual Vector3 get_angular_velocity() const override;
+ StaticBody3D(PhysicsServer3D::BodyMode p_mode = PhysicsServer3D::BODY_MODE_STATIC);
- virtual TypedArray<String> get_configuration_warnings() const override;
+private:
+ void _reload_physics_characteristics();
+};
- StaticBody3D();
+class AnimatableBody3D : public StaticBody3D {
+ GDCLASS(AnimatableBody3D, StaticBody3D);
private:
- void _reload_physics_characteristics();
+ Vector3 linear_velocity;
+ Vector3 angular_velocity;
- void _update_kinematic_motion();
+ bool sync_to_physics = false;
- void set_kinematic_motion_enabled(bool p_enabled);
- bool is_kinematic_motion_enabled() const;
+ Transform3D last_valid_transform;
+
+ static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state);
+ void _body_state_changed(PhysicsDirectBodyState3D *p_state);
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ virtual Vector3 get_linear_velocity() const override;
+ virtual Vector3 get_angular_velocity() const override;
+
+ AnimatableBody3D();
+
+private:
+ void _update_kinematic_motion();
void set_sync_to_physics(bool p_enable);
bool is_sync_to_physics_enabled() const;
@@ -133,6 +140,11 @@ public:
MODE_KINEMATIC,
};
+ enum CenterOfMassMode {
+ CENTER_OF_MASS_MODE_AUTO,
+ CENTER_OF_MASS_MODE_CUSTOM,
+ };
+
GDVIRTUAL1(_integrate_forces, PhysicsDirectBodyState3D *)
protected:
@@ -140,6 +152,10 @@ protected:
Mode mode = MODE_DYNAMIC;
real_t mass = 1.0;
+ Vector3 inertia;
+ CenterOfMassMode center_of_mass_mode = CENTER_OF_MASS_MODE_AUTO;
+ Vector3 center_of_mass;
+
Ref<PhysicsMaterial> physics_material_override;
Vector3 linear_velocity;
@@ -203,6 +219,8 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual void _validate_property(PropertyInfo &property) const override;
+
public:
void set_mode(Mode p_mode);
Mode get_mode() const;
@@ -212,6 +230,15 @@ public:
virtual real_t get_inverse_mass() const override { return 1.0 / mass; }
+ void set_inertia(const Vector3 &p_inertia);
+ const Vector3 &get_inertia() const;
+
+ void set_center_of_mass_mode(CenterOfMassMode p_mode);
+ CenterOfMassMode get_center_of_mass_mode() const;
+
+ void set_center_of_mass(const Vector3 &p_center_of_mass);
+ const Vector3 &get_center_of_mass() const;
+
void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override);
Ref<PhysicsMaterial> get_physics_material_override() const;
@@ -272,6 +299,7 @@ private:
};
VARIANT_ENUM_CAST(RigidBody3D::Mode);
+VARIANT_ENUM_CAST(RigidBody3D::CenterOfMassMode);
class KinematicCollision3D;
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index d93107df2d..411fb2e1f0 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -34,11 +34,13 @@
Size2 CheckBox::get_icon_size() const {
Ref<Texture2D> checked = Control::get_theme_icon(SNAME("checked"));
- Ref<Texture2D> checked_disabled = Control::get_theme_icon(SNAME("checked_disabled"));
Ref<Texture2D> unchecked = Control::get_theme_icon(SNAME("unchecked"));
- Ref<Texture2D> unchecked_disabled = Control::get_theme_icon(SNAME("unchecked_disabled"));
Ref<Texture2D> radio_checked = Control::get_theme_icon(SNAME("radio_checked"));
Ref<Texture2D> radio_unchecked = Control::get_theme_icon(SNAME("radio_unchecked"));
+ Ref<Texture2D> checked_disabled = Control::get_theme_icon(SNAME("checked_disabled"));
+ Ref<Texture2D> unchecked_disabled = Control::get_theme_icon(SNAME("unchecked_disabled"));
+ Ref<Texture2D> radio_checked_disabled = Control::get_theme_icon(SNAME("radio_checked_disabled"));
+ Ref<Texture2D> radio_unchecked_disabled = Control::get_theme_icon(SNAME("radio_unchecked_disabled"));
Size2 tex_size = Size2(0, 0);
if (!checked.is_null()) {
@@ -53,6 +55,18 @@ Size2 CheckBox::get_icon_size() const {
if (!radio_unchecked.is_null()) {
tex_size = Size2(MAX(tex_size.width, radio_unchecked->get_width()), MAX(tex_size.height, radio_unchecked->get_height()));
}
+ if (!checked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, checked_disabled->get_width()), MAX(tex_size.height, checked_disabled->get_height()));
+ }
+ if (!unchecked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, unchecked_disabled->get_width()), MAX(tex_size.height, unchecked_disabled->get_height()));
+ }
+ if (!radio_checked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, radio_checked_disabled->get_width()), MAX(tex_size.height, radio_checked_disabled->get_height()));
+ }
+ if (!radio_unchecked_disabled.is_null()) {
+ tex_size = Size2(MAX(tex_size.width, radio_unchecked_disabled->get_width()), MAX(tex_size.height, radio_unchecked_disabled->get_height()));
+ }
return tex_size;
}
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 7f45a7f529..d05762b6c0 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -1951,7 +1951,7 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
if (pre_brace_pair == -1 && post_brace_pair == -1 && get_caret_column() > 0 && get_caret_column() < get_line(caret_line).length()) {
pre_brace_pair = _get_auto_brace_pair_open_at_pos(caret_line, get_caret_column() + 1);
- if (pre_brace_pair == _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1)) {
+ if (pre_brace_pair != -1 && pre_brace_pair == _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1)) {
remove_text(caret_line, get_caret_column() - 2, caret_line, get_caret_column());
if (_get_auto_brace_pair_close_at_pos(caret_line, get_caret_column() - 1) != pre_brace_pair) {
set_caret_column(get_caret_column() - 1);
@@ -2758,7 +2758,7 @@ void CodeEdit::_filter_code_completion_candidates_impl() {
/* If we have a space, previous word might be a keyword. eg "func |". */
} else if (cofs > 0 && line[cofs - 1] == ' ') {
int ofs = cofs - 1;
- while (ofs >= 0 && line[ofs] == ' ') {
+ while (ofs > 0 && line[ofs] == ' ') {
ofs--;
}
prev_is_word = _is_char(line[ofs]);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 4ac6a58d36..81411d5844 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -30,6 +30,7 @@
#include "control.h"
+#include "container.h"
#include "core/config/project_settings.h"
#include "core/math/geometry_2d.h"
#include "core/object/message_queue.h"
@@ -168,6 +169,20 @@ Size2 Control::_edit_get_minimum_size() const {
}
#endif
+String Control::properties_managed_by_container[] = {
+ "offset_left",
+ "offset_top",
+ "offset_right",
+ "offset_bottom",
+ "anchor_left",
+ "anchor_top",
+ "anchor_right",
+ "anchor_bottom",
+ "rect_position",
+ "rect_scale",
+ "rect_size"
+};
+
void Control::accept_event() {
if (is_inside_tree()) {
get_viewport()->_gui_accept_event();
@@ -442,6 +457,20 @@ void Control::_validate_property(PropertyInfo &property) const {
property.hint_string = hint_string;
}
+ if (!Object::cast_to<Container>(get_parent())) {
+ return;
+ }
+ // Disable the property if it's managed by the parent container.
+ bool property_is_managed_by_container = false;
+ for (unsigned i = 0; i < properties_managed_by_container_count; i++) {
+ property_is_managed_by_container = properties_managed_by_container[i] == property.name;
+ if (property_is_managed_by_container) {
+ break;
+ }
+ }
+ if (property_is_managed_by_container) {
+ property.usage |= PROPERTY_USAGE_READ_ONLY;
+ }
}
Control *Control::get_parent_control() const {
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 0faa617f8d..9cec5d6e8d 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -230,6 +230,9 @@ private:
} data;
+ static constexpr unsigned properties_managed_by_container_count = 11;
+ static String properties_managed_by_container[properties_managed_by_container_count];
+
// used internally
Control *_find_control_at_pos(CanvasItem *p_node, const Point2 &p_pos, const Transform2D &p_xform, Transform2D &r_inv_xform);
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 3605842224..d9acbeb828 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -674,7 +674,7 @@ void LineEdit::_notification(int p_what) {
int y_ofs = style->get_offset().y + (y_area - text_height) / 2;
Color selection_color = get_theme_color(SNAME("selection_color"));
- Color font_color = is_editable() ? get_theme_color(SNAME("font_color")) : get_theme_color(SNAME("font_uneditable_color"));
+ Color font_color = get_theme_color(is_editable() ? SNAME("font_color") : SNAME("font_uneditable_color"));
Color font_selected_color = get_theme_color(SNAME("font_selected_color"));
Color caret_color = get_theme_color(SNAME("caret_color"));
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 845a2ec6c7..137ce7e96f 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -1212,6 +1212,7 @@ void TabContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tab_icon", "tab_idx"), &TabContainer::get_tab_icon);
ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &TabContainer::set_tab_disabled);
ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &TabContainer::get_tab_disabled);
+ ClassDB::bind_method(D_METHOD("get_tab_idx_at_point", "point"), &TabContainer::get_tab_idx_at_point);
ClassDB::bind_method(D_METHOD("set_popup", "popup"), &TabContainer::set_popup);
ClassDB::bind_method(D_METHOD("get_popup"), &TabContainer::get_popup);
ClassDB::bind_method(D_METHOD("set_drag_to_rearrange_enabled", "enabled"), &TabContainer::set_drag_to_rearrange_enabled);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 7e64c13b37..b9e9a4d450 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -557,13 +557,25 @@ void TextEdit::_notification(int p_what) {
}
int minimap_draw_amount = minimap_visible_lines + get_line_wrap_count(minimap_line + 1);
- // draw the minimap
- Color viewport_color = (background_color.get_v() < 0.5) ? Color(1, 1, 1, 0.1) : Color(0, 0, 0, 0.1);
+ // Draw the minimap.
+
+ // Add visual feedback when dragging or hovering the the visible area rectangle.
+ float viewport_alpha;
+ if (dragging_minimap) {
+ viewport_alpha = 0.25;
+ } else if (hovering_minimap) {
+ viewport_alpha = 0.175;
+ } else {
+ viewport_alpha = 0.1;
+ }
+
+ const Color viewport_color = (background_color.get_v() < 0.5) ? Color(1, 1, 1, viewport_alpha) : Color(0, 0, 0, viewport_alpha);
if (rtl) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - (xmargin_end + 2) - minimap_width, viewport_offset_y, minimap_width, viewport_height), viewport_color);
} else {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), viewport_offset_y, minimap_width, viewport_height), viewport_color);
}
+
for (int i = 0; i < minimap_draw_amount; i++) {
minimap_line++;
@@ -1549,6 +1561,10 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
+ if (draw_minimap && !dragging_selection) {
+ _update_minimap_hover();
+ }
+
if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) {
accept_event(); // Accept event if scroll changed.
}
@@ -5644,6 +5660,33 @@ void TextEdit::_scroll_lines_down() {
}
// Minimap
+
+void TextEdit::_update_minimap_hover() {
+ const Point2 mp = get_local_mouse_pos();
+ const int xmargin_end = get_size().width - style_normal->get_margin(SIDE_RIGHT);
+
+ const bool hovering_sidebar = mp.x > xmargin_end - minimap_width && mp.x < xmargin_end;
+ if (!hovering_sidebar) {
+ if (hovering_minimap) {
+ // Only redraw if the hovering status changed.
+ hovering_minimap = false;
+ update();
+ }
+
+ // Return early to avoid running the operations below when not needed.
+ return;
+ }
+
+ const int row = get_minimap_line_at_pos(Point2i(mp.x, mp.y));
+
+ const bool new_hovering_minimap = row >= get_first_visible_line() && row <= get_last_full_visible_line();
+ if (new_hovering_minimap != hovering_minimap) {
+ // Only redraw if the hovering status changed.
+ hovering_minimap = new_hovering_minimap;
+ update();
+ }
+}
+
void TextEdit::_update_minimap_click() {
Point2 mp = get_local_mouse_pos();
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index ced03e19d0..07999c2442 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -446,12 +446,14 @@ private:
// minimap scroll
bool minimap_clicked = false;
+ bool hovering_minimap = false;
bool dragging_minimap = false;
bool can_drag_minimap = false;
double minimap_scroll_ratio = 0.0;
double minimap_scroll_click_pos = 0.0;
+ void _update_minimap_hover();
void _update_minimap_click();
void _update_minimap_drag();
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index f2a2648140..6ffc8475f5 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -123,28 +123,27 @@ void Node::_notification(int p_notification) {
}
} break;
case NOTIFICATION_READY: {
- if (get_script_instance()) {
- if (GDVIRTUAL_IS_OVERRIDDEN(_input)) {
- set_process_input(true);
- }
-
- if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_input)) {
- set_process_unhandled_input(true);
- }
+ if (GDVIRTUAL_IS_OVERRIDDEN(_input)) {
+ set_process_input(true);
+ }
- if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_key_input)) {
- set_process_unhandled_key_input(true);
- }
+ if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_input)) {
+ set_process_unhandled_input(true);
+ }
- if (GDVIRTUAL_IS_OVERRIDDEN(_process)) {
- set_process(true);
- }
- if (GDVIRTUAL_IS_OVERRIDDEN(_physics_process)) {
- set_physics_process(true);
- }
+ if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_key_input)) {
+ set_process_unhandled_key_input(true);
+ }
- GDVIRTUAL_CALL(_ready);
+ if (GDVIRTUAL_IS_OVERRIDDEN(_process)) {
+ set_process(true);
}
+ if (GDVIRTUAL_IS_OVERRIDDEN(_physics_process)) {
+ set_physics_process(true);
+ }
+
+ GDVIRTUAL_CALL(_ready);
+
if (data.filename.length()) {
ERR_FAIL_COND(!is_inside_tree());
get_multiplayer()->scene_enter_exit_notify(data.filename, this, true);
@@ -539,10 +538,10 @@ bool Node::is_network_authority() const {
/***** RPC CONFIG ********/
-uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, MultiplayerPeer::TransferMode p_transfer_mode, int p_channel) {
+uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, Multiplayer::TransferMode p_transfer_mode, int p_channel) {
for (int i = 0; i < data.rpc_methods.size(); i++) {
if (data.rpc_methods[i].name == p_method) {
- MultiplayerAPI::RPCConfig &nd = data.rpc_methods.write[i];
+ Multiplayer::RPCConfig &nd = data.rpc_methods.write[i];
nd.rpc_mode = p_rpc_mode;
nd.transfer_mode = p_transfer_mode;
nd.channel = p_channel;
@@ -550,7 +549,7 @@ uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_
}
}
// New method
- MultiplayerAPI::RPCConfig nd;
+ Multiplayer::RPCConfig nd;
nd.name = p_method;
nd.rpc_mode = p_rpc_mode;
nd.transfer_mode = p_transfer_mode;
@@ -643,7 +642,7 @@ Variant Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::Cal
void Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
ERR_FAIL_COND(!is_inside_tree());
- get_multiplayer()->rpcp(this, p_peer_id, true, p_method, p_arg, p_argcount);
+ get_multiplayer()->rpcp(this, p_peer_id, p_method, p_arg, p_argcount);
}
Ref<MultiplayerAPI> Node::get_multiplayer() const {
@@ -664,7 +663,7 @@ void Node::set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {
multiplayer = p_multiplayer;
}
-Vector<MultiplayerAPI::RPCConfig> Node::get_node_rpc_methods() const {
+Vector<Multiplayer::RPCConfig> Node::get_node_rpc_methods() const {
return data.rpc_methods;
}
@@ -2746,7 +2745,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer);
ClassDB::bind_method(D_METHOD("get_custom_multiplayer"), &Node::get_custom_multiplayer);
ClassDB::bind_method(D_METHOD("set_custom_multiplayer", "api"), &Node::set_custom_multiplayer);
- ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(MultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description);
ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description);
diff --git a/scene/main/node.h b/scene/main/node.h
index d0246ebe84..27d6958140 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -128,7 +128,7 @@ private:
Node *process_owner = nullptr;
int network_authority = 1; // Server by default.
- Vector<MultiplayerAPI::RPCConfig> rpc_methods;
+ Vector<Multiplayer::RPCConfig> rpc_methods;
// Variables used to properly sort the node when processing, ignored otherwise.
// TODO: Should move all the stuff below to bits.
@@ -466,8 +466,8 @@ public:
int get_network_authority() const;
bool is_network_authority() const;
- uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, MultiplayerPeer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC
- Vector<MultiplayerAPI::RPCConfig> get_node_rpc_methods() const;
+ uint16_t rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, Multiplayer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC
+ Vector<Multiplayer::RPCConfig> get_node_rpc_methods() const;
void rpc(const StringName &p_method, VARIANT_ARG_LIST); // RPC, honors RPCMode, TransferMode, channel
void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); // RPC to specific peer(s), honors RPCMode, TransferMode, channel
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index b1b94ae910..19331c1906 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -31,7 +31,7 @@
#ifndef SCENE_TREE_H
#define SCENE_TREE_H
-#include "core/io/multiplayer_api.h"
+#include "core/multiplayer/multiplayer_api.h"
#include "core/os/main_loop.h"
#include "core/os/thread_safe.h"
#include "core/templates/self_list.h"
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 0c97fee711..25c8e3e0b7 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -488,6 +488,7 @@ void register_scene_types() {
GDREGISTER_VIRTUAL_CLASS(CollisionObject3D);
GDREGISTER_VIRTUAL_CLASS(PhysicsBody3D);
GDREGISTER_CLASS(StaticBody3D);
+ GDREGISTER_CLASS(AnimatableBody3D);
GDREGISTER_CLASS(RigidBody3D);
GDREGISTER_CLASS(KinematicCollision3D);
GDREGISTER_CLASS(CharacterBody3D);
@@ -647,6 +648,7 @@ void register_scene_types() {
GDREGISTER_VIRTUAL_CLASS(CollisionObject2D);
GDREGISTER_VIRTUAL_CLASS(PhysicsBody2D);
GDREGISTER_CLASS(StaticBody2D);
+ GDREGISTER_CLASS(AnimatableBody2D);
GDREGISTER_CLASS(RigidBody2D);
GDREGISTER_CLASS(CharacterBody2D);
GDREGISTER_CLASS(KinematicCollision2D);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index fcd31143a8..d383961d87 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -205,25 +205,46 @@ bool TileSet::is_uv_clipping() const {
return uv_clipping;
};
-void TileSet::set_occlusion_layers_count(int p_occlusion_layers_count) {
- ERR_FAIL_COND(p_occlusion_layers_count < 0);
- if (occlusion_layers.size() == p_occlusion_layers_count) {
- return;
- }
+int TileSet::get_occlusion_layers_count() const {
+ return occlusion_layers.size();
+};
- occlusion_layers.resize(p_occlusion_layers_count);
+void TileSet::add_occlusion_layer(int p_index) {
+ if (p_index < 0) {
+ p_index = occlusion_layers.size();
+ }
+ ERR_FAIL_INDEX(p_index, occlusion_layers.size() + 1);
+ occlusion_layers.insert(p_index, OcclusionLayer());
- for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
- E_source->get()->notify_tile_data_properties_should_change();
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->add_occlusion_layer(p_index);
}
notify_property_list_changed();
emit_changed();
}
-int TileSet::get_occlusion_layers_count() const {
- return occlusion_layers.size();
-};
+void TileSet::move_occlusion_layer(int p_from_index, int p_to_pos) {
+ ERR_FAIL_INDEX(p_from_index, occlusion_layers.size());
+ ERR_FAIL_INDEX(p_to_pos, occlusion_layers.size() + 1);
+ occlusion_layers.insert(p_to_pos, occlusion_layers[p_from_index]);
+ occlusion_layers.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->move_occlusion_layer(p_from_index, p_to_pos);
+ }
+ notify_property_list_changed();
+ emit_changed();
+}
+
+void TileSet::remove_occlusion_layer(int p_index) {
+ ERR_FAIL_INDEX(p_index, occlusion_layers.size());
+ occlusion_layers.remove(p_index);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->remove_occlusion_layer(p_index);
+ }
+ notify_property_list_changed();
+ emit_changed();
+}
void TileSet::set_occlusion_layer_light_mask(int p_layer_index, int p_light_mask) {
ERR_FAIL_INDEX(p_layer_index, occlusion_layers.size());
@@ -247,25 +268,45 @@ bool TileSet::get_occlusion_layer_sdf_collision(int p_layer_index) const {
return occlusion_layers[p_layer_index].sdf_collision;
}
-// Physics
-void TileSet::set_physics_layers_count(int p_physics_layers_count) {
- ERR_FAIL_COND(p_physics_layers_count < 0);
- if (physics_layers.size() == p_physics_layers_count) {
- return;
- }
+int TileSet::get_physics_layers_count() const {
+ return physics_layers.size();
+}
- physics_layers.resize(p_physics_layers_count);
+void TileSet::add_physics_layer(int p_index) {
+ if (p_index < 0) {
+ p_index = physics_layers.size();
+ }
+ ERR_FAIL_INDEX(p_index, physics_layers.size() + 1);
+ physics_layers.insert(p_index, PhysicsLayer());
- for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
- E_source->get()->notify_tile_data_properties_should_change();
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->add_physics_layer(p_index);
}
notify_property_list_changed();
emit_changed();
}
-int TileSet::get_physics_layers_count() const {
- return physics_layers.size();
+void TileSet::move_physics_layer(int p_from_index, int p_to_pos) {
+ ERR_FAIL_INDEX(p_from_index, physics_layers.size());
+ ERR_FAIL_INDEX(p_to_pos, physics_layers.size() + 1);
+ physics_layers.insert(p_to_pos, physics_layers[p_from_index]);
+ physics_layers.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->move_physics_layer(p_from_index, p_to_pos);
+ }
+ notify_property_list_changed();
+ emit_changed();
+}
+
+void TileSet::remove_physics_layer(int p_index) {
+ ERR_FAIL_INDEX(p_index, physics_layers.size());
+ physics_layers.remove(p_index);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->remove_physics_layer(p_index);
+ }
+ notify_property_list_changed();
+ emit_changed();
}
void TileSet::set_physics_layer_collision_layer(int p_layer_index, uint32_t p_layer) {
@@ -301,17 +342,45 @@ Ref<PhysicsMaterial> TileSet::get_physics_layer_physics_material(int p_layer_ind
}
// Terrains
-void TileSet::set_terrain_sets_count(int p_terrains_sets_count) {
- ERR_FAIL_COND(p_terrains_sets_count < 0);
+int TileSet::get_terrain_sets_count() const {
+ return terrain_sets.size();
+}
+
+void TileSet::add_terrain_set(int p_index) {
+ if (p_index < 0) {
+ p_index = terrain_sets.size();
+ }
+ ERR_FAIL_INDEX(p_index, terrain_sets.size() + 1);
+ terrain_sets.insert(p_index, TerrainSet());
- terrain_sets.resize(p_terrains_sets_count);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->add_terrain_set(p_index);
+ }
notify_property_list_changed();
emit_changed();
}
-int TileSet::get_terrain_sets_count() const {
- return terrain_sets.size();
+void TileSet::move_terrain_set(int p_from_index, int p_to_pos) {
+ ERR_FAIL_INDEX(p_from_index, terrain_sets.size());
+ ERR_FAIL_INDEX(p_to_pos, terrain_sets.size() + 1);
+ terrain_sets.insert(p_to_pos, terrain_sets[p_from_index]);
+ terrain_sets.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->move_terrain_set(p_from_index, p_to_pos);
+ }
+ notify_property_list_changed();
+ emit_changed();
+}
+
+void TileSet::remove_terrain_set(int p_index) {
+ ERR_FAIL_INDEX(p_index, terrain_sets.size());
+ terrain_sets.remove(p_index);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->remove_terrain_set(p_index);
+ }
+ notify_property_list_changed();
+ emit_changed();
}
void TileSet::set_terrain_set_mode(int p_terrain_set, TerrainMode p_terrain_mode) {
@@ -330,36 +399,61 @@ TileSet::TerrainMode TileSet::get_terrain_set_mode(int p_terrain_set) const {
return terrain_sets[p_terrain_set].mode;
}
-void TileSet::set_terrains_count(int p_terrain_set, int p_terrains_layers_count) {
+int TileSet::get_terrains_count(int p_terrain_set) const {
+ ERR_FAIL_INDEX_V(p_terrain_set, terrain_sets.size(), -1);
+ return terrain_sets[p_terrain_set].terrains.size();
+}
+
+void TileSet::add_terrain(int p_terrain_set, int p_index) {
ERR_FAIL_INDEX(p_terrain_set, terrain_sets.size());
- ERR_FAIL_COND(p_terrains_layers_count < 0);
- if (terrain_sets[p_terrain_set].terrains.size() == p_terrains_layers_count) {
- return;
+ Vector<Terrain> &terrains = terrain_sets.write[p_terrain_set].terrains;
+ if (p_index < 0) {
+ p_index = terrains.size();
}
-
- int old_size = terrain_sets[p_terrain_set].terrains.size();
- terrain_sets.write[p_terrain_set].terrains.resize(p_terrains_layers_count);
+ ERR_FAIL_INDEX(p_index, terrains.size() + 1);
+ terrains.insert(p_index, Terrain());
// Default name and color
- for (int i = old_size; i < terrain_sets.write[p_terrain_set].terrains.size(); i++) {
- float hue_rotate = (i * 2 % 16) / 16.0;
- Color c;
- c.set_hsv(Math::fmod(float(hue_rotate), float(1.0)), 0.5, 0.5);
- terrain_sets.write[p_terrain_set].terrains.write[i].color = c;
- terrain_sets.write[p_terrain_set].terrains.write[i].name = String(vformat("Terrain %d", i));
+ float hue_rotate = (terrains.size() % 16) / 16.0;
+ Color c;
+ c.set_hsv(Math::fmod(float(hue_rotate), float(1.0)), 0.5, 0.5);
+ terrains.write[p_index].color = c;
+ terrains.write[p_index].name = String(vformat("Terrain %d", p_index));
+
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->add_terrain(p_terrain_set, p_index);
}
- for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
- E_source->get()->notify_tile_data_properties_should_change();
- }
+ notify_property_list_changed();
+ emit_changed();
+}
+void TileSet::move_terrain(int p_terrain_set, int p_from_index, int p_to_pos) {
+ ERR_FAIL_INDEX(p_terrain_set, terrain_sets.size());
+ Vector<Terrain> &terrains = terrain_sets.write[p_terrain_set].terrains;
+
+ ERR_FAIL_INDEX(p_from_index, terrains.size());
+ ERR_FAIL_INDEX(p_to_pos, terrains.size() + 1);
+ terrains.insert(p_to_pos, terrains[p_from_index]);
+ terrains.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->move_terrain(p_terrain_set, p_from_index, p_to_pos);
+ }
notify_property_list_changed();
emit_changed();
}
-int TileSet::get_terrains_count(int p_terrain_set) const {
- ERR_FAIL_INDEX_V(p_terrain_set, terrain_sets.size(), -1);
- return terrain_sets[p_terrain_set].terrains.size();
+void TileSet::remove_terrain(int p_terrain_set, int p_index) {
+ ERR_FAIL_INDEX(p_terrain_set, terrain_sets.size());
+ Vector<Terrain> &terrains = terrain_sets.write[p_terrain_set].terrains;
+
+ ERR_FAIL_INDEX(p_index, terrains.size());
+ terrains.remove(p_index);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->remove_terrain(p_terrain_set, p_index);
+ }
+ notify_property_list_changed();
+ emit_changed();
}
void TileSet::set_terrain_name(int p_terrain_set, int p_terrain_index, String p_name) {
@@ -485,24 +579,45 @@ bool TileSet::is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeigh
}
// Navigation
-void TileSet::set_navigation_layers_count(int p_navigation_layers_count) {
- ERR_FAIL_COND(p_navigation_layers_count < 0);
- if (navigation_layers.size() == p_navigation_layers_count) {
- return;
- }
+int TileSet::get_navigation_layers_count() const {
+ return navigation_layers.size();
+}
- navigation_layers.resize(p_navigation_layers_count);
+void TileSet::add_navigation_layer(int p_index) {
+ if (p_index < 0) {
+ p_index = navigation_layers.size();
+ }
+ ERR_FAIL_INDEX(p_index, navigation_layers.size() + 1);
+ navigation_layers.insert(p_index, NavigationLayer());
- for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
- E_source->get()->notify_tile_data_properties_should_change();
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->add_navigation_layer(p_index);
}
notify_property_list_changed();
emit_changed();
}
-int TileSet::get_navigation_layers_count() const {
- return navigation_layers.size();
+void TileSet::move_navigation_layer(int p_from_index, int p_to_pos) {
+ ERR_FAIL_INDEX(p_from_index, navigation_layers.size());
+ ERR_FAIL_INDEX(p_to_pos, navigation_layers.size() + 1);
+ navigation_layers.insert(p_to_pos, navigation_layers[p_from_index]);
+ navigation_layers.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->move_navigation_layer(p_from_index, p_to_pos);
+ }
+ notify_property_list_changed();
+ emit_changed();
+}
+
+void TileSet::remove_navigation_layer(int p_index) {
+ ERR_FAIL_INDEX(p_index, navigation_layers.size());
+ navigation_layers.remove(p_index);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->remove_navigation_layer(p_index);
+ }
+ notify_property_list_changed();
+ emit_changed();
}
void TileSet::set_navigation_layer_layers(int p_layer_index, uint32_t p_layers) {
@@ -517,30 +632,52 @@ uint32_t TileSet::get_navigation_layer_layers(int p_layer_index) const {
}
// Custom data.
-void TileSet::set_custom_data_layers_count(int p_custom_data_layers_count) {
- ERR_FAIL_COND(p_custom_data_layers_count < 0);
- if (custom_data_layers.size() == p_custom_data_layers_count) {
- return;
- }
-
- custom_data_layers.resize(p_custom_data_layers_count);
+int TileSet::get_custom_data_layers_count() const {
+ return custom_data_layers.size();
+}
- for (Map<String, int>::Element *E = custom_data_layers_by_name.front(); E; E = E->next()) {
- if (E->get() >= custom_data_layers.size()) {
- custom_data_layers_by_name.erase(E);
- }
+void TileSet::add_custom_data_layer(int p_index) {
+ if (p_index < 0) {
+ p_index = custom_data_layers.size();
}
+ ERR_FAIL_INDEX(p_index, custom_data_layers.size() + 1);
+ custom_data_layers.insert(p_index, CustomDataLayer());
- for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
- E_source->get()->notify_tile_data_properties_should_change();
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->add_custom_data_layer(p_index);
}
notify_property_list_changed();
emit_changed();
}
-int TileSet::get_custom_data_layers_count() const {
- return custom_data_layers.size();
+void TileSet::move_custom_data_layer(int p_from_index, int p_to_pos) {
+ ERR_FAIL_INDEX(p_from_index, custom_data_layers.size());
+ ERR_FAIL_INDEX(p_to_pos, custom_data_layers.size() + 1);
+ custom_data_layers.insert(p_to_pos, custom_data_layers[p_from_index]);
+ custom_data_layers.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index);
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->move_custom_data_layer(p_from_index, p_to_pos);
+ }
+ notify_property_list_changed();
+ emit_changed();
+}
+
+void TileSet::remove_custom_data_layer(int p_index) {
+ ERR_FAIL_INDEX(p_index, custom_data_layers.size());
+ custom_data_layers.remove(p_index);
+ for (KeyValue<String, int> E : custom_data_layers_by_name) {
+ if (E.value == p_index) {
+ custom_data_layers_by_name.erase(E.key);
+ break;
+ }
+ }
+
+ for (KeyValue<int, Ref<TileSetSource>> source : sources) {
+ source.value->remove_custom_data_layer(p_index);
+ }
+ notify_property_list_changed();
+ emit_changed();
}
int TileSet::get_custom_data_layer_by_name(String p_value) const {
@@ -1110,7 +1247,11 @@ Vector<Vector<Ref<Texture2D>>> TileSet::generate_terrains_icons(Size2i p_size) {
if (is_valid_peering_bit_terrain(terrain_set, cell_neighbor)) {
int terrain = tile_data->get_peering_bit_terrain(cell_neighbor);
if (terrain >= 0) {
- bit_counts[terrain] += 1;
+ if (terrain >= (int)bit_counts.size()) {
+ WARN_PRINT(vformat("Invalid peering bit terrain: %d", terrain));
+ } else {
+ bit_counts[terrain] += 1;
+ }
}
}
}
@@ -1831,13 +1972,13 @@ void TileSet::_compatibility_conversion() {
if (ctd->occluder.is_valid()) {
if (get_occlusion_layers_count() < 1) {
- set_occlusion_layers_count(1);
+ add_occlusion_layer();
}
tile_data->set_occluder(0, ctd->occluder);
}
if (ctd->navigation.is_valid()) {
if (get_navigation_layers_count() < 1) {
- set_navigation_layers_count(1);
+ add_navigation_layer();
}
tile_data->set_navigation_polygon(0, ctd->autotile_navpoly_map[coords]);
}
@@ -1847,7 +1988,7 @@ void TileSet::_compatibility_conversion() {
// Add the shapes.
if (ctd->shapes.size() > 0) {
if (get_physics_layers_count() < 1) {
- set_physics_layers_count(1);
+ add_physics_layer();
}
}
for (int k = 0; k < ctd->shapes.size(); k++) {
@@ -1922,13 +2063,13 @@ void TileSet::_compatibility_conversion() {
tile_data->set_z_index(ctd->z_index);
if (ctd->autotile_occluder_map.has(coords)) {
if (get_occlusion_layers_count() < 1) {
- set_occlusion_layers_count(1);
+ add_occlusion_layer();
}
tile_data->set_occluder(0, ctd->autotile_occluder_map[coords]);
}
if (ctd->autotile_navpoly_map.has(coords)) {
if (get_navigation_layers_count() < 1) {
- set_navigation_layers_count(1);
+ add_navigation_layer();
}
tile_data->set_navigation_polygon(0, ctd->autotile_navpoly_map[coords]);
}
@@ -1942,7 +2083,7 @@ void TileSet::_compatibility_conversion() {
// Add the shapes.
if (ctd->shapes.size() > 0) {
if (get_physics_layers_count() < 1) {
- set_physics_layers_count(1);
+ add_physics_layer();
}
}
for (int k = 0; k < ctd->shapes.size(); k++) {
@@ -2206,15 +2347,15 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(index < 0, false);
if (components[1] == "light_mask") {
ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
- if (index >= occlusion_layers.size()) {
- set_occlusion_layers_count(index + 1);
+ while (index >= occlusion_layers.size()) {
+ add_occlusion_layer();
}
set_occlusion_layer_light_mask(index, p_value);
return true;
} else if (components[1] == "sdf_collision") {
ERR_FAIL_COND_V(p_value.get_type() != Variant::BOOL, false);
- if (index >= occlusion_layers.size()) {
- set_occlusion_layers_count(index + 1);
+ while (index >= occlusion_layers.size()) {
+ add_occlusion_layer();
}
set_occlusion_layer_sdf_collision(index, p_value);
return true;
@@ -2225,23 +2366,22 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(index < 0, false);
if (components[1] == "collision_layer") {
ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
- if (index >= physics_layers.size()) {
- set_physics_layers_count(index + 1);
+ while (index >= physics_layers.size()) {
+ add_physics_layer();
}
set_physics_layer_collision_layer(index, p_value);
return true;
} else if (components[1] == "collision_mask") {
ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
- if (index >= physics_layers.size()) {
- set_physics_layers_count(index + 1);
+ while (index >= physics_layers.size()) {
+ add_physics_layer();
}
set_physics_layer_collision_mask(index, p_value);
return true;
} else if (components[1] == "physics_material") {
Ref<PhysicsMaterial> physics_material = p_value;
- ERR_FAIL_COND_V(!physics_material.is_valid(), false);
- if (index >= physics_layers.size()) {
- set_physics_layers_count(index + 1);
+ while (index >= physics_layers.size()) {
+ add_physics_layer();
}
set_physics_layer_physics_material(index, physics_material);
return true;
@@ -2252,37 +2392,30 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(terrain_set_index < 0, false);
if (components[1] == "mode") {
ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
- if (terrain_set_index >= terrain_sets.size()) {
- set_terrain_sets_count(terrain_set_index + 1);
+ while (terrain_set_index >= terrain_sets.size()) {
+ add_terrain_set();
}
set_terrain_set_mode(terrain_set_index, TerrainMode(int(p_value)));
- } else if (components[1] == "terrains_count") {
- ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
- if (terrain_set_index >= terrain_sets.size()) {
- set_terrain_sets_count(terrain_set_index + 1);
- }
- set_terrains_count(terrain_set_index, p_value);
- return true;
} else if (components.size() >= 3 && components[1].begins_with("terrain_") && components[1].trim_prefix("terrain_").is_valid_int()) {
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);
- if (terrain_set_index >= terrain_sets.size()) {
- set_terrain_sets_count(terrain_set_index + 1);
+ while (terrain_set_index >= terrain_sets.size()) {
+ add_terrain_set();
}
- if (terrain_index >= terrain_sets[terrain_set_index].terrains.size()) {
- set_terrains_count(terrain_set_index, terrain_index + 1);
+ while (terrain_index >= terrain_sets[terrain_set_index].terrains.size()) {
+ add_terrain(terrain_set_index);
}
set_terrain_name(terrain_set_index, terrain_index, p_value);
return true;
} else if (components[2] == "color") {
ERR_FAIL_COND_V(p_value.get_type() != Variant::COLOR, false);
- if (terrain_set_index >= terrain_sets.size()) {
- set_terrain_sets_count(terrain_set_index + 1);
+ while (terrain_set_index >= terrain_sets.size()) {
+ add_terrain_set();
}
- if (terrain_index >= terrain_sets[terrain_set_index].terrains.size()) {
- set_terrains_count(terrain_set_index, terrain_index + 1);
+ while (terrain_index >= terrain_sets[terrain_set_index].terrains.size()) {
+ add_terrain(terrain_set_index);
}
set_terrain_color(terrain_set_index, terrain_index, p_value);
return true;
@@ -2294,8 +2427,8 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(index < 0, false);
if (components[1] == "layers") {
ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
- if (index >= navigation_layers.size()) {
- set_navigation_layers_count(index + 1);
+ while (index >= navigation_layers.size()) {
+ add_navigation_layer();
}
set_navigation_layer_layers(index, p_value);
return true;
@@ -2306,15 +2439,15 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(index < 0, false);
if (components[1] == "name") {
ERR_FAIL_COND_V(p_value.get_type() != Variant::STRING, false);
- if (index >= custom_data_layers.size()) {
- set_custom_data_layers_count(index + 1);
+ while (index >= custom_data_layers.size()) {
+ add_custom_data_layer();
}
set_custom_data_name(index, p_value);
return true;
} else if (components[1] == "type") {
ERR_FAIL_COND_V(p_value.get_type() != Variant::INT, false);
- if (index >= custom_data_layers.size()) {
- set_custom_data_layers_count(index + 1);
+ while (index >= custom_data_layers.size()) {
+ add_custom_data_layer();
}
set_custom_data_type(index, Variant::Type(int(p_value)));
return true;
@@ -2402,9 +2535,6 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
if (components[1] == "mode") {
r_ret = get_terrain_set_mode(terrain_set_index);
return true;
- } else if (components[1] == "terrains_count") {
- r_ret = get_terrains_count(terrain_set_index);
- return true;
} else if (components.size() >= 3 && components[1].begins_with("terrain_") && components[1].trim_prefix("terrain_").is_valid_int()) {
int terrain_index = components[1].trim_prefix("terrain_").to_int();
if (terrain_index < 0 || terrain_index >= terrain_sets[terrain_set_index].terrains.size()) {
@@ -2522,7 +2652,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
for (int terrain_set_index = 0; terrain_set_index < terrain_sets.size(); terrain_set_index++) {
p_list->push_back(PropertyInfo(Variant::INT, vformat("terrain_set_%d/mode", terrain_set_index), PROPERTY_HINT_ENUM, "Match corners and sides,Match corners,Match sides"));
- p_list->push_back(PropertyInfo(Variant::INT, vformat("terrain_set_%d/terrains_count", terrain_set_index), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
+ p_list->push_back(PropertyInfo(Variant::NIL, vformat("terrain_set_%d/terrains", terrain_set_index), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, vformat("terrain_set_%d/terrain_", terrain_set_index)));
for (int terrain_index = 0; terrain_index < terrain_sets[terrain_set_index].terrains.size(); terrain_index++) {
p_list->push_back(PropertyInfo(Variant::STRING, vformat("terrain_set_%d/terrain_%d/name", terrain_set_index, terrain_index)));
p_list->push_back(PropertyInfo(Variant::COLOR, vformat("terrain_set_%d/terrain_%d/color", terrain_set_index, terrain_index)));
@@ -2590,16 +2720,20 @@ void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_uv_clipping", "uv_clipping"), &TileSet::set_uv_clipping);
ClassDB::bind_method(D_METHOD("is_uv_clipping"), &TileSet::is_uv_clipping);
- ClassDB::bind_method(D_METHOD("set_occlusion_layers_count", "occlusion_layers_count"), &TileSet::set_occlusion_layers_count);
ClassDB::bind_method(D_METHOD("get_occlusion_layers_count"), &TileSet::get_occlusion_layers_count);
+ ClassDB::bind_method(D_METHOD("add_occlusion_layer", "to_position"), &TileSet::add_occlusion_layer, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("move_occlusion_layer", "layer_index", "to_position"), &TileSet::move_occlusion_layer);
+ ClassDB::bind_method(D_METHOD("remove_occlusion_layer", "layer_index"), &TileSet::remove_occlusion_layer);
ClassDB::bind_method(D_METHOD("set_occlusion_layer_light_mask", "layer_index", "light_mask"), &TileSet::set_occlusion_layer_light_mask);
ClassDB::bind_method(D_METHOD("get_occlusion_layer_light_mask"), &TileSet::get_occlusion_layer_light_mask);
ClassDB::bind_method(D_METHOD("set_occlusion_layer_sdf_collision", "layer_index", "sdf_collision"), &TileSet::set_occlusion_layer_sdf_collision);
ClassDB::bind_method(D_METHOD("get_occlusion_layer_sdf_collision"), &TileSet::get_occlusion_layer_sdf_collision);
// Physics
- ClassDB::bind_method(D_METHOD("set_physics_layers_count", "physics_layers_count"), &TileSet::set_physics_layers_count);
ClassDB::bind_method(D_METHOD("get_physics_layers_count"), &TileSet::get_physics_layers_count);
+ ClassDB::bind_method(D_METHOD("add_physics_layer", "to_position"), &TileSet::add_physics_layer, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("move_physics_layer", "layer_index", "to_position"), &TileSet::move_physics_layer);
+ ClassDB::bind_method(D_METHOD("remove_physics_layer", "layer_index"), &TileSet::remove_physics_layer);
ClassDB::bind_method(D_METHOD("set_physics_layer_collision_layer", "layer_index", "layer"), &TileSet::set_physics_layer_collision_layer);
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);
@@ -2608,27 +2742,35 @@ void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_physics_layer_physics_material", "layer_index"), &TileSet::get_physics_layer_physics_material);
// Terrains
- ClassDB::bind_method(D_METHOD("set_terrain_sets_count", "terrain_sets_count"), &TileSet::set_terrain_sets_count);
ClassDB::bind_method(D_METHOD("get_terrain_sets_count"), &TileSet::get_terrain_sets_count);
+ ClassDB::bind_method(D_METHOD("add_terrain_set", "to_position"), &TileSet::add_terrain_set, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("move_terrain_set", "layer_index", "to_position"), &TileSet::move_terrain_set);
+ ClassDB::bind_method(D_METHOD("remove_terrain_set", "layer_index"), &TileSet::remove_terrain_set);
ClassDB::bind_method(D_METHOD("set_terrain_set_mode", "terrain_set", "mode"), &TileSet::set_terrain_set_mode);
ClassDB::bind_method(D_METHOD("get_terrain_set_mode", "terrain_set"), &TileSet::get_terrain_set_mode);
- ClassDB::bind_method(D_METHOD("set_terrains_count", "terrain_set", "terrains_count"), &TileSet::set_terrains_count);
ClassDB::bind_method(D_METHOD("get_terrains_count", "terrain_set"), &TileSet::get_terrains_count);
+ ClassDB::bind_method(D_METHOD("add_terrain", "terrain_set", "to_position"), &TileSet::add_terrain, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("move_terrain", "terrain_set", "terrain_index", "to_position"), &TileSet::move_terrain);
+ ClassDB::bind_method(D_METHOD("remove_terrain", "terrain_set", "terrain_index"), &TileSet::remove_terrain);
ClassDB::bind_method(D_METHOD("set_terrain_name", "terrain_set", "terrain_index", "name"), &TileSet::set_terrain_name);
ClassDB::bind_method(D_METHOD("get_terrain_name", "terrain_set", "terrain_index"), &TileSet::get_terrain_name);
ClassDB::bind_method(D_METHOD("set_terrain_color", "terrain_set", "terrain_index", "color"), &TileSet::set_terrain_color);
ClassDB::bind_method(D_METHOD("get_terrain_color", "terrain_set", "terrain_index"), &TileSet::get_terrain_color);
// Navigation
- ClassDB::bind_method(D_METHOD("set_navigation_layers_count", "navigation_layers_count"), &TileSet::set_navigation_layers_count);
ClassDB::bind_method(D_METHOD("get_navigation_layers_count"), &TileSet::get_navigation_layers_count);
+ ClassDB::bind_method(D_METHOD("add_navigation_layer", "to_position"), &TileSet::add_navigation_layer, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("move_navigation_layer", "layer_index", "to_position"), &TileSet::move_navigation_layer);
+ ClassDB::bind_method(D_METHOD("remove_navigation_layer", "layer_index"), &TileSet::remove_navigation_layer);
ClassDB::bind_method(D_METHOD("set_navigation_layer_layers", "layer_index", "layers"), &TileSet::set_navigation_layer_layers);
ClassDB::bind_method(D_METHOD("get_navigation_layer_layers", "layer_index"), &TileSet::get_navigation_layer_layers);
// Custom data
- ClassDB::bind_method(D_METHOD("set_custom_data_layers_count", "custom_data_layers_count"), &TileSet::set_custom_data_layers_count);
ClassDB::bind_method(D_METHOD("get_custom_data_layers_count"), &TileSet::get_custom_data_layers_count);
+ ClassDB::bind_method(D_METHOD("add_custom_data_layer", "to_position"), &TileSet::add_custom_data_layer, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("move_custom_data_layer", "layer_index", "to_position"), &TileSet::move_custom_data_layer);
+ ClassDB::bind_method(D_METHOD("remove_custom_data_layer", "layer_index"), &TileSet::remove_custom_data_layer);
// Tile proxies
ClassDB::bind_method(D_METHOD("set_source_level_tile_proxy", "source_from", "source_to"), &TileSet::set_source_level_tile_proxy);
@@ -2653,19 +2795,19 @@ void TileSet::_bind_methods() {
ADD_GROUP("Rendering", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uv_clipping"), "set_uv_clipping", "is_uv_clipping");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "occlusion_layers_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_occlusion_layers_count", "get_occlusion_layers_count");
+ ADD_ARRAY("occlusion_layers", "occlusion_layer_");
ADD_GROUP("Physics", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "physics_layers_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_physics_layers_count", "get_physics_layers_count");
+ ADD_ARRAY("physics_layers", "physics_layer_");
ADD_GROUP("Terrains", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "terrains_sets_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_terrain_sets_count", "get_terrain_sets_count");
+ ADD_ARRAY("terrain_sets", "terrain_set_");
ADD_GROUP("Navigation", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_navigation_layers_count", "get_navigation_layers_count");
+ ADD_ARRAY("navigation_layers", "navigation_layer_");
ADD_GROUP("Custom data", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "custom_data_layers_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_custom_data_layers_count", "get_custom_data_layers_count");
+ ADD_ARRAY("custom_data_layers", "custom_data_layer_");
// -- Enum binding --
BIND_ENUM_CONSTANT(TILE_SHAPE_SQUARE);
@@ -2750,6 +2892,150 @@ void TileSetAtlasSource::notify_tile_data_properties_should_change() {
}
}
+void TileSetAtlasSource::add_occlusion_layer(int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->add_occlusion_layer(p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::move_occlusion_layer(int p_from_index, int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->move_occlusion_layer(p_from_index, p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::remove_occlusion_layer(int p_index) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->remove_occlusion_layer(p_index);
+ }
+ }
+}
+
+void TileSetAtlasSource::add_physics_layer(int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->add_physics_layer(p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::move_physics_layer(int p_from_index, int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->move_physics_layer(p_from_index, p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::remove_physics_layer(int p_index) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->remove_physics_layer(p_index);
+ }
+ }
+}
+
+void TileSetAtlasSource::add_terrain_set(int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->add_terrain_set(p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::move_terrain_set(int p_from_index, int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->move_terrain_set(p_from_index, p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::remove_terrain_set(int p_index) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->remove_terrain_set(p_index);
+ }
+ }
+}
+
+void TileSetAtlasSource::add_terrain(int p_terrain_set, int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->add_terrain(p_terrain_set, p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::move_terrain(int p_terrain_set, int p_from_index, int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->move_terrain(p_terrain_set, p_from_index, p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::remove_terrain(int p_terrain_set, int p_index) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->remove_terrain(p_terrain_set, p_index);
+ }
+ }
+}
+
+void TileSetAtlasSource::add_navigation_layer(int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->add_navigation_layer(p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::move_navigation_layer(int p_from_index, int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->move_navigation_layer(p_from_index, p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::remove_navigation_layer(int p_index) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->remove_navigation_layer(p_index);
+ }
+ }
+}
+
+void TileSetAtlasSource::add_custom_data_layer(int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->add_custom_data_layer(p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::move_custom_data_layer(int p_from_index, int p_to_pos) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->move_custom_data_layer(p_from_index, p_to_pos);
+ }
+ }
+}
+
+void TileSetAtlasSource::remove_custom_data_layer(int p_index) {
+ for (KeyValue<Vector2i, TileAlternativesData> E_tile : tiles) {
+ for (KeyValue<int, TileData *> E_alternative : E_tile.value.alternatives) {
+ E_alternative.value->remove_custom_data_layer(p_index);
+ }
+ }
+}
+
void TileSetAtlasSource::reset_state() {
// Reset all TileData.
for (Map<Vector2i, TileAlternativesData>::Element *E_tile = tiles.front(); E_tile; E_tile = E_tile->next()) {
@@ -3575,6 +3861,155 @@ void TileData::notify_tile_data_properties_should_change() {
emit_signal(SNAME("changed"));
}
+void TileData::add_occlusion_layer(int p_to_pos) {
+ if (p_to_pos < 0) {
+ p_to_pos = occluders.size();
+ }
+ ERR_FAIL_INDEX(p_to_pos, occluders.size() + 1);
+ occluders.insert(p_to_pos, Ref<OccluderPolygon2D>());
+}
+
+void TileData::move_occlusion_layer(int p_from_index, int p_to_pos) {
+ ERR_FAIL_INDEX(p_from_index, occluders.size());
+ ERR_FAIL_INDEX(p_to_pos, occluders.size() + 1);
+ occluders.insert(p_to_pos, occluders[p_from_index]);
+ occluders.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index);
+}
+
+void TileData::remove_occlusion_layer(int p_index) {
+ ERR_FAIL_INDEX(p_index, occluders.size());
+ occluders.remove(p_index);
+}
+
+void TileData::add_physics_layer(int p_to_pos) {
+ if (p_to_pos < 0) {
+ p_to_pos = physics.size();
+ }
+ ERR_FAIL_INDEX(p_to_pos, physics.size() + 1);
+ physics.insert(p_to_pos, PhysicsLayerTileData());
+}
+
+void TileData::move_physics_layer(int p_from_index, int p_to_pos) {
+ ERR_FAIL_INDEX(p_from_index, physics.size());
+ ERR_FAIL_INDEX(p_to_pos, physics.size() + 1);
+ physics.insert(p_to_pos, physics[p_from_index]);
+ physics.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index);
+}
+
+void TileData::remove_physics_layer(int p_index) {
+ ERR_FAIL_INDEX(p_index, physics.size());
+ physics.remove(p_index);
+}
+
+void TileData::add_terrain_set(int p_to_pos) {
+ if (p_to_pos >= 0 && p_to_pos <= terrain_set) {
+ terrain_set += 1;
+ }
+}
+
+void TileData::move_terrain_set(int p_from_index, int p_to_pos) {
+ if (p_from_index == terrain_set) {
+ terrain_set = (p_from_index < p_to_pos) ? p_to_pos - 1 : p_to_pos;
+ } else {
+ if (p_from_index < terrain_set) {
+ terrain_set -= 1;
+ }
+ if (p_to_pos <= terrain_set) {
+ terrain_set += 1;
+ }
+ }
+}
+
+void TileData::remove_terrain_set(int p_index) {
+ if (p_index == terrain_set) {
+ terrain_set = -1;
+ for (int i = 0; i < 16; i++) {
+ terrain_peering_bits[i] = -1;
+ }
+ } else if (terrain_set > p_index) {
+ terrain_set -= 1;
+ }
+}
+
+void TileData::add_terrain(int p_terrain_set, int p_to_pos) {
+ if (terrain_set == p_terrain_set) {
+ for (int i = 0; i < 16; i++) {
+ if (p_to_pos >= 0 && p_to_pos <= terrain_peering_bits[i]) {
+ terrain_peering_bits[i] += 1;
+ }
+ }
+ }
+}
+
+void TileData::move_terrain(int p_terrain_set, int p_from_index, int p_to_pos) {
+ if (terrain_set == p_terrain_set) {
+ for (int i = 0; i < 16; i++) {
+ if (p_from_index == terrain_peering_bits[i]) {
+ terrain_peering_bits[i] = (p_from_index < p_to_pos) ? p_to_pos - 1 : p_to_pos;
+ } else {
+ if (p_from_index < terrain_peering_bits[i]) {
+ terrain_peering_bits[i] -= 1;
+ }
+ if (p_to_pos <= terrain_peering_bits[i]) {
+ terrain_peering_bits[i] += 1;
+ }
+ }
+ }
+ }
+}
+
+void TileData::remove_terrain(int p_terrain_set, int p_index) {
+ if (terrain_set == p_terrain_set) {
+ for (int i = 0; i < 16; i++) {
+ if (terrain_peering_bits[i] == p_index) {
+ terrain_peering_bits[i] = -1;
+ } else if (terrain_peering_bits[i] > p_index) {
+ terrain_peering_bits[i] -= 1;
+ }
+ }
+ }
+}
+
+void TileData::add_navigation_layer(int p_to_pos) {
+ if (p_to_pos < 0) {
+ p_to_pos = navigation.size();
+ }
+ ERR_FAIL_INDEX(p_to_pos, navigation.size() + 1);
+ navigation.insert(p_to_pos, Ref<NavigationPolygon>());
+}
+
+void TileData::move_navigation_layer(int p_from_index, int p_to_pos) {
+ ERR_FAIL_INDEX(p_from_index, navigation.size());
+ ERR_FAIL_INDEX(p_to_pos, navigation.size() + 1);
+ navigation.insert(p_to_pos, navigation[p_from_index]);
+ navigation.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index);
+}
+
+void TileData::remove_navigation_layer(int p_index) {
+ ERR_FAIL_INDEX(p_index, navigation.size());
+ navigation.remove(p_index);
+}
+
+void TileData::add_custom_data_layer(int p_to_pos) {
+ if (p_to_pos < 0) {
+ p_to_pos = custom_data.size();
+ }
+ ERR_FAIL_INDEX(p_to_pos, custom_data.size() + 1);
+ custom_data.insert(p_to_pos, Variant());
+}
+
+void TileData::move_custom_data_layer(int p_from_index, int p_to_pos) {
+ ERR_FAIL_INDEX(p_from_index, custom_data.size());
+ ERR_FAIL_INDEX(p_to_pos, custom_data.size() + 1);
+ custom_data.insert(p_to_pos, navigation[p_from_index]);
+ custom_data.remove(p_to_pos < p_from_index ? p_from_index + 1 : p_from_index);
+}
+
+void TileData::remove_custom_data_layer(int p_index) {
+ ERR_FAIL_INDEX(p_index, custom_data.size());
+ custom_data.remove(p_index);
+}
+
void TileData::reset_state() {
occluders.clear();
physics.clear();
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 35e6999d13..29a71d31d2 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -225,10 +225,10 @@ private:
bool terrain_bits_meshes_dirty = true;
// Navigation
- struct Navigationlayer {
+ struct NavigationLayer {
uint32_t layers = 1;
};
- Vector<Navigationlayer> navigation_layers;
+ Vector<NavigationLayer> navigation_layers;
// CustomData
struct CustomDataLayer {
@@ -298,16 +298,20 @@ public:
void set_uv_clipping(bool p_uv_clipping);
bool is_uv_clipping() const;
- void set_occlusion_layers_count(int p_occlusion_layers_count);
int get_occlusion_layers_count() const;
+ void add_occlusion_layer(int p_index = -1);
+ void move_occlusion_layer(int p_from_index, int p_to_pos);
+ void remove_occlusion_layer(int p_index);
void set_occlusion_layer_light_mask(int p_layer_index, int p_light_mask);
int get_occlusion_layer_light_mask(int p_layer_index) const;
void set_occlusion_layer_sdf_collision(int p_layer_index, int p_sdf_collision);
bool get_occlusion_layer_sdf_collision(int p_layer_index) const;
// Physics
- void set_physics_layers_count(int p_physics_layers_count);
int get_physics_layers_count() const;
+ void add_physics_layer(int p_index = -1);
+ void move_physics_layer(int p_from_index, int p_to_pos);
+ void remove_physics_layer(int p_index);
void set_physics_layer_collision_layer(int p_layer_index, uint32_t p_layer);
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);
@@ -315,13 +319,19 @@ public:
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;
- // Terrains
- void set_terrain_sets_count(int p_terrains_sets_count);
+ // Terrain sets
int get_terrain_sets_count() const;
+ void add_terrain_set(int p_index = -1);
+ void move_terrain_set(int p_from_index, int p_to_pos);
+ void remove_terrain_set(int p_index);
void set_terrain_set_mode(int p_terrain_set, TerrainMode p_terrain_mode);
TerrainMode get_terrain_set_mode(int p_terrain_set) const;
- void set_terrains_count(int p_terrain_set, int p_terrains_count);
+
+ // Terrains
int get_terrains_count(int p_terrain_set) const;
+ void add_terrain(int p_terrain_set, int p_index = -1);
+ void move_terrain(int p_terrain_set, int p_from_index, int p_to_pos);
+ void remove_terrain(int p_terrain_set, int p_index);
void set_terrain_name(int p_terrain_set, int p_terrain_index, String p_name);
String get_terrain_name(int p_terrain_set, int p_terrain_index) const;
void set_terrain_color(int p_terrain_set, int p_terrain_index, Color p_color);
@@ -330,14 +340,18 @@ public:
bool is_valid_peering_bit_terrain(int p_terrain_set, TileSet::CellNeighbor p_peering_bit) const;
// Navigation
- void set_navigation_layers_count(int p_navigation_layers_count);
int get_navigation_layers_count() const;
+ void add_navigation_layer(int p_index = -1);
+ void move_navigation_layer(int p_from_index, int p_to_pos);
+ void remove_navigation_layer(int p_index);
void set_navigation_layer_layers(int p_layer_index, uint32_t p_layers);
uint32_t get_navigation_layer_layers(int p_layer_index) const;
// Custom data
- void set_custom_data_layers_count(int p_custom_data_layers_count);
int get_custom_data_layers_count() const;
+ void add_custom_data_layer(int p_index = -1);
+ void move_custom_data_layer(int p_from_index, int p_to_pos);
+ void remove_custom_data_layer(int p_index);
int get_custom_data_layer_by_name(String p_value) const;
void set_custom_data_name(int p_layer_id, String p_value);
String get_custom_data_name(int p_layer_id) const;
@@ -397,6 +411,24 @@ public:
// Not exposed.
virtual void set_tile_set(const TileSet *p_tile_set);
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.
@@ -448,6 +480,24 @@ public:
// Not exposed.
virtual void set_tile_set(const TileSet *p_tile_set) override;
virtual void notify_tile_data_properties_should_change() override;
+ virtual void add_occlusion_layer(int p_index) override;
+ virtual void move_occlusion_layer(int p_from_index, int p_to_pos) override;
+ virtual void remove_occlusion_layer(int p_index) override;
+ virtual void add_physics_layer(int p_index) override;
+ virtual void move_physics_layer(int p_from_index, int p_to_pos) override;
+ virtual void remove_physics_layer(int p_index) override;
+ virtual void add_terrain_set(int p_index) override;
+ virtual void move_terrain_set(int p_from_index, int p_to_pos) override;
+ virtual void remove_terrain_set(int p_index) override;
+ virtual void add_terrain(int p_terrain_set, int p_index) override;
+ virtual void move_terrain(int p_terrain_set, int p_from_index, int p_to_pos) override;
+ virtual void remove_terrain(int p_terrain_set, int p_index) override;
+ virtual void add_navigation_layer(int p_index) override;
+ virtual void move_navigation_layer(int p_from_index, int p_to_pos) override;
+ virtual void remove_navigation_layer(int p_index) override;
+ virtual void add_custom_data_layer(int p_index) override;
+ virtual void move_custom_data_layer(int p_from_index, int p_to_pos) override;
+ virtual void remove_custom_data_layer(int p_index) override;
virtual void reset_state() override;
// Base properties.
@@ -528,7 +578,7 @@ public:
int get_alternative_tile_id(const Vector2i p_atlas_coords, int p_index) const override;
bool has_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_tile) const override;
- // Scenes sccessors. Lot are similar to "Alternative tiles".
+ // 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); };
@@ -597,6 +647,24 @@ public:
// Not exposed.
void set_tile_set(const TileSet *p_tile_set);
void notify_tile_data_properties_should_change();
+ void add_occlusion_layer(int p_index);
+ void move_occlusion_layer(int p_from_index, int p_to_pos);
+ void remove_occlusion_layer(int p_index);
+ void add_physics_layer(int p_index);
+ void move_physics_layer(int p_from_index, int p_to_pos);
+ void remove_physics_layer(int p_index);
+ void add_terrain_set(int p_index);
+ void move_terrain_set(int p_from_index, int p_to_pos);
+ void remove_terrain_set(int p_index);
+ void add_terrain(int p_terrain_set, int p_index);
+ void move_terrain(int p_terrain_set, int p_from_index, int p_to_pos);
+ void remove_terrain(int p_terrain_set, int p_index);
+ void add_navigation_layer(int p_index);
+ void move_navigation_layer(int p_from_index, int p_to_pos);
+ void remove_navigation_layer(int p_index);
+ void add_custom_data_layer(int p_index);
+ void move_custom_data_layer(int p_from_index, int p_to_pos);
+ void remove_custom_data_layer(int p_index);
void reset_state();
void set_allow_transform(bool p_allow_transform);
bool is_allowing_transform() const;