summaryrefslogtreecommitdiffstats
path: root/scene/2d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d')
-rw-r--r--scene/2d/animated_sprite_2d.cpp4
-rw-r--r--scene/2d/audio_stream_player_2d.cpp13
-rw-r--r--scene/2d/canvas_modulate.cpp2
-rw-r--r--scene/2d/gpu_particles_2d.cpp23
-rw-r--r--scene/2d/light_2d.cpp2
-rw-r--r--scene/2d/light_occluder_2d.cpp2
-rw-r--r--scene/2d/navigation_link_2d.cpp135
-rw-r--r--scene/2d/navigation_link_2d.h13
-rw-r--r--scene/2d/navigation_region_2d.cpp1
-rw-r--r--scene/2d/parallax_2d.cpp18
-rw-r--r--scene/2d/parallax_2d.h1
-rw-r--r--scene/2d/parallax_layer.cpp10
-rw-r--r--scene/2d/path_2d.cpp9
-rw-r--r--scene/2d/physics/collision_object_2d.cpp2
-rw-r--r--scene/2d/physics/collision_polygon_2d.cpp2
-rw-r--r--scene/2d/physics/collision_shape_2d.cpp2
-rw-r--r--scene/2d/physics/physical_bone_2d.cpp2
-rw-r--r--scene/2d/physics/shape_cast_2d.cpp6
-rw-r--r--scene/2d/physics/shape_cast_2d.h2
-rw-r--r--scene/2d/polygon_2d.cpp2
-rw-r--r--scene/2d/remote_transform_2d.cpp12
-rw-r--r--scene/2d/skeleton_2d.cpp42
-rw-r--r--scene/2d/tile_map.cpp20
-rw-r--r--scene/2d/tile_map.h4
-rw-r--r--scene/2d/tile_map_layer.cpp137
-rw-r--r--scene/2d/tile_map_layer.h12
26 files changed, 316 insertions, 162 deletions
diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp
index 014419573c..1cab29f383 100644
--- a/scene/2d/animated_sprite_2d.cpp
+++ b/scene/2d/animated_sprite_2d.cpp
@@ -463,7 +463,7 @@ void AnimatedSprite2D::play(const StringName &p_name, float p_custom_scale, bool
name = animation;
}
- ERR_FAIL_NULL_MSG(frames, vformat("There is no animation with name '%s'.", name));
+ ERR_FAIL_COND_MSG(frames.is_null(), vformat("There is no animation with name '%s'.", name));
ERR_FAIL_COND_MSG(!frames->get_animation_names().has(name), vformat("There is no animation with name '%s'.", name));
if (frames->get_frame_count(name) == 0) {
@@ -541,7 +541,7 @@ void AnimatedSprite2D::set_animation(const StringName &p_name) {
emit_signal(SceneStringName(animation_changed));
- if (frames == nullptr) {
+ if (frames.is_null()) {
animation = StringName();
stop();
ERR_FAIL_MSG(vformat("There is no animation with name '%s'.", p_name));
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index 8e91dce425..7c60e47e64 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -242,7 +242,7 @@ void AudioStreamPlayer2D::seek(float p_seconds) {
void AudioStreamPlayer2D::stop() {
setplay.set(-1);
- internal->stop();
+ internal->stop_basic();
}
bool AudioStreamPlayer2D::is_playing() const {
@@ -276,10 +276,6 @@ void AudioStreamPlayer2D::_set_playing(bool p_enable) {
internal->set_playing(p_enable);
}
-bool AudioStreamPlayer2D::_is_active() const {
- return internal->is_active();
-}
-
void AudioStreamPlayer2D::_validate_property(PropertyInfo &p_property) const {
internal->validate_property(p_property);
}
@@ -385,8 +381,7 @@ void AudioStreamPlayer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioStreamPlayer2D::set_autoplay);
ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer2D::is_autoplay_enabled);
- ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioStreamPlayer2D::_set_playing);
- ClassDB::bind_method(D_METHOD("_is_active"), &AudioStreamPlayer2D::_is_active);
+ ClassDB::bind_method(D_METHOD("set_playing", "enable"), &AudioStreamPlayer2D::_set_playing);
ClassDB::bind_method(D_METHOD("set_max_distance", "pixels"), &AudioStreamPlayer2D::set_max_distance);
ClassDB::bind_method(D_METHOD("get_max_distance"), &AudioStreamPlayer2D::get_max_distance);
@@ -415,7 +410,7 @@ void AudioStreamPlayer2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_db", PROPERTY_HINT_RANGE, "-80,24,suffix:dB"), "set_volume_db", "get_volume_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,4,0.01,or_greater"), "set_pitch_scale", "get_pitch_scale");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "is_playing");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_playing", "is_playing");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stream_paused", PROPERTY_HINT_NONE, ""), "set_stream_paused", "get_stream_paused");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "1,4096,1,or_greater,exp,suffix:px"), "set_max_distance", "get_max_distance");
@@ -430,7 +425,7 @@ void AudioStreamPlayer2D::_bind_methods() {
}
AudioStreamPlayer2D::AudioStreamPlayer2D() {
- internal = memnew(AudioStreamPlayerInternal(this, callable_mp(this, &AudioStreamPlayer2D::play), true));
+ internal = memnew(AudioStreamPlayerInternal(this, callable_mp(this, &AudioStreamPlayer2D::play), callable_mp(this, &AudioStreamPlayer2D::stop), true));
cached_global_panning_strength = GLOBAL_GET("audio/general/2d_panning_strength");
set_hide_clip_children(true);
}
diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp
index 2c5c6a1a16..dc83775c71 100644
--- a/scene/2d/canvas_modulate.cpp
+++ b/scene/2d/canvas_modulate.cpp
@@ -114,7 +114,7 @@ Color CanvasModulate::get_color() const {
}
PackedStringArray CanvasModulate::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
if (is_in_canvas && is_visible_in_tree()) {
List<Node *> nodes;
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index 1d3f1ceada..bfbdb49f22 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -688,6 +688,7 @@ void GPUParticles2D::_notification(int p_what) {
RS::get_singleton()->particles_set_speed_scale(particles, 0);
}
set_process_internal(true);
+ set_physics_process_internal(true);
previous_position = get_global_position();
} break;
@@ -711,15 +712,6 @@ void GPUParticles2D::_notification(int p_what) {
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
- const Vector3 velocity = Vector3((get_global_position() - previous_position).x, (get_global_position() - previous_position).y, 0.0) /
- get_process_delta_time();
-
- if (velocity != previous_velocity) {
- RS::get_singleton()->particles_set_emitter_velocity(particles, velocity);
- previous_velocity = velocity;
- }
- previous_position = get_global_position();
-
if (one_shot) {
time += get_process_delta_time();
if (time > emission_time) {
@@ -739,6 +731,19 @@ void GPUParticles2D::_notification(int p_what) {
}
}
} break;
+
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ // Update velocity in physics process, so that velocity calculations remain correct
+ // if the physics tick rate is lower than the rendered framerate (especially without physics interpolation).
+ const Vector3 velocity = Vector3((get_global_position() - previous_position).x, (get_global_position() - previous_position).y, 0.0) /
+ get_physics_process_delta_time();
+
+ if (velocity != previous_velocity) {
+ RS::get_singleton()->particles_set_emitter_velocity(particles, velocity);
+ previous_velocity = velocity;
+ }
+ previous_position = get_global_position();
+ } break;
}
}
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 5ce26b3ed4..50c5873781 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -417,7 +417,7 @@ Vector2 PointLight2D::get_texture_offset() const {
}
PackedStringArray PointLight2D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
if (!texture.is_valid()) {
warnings.push_back(RTR("A texture with the shape of the light must be supplied to the \"Texture\" property."));
diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp
index 092c987ac0..7c3fb61d04 100644
--- a/scene/2d/light_occluder_2d.cpp
+++ b/scene/2d/light_occluder_2d.cpp
@@ -263,7 +263,7 @@ int LightOccluder2D::get_occluder_light_mask() const {
}
PackedStringArray LightOccluder2D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
if (!occluder_polygon.is_valid()) {
warnings.push_back(RTR("An occluder polygon must be set (or drawn) for this occluder to take effect."));
diff --git a/scene/2d/navigation_link_2d.cpp b/scene/2d/navigation_link_2d.cpp
index 04ba550888..4961e18dc9 100644
--- a/scene/2d/navigation_link_2d.cpp
+++ b/scene/2d/navigation_link_2d.cpp
@@ -41,6 +41,9 @@ void NavigationLink2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink2D::is_enabled);
+ ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationLink2D::set_navigation_map);
+ ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationLink2D::get_navigation_map);
+
ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink2D::set_bidirectional);
ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink2D::is_bidirectional);
@@ -106,12 +109,7 @@ bool NavigationLink2D::_get(const StringName &p_name, Variant &r_ret) const {
void NavigationLink2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- if (enabled) {
- NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());
- }
- current_global_transform = get_global_transform();
- NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
- NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
+ _link_enter_navigation_map();
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -120,36 +118,15 @@ void NavigationLink2D::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
set_physics_process_internal(false);
- if (is_inside_tree()) {
- Transform2D new_global_transform = get_global_transform();
- if (current_global_transform != new_global_transform) {
- current_global_transform = new_global_transform;
- NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
- NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
- queue_redraw();
- }
- }
+ _link_update_transform();
} break;
case NOTIFICATION_EXIT_TREE: {
- NavigationServer2D::get_singleton()->link_set_map(link, RID());
+ _link_exit_navigation_map();
} break;
case NOTIFICATION_DRAW: {
#ifdef DEBUG_ENABLED
- if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled())) {
- Color color;
- if (enabled) {
- color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_color();
- } else {
- color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_disabled_color();
- }
-
- real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());
-
- draw_line(get_start_position(), get_end_position(), color);
- draw_arc(get_start_position(), radius, 0, Math_TAU, 10, color);
- draw_arc(get_end_position(), radius, 0, Math_TAU, 10, color);
- }
+ _update_debug_mesh();
#endif // DEBUG_ENABLED
} break;
}
@@ -188,15 +165,32 @@ void NavigationLink2D::set_enabled(bool p_enabled) {
enabled = p_enabled;
- NavigationServer3D::get_singleton()->link_set_enabled(link, enabled);
+ NavigationServer2D::get_singleton()->link_set_enabled(link, enabled);
#ifdef DEBUG_ENABLED
- if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
- queue_redraw();
- }
+ queue_redraw();
#endif // DEBUG_ENABLED
}
+void NavigationLink2D::set_navigation_map(RID p_navigation_map) {
+ if (map_override == p_navigation_map) {
+ return;
+ }
+
+ map_override = p_navigation_map;
+
+ NavigationServer2D::get_singleton()->link_set_map(link, map_override);
+}
+
+RID NavigationLink2D::get_navigation_map() const {
+ if (map_override.is_valid()) {
+ return map_override;
+ } else if (is_inside_tree()) {
+ return get_world_2d()->get_navigation_map();
+ }
+ return RID();
+}
+
void NavigationLink2D::set_bidirectional(bool p_bidirectional) {
if (bidirectional == p_bidirectional) {
return;
@@ -255,9 +249,7 @@ void NavigationLink2D::set_start_position(Vector2 p_position) {
update_configuration_warnings();
#ifdef DEBUG_ENABLED
- if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
- queue_redraw();
- }
+ queue_redraw();
#endif // DEBUG_ENABLED
}
@@ -277,9 +269,7 @@ void NavigationLink2D::set_end_position(Vector2 p_position) {
update_configuration_warnings();
#ifdef DEBUG_ENABLED
- if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
- queue_redraw();
- }
+ queue_redraw();
#endif // DEBUG_ENABLED
}
@@ -338,7 +328,7 @@ void NavigationLink2D::set_travel_cost(real_t p_travel_cost) {
}
PackedStringArray NavigationLink2D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
if (start_position.is_equal_approx(end_position)) {
warnings.push_back(RTR("NavigationLink2D start position should be different than the end position to be useful."));
@@ -347,6 +337,69 @@ PackedStringArray NavigationLink2D::get_configuration_warnings() const {
return warnings;
}
+void NavigationLink2D::_link_enter_navigation_map() {
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ if (map_override.is_valid()) {
+ NavigationServer2D::get_singleton()->link_set_map(link, map_override);
+ } else {
+ NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());
+ }
+
+ current_global_transform = get_global_transform();
+
+ NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
+ NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
+ NavigationServer2D::get_singleton()->link_set_enabled(link, enabled);
+
+ queue_redraw();
+}
+
+void NavigationLink2D::_link_exit_navigation_map() {
+ NavigationServer2D::get_singleton()->link_set_map(link, RID());
+}
+
+void NavigationLink2D::_link_update_transform() {
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ Transform2D new_global_transform = get_global_transform();
+ if (current_global_transform != new_global_transform) {
+ current_global_transform = new_global_transform;
+ NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
+ NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
+ queue_redraw();
+ }
+}
+
+#ifdef DEBUG_ENABLED
+void NavigationLink2D::_update_debug_mesh() {
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ if (!Engine::get_singleton()->is_editor_hint() && !NavigationServer2D::get_singleton()->get_debug_enabled()) {
+ return;
+ }
+
+ Color color;
+ if (enabled) {
+ color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_color();
+ } else {
+ color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_disabled_color();
+ }
+
+ real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());
+
+ draw_line(get_start_position(), get_end_position(), color);
+ draw_arc(get_start_position(), radius, 0, Math_TAU, 10, color);
+ draw_arc(get_end_position(), radius, 0, Math_TAU, 10, color);
+}
+#endif // DEBUG_ENABLED
+
NavigationLink2D::NavigationLink2D() {
link = NavigationServer2D::get_singleton()->link_create();
diff --git a/scene/2d/navigation_link_2d.h b/scene/2d/navigation_link_2d.h
index 2929691c04..c724096607 100644
--- a/scene/2d/navigation_link_2d.h
+++ b/scene/2d/navigation_link_2d.h
@@ -38,6 +38,7 @@ class NavigationLink2D : public Node2D {
bool enabled = true;
RID link;
+ RID map_override;
bool bidirectional = true;
uint32_t navigation_layers = 1;
Vector2 end_position;
@@ -47,6 +48,10 @@ class NavigationLink2D : public Node2D {
Transform2D current_global_transform;
+#ifdef DEBUG_ENABLED
+ void _update_debug_mesh();
+#endif // DEBUG_ENABLED
+
protected:
static void _bind_methods();
void _notification(int p_what);
@@ -66,6 +71,9 @@ public:
void set_enabled(bool p_enabled);
bool is_enabled() const { return enabled; }
+ void set_navigation_map(RID p_navigation_map);
+ RID get_navigation_map() const;
+
void set_bidirectional(bool p_bidirectional);
bool is_bidirectional() const { return bidirectional; }
@@ -97,6 +105,11 @@ public:
NavigationLink2D();
~NavigationLink2D();
+
+private:
+ void _link_enter_navigation_map();
+ void _link_exit_navigation_map();
+ void _link_update_transform();
};
#endif // NAVIGATION_LINK_2D_H
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index 9b3c7bb9ea..f65a3c0ecc 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -452,6 +452,7 @@ void NavigationRegion2D::_update_debug_mesh() {
const Transform2D region_gt = get_global_transform();
rs->canvas_item_set_parent(debug_instance_rid, get_world_2d()->get_canvas());
+ rs->canvas_item_set_z_index(debug_instance_rid, RS::CANVAS_ITEM_Z_MAX - 2);
rs->canvas_item_set_transform(debug_instance_rid, region_gt);
if (!debug_mesh_dirty) {
diff --git a/scene/2d/parallax_2d.cpp b/scene/2d/parallax_2d.cpp
index 9dd9d4a376..fdb2d2cdd0 100644
--- a/scene/2d/parallax_2d.cpp
+++ b/scene/2d/parallax_2d.cpp
@@ -47,9 +47,18 @@ void Parallax2D::_notification(int p_what) {
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
- autoscroll_offset += autoscroll * get_process_delta_time();
- autoscroll_offset = autoscroll_offset.posmodv(repeat_size);
+ Point2 offset = scroll_offset;
+ offset += autoscroll * get_process_delta_time();
+ if (repeat_size.x) {
+ offset.x = Math::fposmod(offset.x, repeat_size.x);
+ }
+
+ if (repeat_size.y) {
+ offset.y = Math::fposmod(offset.y, repeat_size.y);
+ }
+
+ scroll_offset = offset;
_update_scroll();
} break;
@@ -106,14 +115,14 @@ void Parallax2D::_update_scroll() {
scroll_ofs *= scroll_scale;
if (repeat_size.x) {
- real_t mod = Math::fposmod(scroll_ofs.x - scroll_offset.x - autoscroll_offset.x, repeat_size.x * get_scale().x);
+ real_t mod = Math::fposmod(scroll_ofs.x - scroll_offset.x, repeat_size.x * get_scale().x);
scroll_ofs.x = screen_offset.x - mod;
} else {
scroll_ofs.x = screen_offset.x + scroll_offset.x - scroll_ofs.x;
}
if (repeat_size.y) {
- real_t mod = Math::fposmod(scroll_ofs.y - scroll_offset.y - autoscroll_offset.y, repeat_size.y * get_scale().y);
+ real_t mod = Math::fposmod(scroll_ofs.y - scroll_offset.y, repeat_size.y * get_scale().y);
scroll_ofs.y = screen_offset.y - mod;
} else {
scroll_ofs.y = screen_offset.y + scroll_offset.y - scroll_ofs.y;
@@ -193,7 +202,6 @@ void Parallax2D::set_autoscroll(const Point2 &p_autoscroll) {
}
autoscroll = p_autoscroll;
- autoscroll_offset = Point2();
_update_process();
_update_scroll();
diff --git a/scene/2d/parallax_2d.h b/scene/2d/parallax_2d.h
index 5fbc3a20c8..f15e3fa9ff 100644
--- a/scene/2d/parallax_2d.h
+++ b/scene/2d/parallax_2d.h
@@ -47,7 +47,6 @@ class Parallax2D : public Node2D {
Point2 limit_begin = Point2(-DEFAULT_LIMIT, -DEFAULT_LIMIT);
Point2 limit_end = Point2(DEFAULT_LIMIT, DEFAULT_LIMIT);
Point2 autoscroll;
- Point2 autoscroll_offset;
bool follow_viewport = true;
bool ignore_camera_scroll = false;
diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp
index dfe321a435..24f261deb6 100644
--- a/scene/2d/parallax_layer.cpp
+++ b/scene/2d/parallax_layer.cpp
@@ -78,13 +78,7 @@ void ParallaxLayer::_update_mirroring() {
}
void ParallaxLayer::set_mirroring(const Size2 &p_mirroring) {
- mirroring = p_mirroring;
- if (mirroring.x < 0) {
- mirroring.x = 0;
- }
- if (mirroring.y < 0) {
- mirroring.y = 0;
- }
+ mirroring = p_mirroring.maxf(0);
_update_mirroring();
}
@@ -139,7 +133,7 @@ void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, real_t p_s
}
PackedStringArray ParallaxLayer::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
if (!Object::cast_to<ParallaxBackground>(get_parent())) {
warnings.push_back(RTR("ParallaxLayer node only works when set as child of a ParallaxBackground node."));
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index 282d14da5d..5813ab02e3 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -288,7 +288,7 @@ void PathFollow2D::_validate_property(PropertyInfo &p_property) const {
}
PackedStringArray PathFollow2D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
if (is_visible_in_tree() && is_inside_tree()) {
if (!Object::cast_to<Path2D>(get_parent())) {
@@ -378,9 +378,10 @@ real_t PathFollow2D::get_progress() const {
}
void PathFollow2D::set_progress_ratio(real_t p_ratio) {
- if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
- set_progress(p_ratio * path->get_curve()->get_baked_length());
- }
+ ERR_FAIL_NULL_MSG(path, "Can only set progress ratio on a PathFollow2D that is the child of a Path2D which is itself part of the scene tree.");
+ ERR_FAIL_COND_MSG(path->get_curve().is_null(), "Can't set progress ratio on a PathFollow2D that does not have a Curve.");
+ ERR_FAIL_COND_MSG(!path->get_curve()->get_baked_length(), "Can't set progress ratio on a PathFollow2D that has a 0 length curve.");
+ set_progress(p_ratio * path->get_curve()->get_baked_length());
}
real_t PathFollow2D::get_progress_ratio() const {
diff --git a/scene/2d/physics/collision_object_2d.cpp b/scene/2d/physics/collision_object_2d.cpp
index 00b6085f0c..27ee6b883c 100644
--- a/scene/2d/physics/collision_object_2d.cpp
+++ b/scene/2d/physics/collision_object_2d.cpp
@@ -582,7 +582,7 @@ void CollisionObject2D::_update_pickable() {
}
PackedStringArray CollisionObject2D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
if (shapes.is_empty()) {
warnings.push_back(RTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape2D or CollisionPolygon2D as a child to define its shape."));
diff --git a/scene/2d/physics/collision_polygon_2d.cpp b/scene/2d/physics/collision_polygon_2d.cpp
index a9b47ef4d4..b49badac1f 100644
--- a/scene/2d/physics/collision_polygon_2d.cpp
+++ b/scene/2d/physics/collision_polygon_2d.cpp
@@ -232,7 +232,7 @@ bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, doubl
#endif
PackedStringArray CollisionPolygon2D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
if (!Object::cast_to<CollisionObject2D>(get_parent())) {
warnings.push_back(RTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, CharacterBody2D, etc. to give them a shape."));
diff --git a/scene/2d/physics/collision_shape_2d.cpp b/scene/2d/physics/collision_shape_2d.cpp
index 6fc29ffe63..bdd0d06b5e 100644
--- a/scene/2d/physics/collision_shape_2d.cpp
+++ b/scene/2d/physics/collision_shape_2d.cpp
@@ -174,7 +174,7 @@ bool CollisionShape2D::_edit_is_selected_on_click(const Point2 &p_point, double
}
PackedStringArray CollisionShape2D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
CollisionObject2D *col_object = Object::cast_to<CollisionObject2D>(get_parent());
if (col_object == nullptr) {
diff --git a/scene/2d/physics/physical_bone_2d.cpp b/scene/2d/physics/physical_bone_2d.cpp
index 77bb8c24b8..19274c8084 100644
--- a/scene/2d/physics/physical_bone_2d.cpp
+++ b/scene/2d/physics/physical_bone_2d.cpp
@@ -107,7 +107,7 @@ void PhysicalBone2D::_find_joint_child() {
}
PackedStringArray PhysicalBone2D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = RigidBody2D::get_configuration_warnings();
if (!parent_skeleton) {
warnings.push_back(RTR("A PhysicalBone2D only works with a Skeleton2D or another PhysicalBone2D as a parent node!"));
diff --git a/scene/2d/physics/shape_cast_2d.cpp b/scene/2d/physics/shape_cast_2d.cpp
index 00be84b622..b92978bcad 100644
--- a/scene/2d/physics/shape_cast_2d.cpp
+++ b/scene/2d/physics/shape_cast_2d.cpp
@@ -382,7 +382,7 @@ bool ShapeCast2D::is_collide_with_bodies_enabled() const {
return collide_with_bodies;
}
-Array ShapeCast2D::_get_collision_result() const {
+Array ShapeCast2D::get_collision_result() const {
Array ret;
for (int i = 0; i < result.size(); ++i) {
@@ -464,7 +464,7 @@ void ShapeCast2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &ShapeCast2D::set_collide_with_bodies);
ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &ShapeCast2D::is_collide_with_bodies_enabled);
- ClassDB::bind_method(D_METHOD("_get_collision_result"), &ShapeCast2D::_get_collision_result);
+ ClassDB::bind_method(D_METHOD("get_collision_result"), &ShapeCast2D::get_collision_result);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape");
@@ -473,7 +473,7 @@ void ShapeCast2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01,suffix:px"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_results"), "set_max_results", "get_max_results");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "collision_result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "", "_get_collision_result");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "collision_result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "", "get_collision_result");
ADD_GROUP("Collide With", "collide_with");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_bodies", "is_collide_with_bodies_enabled");
diff --git a/scene/2d/physics/shape_cast_2d.h b/scene/2d/physics/shape_cast_2d.h
index 6b8fd5b798..d866dd4edb 100644
--- a/scene/2d/physics/shape_cast_2d.h
+++ b/scene/2d/physics/shape_cast_2d.h
@@ -60,7 +60,6 @@ class ShapeCast2D : public Node2D {
real_t collision_safe_fraction = 1.0;
real_t collision_unsafe_fraction = 1.0;
- Array _get_collision_result() const;
void _shape_changed();
protected:
@@ -102,6 +101,7 @@ public:
void force_shapecast_update();
bool is_colliding() const;
+ Array get_collision_result() const;
int get_collision_count() const;
Object *get_collider(int p_idx) const;
RID get_collider_rid(int p_idx) const;
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 4266060466..42f7a75c0a 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -682,7 +682,7 @@ void Polygon2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "uv"), "set_uv", "get_uv");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "vertex_colors"), "set_vertex_colors", "get_vertex_colors");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons"), "set_polygons", "get_polygons");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "_set_bones", "_get_bones");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_bones", "_get_bones");
ADD_PROPERTY(PropertyInfo(Variant::INT, "internal_vertex_count", PROPERTY_HINT_RANGE, "0,1000"), "set_internal_vertex_count", "get_internal_vertex_count");
}
diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp
index 5ea5098475..1816a3409b 100644
--- a/scene/2d/remote_transform_2d.cpp
+++ b/scene/2d/remote_transform_2d.cpp
@@ -114,6 +114,16 @@ void RemoteTransform2D::_notification(int p_what) {
_update_cache();
} break;
+ case NOTIFICATION_RESET_PHYSICS_INTERPOLATION: {
+ if (cache.is_valid()) {
+ _update_remote();
+ Node2D *n = Object::cast_to<Node2D>(ObjectDB::get_instance(cache));
+ if (n) {
+ n->reset_physics_interpolation();
+ }
+ }
+ } break;
+
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED:
case NOTIFICATION_TRANSFORM_CHANGED: {
if (!is_inside_tree()) {
@@ -201,7 +211,7 @@ void RemoteTransform2D::force_update_cache() {
}
PackedStringArray RemoteTransform2D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
if (!has_node(remote_node) || !Object::cast_to<Node2D>(get_node(remote_node))) {
warnings.push_back(RTR("Path property must point to a valid Node2D node to work."));
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index 8aa50668eb..90bfb4c84c 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -39,19 +39,17 @@
#endif //TOOLS_ENABLED
bool Bone2D::_set(const StringName &p_path, const Variant &p_value) {
- String path = p_path;
-
- if (path.begins_with("auto_calculate_length_and_angle")) {
+ if (p_path == SNAME("auto_calculate_length_and_angle")) {
set_autocalculate_length_and_angle(p_value);
- } else if (path.begins_with("length")) {
+ } else if (p_path == SNAME("length")) {
set_length(p_value);
- } else if (path.begins_with("bone_angle")) {
+ } else if (p_path == SNAME("bone_angle")) {
set_bone_angle(Math::deg_to_rad(real_t(p_value)));
- } else if (path.begins_with("default_length")) {
+ } else if (p_path == SNAME("default_length")) {
set_length(p_value);
}
#ifdef TOOLS_ENABLED
- else if (path.begins_with("editor_settings/show_bone_gizmo")) {
+ else if (p_path == SNAME("editor_settings/show_bone_gizmo")) {
_editor_set_show_bone_gizmo(p_value);
}
#endif // TOOLS_ENABLED
@@ -63,19 +61,17 @@ bool Bone2D::_set(const StringName &p_path, const Variant &p_value) {
}
bool Bone2D::_get(const StringName &p_path, Variant &r_ret) const {
- String path = p_path;
-
- if (path.begins_with("auto_calculate_length_and_angle")) {
+ if (p_path == SNAME("auto_calculate_length_and_angle")) {
r_ret = get_autocalculate_length_and_angle();
- } else if (path.begins_with("length")) {
+ } else if (p_path == SNAME("length")) {
r_ret = get_length();
- } else if (path.begins_with("bone_angle")) {
+ } else if (p_path == SNAME("bone_angle")) {
r_ret = Math::rad_to_deg(get_bone_angle());
- } else if (path.begins_with("default_length")) {
+ } else if (p_path == SNAME("default_length")) {
r_ret = get_length();
}
#ifdef TOOLS_ENABLED
- else if (path.begins_with("editor_settings/show_bone_gizmo")) {
+ else if (p_path == SNAME("editor_settings/show_bone_gizmo")) {
r_ret = _editor_get_show_bone_gizmo();
}
#endif // TOOLS_ENABLED
@@ -330,9 +326,7 @@ bool Bone2D::_editor_get_bone_shape(Vector<Vector2> *p_shape, Vector<Vector2> *p
rel = (p_other_bone->get_global_position() - get_global_position());
rel = rel.rotated(-get_global_rotation()); // Undo Bone2D node's rotation so its drawn correctly regardless of the node's rotation
} else {
- real_t angle_to_use = get_rotation() + bone_angle;
- rel = Vector2(cos(angle_to_use), sin(angle_to_use)) * (length * MIN(get_global_scale().x, get_global_scale().y));
- rel = rel.rotated(-get_rotation()); // Undo Bone2D node's rotation so its drawn correctly regardless of the node's rotation
+ rel = Vector2(Math::cos(bone_angle), Math::sin(bone_angle)) * length * get_global_scale();
}
Vector2 relt = rel.rotated(Math_PI * 0.5).normalized() * bone_width;
@@ -418,7 +412,7 @@ int Bone2D::get_index_in_skeleton() const {
}
PackedStringArray Bone2D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
if (!skeleton) {
if (parent_bone) {
warnings.push_back(RTR("This Bone2D chain should end at a Skeleton2D node."));
@@ -518,23 +512,19 @@ Bone2D::~Bone2D() {
//////////////////////////////////////
bool Skeleton2D::_set(const StringName &p_path, const Variant &p_value) {
- String path = p_path;
-
- if (path.begins_with("modification_stack")) {
+ if (p_path == SNAME("modification_stack")) {
set_modification_stack(p_value);
return true;
}
- return true;
+ return false;
}
bool Skeleton2D::_get(const StringName &p_path, Variant &r_ret) const {
- String path = p_path;
-
- if (path.begins_with("modification_stack")) {
+ if (p_path == SNAME("modification_stack")) {
r_ret = get_modification_stack();
return true;
}
- return true;
+ return false;
}
void Skeleton2D::_get_property_list(List<PropertyInfo> *p_list) const {
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 48ade1e5cc..45cfb8cf33 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -532,6 +532,18 @@ TileData *TileMap::get_cell_tile_data(int p_layer, const Vector2i &p_coords, boo
}
}
+bool TileMap::is_cell_flipped_h(int p_layer, const Vector2i &p_coords, bool p_use_proxies) const {
+ return get_cell_alternative_tile(p_layer, p_coords, p_use_proxies) & TileSetAtlasSource::TRANSFORM_FLIP_H;
+}
+
+bool TileMap::is_cell_flipped_v(int p_layer, const Vector2i &p_coords, bool p_use_proxies) const {
+ return get_cell_alternative_tile(p_layer, p_coords, p_use_proxies) & TileSetAtlasSource::TRANSFORM_FLIP_V;
+}
+
+bool TileMap::is_cell_transposed(int p_layer, const Vector2i &p_coords, bool p_use_proxies) const {
+ return get_cell_alternative_tile(p_layer, p_coords, p_use_proxies) & TileSetAtlasSource::TRANSFORM_TRANSPOSE;
+}
+
Ref<TileMapPattern> TileMap::get_pattern(int p_layer, TypedArray<Vector2i> p_coords_array) {
TILEMAP_CALL_FOR_LAYER_V(p_layer, Ref<TileMapPattern>(), get_pattern, p_coords_array);
}
@@ -815,7 +827,9 @@ TypedArray<Vector2i> TileMap::get_surrounding_cells(const Vector2i &p_coords) {
}
PackedStringArray TileMap::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Node2D::get_configuration_warnings();
+
+ warnings.push_back(RTR("The TileMap node is deprecated as it is superseded by the use of multiple TileMapLayer nodes.\nTo convert a TileMap to a set of TileMapLayer nodes, open the TileMap bottom panel with this node selected, click the toolbox icon in the top-right corner and choose \"Extract TileMap layers as individual TileMapLayer nodes\"."));
// Retrieve the set of Z index values with a Y-sorted layer.
RBSet<int> y_sorted_z_index;
@@ -924,6 +938,10 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "layer", "coords", "use_proxies"), &TileMap::get_cell_alternative_tile, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_cell_tile_data", "layer", "coords", "use_proxies"), &TileMap::get_cell_tile_data, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("is_cell_flipped_h", "layer", "coords", "use_proxies"), &TileMap::is_cell_flipped_h, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("is_cell_flipped_v", "layer", "coords", "use_proxies"), &TileMap::is_cell_flipped_v, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("is_cell_transposed", "layer", "coords", "use_proxies"), &TileMap::is_cell_transposed, DEFVAL(false));
+
ClassDB::bind_method(D_METHOD("get_coords_for_body_rid", "body"), &TileMap::get_coords_for_body_rid);
ClassDB::bind_method(D_METHOD("get_layer_for_body_rid", "body"), &TileMap::get_layer_for_body_rid);
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 690102f730..142dc1193f 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -167,6 +167,10 @@ public:
// Helper method to make accessing the data easier.
TileData *get_cell_tile_data(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const;
+ bool is_cell_flipped_h(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const;
+ bool is_cell_flipped_v(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const;
+ bool is_cell_transposed(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const;
+
// Patterns.
Ref<TileMapPattern> get_pattern(int p_layer, TypedArray<Vector2i> p_coords_array);
Vector2i map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern);
diff --git a/scene/2d/tile_map_layer.cpp b/scene/2d/tile_map_layer.cpp
index 437790bb99..ebb03e4e73 100644
--- a/scene/2d/tile_map_layer.cpp
+++ b/scene/2d/tile_map_layer.cpp
@@ -411,7 +411,7 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
}
// ----------- Occluders processing -----------
- if (forced_cleanup) {
+ if (forced_cleanup || !occlusion_enabled) {
// Clean everything.
for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
_rendering_occluders_clear_cell(kv.value);
@@ -433,7 +433,7 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
// -----------
// Mark the rendering state as up to date.
- _rendering_was_cleaned_up = forced_cleanup;
+ _rendering_was_cleaned_up = forced_cleanup || !occlusion_enabled;
}
void TileMapLayer::_rendering_notification(int p_what) {
@@ -443,13 +443,15 @@ void TileMapLayer::_rendering_notification(int p_what) {
Transform2D tilemap_xform = get_global_transform();
for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
const CellData &cell_data = kv.value;
- for (const RID &occluder : cell_data.occluders) {
- if (occluder.is_null()) {
- continue;
+ for (const LocalVector<RID> &polygons : cell_data.occluders) {
+ for (const RID &rid : polygons) {
+ if (rid.is_null()) {
+ continue;
+ }
+ Transform2D xform(0, tile_set->map_to_local(kv.key));
+ rs->canvas_light_occluder_attach_to_canvas(rid, get_canvas());
+ rs->canvas_light_occluder_set_transform(rid, tilemap_xform * xform);
}
- Transform2D xform(0, tile_set->map_to_local(kv.key));
- rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
- rs->canvas_light_occluder_set_transform(occluder, tilemap_xform * xform);
}
}
}
@@ -557,8 +559,10 @@ void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) {
RenderingServer *rs = RenderingServer::get_singleton();
// Free the occluders.
- for (const RID &rid : r_cell_data.occluders) {
- rs->free(rid);
+ for (const LocalVector<RID> &polygons : r_cell_data.occluders) {
+ for (const RID &rid : polygons) {
+ rs->free(rid);
+ }
}
r_cell_data.occluders.clear();
}
@@ -566,11 +570,12 @@ void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) {
void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
RenderingServer *rs = RenderingServer::get_singleton();
- // Free unused occluders then resize the occluders array.
+ // Free unused occluders then resize the occluder array.
for (uint32_t i = tile_set->get_occlusion_layers_count(); i < r_cell_data.occluders.size(); i++) {
- RID occluder_id = r_cell_data.occluders[i];
- if (occluder_id.is_valid()) {
- rs->free(occluder_id);
+ for (const RID &occluder_id : r_cell_data.occluders[i]) {
+ if (occluder_id.is_valid()) {
+ rs->free(occluder_id);
+ }
}
}
r_cell_data.occluders.resize(tile_set->get_occlusion_layers_count());
@@ -598,30 +603,42 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
// Create, update or clear occluders.
bool needs_set_not_interpolated = is_inside_tree() && get_tree()->is_physics_interpolation_enabled() && !is_physics_interpolated();
for (uint32_t occlusion_layer_index = 0; occlusion_layer_index < r_cell_data.occluders.size(); occlusion_layer_index++) {
- Ref<OccluderPolygon2D> occluder_polygon = tile_data->get_occluder(occlusion_layer_index);
-
- RID &occluder = r_cell_data.occluders[occlusion_layer_index];
+ LocalVector<RID> &occluders = r_cell_data.occluders[occlusion_layer_index];
- if (occluder_polygon.is_valid()) {
- // Create or update occluder.
- Transform2D xform;
- xform.set_origin(tile_set->map_to_local(r_cell_data.coords));
- if (!occluder.is_valid()) {
- occluder = rs->canvas_light_occluder_create();
- if (needs_set_not_interpolated) {
- rs->canvas_light_occluder_set_interpolated(occluder, false);
- }
+ // Free unused occluders then resize the occluders array.
+ for (uint32_t i = tile_data->get_occluder_polygons_count(occlusion_layer_index); i < r_cell_data.occluders[occlusion_layer_index].size(); i++) {
+ RID occluder_id = occluders[i];
+ if (occluder_id.is_valid()) {
+ rs->free(occluder_id);
}
- rs->canvas_light_occluder_set_transform(occluder, get_global_transform() * xform);
- rs->canvas_light_occluder_set_polygon(occluder, tile_data->get_occluder(occlusion_layer_index, flip_h, flip_v, transpose)->get_rid());
- rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
- rs->canvas_light_occluder_set_light_mask(occluder, tile_set->get_occlusion_layer_light_mask(occlusion_layer_index));
- rs->canvas_light_occluder_set_as_sdf_collision(occluder, tile_set->get_occlusion_layer_sdf_collision(occlusion_layer_index));
- } else {
- // Clear occluder.
- if (occluder.is_valid()) {
- rs->free(occluder);
- occluder = RID();
+ }
+ occluders.resize(tile_data->get_occluder_polygons_count(occlusion_layer_index));
+
+ for (uint32_t occlusion_polygon_index = 0; occlusion_polygon_index < occluders.size(); occlusion_polygon_index++) {
+ RID &occluder = occluders[occlusion_polygon_index];
+ Ref<OccluderPolygon2D> occluder_polygon = tile_data->get_occluder_polygon(occlusion_layer_index, occlusion_polygon_index);
+ if (occluder_polygon.is_valid()) {
+ // Create or update occluder.
+
+ Transform2D xform;
+ xform.set_origin(tile_set->map_to_local(r_cell_data.coords));
+ if (!occluder.is_valid()) {
+ occluder = rs->canvas_light_occluder_create();
+ if (needs_set_not_interpolated) {
+ rs->canvas_light_occluder_set_interpolated(occluder, false);
+ }
+ }
+ rs->canvas_light_occluder_set_transform(occluder, get_global_transform() * xform);
+ rs->canvas_light_occluder_set_polygon(occluder, tile_data->get_occluder_polygon(occlusion_layer_index, occlusion_polygon_index, flip_h, flip_v, transpose)->get_rid());
+ rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
+ rs->canvas_light_occluder_set_light_mask(occluder, tile_set->get_occlusion_layer_light_mask(occlusion_layer_index));
+ rs->canvas_light_occluder_set_as_sdf_collision(occluder, tile_set->get_occlusion_layer_sdf_collision(occlusion_layer_index));
+ } else {
+ // Clear occluder.
+ if (occluder.is_valid()) {
+ rs->free(occluder);
+ occluder = RID();
+ }
}
}
}
@@ -957,7 +974,7 @@ void TileMapLayer::_navigation_update(bool p_force_cleanup) {
// Create a dedicated map for each layer.
RID new_layer_map = ns->map_create();
// Set the default NavigationPolygon cell_size on the new map as a mismatch causes an error.
- ns->map_set_cell_size(new_layer_map, 1.0);
+ ns->map_set_cell_size(new_layer_map, NavigationDefaults2D::navmesh_cell_size);
ns->map_set_active(new_layer_map, true);
navigation_map_override = new_layer_map;
}
@@ -1709,11 +1726,13 @@ void TileMapLayer::_physics_interpolated_changed() {
}
for (const KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
- for (const RID &occluder : E.value.occluders) {
- if (occluder.is_valid()) {
- rs->canvas_light_occluder_set_interpolated(occluder, interpolated);
- if (needs_reset) {
- rs->canvas_light_occluder_reset_physics_interpolation(occluder);
+ for (const LocalVector<RID> &polygons : E.value.occluders) {
+ for (const RID &occluder_id : polygons) {
+ if (occluder_id.is_valid()) {
+ rs->canvas_light_occluder_set_interpolated(occluder_id, interpolated);
+ if (needs_reset) {
+ rs->canvas_light_occluder_reset_physics_interpolation(occluder_id);
+ }
}
}
}
@@ -1773,6 +1792,10 @@ void TileMapLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords"), &TileMapLayer::get_cell_alternative_tile);
ClassDB::bind_method(D_METHOD("get_cell_tile_data", "coords"), &TileMapLayer::get_cell_tile_data);
+ ClassDB::bind_method(D_METHOD("is_cell_flipped_h", "coords"), &TileMapLayer::is_cell_flipped_h);
+ ClassDB::bind_method(D_METHOD("is_cell_flipped_v", "coords"), &TileMapLayer::is_cell_flipped_v);
+ ClassDB::bind_method(D_METHOD("is_cell_transposed", "coords"), &TileMapLayer::is_cell_transposed);
+
ClassDB::bind_method(D_METHOD("get_used_cells"), &TileMapLayer::get_used_cells);
ClassDB::bind_method(D_METHOD("get_used_cells_by_id", "source_id", "atlas_coords", "alternative_tile"), &TileMapLayer::get_used_cells_by_id, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
ClassDB::bind_method(D_METHOD("get_used_rect"), &TileMapLayer::get_used_rect);
@@ -1824,6 +1847,9 @@ void TileMapLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_visibility_mode", "visibility_mode"), &TileMapLayer::set_collision_visibility_mode);
ClassDB::bind_method(D_METHOD("get_collision_visibility_mode"), &TileMapLayer::get_collision_visibility_mode);
+ ClassDB::bind_method(D_METHOD("set_occlusion_enabled", "enabled"), &TileMapLayer::set_occlusion_enabled);
+ ClassDB::bind_method(D_METHOD("is_occlusion_enabled"), &TileMapLayer::is_occlusion_enabled);
+
ClassDB::bind_method(D_METHOD("set_navigation_enabled", "enabled"), &TileMapLayer::set_navigation_enabled);
ClassDB::bind_method(D_METHOD("is_navigation_enabled"), &TileMapLayer::is_navigation_enabled);
ClassDB::bind_method(D_METHOD("set_navigation_map", "map"), &TileMapLayer::set_navigation_map);
@@ -1839,6 +1865,7 @@ void TileMapLayer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tile_set", PROPERTY_HINT_RESOURCE_TYPE, "TileSet"), "set_tile_set", "get_tile_set");
ADD_GROUP("Rendering", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "occlusion_enabled"), "set_occlusion_enabled", "is_occlusion_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "y_sort_origin"), "set_y_sort_origin", "get_y_sort_origin");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "x_draw_order_reversed"), "set_x_draw_order_reversed", "is_x_draw_order_reversed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "rendering_quadrant_size"), "set_rendering_quadrant_size", "get_rendering_quadrant_size");
@@ -2490,6 +2517,18 @@ Rect2i TileMapLayer::get_used_rect() const {
return used_rect_cache;
}
+bool TileMapLayer::is_cell_flipped_h(const Vector2i &p_coords) const {
+ return get_cell_alternative_tile(p_coords) & TileSetAtlasSource::TRANSFORM_FLIP_H;
+}
+
+bool TileMapLayer::is_cell_flipped_v(const Vector2i &p_coords) const {
+ return get_cell_alternative_tile(p_coords) & TileSetAtlasSource::TRANSFORM_FLIP_V;
+}
+
+bool TileMapLayer::is_cell_transposed(const Vector2i &p_coords) const {
+ return get_cell_alternative_tile(p_coords) & TileSetAtlasSource::TRANSFORM_TRANSPOSE;
+}
+
Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_array) {
ERR_FAIL_COND_V(tile_set.is_null(), nullptr);
@@ -2944,6 +2983,20 @@ TileMapLayer::DebugVisibilityMode TileMapLayer::get_collision_visibility_mode()
return collision_visibility_mode;
}
+void TileMapLayer::set_occlusion_enabled(bool p_enabled) {
+ if (occlusion_enabled == p_enabled) {
+ return;
+ }
+ occlusion_enabled = p_enabled;
+ dirty.flags[DIRTY_FLAGS_LAYER_OCCLUSION_ENABLED] = true;
+ _queue_internal_update();
+ emit_signal(CoreStringName(changed));
+}
+
+bool TileMapLayer::is_occlusion_enabled() const {
+ return occlusion_enabled;
+}
+
void TileMapLayer::set_navigation_enabled(bool p_enabled) {
if (navigation_enabled == p_enabled) {
return;
diff --git a/scene/2d/tile_map_layer.h b/scene/2d/tile_map_layer.h
index c71f13d7be..cc0a5b49fb 100644
--- a/scene/2d/tile_map_layer.h
+++ b/scene/2d/tile_map_layer.h
@@ -108,7 +108,7 @@ struct CellData {
// Rendering.
Ref<RenderingQuadrant> rendering_quadrant;
SelfList<CellData> rendering_quadrant_list_element;
- LocalVector<RID> occluders;
+ LocalVector<LocalVector<RID>> occluders;
// Physics.
LocalVector<RID> bodies;
@@ -254,6 +254,7 @@ public:
DIRTY_FLAGS_LAYER_COLLISION_ENABLED,
DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES,
DIRTY_FLAGS_LAYER_COLLISION_VISIBILITY_MODE,
+ DIRTY_FLAGS_LAYER_OCCLUSION_ENABLED,
DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED,
DIRTY_FLAGS_LAYER_NAVIGATION_MAP,
DIRTY_FLAGS_LAYER_NAVIGATION_VISIBILITY_MODE,
@@ -288,6 +289,8 @@ private:
bool use_kinematic_bodies = false;
DebugVisibilityMode collision_visibility_mode = DEBUG_VISIBILITY_MODE_DEFAULT;
+ bool occlusion_enabled = true;
+
bool navigation_enabled = true;
RID navigation_map_override;
DebugVisibilityMode navigation_visibility_mode = DEBUG_VISIBILITY_MODE_DEFAULT;
@@ -438,6 +441,10 @@ public:
TypedArray<Vector2i> get_used_cells_by_id(int p_source_id = TileSet::INVALID_SOURCE, const Vector2i &p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE) const;
Rect2i get_used_rect() const;
+ bool is_cell_flipped_h(const Vector2i &p_coords) const;
+ bool is_cell_flipped_v(const Vector2i &p_coords) const;
+ bool is_cell_transposed(const Vector2i &p_coords) const;
+
// Patterns.
Ref<TileMapPattern> get_pattern(TypedArray<Vector2i> p_coords_array);
void set_pattern(const Vector2i &p_position, const Ref<TileMapPattern> p_pattern);
@@ -493,6 +500,9 @@ public:
void set_collision_visibility_mode(DebugVisibilityMode p_show_collision);
DebugVisibilityMode get_collision_visibility_mode() const;
+ void set_occlusion_enabled(bool p_enabled);
+ bool is_occlusion_enabled() const;
+
void set_navigation_enabled(bool p_enabled);
bool is_navigation_enabled() const;
void set_navigation_map(RID p_map);