diff options
Diffstat (limited to 'scene/2d')
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); |