summaryrefslogtreecommitdiff
path: root/scene/2d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d')
-rw-r--r--scene/2d/audio_listener_2d.cpp1
-rw-r--r--scene/2d/camera_2d.cpp124
-rw-r--r--scene/2d/camera_2d.h31
-rw-r--r--scene/2d/collision_object_2d.cpp20
-rw-r--r--scene/2d/collision_shape_2d.cpp49
-rw-r--r--scene/2d/collision_shape_2d.h10
-rw-r--r--scene/2d/cpu_particles_2d.cpp71
-rw-r--r--scene/2d/cpu_particles_2d.h4
-rw-r--r--scene/2d/gpu_particles_2d.cpp10
-rw-r--r--scene/2d/light_2d.cpp2
-rw-r--r--scene/2d/navigation_agent_2d.cpp42
-rw-r--r--scene/2d/navigation_agent_2d.h9
-rw-r--r--scene/2d/navigation_obstacle_2d.cpp10
-rw-r--r--scene/2d/navigation_region_2d.cpp34
-rw-r--r--scene/2d/navigation_region_2d.h4
-rw-r--r--scene/2d/node_2d.cpp2
-rw-r--r--scene/2d/parallax_background.cpp28
-rw-r--r--scene/2d/parallax_layer.cpp12
-rw-r--r--scene/2d/physics_body_2d.cpp49
-rw-r--r--scene/2d/skeleton_2d.cpp12
-rw-r--r--scene/2d/sprite_2d.cpp6
-rw-r--r--scene/2d/tile_map.cpp159
-rw-r--r--scene/2d/tile_map.h4
23 files changed, 432 insertions, 261 deletions
diff --git a/scene/2d/audio_listener_2d.cpp b/scene/2d/audio_listener_2d.cpp
index f7dd20d7c0..3cc64b2170 100644
--- a/scene/2d/audio_listener_2d.cpp
+++ b/scene/2d/audio_listener_2d.cpp
@@ -103,7 +103,6 @@ bool AudioListener2D::is_current() const {
} else {
return current;
}
- return false;
}
void AudioListener2D::_bind_methods() {
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index a11b2b66bf..aa7df4ea9c 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -155,11 +155,11 @@ Transform2D Camera2D::get_camera_transform() {
}
}
- if (smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) {
- real_t c = smoothing * (process_callback == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time());
+ if (follow_smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) {
+ real_t c = position_smoothing_speed * (process_callback == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time());
smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos;
ret_camera_pos = smoothed_camera_pos;
- //camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing;
+ //camera_pos=camera_pos*(1.0-position_smoothing_speed)+new_camera_pos*position_smoothing_speed;
} else {
ret_camera_pos = smoothed_camera_pos = camera_pos;
}
@@ -171,14 +171,19 @@ Transform2D Camera2D::get_camera_transform() {
Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom_scale) : Point2());
- real_t angle = get_global_rotation();
- if (rotating) {
- screen_offset = screen_offset.rotated(angle);
+ if (!ignore_rotation) {
+ if (rotation_smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) {
+ real_t step = rotation_smoothing_speed * (process_callback == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time());
+ camera_angle = Math::lerp_angle(camera_angle, get_global_rotation(), step);
+ } else {
+ camera_angle = get_global_rotation();
+ }
+ screen_offset = screen_offset.rotated(camera_angle);
}
Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom_scale);
- if (!smoothing_enabled || !limit_smoothing_enabled) {
+ if (!follow_smoothing_enabled || !limit_smoothing_enabled) {
if (screen_rect.position.x < limit[SIDE_LEFT]) {
screen_rect.position.x = limit[SIDE_LEFT];
}
@@ -204,8 +209,8 @@ Transform2D Camera2D::get_camera_transform() {
Transform2D xform;
xform.scale_basis(zoom_scale);
- if (rotating) {
- xform.set_rotation(angle);
+ if (!ignore_rotation) {
+ xform.set_rotation(camera_angle);
}
xform.set_origin(screen_rect.position);
@@ -363,15 +368,21 @@ Camera2D::AnchorMode Camera2D::get_anchor_mode() const {
return anchor_mode;
}
-void Camera2D::set_rotating(bool p_rotating) {
- rotating = p_rotating;
+void Camera2D::set_ignore_rotation(bool p_ignore) {
+ ignore_rotation = p_ignore;
Point2 old_smoothed_camera_pos = smoothed_camera_pos;
+
+ // Reset back to zero so it matches the camera rotation when ignore_rotation is enabled.
+ if (ignore_rotation) {
+ camera_angle = 0.0;
+ }
+
_update_scroll();
smoothed_camera_pos = old_smoothed_camera_pos;
}
-bool Camera2D::is_rotating() const {
- return rotating;
+bool Camera2D::is_ignoring_rotation() const {
+ return ignore_rotation;
}
void Camera2D::set_process_callback(Camera2DProcessCallback p_mode) {
@@ -415,6 +426,14 @@ void Camera2D::set_current(bool p_current) {
}
}
+void Camera2D::_update_process_internal_for_smoothing() {
+ bool is_not_in_scene_or_editor = !(is_inside_tree() && Engine::get_singleton()->is_editor_hint());
+ bool is_any_smoothing_valid = position_smoothing_speed > 0 || rotation_smoothing_speed > 0;
+
+ bool enabled = is_any_smoothing_valid && is_not_in_scene_or_editor;
+ set_process_internal(enabled);
+}
+
bool Camera2D::is_current() const {
return current;
}
@@ -506,17 +525,31 @@ void Camera2D::align() {
_update_scroll();
}
-void Camera2D::set_follow_smoothing(real_t p_speed) {
- smoothing = p_speed;
- if (smoothing > 0 && !(is_inside_tree() && Engine::get_singleton()->is_editor_hint())) {
- set_process_internal(true);
- } else {
- set_process_internal(false);
- }
+void Camera2D::set_position_smoothing_speed(real_t p_speed) {
+ position_smoothing_speed = p_speed;
+ _update_process_internal_for_smoothing();
+}
+
+real_t Camera2D::get_position_smoothing_speed() const {
+ return position_smoothing_speed;
+}
+
+void Camera2D::set_rotation_smoothing_speed(real_t p_speed) {
+ rotation_smoothing_speed = p_speed;
+ _update_process_internal_for_smoothing();
}
-real_t Camera2D::get_follow_smoothing() const {
- return smoothing;
+real_t Camera2D::get_rotation_smoothing_speed() const {
+ return rotation_smoothing_speed;
+}
+
+void Camera2D::set_rotation_smoothing_enabled(bool p_enabled) {
+ rotation_smoothing_enabled = p_enabled;
+ notify_property_list_changed();
+}
+
+bool Camera2D::is_rotation_smoothing_enabled() const {
+ return rotation_smoothing_enabled;
}
Point2 Camera2D::get_camera_screen_center() const {
@@ -574,18 +607,18 @@ real_t Camera2D::get_drag_horizontal_offset() const {
void Camera2D::_set_old_smoothing(real_t p_enable) {
//compatibility
if (p_enable > 0) {
- smoothing_enabled = true;
- set_follow_smoothing(p_enable);
+ follow_smoothing_enabled = true;
+ set_position_smoothing_speed(p_enable);
}
}
-void Camera2D::set_enable_follow_smoothing(bool p_enabled) {
- smoothing_enabled = p_enabled;
+void Camera2D::set_position_smoothing_enabled(bool p_enabled) {
+ follow_smoothing_enabled = p_enabled;
notify_property_list_changed();
}
-bool Camera2D::is_follow_smoothing_enabled() const {
- return smoothing_enabled;
+bool Camera2D::is_position_smoothing_enabled() const {
+ return follow_smoothing_enabled;
}
void Camera2D::set_custom_viewport(Node *p_viewport) {
@@ -656,7 +689,10 @@ bool Camera2D::is_margin_drawing_enabled() const {
}
void Camera2D::_validate_property(PropertyInfo &p_property) const {
- if (!smoothing_enabled && p_property.name == "smoothing_speed") {
+ if (!follow_smoothing_enabled && p_property.name == "smoothing_speed") {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+ if (!rotation_smoothing_enabled && p_property.name == "rotation_smoothing_speed") {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
}
@@ -668,8 +704,8 @@ void Camera2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_anchor_mode", "anchor_mode"), &Camera2D::set_anchor_mode);
ClassDB::bind_method(D_METHOD("get_anchor_mode"), &Camera2D::get_anchor_mode);
- ClassDB::bind_method(D_METHOD("set_rotating", "rotating"), &Camera2D::set_rotating);
- ClassDB::bind_method(D_METHOD("is_rotating"), &Camera2D::is_rotating);
+ ClassDB::bind_method(D_METHOD("set_ignore_rotation", "ignore"), &Camera2D::set_ignore_rotation);
+ ClassDB::bind_method(D_METHOD("is_ignoring_rotation"), &Camera2D::is_ignoring_rotation);
ClassDB::bind_method(D_METHOD("_update_scroll"), &Camera2D::_update_scroll);
@@ -710,11 +746,17 @@ void Camera2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_custom_viewport", "viewport"), &Camera2D::set_custom_viewport);
ClassDB::bind_method(D_METHOD("get_custom_viewport"), &Camera2D::get_custom_viewport);
- ClassDB::bind_method(D_METHOD("set_follow_smoothing", "follow_smoothing"), &Camera2D::set_follow_smoothing);
- ClassDB::bind_method(D_METHOD("get_follow_smoothing"), &Camera2D::get_follow_smoothing);
+ ClassDB::bind_method(D_METHOD("set_position_smoothing_speed", "position_smoothing_speed"), &Camera2D::set_position_smoothing_speed);
+ ClassDB::bind_method(D_METHOD("get_position_smoothing_speed"), &Camera2D::get_position_smoothing_speed);
- ClassDB::bind_method(D_METHOD("set_enable_follow_smoothing", "follow_smoothing"), &Camera2D::set_enable_follow_smoothing);
- ClassDB::bind_method(D_METHOD("is_follow_smoothing_enabled"), &Camera2D::is_follow_smoothing_enabled);
+ ClassDB::bind_method(D_METHOD("set_position_smoothing_enabled", "position_smoothing_speed"), &Camera2D::set_position_smoothing_enabled);
+ ClassDB::bind_method(D_METHOD("is_position_smoothing_enabled"), &Camera2D::is_position_smoothing_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_rotation_smoothing_enabled", "enabled"), &Camera2D::set_rotation_smoothing_enabled);
+ ClassDB::bind_method(D_METHOD("is_rotation_smoothing_enabled"), &Camera2D::is_rotation_smoothing_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_rotation_smoothing_speed", "speed"), &Camera2D::set_rotation_smoothing_speed);
+ ClassDB::bind_method(D_METHOD("get_rotation_smoothing_speed"), &Camera2D::get_rotation_smoothing_speed);
ClassDB::bind_method(D_METHOD("force_update_scroll"), &Camera2D::force_update_scroll);
ClassDB::bind_method(D_METHOD("reset_smoothing"), &Camera2D::reset_smoothing);
@@ -733,7 +775,7 @@ void Camera2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_mode", PROPERTY_HINT_ENUM, "Fixed TopLeft,Drag Center"), "set_anchor_mode", "get_anchor_mode");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotating"), "set_rotating", "is_rotating");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_rotation"), "set_ignore_rotation", "is_ignoring_rotation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom", PROPERTY_HINT_LINK), "set_zoom", "get_zoom");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", PROPERTY_USAGE_NONE), "set_custom_viewport", "get_custom_viewport");
@@ -746,9 +788,13 @@ void Camera2D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_bottom", PROPERTY_HINT_NONE, "suffix:px"), "set_limit", "get_limit", SIDE_BOTTOM);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "limit_smoothed"), "set_limit_smoothing_enabled", "is_limit_smoothing_enabled");
- ADD_GROUP("Smoothing", "smoothing_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smoothing_enabled"), "set_enable_follow_smoothing", "is_follow_smoothing_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "smoothing_speed", PROPERTY_HINT_NONE, "suffix:px/s"), "set_follow_smoothing", "get_follow_smoothing");
+ ADD_GROUP("Follow Smoothing", "follow_smoothing_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "position_smoothing_enabled"), "set_position_smoothing_enabled", "is_position_smoothing_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "position_smoothing_speed", PROPERTY_HINT_NONE, "suffix:px/s"), "set_position_smoothing_speed", "get_position_smoothing_speed");
+
+ ADD_GROUP("Rotation Smoothing", "rotation_smoothing_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotation_smoothing_enabled"), "set_rotation_smoothing_enabled", "is_rotation_smoothing_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_smoothing_speed"), "set_rotation_smoothing_speed", "get_rotation_smoothing_speed");
ADD_GROUP("Drag", "drag_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_horizontal_enabled"), "set_drag_horizontal_enabled", "is_drag_horizontal_enabled");
diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h
index 78654ee606..ae172f47b1 100644
--- a/scene/2d/camera_2d.h
+++ b/scene/2d/camera_2d.h
@@ -63,10 +63,15 @@ protected:
Vector2 zoom = Vector2(1, 1);
Vector2 zoom_scale = Vector2(1, 1);
AnchorMode anchor_mode = ANCHOR_MODE_DRAG_CENTER;
- bool rotating = false;
+ bool ignore_rotation = true;
bool current = false;
- real_t smoothing = 5.0;
- bool smoothing_enabled = false;
+ real_t position_smoothing_speed = 5.0;
+ bool follow_smoothing_enabled = false;
+
+ real_t camera_angle = 0.0;
+ real_t rotation_smoothing_speed = 5.0;
+ bool rotation_smoothing_enabled = false;
+
int limit[4];
bool limit_smoothing_enabled = false;
@@ -87,6 +92,8 @@ protected:
void _set_old_smoothing(real_t p_enable);
+ void _update_process_internal_for_smoothing();
+
bool screen_drawing_enabled = true;
bool limit_drawing_enabled = false;
bool margin_drawing_enabled = false;
@@ -109,8 +116,8 @@ public:
void set_anchor_mode(AnchorMode p_anchor_mode);
AnchorMode get_anchor_mode() const;
- void set_rotating(bool p_rotating);
- bool is_rotating() const;
+ void set_ignore_rotation(bool p_ignore);
+ bool is_ignoring_rotation() const;
void set_limit(Side p_side, int p_limit);
int get_limit(Side p_side) const;
@@ -133,11 +140,17 @@ public:
void set_drag_vertical_offset(real_t p_offset);
real_t get_drag_vertical_offset() const;
- void set_enable_follow_smoothing(bool p_enabled);
- bool is_follow_smoothing_enabled() const;
+ void set_position_smoothing_enabled(bool p_enabled);
+ bool is_position_smoothing_enabled() const;
+
+ void set_position_smoothing_speed(real_t p_speed);
+ real_t get_position_smoothing_speed() const;
+
+ void set_rotation_smoothing_speed(real_t p_speed);
+ real_t get_rotation_smoothing_speed() const;
- void set_follow_smoothing(real_t p_speed);
- real_t get_follow_smoothing() const;
+ void set_rotation_smoothing_enabled(bool p_enabled);
+ bool is_rotation_smoothing_enabled() const;
void set_process_callback(Camera2DProcessCallback p_mode);
Camera2DProcessCallback get_process_callback() const;
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index 23948c2fd3..df75d34e0f 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -36,12 +36,12 @@
void CollisionObject2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- Transform2D global_transform = get_global_transform();
+ Transform2D gl_transform = get_global_transform();
if (area) {
- PhysicsServer2D::get_singleton()->area_set_transform(rid, global_transform);
+ PhysicsServer2D::get_singleton()->area_set_transform(rid, gl_transform);
} else {
- PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, global_transform);
+ PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, gl_transform);
}
bool disabled = !is_enabled();
@@ -81,12 +81,12 @@ void CollisionObject2D::_notification(int p_what) {
return;
}
- Transform2D global_transform = get_global_transform();
+ Transform2D gl_transform = get_global_transform();
if (area) {
- PhysicsServer2D::get_singleton()->area_set_transform(rid, global_transform);
+ PhysicsServer2D::get_singleton()->area_set_transform(rid, gl_transform);
} else {
- PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, global_transform);
+ PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, gl_transform);
}
} break;
@@ -153,13 +153,13 @@ uint32_t CollisionObject2D::get_collision_mask() const {
void CollisionObject2D::set_collision_layer_value(int p_layer_number, bool p_value) {
ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive.");
ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive.");
- uint32_t collision_layer = get_collision_layer();
+ uint32_t collision_layer_new = get_collision_layer();
if (p_value) {
- collision_layer |= 1 << (p_layer_number - 1);
+ collision_layer_new |= 1 << (p_layer_number - 1);
} else {
- collision_layer &= ~(1 << (p_layer_number - 1));
+ collision_layer_new &= ~(1 << (p_layer_number - 1));
}
- set_collision_layer(collision_layer);
+ set_collision_layer(collision_layer_new);
}
bool CollisionObject2D::get_collision_layer_value(int p_layer_number) const {
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index 7e167a3807..5fe05c4ddd 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -49,6 +49,11 @@ void CollisionShape2D::_update_in_shape_owner(bool p_xform_only) {
parent->shape_owner_set_one_way_collision_margin(owner_id, one_way_collision_margin);
}
+Color CollisionShape2D::_get_default_debug_color() const {
+ SceneTree *st = SceneTree::get_singleton();
+ return st ? st->get_debug_collisions_color() : Color();
+}
+
void CollisionShape2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_PARENTED: {
@@ -95,7 +100,7 @@ void CollisionShape2D::_notification(int p_what) {
rect = Rect2();
- Color draw_col = get_tree()->get_debug_collisions_color();
+ Color draw_col = debug_color;
if (disabled) {
float g = draw_col.get_v();
draw_col.r = g;
@@ -110,7 +115,7 @@ void CollisionShape2D::_notification(int p_what) {
if (one_way_collision) {
// Draw an arrow indicating the one-way collision direction
- draw_col = get_tree()->get_debug_collisions_color().inverted();
+ draw_col = debug_color.inverted();
if (disabled) {
draw_col = draw_col.darkened(0.25);
}
@@ -226,6 +231,40 @@ real_t CollisionShape2D::get_one_way_collision_margin() const {
return one_way_collision_margin;
}
+void CollisionShape2D::set_debug_color(const Color &p_color) {
+ debug_color = p_color;
+ queue_redraw();
+}
+
+Color CollisionShape2D::get_debug_color() const {
+ return debug_color;
+}
+
+bool CollisionShape2D::_property_can_revert(const StringName &p_name) const {
+ if (p_name == "debug_color") {
+ return true;
+ }
+ return false;
+}
+
+bool CollisionShape2D::_property_get_revert(const StringName &p_name, Variant &r_property) const {
+ if (p_name == "debug_color") {
+ r_property = _get_default_debug_color();
+ return true;
+ }
+ return false;
+}
+
+void CollisionShape2D::_validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "debug_color") {
+ if (debug_color == _get_default_debug_color()) {
+ p_property.usage = PROPERTY_USAGE_DEFAULT & ~PROPERTY_USAGE_STORAGE;
+ } else {
+ p_property.usage = PROPERTY_USAGE_DEFAULT;
+ }
+ }
+}
+
void CollisionShape2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shape", "shape"), &CollisionShape2D::set_shape);
ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape2D::get_shape);
@@ -235,13 +274,19 @@ void CollisionShape2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_one_way_collision_enabled"), &CollisionShape2D::is_one_way_collision_enabled);
ClassDB::bind_method(D_METHOD("set_one_way_collision_margin", "margin"), &CollisionShape2D::set_one_way_collision_margin);
ClassDB::bind_method(D_METHOD("get_one_way_collision_margin"), &CollisionShape2D::get_one_way_collision_margin);
+ ClassDB::bind_method(D_METHOD("set_debug_color", "color"), &CollisionShape2D::set_debug_color);
+ ClassDB::bind_method(D_METHOD("get_debug_color"), &CollisionShape2D::get_debug_color);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_way_collision"), "set_one_way_collision", "is_one_way_collision_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "one_way_collision_margin", PROPERTY_HINT_RANGE, "0,128,0.1,suffix:px"), "set_one_way_collision_margin", "get_one_way_collision_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_color"), "set_debug_color", "get_debug_color");
+ // Default value depends on a project setting, override for doc generation purposes.
+ ADD_PROPERTY_DEFAULT("debug_color", Color());
}
CollisionShape2D::CollisionShape2D() {
set_notify_local_transform(true);
+ debug_color = _get_default_debug_color();
}
diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h
index 5e50420e00..b0b8a7cb0f 100644
--- a/scene/2d/collision_shape_2d.h
+++ b/scene/2d/collision_shape_2d.h
@@ -42,15 +42,20 @@ class CollisionShape2D : public Node2D {
Rect2 rect = Rect2(-Point2(10, 10), Point2(20, 20));
uint32_t owner_id = 0;
CollisionObject2D *parent = nullptr;
- void _shape_changed();
bool disabled = false;
bool one_way_collision = false;
real_t one_way_collision_margin = 1.0;
+ Color debug_color;
+ void _shape_changed();
void _update_in_shape_owner(bool p_xform_only = false);
+ Color _get_default_debug_color() const;
protected:
void _notification(int p_what);
+ bool _property_can_revert(const StringName &p_name) const;
+ bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
+ void _validate_property(PropertyInfo &p_property) const;
static void _bind_methods();
public:
@@ -72,6 +77,9 @@ public:
void set_one_way_collision_margin(real_t p_margin);
real_t get_one_way_collision_margin() const;
+ void set_debug_color(const Color &p_color);
+ Color get_debug_color() const;
+
PackedStringArray get_configuration_warnings() const override;
CollisionShape2D();
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index eece90190b..c6296f4732 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -1162,74 +1162,73 @@ void CPUParticles2D::_notification(int p_what) {
}
void CPUParticles2D::convert_from_particles(Node *p_particles) {
- GPUParticles2D *particles = Object::cast_to<GPUParticles2D>(p_particles);
- ERR_FAIL_COND_MSG(!particles, "Only GPUParticles2D nodes can be converted to CPUParticles2D.");
-
- set_emitting(particles->is_emitting());
- set_amount(particles->get_amount());
- set_lifetime(particles->get_lifetime());
- set_one_shot(particles->get_one_shot());
- set_pre_process_time(particles->get_pre_process_time());
- set_explosiveness_ratio(particles->get_explosiveness_ratio());
- set_randomness_ratio(particles->get_randomness_ratio());
- set_use_local_coordinates(particles->get_use_local_coordinates());
- set_fixed_fps(particles->get_fixed_fps());
- set_fractional_delta(particles->get_fractional_delta());
- set_speed_scale(particles->get_speed_scale());
- set_draw_order(DrawOrder(particles->get_draw_order()));
- set_texture(particles->get_texture());
-
- Ref<Material> mat = particles->get_material();
+ GPUParticles2D *gpu_particles = Object::cast_to<GPUParticles2D>(p_particles);
+ ERR_FAIL_COND_MSG(!gpu_particles, "Only GPUParticles2D nodes can be converted to CPUParticles2D.");
+
+ set_emitting(gpu_particles->is_emitting());
+ set_amount(gpu_particles->get_amount());
+ set_lifetime(gpu_particles->get_lifetime());
+ set_one_shot(gpu_particles->get_one_shot());
+ set_pre_process_time(gpu_particles->get_pre_process_time());
+ set_explosiveness_ratio(gpu_particles->get_explosiveness_ratio());
+ set_randomness_ratio(gpu_particles->get_randomness_ratio());
+ set_use_local_coordinates(gpu_particles->get_use_local_coordinates());
+ set_fixed_fps(gpu_particles->get_fixed_fps());
+ set_fractional_delta(gpu_particles->get_fractional_delta());
+ set_speed_scale(gpu_particles->get_speed_scale());
+ set_draw_order(DrawOrder(gpu_particles->get_draw_order()));
+ set_texture(gpu_particles->get_texture());
+
+ Ref<Material> mat = gpu_particles->get_material();
if (mat.is_valid()) {
set_material(mat);
}
- Ref<ParticleProcessMaterial> material = particles->get_process_material();
- if (material.is_null()) {
+ Ref<ParticleProcessMaterial> proc_mat = gpu_particles->get_process_material();
+ if (proc_mat.is_null()) {
return;
}
- Vector3 dir = material->get_direction();
+ Vector3 dir = proc_mat->get_direction();
set_direction(Vector2(dir.x, dir.y));
- set_spread(material->get_spread());
+ set_spread(proc_mat->get_spread());
- set_color(material->get_color());
+ set_color(proc_mat->get_color());
- Ref<GradientTexture1D> gt = material->get_color_ramp();
+ Ref<GradientTexture1D> gt = proc_mat->get_color_ramp();
if (gt.is_valid()) {
set_color_ramp(gt->get_gradient());
}
- Ref<GradientTexture1D> gti = material->get_color_initial_ramp();
+ Ref<GradientTexture1D> gti = proc_mat->get_color_initial_ramp();
if (gti.is_valid()) {
set_color_initial_ramp(gti->get_gradient());
}
- set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, material->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY));
+ set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, proc_mat->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY));
- set_emission_shape(EmissionShape(material->get_emission_shape()));
- set_emission_sphere_radius(material->get_emission_sphere_radius());
- Vector2 rect_extents = Vector2(material->get_emission_box_extents().x, material->get_emission_box_extents().y);
+ set_emission_shape(EmissionShape(proc_mat->get_emission_shape()));
+ set_emission_sphere_radius(proc_mat->get_emission_sphere_radius());
+ Vector2 rect_extents = Vector2(proc_mat->get_emission_box_extents().x, proc_mat->get_emission_box_extents().y);
set_emission_rect_extents(rect_extents);
- Ref<CurveXYZTexture> scale3D = material->get_param_texture(ParticleProcessMaterial::PARAM_SCALE);
+ Ref<CurveXYZTexture> scale3D = proc_mat->get_param_texture(ParticleProcessMaterial::PARAM_SCALE);
if (scale3D.is_valid()) {
split_scale = true;
scale_curve_x = scale3D->get_curve_x();
scale_curve_y = scale3D->get_curve_y();
}
- Vector2 gravity = Vector2(material->get_gravity().x, material->get_gravity().y);
- set_gravity(gravity);
- set_lifetime_randomness(material->get_lifetime_randomness());
+ set_gravity(Vector2(proc_mat->get_gravity().x, proc_mat->get_gravity().y));
+ set_lifetime_randomness(proc_mat->get_lifetime_randomness());
#define CONVERT_PARAM(m_param) \
- set_param_min(m_param, material->get_param_min(ParticleProcessMaterial::m_param)); \
+ set_param_min(m_param, proc_mat->get_param_min(ParticleProcessMaterial::m_param)); \
{ \
- Ref<CurveTexture> ctex = material->get_param_texture(ParticleProcessMaterial::m_param); \
+ Ref<CurveTexture> ctex = proc_mat->get_param_texture(ParticleProcessMaterial::m_param); \
if (ctex.is_valid()) \
set_param_curve(m_param, ctex->get_curve()); \
} \
- set_param_max(m_param, material->get_param_max(ParticleProcessMaterial::m_param));
+ set_param_max(m_param, proc_mat->get_param_max(ParticleProcessMaterial::m_param));
CONVERT_PARAM(PARAM_INITIAL_LINEAR_VELOCITY);
CONVERT_PARAM(PARAM_ANGULAR_VELOCITY);
diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h
index ea735411a8..141e5f9139 100644
--- a/scene/2d/cpu_particles_2d.h
+++ b/scene/2d/cpu_particles_2d.h
@@ -152,8 +152,8 @@ private:
Vector2 direction = Vector2(1, 0);
real_t spread = 45.0;
- real_t parameters_min[PARAM_MAX];
- real_t parameters_max[PARAM_MAX];
+ real_t parameters_min[PARAM_MAX] = {};
+ real_t parameters_max[PARAM_MAX] = {};
Ref<Curve> curve_parameters[PARAM_MAX];
Color color;
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index 18f709f241..9786b01058 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -353,13 +353,13 @@ void GPUParticles2D::_validate_property(PropertyInfo &p_property) const {
}
void GPUParticles2D::emit_particle(const Transform2D &p_transform2d, const Vector2 &p_velocity2d, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
- Transform3D transform;
- transform.basis.set_column(0, Vector3(p_transform2d.columns[0].x, p_transform2d.columns[0].y, 0));
- transform.basis.set_column(1, Vector3(p_transform2d.columns[1].x, p_transform2d.columns[1].y, 0));
- transform.set_origin(Vector3(p_transform2d.get_origin().x, p_transform2d.get_origin().y, 0));
+ Transform3D emit_transform;
+ emit_transform.basis.set_column(0, Vector3(p_transform2d.columns[0].x, p_transform2d.columns[0].y, 0));
+ emit_transform.basis.set_column(1, Vector3(p_transform2d.columns[1].x, p_transform2d.columns[1].y, 0));
+ emit_transform.set_origin(Vector3(p_transform2d.get_origin().x, p_transform2d.get_origin().y, 0));
Vector3 velocity = Vector3(p_velocity2d.x, p_velocity2d.y, 0);
- RS::get_singleton()->particles_emit(particles, transform, velocity, p_color, p_custom, p_emit_flags);
+ RS::get_singleton()->particles_emit(particles, emit_transform, velocity, p_color, p_custom, p_emit_flags);
}
void GPUParticles2D::_attach_sub_emitter() {
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 90402260ed..80169bc80c 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -454,7 +454,7 @@ void DirectionalLight2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_max_distance", "pixels"), &DirectionalLight2D::set_max_distance);
ClassDB::bind_method(D_METHOD("get_max_distance"), &DirectionalLight2D::get_max_distance);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0,1,0.01,suffix:px"), "set_height", "get_height");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_height", "get_height");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "0,16384.0,1.0,or_greater,suffix:px"), "set_max_distance", "get_max_distance");
}
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 55cebdaadc..f077f7f5e6 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -178,6 +178,13 @@ NavigationAgent2D::NavigationAgent2D() {
set_time_horizon(20.0);
set_radius(10.0);
set_max_speed(200.0);
+
+ // Preallocate query and result objects to improve performance.
+ navigation_query = Ref<NavigationPathQueryParameters2D>();
+ navigation_query.instantiate();
+
+ navigation_result = Ref<NavigationPathQueryResult2D>();
+ navigation_result.instantiate();
}
NavigationAgent2D::~NavigationAgent2D() {
@@ -314,6 +321,8 @@ Vector2 NavigationAgent2D::get_target_location() const {
Vector2 NavigationAgent2D::get_next_location() {
update_navigation();
+
+ const Vector<Vector2> &navigation_path = navigation_result->get_path();
if (navigation_path.size() == 0) {
ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector2(), "The agent has no parent.");
return agent_parent->get_global_position();
@@ -322,6 +331,10 @@ Vector2 NavigationAgent2D::get_next_location() {
}
}
+const Vector<Vector2> &NavigationAgent2D::get_nav_path() const {
+ return navigation_result->get_path();
+}
+
real_t NavigationAgent2D::distance_to_target() const {
ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent.");
return agent_parent->get_global_position().distance_to(target_location);
@@ -342,6 +355,8 @@ bool NavigationAgent2D::is_navigation_finished() {
Vector2 NavigationAgent2D::get_final_location() {
update_navigation();
+
+ const Vector<Vector2> &navigation_path = navigation_result->get_path();
if (navigation_path.size() == 0) {
return Vector2();
}
@@ -391,22 +406,24 @@ void NavigationAgent2D::update_navigation() {
update_frame_id = Engine::get_singleton()->get_physics_frames();
- Vector2 o = agent_parent->get_global_position();
+ Vector2 origin = agent_parent->get_global_position();
bool reload_path = false;
if (NavigationServer2D::get_singleton()->agent_is_map_changed(agent)) {
reload_path = true;
- } else if (navigation_path.size() == 0) {
+ } else if (navigation_result->get_path().size() == 0) {
reload_path = true;
} else {
// Check if too far from the navigation path
if (nav_path_index > 0) {
+ const Vector<Vector2> &navigation_path = navigation_result->get_path();
+
Vector2 segment[2];
segment[0] = navigation_path[nav_path_index - 1];
segment[1] = navigation_path[nav_path_index];
- Vector2 p = Geometry2D::get_closest_point_to_segment(o, segment);
- if (o.distance_to(p) >= path_max_distance) {
+ Vector2 p = Geometry2D::get_closest_point_to_segment(origin, segment);
+ if (origin.distance_to(p) >= path_max_distance) {
// To faraway, reload path
reload_path = true;
}
@@ -414,24 +431,31 @@ void NavigationAgent2D::update_navigation() {
}
if (reload_path) {
+ navigation_query->set_start_position(origin);
+ navigation_query->set_target_position(target_location);
+ navigation_query->set_navigation_layers(navigation_layers);
+
if (map_override.is_valid()) {
- navigation_path = NavigationServer2D::get_singleton()->map_get_path(map_override, o, target_location, true, navigation_layers);
+ navigation_query->set_map(map_override);
} else {
- navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true, navigation_layers);
+ navigation_query->set_map(agent_parent->get_world_2d()->get_navigation_map());
}
+
+ NavigationServer2D::get_singleton()->query_path(navigation_query, navigation_result);
navigation_finished = false;
nav_path_index = 0;
emit_signal(SNAME("path_changed"));
}
- if (navigation_path.size() == 0) {
+ if (navigation_result->get_path().size() == 0) {
return;
}
// Check if we can advance the navigation path
if (navigation_finished == false) {
// Advances to the next far away location.
- while (o.distance_to(navigation_path[nav_path_index]) < path_desired_distance) {
+ const Vector<Vector2> &navigation_path = navigation_result->get_path();
+ while (origin.distance_to(navigation_path[nav_path_index]) < path_desired_distance) {
nav_path_index += 1;
if (nav_path_index == navigation_path.size()) {
_check_distance_to_target();
@@ -445,7 +469,7 @@ void NavigationAgent2D::update_navigation() {
}
void NavigationAgent2D::_request_repath() {
- navigation_path.clear();
+ navigation_result->reset();
target_reached = false;
navigation_finished = false;
update_frame_id = 0;
diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h
index 2fbacc4c76..5abd3c0317 100644
--- a/scene/2d/navigation_agent_2d.h
+++ b/scene/2d/navigation_agent_2d.h
@@ -34,6 +34,8 @@
#include "scene/main/node.h"
class Node2D;
+class NavigationPathQueryParameters2D;
+class NavigationPathQueryResult2D;
class NavigationAgent2D : public Node {
GDCLASS(NavigationAgent2D, Node);
@@ -58,7 +60,8 @@ class NavigationAgent2D : public Node {
real_t path_max_distance = 3.0;
Vector2 target_location;
- Vector<Vector2> navigation_path;
+ Ref<NavigationPathQueryParameters2D> navigation_query;
+ Ref<NavigationPathQueryResult2D> navigation_result;
int nav_path_index = 0;
bool velocity_submitted = false;
Vector2 prev_safe_velocity;
@@ -138,9 +141,7 @@ public:
Vector2 get_next_location();
- Vector<Vector2> get_nav_path() const {
- return navigation_path;
- }
+ const Vector<Vector2> &get_nav_path() const;
int get_nav_path_index() const {
return nav_path_index;
diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp
index e46bb79551..cbec4db4c5 100644
--- a/scene/2d/navigation_obstacle_2d.cpp
+++ b/scene/2d/navigation_obstacle_2d.cpp
@@ -153,7 +153,7 @@ void NavigationObstacle2D::reevaluate_agent_radius() {
real_t NavigationObstacle2D::estimate_agent_radius() const {
if (parent_node2d && parent_node2d->is_inside_tree()) {
// Estimate the radius of this physics body
- real_t radius = 0.0;
+ real_t max_radius = 0.0;
for (int i(0); i < parent_node2d->get_child_count(); i++) {
// For each collision shape
CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(parent_node2d->get_child(i));
@@ -167,17 +167,17 @@ real_t NavigationObstacle2D::estimate_agent_radius() const {
Size2 s = cs->get_global_scale();
r *= MAX(s.x, s.y);
// Takes the biggest radius
- radius = MAX(radius, r);
+ max_radius = MAX(max_radius, r);
} else if (cs && !cs->is_inside_tree()) {
WARN_PRINT("A CollisionShape2D of the NavigationObstacle2D parent node was not inside the SceneTree when estimating the obstacle radius."
"\nMove the NavigationObstacle2D to a child position below any CollisionShape2D node of the parent node so the CollisionShape2D is already inside the SceneTree.");
}
}
Vector2 s = parent_node2d->get_global_scale();
- radius *= MAX(s.x, s.y);
+ max_radius *= MAX(s.x, s.y);
- if (radius > 0.0) {
- return radius;
+ if (max_radius > 0.0) {
+ return max_radius;
}
}
return 1.0; // Never a 0 radius
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index b1e2875a8b..6e8ecb13b1 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -354,10 +354,13 @@ void NavigationPolygon::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines");
}
+/////////////////////////////
+
void NavigationRegion2D::set_enabled(bool p_enabled) {
if (enabled == p_enabled) {
return;
}
+
enabled = p_enabled;
if (!is_inside_tree()) {
@@ -384,35 +387,50 @@ bool NavigationRegion2D::is_enabled() const {
}
void NavigationRegion2D::set_navigation_layers(uint32_t p_navigation_layers) {
- NavigationServer2D::get_singleton()->region_set_navigation_layers(region, p_navigation_layers);
+ if (navigation_layers == p_navigation_layers) {
+ return;
+ }
+
+ navigation_layers = p_navigation_layers;
+
+ NavigationServer2D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
}
uint32_t NavigationRegion2D::get_navigation_layers() const {
- return NavigationServer2D::get_singleton()->region_get_navigation_layers(region);
+ return navigation_layers;
}
void NavigationRegion2D::set_navigation_layer_value(int p_layer_number, bool p_value) {
ERR_FAIL_COND_MSG(p_layer_number < 1, "Navigation layer number must be between 1 and 32 inclusive.");
ERR_FAIL_COND_MSG(p_layer_number > 32, "Navigation layer number must be between 1 and 32 inclusive.");
+
uint32_t _navigation_layers = get_navigation_layers();
+
if (p_value) {
_navigation_layers |= 1 << (p_layer_number - 1);
} else {
_navigation_layers &= ~(1 << (p_layer_number - 1));
}
+
set_navigation_layers(_navigation_layers);
}
bool NavigationRegion2D::get_navigation_layer_value(int p_layer_number) const {
ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Navigation layer number must be between 1 and 32 inclusive.");
ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Navigation layer number must be between 1 and 32 inclusive.");
+
return get_navigation_layers() & (1 << (p_layer_number - 1));
}
void NavigationRegion2D::set_enter_cost(real_t p_enter_cost) {
ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive.");
- enter_cost = MAX(p_enter_cost, 0.0);
- NavigationServer2D::get_singleton()->region_set_enter_cost(region, p_enter_cost);
+ if (Math::is_equal_approx(enter_cost, p_enter_cost)) {
+ return;
+ }
+
+ enter_cost = p_enter_cost;
+
+ NavigationServer2D::get_singleton()->region_set_enter_cost(region, enter_cost);
}
real_t NavigationRegion2D::get_enter_cost() const {
@@ -421,7 +439,12 @@ real_t NavigationRegion2D::get_enter_cost() const {
void NavigationRegion2D::set_travel_cost(real_t p_travel_cost) {
ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive.");
- travel_cost = MAX(p_travel_cost, 0.0);
+ if (Math::is_equal_approx(travel_cost, p_travel_cost)) {
+ return;
+ }
+
+ travel_cost = p_travel_cost;
+
NavigationServer2D::get_singleton()->region_set_travel_cost(region, travel_cost);
}
@@ -433,7 +456,6 @@ RID NavigationRegion2D::get_region_rid() const {
return region;
}
-/////////////////////////////
#ifdef TOOLS_ENABLED
Rect2 NavigationRegion2D::_edit_get_rect() const {
return navpoly.is_valid() ? navpoly->_edit_get_rect() : Rect2();
diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h
index 893de41a94..c630e20780 100644
--- a/scene/2d/navigation_region_2d.h
+++ b/scene/2d/navigation_region_2d.h
@@ -96,10 +96,10 @@ class NavigationRegion2D : public Node2D {
bool enabled = true;
RID region;
- Ref<NavigationPolygon> navpoly;
-
+ uint32_t navigation_layers = 1;
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
+ Ref<NavigationPolygon> navpoly;
void _navpoly_changed();
void _map_changed(RID p_RID);
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 7765533016..2518069b78 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -437,7 +437,7 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent);
ADD_GROUP("Transform", "");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_less,or_greater,no_slider,suffix:px"), "set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_less,or_greater,hide_slider,suffix:px"), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians"), "set_rotation", "get_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale", PROPERTY_HINT_LINK), "set_scale", "get_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "skew", PROPERTY_HINT_RANGE, "-89.9,89.9,0.1,radians"), "set_skew", "get_skew");
diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp
index f1a28b7852..b7e6eb8ea5 100644
--- a/scene/2d/parallax_background.cpp
+++ b/scene/2d/parallax_background.cpp
@@ -71,29 +71,29 @@ void ParallaxBackground::_update_scroll() {
return;
}
- Vector2 ofs = base_offset + offset * base_scale;
+ Vector2 scroll_ofs = base_offset + offset * base_scale;
Size2 vps = get_viewport_size();
- ofs = -ofs;
+ scroll_ofs = -scroll_ofs;
if (limit_begin.x < limit_end.x) {
- if (ofs.x < limit_begin.x) {
- ofs.x = limit_begin.x;
- } else if (ofs.x + vps.x > limit_end.x) {
- ofs.x = limit_end.x - vps.x;
+ if (scroll_ofs.x < limit_begin.x) {
+ scroll_ofs.x = limit_begin.x;
+ } else if (scroll_ofs.x + vps.x > limit_end.x) {
+ scroll_ofs.x = limit_end.x - vps.x;
}
}
if (limit_begin.y < limit_end.y) {
- if (ofs.y < limit_begin.y) {
- ofs.y = limit_begin.y;
- } else if (ofs.y + vps.y > limit_end.y) {
- ofs.y = limit_end.y - vps.y;
+ if (scroll_ofs.y < limit_begin.y) {
+ scroll_ofs.y = limit_begin.y;
+ } else if (scroll_ofs.y + vps.y > limit_end.y) {
+ scroll_ofs.y = limit_end.y - vps.y;
}
}
- ofs = -ofs;
+ scroll_ofs = -scroll_ofs;
- final_offset = ofs;
+ final_offset = scroll_ofs;
for (int i = 0; i < get_child_count(); i++) {
ParallaxLayer *l = Object::cast_to<ParallaxLayer>(get_child(i));
@@ -102,9 +102,9 @@ void ParallaxBackground::_update_scroll() {
}
if (ignore_camera_zoom) {
- l->set_base_offset_and_scale((ofs + screen_offset * (scale - 1)) / scale, 1.0);
+ l->set_base_offset_and_scale((scroll_ofs + screen_offset * (scale - 1)) / scale, 1.0);
} else {
- l->set_base_offset_and_scale(ofs, scale);
+ l->set_base_offset_and_scale(scroll_ofs, scale);
}
}
}
diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp
index 01e4bf19f3..feb1fcd90c 100644
--- a/scene/2d/parallax_layer.cpp
+++ b/scene/2d/parallax_layer.cpp
@@ -37,9 +37,9 @@ void ParallaxLayer::set_motion_scale(const Size2 &p_scale) {
ParallaxBackground *pb = Object::cast_to<ParallaxBackground>(get_parent());
if (pb && is_inside_tree()) {
- Vector2 ofs = pb->get_final_offset();
- real_t scale = pb->get_scroll_scale();
- set_base_offset_and_scale(ofs, scale);
+ Vector2 final_ofs = pb->get_final_offset();
+ real_t scroll_scale = pb->get_scroll_scale();
+ set_base_offset_and_scale(final_ofs, scroll_scale);
}
}
@@ -52,9 +52,9 @@ void ParallaxLayer::set_motion_offset(const Size2 &p_offset) {
ParallaxBackground *pb = Object::cast_to<ParallaxBackground>(get_parent());
if (pb && is_inside_tree()) {
- Vector2 ofs = pb->get_final_offset();
- real_t scale = pb->get_scroll_scale();
- set_base_offset_and_scale(ofs, scale);
+ Vector2 final_ofs = pb->get_final_offset();
+ real_t scroll_scale = pb->get_scroll_scale();
+ set_base_offset_and_scale(final_ofs, scroll_scale);
}
}
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 7a3471777d..0f3e6c7529 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -62,7 +62,7 @@ Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_distance, bool p
if (move_and_collide(parameters, result, p_test_only)) {
// Create a new instance when the cached reference is invalid or still in use in script.
- if (motion_cache.is_null() || motion_cache->reference_get_count() > 1) {
+ if (motion_cache.is_null() || motion_cache->get_reference_count() > 1) {
motion_cache.instantiate();
motion_cache->owner = this;
}
@@ -262,21 +262,16 @@ void AnimatableBody2D::_update_kinematic_motion() {
#endif
if (sync_to_physics) {
- PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
+ PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &AnimatableBody2D::_body_state_changed));
set_only_update_transform_changes(true);
set_notify_local_transform(true);
} else {
- PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), nullptr, nullptr);
+ PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), Callable());
set_only_update_transform_changes(false);
set_notify_local_transform(false);
}
}
-void AnimatableBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) {
- AnimatableBody2D *body = static_cast<AnimatableBody2D *>(p_instance);
- body->_body_state_changed(p_state);
-}
-
void AnimatableBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
if (!sync_to_physics) {
return;
@@ -438,11 +433,6 @@ struct _RigidBody2DInOut {
int local_shape = 0;
};
-void RigidBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) {
- RigidBody2D *body = static_cast<RigidBody2D *>(p_instance);
- body->_body_state_changed(p_state);
-}
-
void RigidBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
set_block_transform_notify(true); // don't want notify (would feedback loop)
if (!freeze || freeze_mode != FREEZE_MODE_KINEMATIC) {
@@ -481,28 +471,28 @@ void RigidBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) {
//put the ones to add
for (int i = 0; i < p_state->get_contact_count(); i++) {
- RID rid = p_state->get_contact_collider(i);
- ObjectID obj = p_state->get_contact_collider_id(i);
+ RID col_rid = p_state->get_contact_collider(i);
+ ObjectID col_obj = p_state->get_contact_collider_id(i);
int local_shape = p_state->get_contact_local_shape(i);
- int shape = p_state->get_contact_collider_shape(i);
+ int col_shape = p_state->get_contact_collider_shape(i);
- HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(obj);
+ HashMap<ObjectID, BodyState>::Iterator E = contact_monitor->body_map.find(col_obj);
if (!E) {
- toadd[toadd_count].rid = rid;
+ toadd[toadd_count].rid = col_rid;
toadd[toadd_count].local_shape = local_shape;
- toadd[toadd_count].id = obj;
- toadd[toadd_count].shape = shape;
+ toadd[toadd_count].id = col_obj;
+ toadd[toadd_count].shape = col_shape;
toadd_count++;
continue;
}
- ShapePair sp(shape, local_shape);
+ ShapePair sp(col_shape, local_shape);
int idx = E->value.shapes.find(sp);
if (idx == -1) {
- toadd[toadd_count].rid = rid;
+ toadd[toadd_count].rid = col_rid;
toadd[toadd_count].local_shape = local_shape;
- toadd[toadd_count].id = obj;
- toadd[toadd_count].shape = shape;
+ toadd[toadd_count].id = col_obj;
+ toadd[toadd_count].shape = col_shape;
toadd_count++;
continue;
}
@@ -1079,7 +1069,7 @@ void RigidBody2D::_validate_property(PropertyInfo &p_property) const {
RigidBody2D::RigidBody2D() :
PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) {
- PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback);
+ PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &RigidBody2D::_body_state_changed));
}
RigidBody2D::~RigidBody2D() {
@@ -1144,6 +1134,7 @@ bool CharacterBody2D::move_and_slide() {
if (!current_platform_velocity.is_zero_approx()) {
PhysicsServer2D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
parameters.exclude_bodies.insert(platform_rid);
if (platform_object_id.is_valid()) {
parameters.exclude_objects.insert(platform_object_id);
@@ -1202,6 +1193,7 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
for (int iteration = 0; iteration < max_slides; ++iteration) {
PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
Vector2 prev_position = parameters.from.columns[2];
@@ -1358,6 +1350,7 @@ void CharacterBody2D::_move_and_slide_floating(double p_delta) {
bool first_slide = true;
for (int iteration = 0; iteration < max_slides; ++iteration) {
PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
PhysicsServer2D::MotionResult result;
bool collided = move_and_collide(parameters, result, false, false);
@@ -1404,7 +1397,7 @@ void CharacterBody2D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_
real_t length = MAX(floor_snap_length, margin);
PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
- parameters.recovery_as_collision = true; // Report margin recovery as collision to improve floor detection.
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
parameters.collide_separation_ray = true;
PhysicsServer2D::MotionResult result;
@@ -1440,7 +1433,7 @@ bool CharacterBody2D::_on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_f
real_t length = MAX(floor_snap_length, margin);
PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
- parameters.recovery_as_collision = true; // Report margin recovery as collision to improve floor detection.
+ parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
parameters.collide_separation_ray = true;
PhysicsServer2D::MotionResult result;
@@ -1554,7 +1547,7 @@ Ref<KinematicCollision2D> CharacterBody2D::_get_slide_collision(int p_bounce) {
}
// Create a new instance when the cached reference is invalid or still in use in script.
- if (slide_colliders[p_bounce].is_null() || slide_colliders[p_bounce]->reference_get_count() > 1) {
+ if (slide_colliders[p_bounce].is_null() || slide_colliders[p_bounce]->get_reference_count() > 1) {
slide_colliders.write[p_bounce].instantiate();
slide_colliders.write[p_bounce]->owner = this;
}
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index b5759c54f7..f80b2a07c9 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -146,9 +146,9 @@ void Bone2D::_notification(int p_what) {
queue_redraw();
if (get_parent()) {
- Bone2D *parent_bone = Object::cast_to<Bone2D>(get_parent());
- if (parent_bone) {
- parent_bone->queue_redraw();
+ Bone2D *p_bone = Object::cast_to<Bone2D>(get_parent());
+ if (p_bone) {
+ p_bone->queue_redraw();
}
}
#endif // TOOLS_ENABLED
@@ -192,10 +192,8 @@ void Bone2D::_notification(int p_what) {
cache_transform = tmp_trans;
} break;
- // Bone2D Editor gizmo drawing:
-#ifndef _MSC_VER
-#warning TODO Bone2D gizmo drawing needs to be moved to an editor plugin
-#endif
+ // Bone2D Editor gizmo drawing.
+ // TODO: Bone2D gizmo drawing needs to be moved to an editor plugin.
case NOTIFICATION_DRAW: {
// Only draw the gizmo in the editor!
if (Engine::get_singleton()->is_editor_hint() == false) {
diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp
index 0ecf8333a0..0784318442 100644
--- a/scene/2d/sprite_2d.cpp
+++ b/scene/2d/sprite_2d.cpp
@@ -309,9 +309,7 @@ bool Sprite2D::is_pixel_opaque(const Point2 &p_point) const {
q.y = 1.0f - q.y;
}
q = q * src_rect.size + src_rect.position;
-#ifndef _MSC_VER
-#warning this need to be obtained from CanvasItem new repeat mode (but it needs to guess it from hierarchy, need to add a function for that)
-#endif
+ // TODO: This need to be obtained from CanvasItem new repeat mode (but it needs to guess it from hierarchy, need to add a function for that).
bool is_repeat = false;
bool is_mirrored_repeat = false;
if (is_repeat) {
@@ -446,7 +444,7 @@ void Sprite2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes");
ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "frame_coords", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
ADD_GROUP("Region", "region_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled");
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 42b76d0136..26627a4fca 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -43,10 +43,10 @@ HashMap<Vector2i, TileSet::CellNeighbor> TileMap::TerrainConstraint::get_overlap
ERR_FAIL_COND_V(is_center_bit(), output);
- Ref<TileSet> tile_set = tile_map->get_tileset();
- ERR_FAIL_COND_V(!tile_set.is_valid(), output);
+ Ref<TileSet> ts = tile_map->get_tileset();
+ ERR_FAIL_COND_V(!ts.is_valid(), output);
- TileSet::TileShape shape = tile_set->get_tile_shape();
+ TileSet::TileShape shape = ts->get_tile_shape();
if (shape == TileSet::TILE_SHAPE_SQUARE) {
switch (bit) {
case 1:
@@ -87,7 +87,7 @@ HashMap<Vector2i, TileSet::CellNeighbor> TileMap::TerrainConstraint::get_overlap
}
} else {
// Half offset shapes.
- TileSet::TileOffsetAxis offset_axis = tile_set->get_tile_offset_axis();
+ TileSet::TileOffsetAxis offset_axis = ts->get_tile_offset_axis();
if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
switch (bit) {
case 1:
@@ -150,8 +150,8 @@ HashMap<Vector2i, TileSet::CellNeighbor> TileMap::TerrainConstraint::get_overlap
TileMap::TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const Vector2i &p_position, int p_terrain) {
tile_map = p_tile_map;
- Ref<TileSet> tile_set = tile_map->get_tileset();
- ERR_FAIL_COND(!tile_set.is_valid());
+ Ref<TileSet> ts = tile_map->get_tileset();
+ ERR_FAIL_COND(!ts.is_valid());
bit = 0;
base_cell_coords = p_position;
@@ -162,10 +162,10 @@ TileMap::TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const V
// The way we build the constraint make it easy to detect conflicting constraints.
tile_map = p_tile_map;
- Ref<TileSet> tile_set = tile_map->get_tileset();
- ERR_FAIL_COND(!tile_set.is_valid());
+ Ref<TileSet> ts = tile_map->get_tileset();
+ ERR_FAIL_COND(!ts.is_valid());
- TileSet::TileShape shape = tile_set->get_tile_shape();
+ TileSet::TileShape shape = ts->get_tile_shape();
if (shape == TileSet::TILE_SHAPE_SQUARE) {
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
@@ -244,7 +244,7 @@ TileMap::TerrainConstraint::TerrainConstraint(const TileMap *p_tile_map, const V
}
} else {
// Half-offset shapes
- TileSet::TileOffsetAxis offset_axis = tile_set->get_tile_offset_axis();
+ TileSet::TileOffsetAxis offset_axis = ts->get_tile_offset_axis();
if (offset_axis == TileSet::TILE_OFFSET_AXIS_HORIZONTAL) {
switch (p_bit) {
case TileSet::CELL_NEIGHBOR_RIGHT_SIDE:
@@ -758,12 +758,12 @@ void TileMap::set_y_sort_enabled(bool p_enable) {
}
Vector2i TileMap::_coords_to_quadrant_coords(int p_layer, const Vector2i &p_coords) const {
- int quadrant_size = get_effective_quadrant_size(p_layer);
+ int quad_size = get_effective_quadrant_size(p_layer);
// Rounding down, instead of simply rounding towards zero (truncating)
return Vector2i(
- p_coords.x > 0 ? p_coords.x / quadrant_size : (p_coords.x - (quadrant_size - 1)) / quadrant_size,
- p_coords.y > 0 ? p_coords.y / quadrant_size : (p_coords.y - (quadrant_size - 1)) / quadrant_size);
+ p_coords.x > 0 ? p_coords.x / quad_size : (p_coords.x - (quad_size - 1)) / quad_size,
+ p_coords.y > 0 ? p_coords.y / quad_size : (p_coords.y - (quad_size - 1)) / quad_size);
}
HashMap<Vector2i, TileMapQuadrant>::Iterator TileMap::_create_quadrant(int p_layer, const Vector2i &p_qk) {
@@ -1007,8 +1007,24 @@ void TileMap::_recompute_rect_cache() {
void TileMap::_rendering_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_ENTER_CANVAS: {
+ bool node_visible = is_visible_in_tree();
+ for (int layer = 0; layer < (int)layers.size(); layer++) {
+ for (KeyValue<Vector2i, TileMapQuadrant> &E_quadrant : layers[layer].quadrant_map) {
+ TileMapQuadrant &q = E_quadrant.value;
+ for (const KeyValue<Vector2i, RID> &kv : q.occluders) {
+ Transform2D xform;
+ xform.set_origin(map_to_local(kv.key));
+ RS::get_singleton()->canvas_light_occluder_attach_to_canvas(kv.value, get_canvas());
+ RS::get_singleton()->canvas_light_occluder_set_transform(kv.value, get_global_transform() * xform);
+ RS::get_singleton()->canvas_light_occluder_set_enabled(kv.value, node_visible);
+ }
+ }
+ }
+ } break;
+
case NOTIFICATION_VISIBILITY_CHANGED: {
- bool visible = is_visible_in_tree();
+ bool node_visible = is_visible_in_tree();
for (int layer = 0; layer < (int)layers.size(); layer++) {
for (KeyValue<Vector2i, TileMapQuadrant> &E_quadrant : layers[layer].quadrant_map) {
TileMapQuadrant &q = E_quadrant.value;
@@ -1017,8 +1033,8 @@ void TileMap::_rendering_notification(int p_what) {
for (const KeyValue<Vector2i, Vector2i> &E_cell : q.local_to_map) {
Transform2D xform;
xform.set_origin(E_cell.key);
- for (const RID &occluder : q.occluders) {
- RS::get_singleton()->canvas_light_occluder_set_enabled(occluder, visible);
+ for (const KeyValue<Vector2i, RID> &kv : q.occluders) {
+ RS::get_singleton()->canvas_light_occluder_set_enabled(kv.value, node_visible);
}
}
}
@@ -1034,12 +1050,10 @@ void TileMap::_rendering_notification(int p_what) {
TileMapQuadrant &q = E_quadrant.value;
// Update occluders transform.
- for (const KeyValue<Vector2i, Vector2i> &E_cell : q.local_to_map) {
+ for (const KeyValue<Vector2i, RID> &kv : q.occluders) {
Transform2D xform;
- xform.set_origin(E_cell.key);
- for (const RID &occluder : q.occluders) {
- RS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform() * xform);
- }
+ xform.set_origin(map_to_local(kv.key));
+ RenderingServer::get_singleton()->canvas_light_occluder_set_transform(kv.value, get_global_transform() * xform);
}
}
}
@@ -1050,6 +1064,17 @@ void TileMap::_rendering_notification(int p_what) {
RenderingServer::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), is_y_sort_enabled());
}
} break;
+
+ case NOTIFICATION_EXIT_CANVAS: {
+ for (int layer = 0; layer < (int)layers.size(); layer++) {
+ for (KeyValue<Vector2i, TileMapQuadrant> &E_quadrant : layers[layer].quadrant_map) {
+ TileMapQuadrant &q = E_quadrant.value;
+ for (const KeyValue<Vector2i, RID> &kv : q.occluders) {
+ RS::get_singleton()->canvas_light_occluder_attach_to_canvas(kv.value, RID());
+ }
+ }
+ }
+ } break;
}
}
@@ -1091,7 +1116,7 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List
ERR_FAIL_COND(!is_inside_tree());
ERR_FAIL_COND(!tile_set.is_valid());
- bool visible = is_visible_in_tree();
+ bool node_visible = is_visible_in_tree();
SelfList<TileMapQuadrant> *q_list_element = r_dirty_quadrant_list.first();
while (q_list_element) {
@@ -1106,26 +1131,26 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List
q.canvas_items.clear();
// Free the occluders.
- for (const RID &occluder : q.occluders) {
- rs->free(occluder);
+ for (const KeyValue<Vector2i, RID> &kv : q.occluders) {
+ rs->free(kv.value);
}
q.occluders.clear();
// Those allow to group cell per material or z-index.
Ref<Material> prev_material;
int prev_z_index = 0;
- RID prev_canvas_item;
+ RID prev_ci;
- Color modulate = get_self_modulate();
- modulate *= get_layer_modulate(q.layer);
+ Color tile_modulate = get_self_modulate();
+ tile_modulate *= get_layer_modulate(q.layer);
if (selected_layer >= 0) {
int z1 = get_layer_z_index(q.layer);
int z2 = get_layer_z_index(selected_layer);
if (z1 < z2 || (z1 == z2 && q.layer < selected_layer)) {
- modulate = modulate.darkened(0.5);
+ tile_modulate = tile_modulate.darkened(0.5);
} else if (z1 > z2 || (z1 == z2 && q.layer > selected_layer)) {
- modulate = modulate.darkened(0.5);
- modulate.a *= 0.3;
+ tile_modulate = tile_modulate.darkened(0.5);
+ tile_modulate.a *= 0.3;
}
}
@@ -1152,53 +1177,53 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List
}
Ref<Material> mat = tile_data->get_material();
- int z_index = tile_data->get_z_index();
+ int tile_z_index = tile_data->get_z_index();
// Quandrant pos.
- Vector2 position = map_to_local(q.coords * get_effective_quadrant_size(q.layer));
+ Vector2 tile_position = map_to_local(q.coords * get_effective_quadrant_size(q.layer));
if (is_y_sort_enabled() && layers[q.layer].y_sort_enabled) {
// When Y-sorting, the quandrant size is sure to be 1, we can thus offset the CanvasItem.
- position.y += layers[q.layer].y_sort_origin + tile_data->get_y_sort_origin();
+ tile_position.y += layers[q.layer].y_sort_origin + tile_data->get_y_sort_origin();
}
// --- CanvasItems ---
// Create two canvas items, for rendering and debug.
- RID canvas_item;
+ RID ci;
// Check if the material or the z_index changed.
- if (prev_canvas_item == RID() || prev_material != mat || prev_z_index != z_index) {
+ if (prev_ci == RID() || prev_material != mat || prev_z_index != tile_z_index) {
// If so, create a new CanvasItem.
- canvas_item = rs->canvas_item_create();
+ ci = rs->canvas_item_create();
if (mat.is_valid()) {
- rs->canvas_item_set_material(canvas_item, mat->get_rid());
+ rs->canvas_item_set_material(ci, mat->get_rid());
}
- rs->canvas_item_set_parent(canvas_item, layers[q.layer].canvas_item);
- rs->canvas_item_set_use_parent_material(canvas_item, get_use_parent_material() || get_material().is_valid());
+ rs->canvas_item_set_parent(ci, layers[q.layer].canvas_item);
+ rs->canvas_item_set_use_parent_material(ci, get_use_parent_material() || get_material().is_valid());
Transform2D xform;
- xform.set_origin(position);
- rs->canvas_item_set_transform(canvas_item, xform);
+ xform.set_origin(tile_position);
+ rs->canvas_item_set_transform(ci, xform);
- rs->canvas_item_set_light_mask(canvas_item, get_light_mask());
- rs->canvas_item_set_z_as_relative_to_parent(canvas_item, true);
- rs->canvas_item_set_z_index(canvas_item, z_index);
+ rs->canvas_item_set_light_mask(ci, get_light_mask());
+ rs->canvas_item_set_z_as_relative_to_parent(ci, true);
+ rs->canvas_item_set_z_index(ci, tile_z_index);
- rs->canvas_item_set_default_texture_filter(canvas_item, RS::CanvasItemTextureFilter(get_texture_filter()));
- rs->canvas_item_set_default_texture_repeat(canvas_item, RS::CanvasItemTextureRepeat(get_texture_repeat()));
+ rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(get_texture_filter()));
+ rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(get_texture_repeat()));
- q.canvas_items.push_back(canvas_item);
+ q.canvas_items.push_back(ci);
- prev_canvas_item = canvas_item;
+ prev_ci = ci;
prev_material = mat;
- prev_z_index = z_index;
+ prev_z_index = tile_z_index;
} else {
// Keep the same canvas_item to draw on.
- canvas_item = prev_canvas_item;
+ ci = prev_ci;
}
// Drawing the tile in the canvas item.
- draw_tile(canvas_item, E_cell.key - position, tile_set, c.source_id, c.get_atlas_coords(), c.alternative_tile, -1, modulate, tile_data);
+ draw_tile(ci, E_cell.key - tile_position, tile_set, c.source_id, c.get_atlas_coords(), c.alternative_tile, -1, tile_modulate, tile_data);
// --- Occluders ---
for (int i = 0; i < tile_set->get_occlusion_layers_count(); i++) {
@@ -1206,12 +1231,12 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List
xform.set_origin(E_cell.key);
if (tile_data->get_occluder(i).is_valid()) {
RID occluder_id = rs->canvas_light_occluder_create();
- rs->canvas_light_occluder_set_enabled(occluder_id, visible);
+ rs->canvas_light_occluder_set_enabled(occluder_id, node_visible);
rs->canvas_light_occluder_set_transform(occluder_id, get_global_transform() * xform);
rs->canvas_light_occluder_set_polygon(occluder_id, tile_data->get_occluder(i)->get_rid());
rs->canvas_light_occluder_attach_to_canvas(occluder_id, get_canvas());
rs->canvas_light_occluder_set_light_mask(occluder_id, tile_set->get_occlusion_layer_light_mask(i));
- q.occluders.push_back(occluder_id);
+ q.occluders[E_cell.value] = occluder_id;
}
}
}
@@ -1259,8 +1284,8 @@ void TileMap::_rendering_cleanup_quadrant(TileMapQuadrant *p_quadrant) {
p_quadrant->canvas_items.clear();
// Free the occluders.
- for (const RID &occluder : p_quadrant->occluders) {
- RenderingServer::get_singleton()->free(occluder);
+ for (const KeyValue<Vector2i, RID> &kv : p_quadrant->occluders) {
+ RenderingServer::get_singleton()->free(kv.value);
}
p_quadrant->occluders.clear();
}
@@ -1420,7 +1445,7 @@ void TileMap::_physics_notification(int p_what) {
#endif
if (is_inside_tree() && (!collision_animatable || in_editor)) {
// Update the new transform directly if we are not in animatable mode.
- Transform2D global_transform = get_global_transform();
+ Transform2D gl_transform = get_global_transform();
for (int layer = 0; layer < (int)layers.size(); layer++) {
for (KeyValue<Vector2i, TileMapQuadrant> &E : layers[layer].quadrant_map) {
TileMapQuadrant &q = E.value;
@@ -1428,7 +1453,7 @@ void TileMap::_physics_notification(int p_what) {
for (RID body : q.bodies) {
Transform2D xform;
xform.set_origin(map_to_local(bodies_coords[body]));
- xform = global_transform * xform;
+ xform = gl_transform * xform;
PhysicsServer2D::get_singleton()->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
}
}
@@ -1471,9 +1496,9 @@ void TileMap::_physics_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r
ERR_FAIL_COND(!is_inside_tree());
ERR_FAIL_COND(!tile_set.is_valid());
- Transform2D global_transform = get_global_transform();
- last_valid_transform = global_transform;
- new_transform = global_transform;
+ Transform2D gl_transform = get_global_transform();
+ last_valid_transform = gl_transform;
+ new_transform = gl_transform;
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
RID space = get_world_2d()->get_space();
@@ -1521,7 +1546,7 @@ void TileMap::_physics_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r
Transform2D xform;
xform.set_origin(map_to_local(E_cell));
- xform = global_transform * xform;
+ xform = gl_transform * xform;
ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
ps->body_attach_object_instance_id(body, get_instance_id());
@@ -1861,7 +1886,6 @@ void TileMap::_scenes_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r_
Ref<PackedScene> packed_scene = scenes_collection_source->get_scene_tile_scene(c.alternative_tile);
if (packed_scene.is_valid()) {
Node *scene = packed_scene->instantiate();
- add_child(scene);
Control *scene_as_control = Object::cast_to<Control>(scene);
Node2D *scene_as_node2d = Object::cast_to<Node2D>(scene);
if (scene_as_control) {
@@ -1871,6 +1895,7 @@ void TileMap::_scenes_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r_
xform.set_origin(map_to_local(E_cell));
scene_as_node2d->set_transform(xform * scene_as_node2d->get_transform());
}
+ add_child(scene);
q.scenes[E_cell] = scene->get_name();
}
}
@@ -2794,9 +2819,9 @@ Vector<int> TileMap::_get_tile_data(int p_layer) const {
// Export tile data to raw format
const HashMap<Vector2i, TileMapCell> &tile_map = layers[p_layer].tile_map;
- Vector<int> data;
- data.resize(tile_map.size() * 3);
- int *w = data.ptrw();
+ Vector<int> tile_data;
+ tile_data.resize(tile_map.size() * 3);
+ int *w = tile_data.ptrw();
// Save in highest format
@@ -2812,7 +2837,7 @@ Vector<int> TileMap::_get_tile_data(int p_layer) const {
idx += 3;
}
- return data;
+ return tile_data;
}
void TileMap::_build_runtime_update_tile_data(SelfList<TileMapQuadrant>::List &r_dirty_quadrant_list) {
@@ -3615,7 +3640,7 @@ TypedArray<Vector2i> TileMap::get_used_cells(int p_layer) const {
return a;
}
-Rect2 TileMap::get_used_rect() { // Not const because of cache
+Rect2i TileMap::get_used_rect() { // Not const because of cache
// Return the rect of the currently used area
if (used_rect_cache_dirty) {
bool first = true;
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index b1a2118c6b..d468675e91 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -68,7 +68,7 @@ struct TileMapQuadrant {
// Rendering.
List<RID> canvas_items;
- List<RID> occluders;
+ HashMap<Vector2i, RID> occluders;
// Physics.
List<RID> bodies;
@@ -375,7 +375,7 @@ public:
Vector2i get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const;
TypedArray<Vector2i> get_used_cells(int p_layer) const;
- Rect2 get_used_rect(); // Not const because of cache
+ Rect2i get_used_rect(); // Not const because of cache
// Override some methods of the CanvasItem class to pass the changes to the quadrants CanvasItems
virtual void set_light_mask(int p_light_mask) override;