diff options
Diffstat (limited to 'scene/2d')
51 files changed, 532 insertions, 286 deletions
diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index b1b1cb23ed..7ee9861d3f 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -63,9 +63,13 @@ Rect2 AnimatedSprite2D::_edit_get_rect() const { } bool AnimatedSprite2D::_edit_use_rect() const { - if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { + if (frames.is_null() || !frames->has_animation(animation)) { return false; } + if (frame < 0 || frame >= frames->get_frame_count(animation)) { + return false; + } + Ref<Texture2D> t; if (animation) { t = frames->get_frame(animation, frame); @@ -79,7 +83,10 @@ Rect2 AnimatedSprite2D::get_anchorable_rect() const { } Rect2 AnimatedSprite2D::_get_rect() const { - if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { + if (frames.is_null() || !frames->has_animation(animation)) { + return Rect2(); + } + if (frame < 0 || frame >= frames->get_frame_count(animation)) { return Rect2(); } @@ -108,6 +115,7 @@ void AnimatedSprite2D::_validate_property(PropertyInfo &p_property) const { if (!frames.is_valid()) { return; } + if (p_property.name == "animation") { p_property.hint = PROPERTY_HINT_ENUM; List<StringName> names; @@ -137,9 +145,15 @@ void AnimatedSprite2D::_validate_property(PropertyInfo &p_property) const { p_property.hint_string = String(animation) + "," + p_property.hint_string; } } + return; } if (p_property.name == "frame") { + if (playing) { + p_property.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY; + return; + } + p_property.hint = PROPERTY_HINT_RANGE; if (frames->has_animation(animation) && frames->get_frame_count(animation) > 0) { p_property.hint_string = "0," + itos(frames->get_frame_count(animation) - 1) + ",1"; @@ -154,54 +168,52 @@ void AnimatedSprite2D::_validate_property(PropertyInfo &p_property) const { void AnimatedSprite2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_INTERNAL_PROCESS: { - if (frames.is_null()) { + if (frames.is_null() || !frames->has_animation(animation)) { return; } - if (!frames->has_animation(animation)) { - return; - } - if (frame < 0) { - return; + + double speed = frames->get_animation_speed(animation) * Math::abs(speed_scale); + if (speed == 0) { + return; // Do nothing. } + int last_frame = frames->get_frame_count(animation) - 1; double remaining = get_process_delta_time(); - while (remaining) { - double speed = frames->get_animation_speed(animation) * speed_scale; - if (speed == 0) { - return; // Do nothing. - } - if (timeout <= 0) { timeout = _get_frame_duration(); - int fc = frames->get_frame_count(animation); - if ((!backwards && frame >= fc - 1) || (backwards && frame <= 0)) { - if (frames->get_animation_loop(animation)) { - if (backwards) { - frame = fc - 1; - } else { - frame = 0; - } - - emit_signal(SceneStringNames::get_singleton()->animation_finished); - } else { - if (backwards) { + if (!playing_backwards) { + // Forward. + if (frame >= last_frame) { + if (frames->get_animation_loop(animation)) { frame = 0; - } else { - frame = fc - 1; - } - - if (!is_over) { - is_over = true; emit_signal(SceneStringNames::get_singleton()->animation_finished); + } else { + frame = last_frame; + if (!is_over) { + is_over = true; + emit_signal(SceneStringNames::get_singleton()->animation_finished); + } } + } else { + frame++; } } else { - if (backwards) { - frame--; + // Reversed. + if (frame <= 0) { + if (frames->get_animation_loop(animation)) { + frame = last_frame; + emit_signal(SceneStringNames::get_singleton()->animation_finished); + } else { + frame = 0; + if (!is_over) { + is_over = true; + emit_signal(SceneStringNames::get_singleton()->animation_finished); + } + } } else { - frame++; + frame--; } } @@ -217,13 +229,7 @@ void AnimatedSprite2D::_notification(int p_what) { } break; case NOTIFICATION_DRAW: { - if (frames.is_null()) { - return; - } - if (frame < 0) { - return; - } - if (!frames->has_animation(animation)) { + if (frames.is_null() || !frames->has_animation(animation)) { return; } @@ -259,14 +265,15 @@ void AnimatedSprite2D::_notification(int p_what) { void AnimatedSprite2D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) { if (frames.is_valid()) { - frames->disconnect("changed", callable_mp(this, &AnimatedSprite2D::_res_changed)); + frames->disconnect(SceneStringNames::get_singleton()->changed, callable_mp(this, &AnimatedSprite2D::_res_changed)); } + frames = p_frames; if (frames.is_valid()) { - frames->connect("changed", callable_mp(this, &AnimatedSprite2D::_res_changed)); + frames->connect(SceneStringNames::get_singleton()->changed, callable_mp(this, &AnimatedSprite2D::_res_changed)); } - if (!frames.is_valid()) { + if (frames.is_null()) { frame = 0; } else { set_frame(frame); @@ -283,7 +290,7 @@ Ref<SpriteFrames> AnimatedSprite2D::get_sprite_frames() const { } void AnimatedSprite2D::set_frame(int p_frame) { - if (!frames.is_valid()) { + if (frames.is_null()) { return; } @@ -314,11 +321,16 @@ int AnimatedSprite2D::get_frame() const { } void AnimatedSprite2D::set_speed_scale(double p_speed_scale) { + if (speed_scale == p_speed_scale) { + return; + } + double elapsed = _get_frame_duration() - timeout; - speed_scale = MAX(p_speed_scale, 0.0f); + speed_scale = p_speed_scale; + playing_backwards = signbit(speed_scale) != backwards; - // We adapt the timeout so that the animation speed adapts as soon as the speed scale is changed + // We adapt the timeout so that the animation speed adapts as soon as the speed scale is changed. _reset_timeout(); timeout -= elapsed; } @@ -378,18 +390,20 @@ void AnimatedSprite2D::set_playing(bool p_playing) { playing = p_playing; _reset_timeout(); set_process_internal(playing); + notify_property_list_changed(); } bool AnimatedSprite2D::is_playing() const { return playing; } -void AnimatedSprite2D::play(const StringName &p_animation, const bool p_backwards) { +void AnimatedSprite2D::play(const StringName &p_animation, bool p_backwards) { backwards = p_backwards; + playing_backwards = signbit(speed_scale) != backwards; if (p_animation) { set_animation(p_animation); - if (frames.is_valid() && backwards && get_frame() == 0) { + if (frames.is_valid() && playing_backwards && get_frame() == 0) { set_frame(frames->get_frame_count(p_animation) - 1); } } @@ -404,7 +418,7 @@ void AnimatedSprite2D::stop() { double AnimatedSprite2D::_get_frame_duration() { if (frames.is_valid() && frames->has_animation(animation)) { - double speed = frames->get_animation_speed(animation) * speed_scale; + double speed = frames->get_animation_speed(animation) * Math::abs(speed_scale); if (speed > 0) { return 1.0 / speed; } @@ -440,11 +454,11 @@ StringName AnimatedSprite2D::get_animation() const { return animation; } -TypedArray<String> AnimatedSprite2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray AnimatedSprite2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (frames.is_null()) { - warnings.push_back(RTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite to display frames.")); + warnings.push_back(RTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite2D to display frames.")); } return warnings; diff --git a/scene/2d/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h index 0a19e250d8..11c4adb816 100644 --- a/scene/2d/animated_sprite_2d.h +++ b/scene/2d/animated_sprite_2d.h @@ -39,6 +39,7 @@ class AnimatedSprite2D : public Node2D { Ref<SpriteFrames> frames; bool playing = false; + bool playing_backwards = false; bool backwards = false; StringName animation = "default"; int frame = 0; @@ -81,7 +82,7 @@ public: void set_sprite_frames(const Ref<SpriteFrames> &p_frames); Ref<SpriteFrames> get_sprite_frames() const; - void play(const StringName &p_animation = StringName(), const bool p_backwards = false); + void play(const StringName &p_animation = StringName(), bool p_backwards = false); void stop(); void set_playing(bool p_playing); @@ -108,7 +109,7 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; AnimatedSprite2D(); diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 3def41eaa5..b3f80b5e43 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -459,6 +459,16 @@ TypedArray<Area2D> Area2D::get_overlapping_areas() const { return ret; } +bool Area2D::has_overlapping_bodies() const { + ERR_FAIL_COND_V_MSG(!monitoring, false, "Can't find overlapping bodies when monitoring is off."); + return !body_map.is_empty(); +} + +bool Area2D::has_overlapping_areas() const { + ERR_FAIL_COND_V_MSG(!monitoring, false, "Can't find overlapping areas when monitoring is off."); + return !area_map.is_empty(); +} + bool Area2D::overlaps_area(Node *p_area) const { ERR_FAIL_NULL_V(p_area, false); HashMap<ObjectID, AreaState>::ConstIterator E = area_map.find(p_area->get_instance_id()); @@ -578,6 +588,9 @@ void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_overlapping_bodies"), &Area2D::get_overlapping_bodies); ClassDB::bind_method(D_METHOD("get_overlapping_areas"), &Area2D::get_overlapping_areas); + ClassDB::bind_method(D_METHOD("has_overlapping_bodies"), &Area2D::has_overlapping_bodies); + ClassDB::bind_method(D_METHOD("has_overlapping_areas"), &Area2D::has_overlapping_areas); + ClassDB::bind_method(D_METHOD("overlaps_body", "body"), &Area2D::overlaps_body); ClassDB::bind_method(D_METHOD("overlaps_area", "area"), &Area2D::overlaps_area); diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index 3d8d77eabb..f70f1dfc3d 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -180,6 +180,9 @@ public: TypedArray<Node2D> get_overlapping_bodies() const; //function for script TypedArray<Area2D> get_overlapping_areas() const; //function for script + bool has_overlapping_bodies() const; + bool has_overlapping_areas() const; + bool overlaps_area(Node *p_area) const; bool overlaps_body(Node *p_body) const; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index fc019b6cf9..85ec745aee 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -43,13 +43,18 @@ void AudioStreamPlayer2D::_notification(int p_what) { if (autoplay && !Engine::get_singleton()->is_editor_hint()) { play(); } + set_stream_paused(false); } break; case NOTIFICATION_EXIT_TREE: { - stop(); + set_stream_paused(true); AudioServer::get_singleton()->remove_listener_changed_callback(_listener_changed_cb, this); } break; + case NOTIFICATION_PREDELETE: { + stop(); + } break; + case NOTIFICATION_PAUSED: { if (!can_process()) { // Node can't process so we start fading out to silence. diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index ce77c6ba8d..aeaaaf3aec 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -171,9 +171,14 @@ Transform2D Camera2D::get_camera_transform() { Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom_scale) : Point2()); - real_t angle = get_global_rotation(); - if (rotating) { - screen_offset = screen_offset.rotated(angle); + if (!ignore_rotation) { + if (rotation_smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) { + real_t step = rotation_smoothing_speed * (process_callback == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time()); + camera_angle = Math::lerp_angle(camera_angle, get_global_rotation(), step); + } else { + camera_angle = get_global_rotation(); + } + screen_offset = screen_offset.rotated(camera_angle); } Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom_scale); @@ -204,8 +209,8 @@ Transform2D Camera2D::get_camera_transform() { Transform2D xform; xform.scale_basis(zoom_scale); - if (rotating) { - xform.set_rotation(angle); + if (!ignore_rotation) { + xform.set_rotation(camera_angle); } xform.set_origin(screen_rect.position); @@ -363,15 +368,21 @@ Camera2D::AnchorMode Camera2D::get_anchor_mode() const { return anchor_mode; } -void Camera2D::set_rotating(bool p_rotating) { - rotating = p_rotating; +void Camera2D::set_ignore_rotation(bool p_ignore) { + ignore_rotation = p_ignore; Point2 old_smoothed_camera_pos = smoothed_camera_pos; + + // Reset back to zero so it matches the camera rotation when ignore_rotation is enabled. + if (ignore_rotation) { + camera_angle = 0.0; + } + _update_scroll(); smoothed_camera_pos = old_smoothed_camera_pos; } -bool Camera2D::is_rotating() const { - return rotating; +bool Camera2D::is_ignoring_rotation() const { + return ignore_rotation; } void Camera2D::set_process_callback(Camera2DProcessCallback p_mode) { @@ -415,6 +426,14 @@ void Camera2D::set_current(bool p_current) { } } +void Camera2D::_update_process_internal_for_smoothing() { + bool is_not_in_scene_or_editor = !(is_inside_tree() && Engine::get_singleton()->is_editor_hint()); + bool is_any_smoothing_valid = smoothing > 0 || rotation_smoothing_speed > 0; + + bool enabled = is_any_smoothing_valid && is_not_in_scene_or_editor; + set_process_internal(enabled); +} + bool Camera2D::is_current() const { return current; } @@ -508,17 +527,31 @@ void Camera2D::align() { void Camera2D::set_follow_smoothing(real_t p_speed) { smoothing = p_speed; - if (smoothing > 0 && !(is_inside_tree() && Engine::get_singleton()->is_editor_hint())) { - set_process_internal(true); - } else { - set_process_internal(false); - } + _update_process_internal_for_smoothing(); } real_t Camera2D::get_follow_smoothing() const { return smoothing; } +void Camera2D::set_rotation_smoothing_speed(real_t p_speed) { + rotation_smoothing_speed = p_speed; + _update_process_internal_for_smoothing(); +} + +real_t Camera2D::get_rotation_smoothing_speed() const { + return rotation_smoothing_speed; +} + +void Camera2D::set_rotation_smoothing_enabled(bool p_enabled) { + rotation_smoothing_enabled = p_enabled; + notify_property_list_changed(); +} + +bool Camera2D::is_rotation_smoothing_enabled() const { + return rotation_smoothing_enabled; +} + Point2 Camera2D::get_camera_screen_center() const { return camera_screen_center; } @@ -659,6 +692,9 @@ void Camera2D::_validate_property(PropertyInfo &p_property) const { if (!smoothing_enabled && p_property.name == "smoothing_speed") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; } + if (!rotation_smoothing_enabled && p_property.name == "rotation_smoothing_speed") { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; + } } void Camera2D::_bind_methods() { @@ -668,8 +704,8 @@ void Camera2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_anchor_mode", "anchor_mode"), &Camera2D::set_anchor_mode); ClassDB::bind_method(D_METHOD("get_anchor_mode"), &Camera2D::get_anchor_mode); - ClassDB::bind_method(D_METHOD("set_rotating", "rotating"), &Camera2D::set_rotating); - ClassDB::bind_method(D_METHOD("is_rotating"), &Camera2D::is_rotating); + ClassDB::bind_method(D_METHOD("set_ignore_rotation", "ignore"), &Camera2D::set_ignore_rotation); + ClassDB::bind_method(D_METHOD("is_ignoring_rotation"), &Camera2D::is_ignoring_rotation); ClassDB::bind_method(D_METHOD("_update_scroll"), &Camera2D::_update_scroll); @@ -701,8 +737,8 @@ void Camera2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_drag_margin", "margin", "drag_margin"), &Camera2D::set_drag_margin); ClassDB::bind_method(D_METHOD("get_drag_margin", "margin"), &Camera2D::get_drag_margin); - ClassDB::bind_method(D_METHOD("get_camera_position"), &Camera2D::get_camera_position); - ClassDB::bind_method(D_METHOD("get_camera_screen_center"), &Camera2D::get_camera_screen_center); + ClassDB::bind_method(D_METHOD("get_target_position"), &Camera2D::get_camera_position); + ClassDB::bind_method(D_METHOD("get_screen_center_position"), &Camera2D::get_camera_screen_center); ClassDB::bind_method(D_METHOD("set_zoom", "zoom"), &Camera2D::set_zoom); ClassDB::bind_method(D_METHOD("get_zoom"), &Camera2D::get_zoom); @@ -716,6 +752,12 @@ void Camera2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enable_follow_smoothing", "follow_smoothing"), &Camera2D::set_enable_follow_smoothing); ClassDB::bind_method(D_METHOD("is_follow_smoothing_enabled"), &Camera2D::is_follow_smoothing_enabled); + ClassDB::bind_method(D_METHOD("set_rotation_smoothing_enabled", "enabled"), &Camera2D::set_rotation_smoothing_enabled); + ClassDB::bind_method(D_METHOD("is_rotation_smoothing_enabled"), &Camera2D::is_rotation_smoothing_enabled); + + ClassDB::bind_method(D_METHOD("set_rotation_smoothing_speed", "speed"), &Camera2D::set_rotation_smoothing_speed); + ClassDB::bind_method(D_METHOD("get_rotation_smoothing_speed"), &Camera2D::get_rotation_smoothing_speed); + ClassDB::bind_method(D_METHOD("force_update_scroll"), &Camera2D::force_update_scroll); ClassDB::bind_method(D_METHOD("reset_smoothing"), &Camera2D::reset_smoothing); ClassDB::bind_method(D_METHOD("align"), &Camera2D::align); @@ -733,7 +775,7 @@ void Camera2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_mode", PROPERTY_HINT_ENUM, "Fixed TopLeft,Drag Center"), "set_anchor_mode", "get_anchor_mode"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotating"), "set_rotating", "is_rotating"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_rotation"), "set_ignore_rotation", "is_ignoring_rotation"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom", PROPERTY_HINT_LINK), "set_zoom", "get_zoom"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", PROPERTY_USAGE_NONE), "set_custom_viewport", "get_custom_viewport"); @@ -750,6 +792,10 @@ void Camera2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smoothing_enabled"), "set_enable_follow_smoothing", "is_follow_smoothing_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "smoothing_speed", PROPERTY_HINT_NONE, "suffix:px/s"), "set_follow_smoothing", "get_follow_smoothing"); + ADD_GROUP("Rotation Smoothing", "rotation_smoothing_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotation_smoothing_enabled"), "set_rotation_smoothing_enabled", "is_rotation_smoothing_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_smoothing_speed"), "set_rotation_smoothing_speed", "get_rotation_smoothing_speed"); + ADD_GROUP("Drag", "drag_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_horizontal_enabled"), "set_drag_horizontal_enabled", "is_drag_horizontal_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_vertical_enabled"), "set_drag_vertical_enabled", "is_drag_vertical_enabled"); diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 78654ee606..1411175af2 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -63,10 +63,15 @@ protected: Vector2 zoom = Vector2(1, 1); Vector2 zoom_scale = Vector2(1, 1); AnchorMode anchor_mode = ANCHOR_MODE_DRAG_CENTER; - bool rotating = false; + bool ignore_rotation = true; bool current = false; real_t smoothing = 5.0; bool smoothing_enabled = false; + + real_t camera_angle = 0.0; + real_t rotation_smoothing_speed = 5.0; + bool rotation_smoothing_enabled = false; + int limit[4]; bool limit_smoothing_enabled = false; @@ -87,6 +92,8 @@ protected: void _set_old_smoothing(real_t p_enable); + void _update_process_internal_for_smoothing(); + bool screen_drawing_enabled = true; bool limit_drawing_enabled = false; bool margin_drawing_enabled = false; @@ -109,8 +116,8 @@ public: void set_anchor_mode(AnchorMode p_anchor_mode); AnchorMode get_anchor_mode() const; - void set_rotating(bool p_rotating); - bool is_rotating() const; + void set_ignore_rotation(bool p_ignore); + bool is_ignoring_rotation() const; void set_limit(Side p_side, int p_limit); int get_limit(Side p_side) const; @@ -139,6 +146,12 @@ public: void set_follow_smoothing(real_t p_speed); real_t get_follow_smoothing() const; + void set_rotation_smoothing_speed(real_t p_speed); + real_t get_rotation_smoothing_speed() const; + + void set_rotation_smoothing_enabled(bool p_enabled); + bool is_rotation_smoothing_enabled() const; + void set_process_callback(Camera2DProcessCallback p_mode); Camera2DProcessCallback get_process_callback() const; diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp index 61a17a4845..330afe4a1b 100644 --- a/scene/2d/canvas_modulate.cpp +++ b/scene/2d/canvas_modulate.cpp @@ -78,8 +78,8 @@ Color CanvasModulate::get_color() const { return color; } -TypedArray<String> CanvasModulate::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray CanvasModulate::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (is_visible_in_tree() && is_inside_tree()) { List<Node *> nodes; diff --git a/scene/2d/canvas_modulate.h b/scene/2d/canvas_modulate.h index 1fd54898f8..4f522ca1c7 100644 --- a/scene/2d/canvas_modulate.h +++ b/scene/2d/canvas_modulate.h @@ -46,7 +46,7 @@ public: void set_color(const Color &p_color); Color get_color() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; CanvasModulate(); ~CanvasModulate(); diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index a79c81e8bd..23948c2fd3 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -565,8 +565,8 @@ void CollisionObject2D::_update_pickable() { } } -TypedArray<String> CollisionObject2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray CollisionObject2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::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/collision_object_2d.h b/scene/2d/collision_object_2d.h index 48ea59e040..6b778d1b60 100644 --- a/scene/2d/collision_object_2d.h +++ b/scene/2d/collision_object_2d.h @@ -157,7 +157,7 @@ public: void set_pickable(bool p_enabled); bool is_pickable() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; _FORCE_INLINE_ RID get_rid() const { return rid; } diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index b69b19d30d..d06461b566 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -235,8 +235,8 @@ bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, doubl } #endif -TypedArray<String> CollisionPolygon2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray CollisionPolygon2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::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/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index e18022ab7e..066f7271c6 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -77,7 +77,7 @@ public: void set_polygon(const Vector<Point2> &p_polygon); Vector<Point2> get_polygon() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_disabled(bool p_disabled); bool is_disabled() const; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 039bfee451..5fe05c4ddd 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -49,6 +49,11 @@ void CollisionShape2D::_update_in_shape_owner(bool p_xform_only) { parent->shape_owner_set_one_way_collision_margin(owner_id, one_way_collision_margin); } +Color CollisionShape2D::_get_default_debug_color() const { + SceneTree *st = SceneTree::get_singleton(); + return st ? st->get_debug_collisions_color() : Color(); +} + void CollisionShape2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_PARENTED: { @@ -95,7 +100,7 @@ void CollisionShape2D::_notification(int p_what) { rect = Rect2(); - Color draw_col = get_tree()->get_debug_collisions_color(); + Color draw_col = debug_color; if (disabled) { float g = draw_col.get_v(); draw_col.r = g; @@ -110,7 +115,7 @@ void CollisionShape2D::_notification(int p_what) { if (one_way_collision) { // Draw an arrow indicating the one-way collision direction - draw_col = get_tree()->get_debug_collisions_color().inverted(); + draw_col = debug_color.inverted(); if (disabled) { draw_col = draw_col.darkened(0.25); } @@ -168,8 +173,8 @@ bool CollisionShape2D::_edit_is_selected_on_click(const Point2 &p_point, double return shape->_edit_is_selected_on_click(p_point, p_tolerance); } -TypedArray<String> CollisionShape2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray CollisionShape2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to<CollisionObject2D>(get_parent())) { warnings.push_back(RTR("CollisionShape2D 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.")); @@ -226,6 +231,40 @@ real_t CollisionShape2D::get_one_way_collision_margin() const { return one_way_collision_margin; } +void CollisionShape2D::set_debug_color(const Color &p_color) { + debug_color = p_color; + queue_redraw(); +} + +Color CollisionShape2D::get_debug_color() const { + return debug_color; +} + +bool CollisionShape2D::_property_can_revert(const StringName &p_name) const { + if (p_name == "debug_color") { + return true; + } + return false; +} + +bool CollisionShape2D::_property_get_revert(const StringName &p_name, Variant &r_property) const { + if (p_name == "debug_color") { + r_property = _get_default_debug_color(); + return true; + } + return false; +} + +void CollisionShape2D::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "debug_color") { + if (debug_color == _get_default_debug_color()) { + p_property.usage = PROPERTY_USAGE_DEFAULT & ~PROPERTY_USAGE_STORAGE; + } else { + p_property.usage = PROPERTY_USAGE_DEFAULT; + } + } +} + void CollisionShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &CollisionShape2D::set_shape); ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape2D::get_shape); @@ -235,13 +274,19 @@ void CollisionShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("is_one_way_collision_enabled"), &CollisionShape2D::is_one_way_collision_enabled); ClassDB::bind_method(D_METHOD("set_one_way_collision_margin", "margin"), &CollisionShape2D::set_one_way_collision_margin); ClassDB::bind_method(D_METHOD("get_one_way_collision_margin"), &CollisionShape2D::get_one_way_collision_margin); + ClassDB::bind_method(D_METHOD("set_debug_color", "color"), &CollisionShape2D::set_debug_color); + ClassDB::bind_method(D_METHOD("get_debug_color"), &CollisionShape2D::get_debug_color); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_way_collision"), "set_one_way_collision", "is_one_way_collision_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "one_way_collision_margin", PROPERTY_HINT_RANGE, "0,128,0.1,suffix:px"), "set_one_way_collision_margin", "get_one_way_collision_margin"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_color"), "set_debug_color", "get_debug_color"); + // Default value depends on a project setting, override for doc generation purposes. + ADD_PROPERTY_DEFAULT("debug_color", Color()); } CollisionShape2D::CollisionShape2D() { set_notify_local_transform(true); + debug_color = _get_default_debug_color(); } diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h index dbc81e8424..b0b8a7cb0f 100644 --- a/scene/2d/collision_shape_2d.h +++ b/scene/2d/collision_shape_2d.h @@ -42,15 +42,20 @@ class CollisionShape2D : public Node2D { Rect2 rect = Rect2(-Point2(10, 10), Point2(20, 20)); uint32_t owner_id = 0; CollisionObject2D *parent = nullptr; - void _shape_changed(); bool disabled = false; bool one_way_collision = false; real_t one_way_collision_margin = 1.0; + Color debug_color; + void _shape_changed(); void _update_in_shape_owner(bool p_xform_only = false); + Color _get_default_debug_color() const; protected: void _notification(int p_what); + bool _property_can_revert(const StringName &p_name) const; + bool _property_get_revert(const StringName &p_name, Variant &r_property) const; + void _validate_property(PropertyInfo &p_property) const; static void _bind_methods(); public: @@ -72,7 +77,10 @@ public: void set_one_way_collision_margin(real_t p_margin); real_t get_one_way_collision_margin() const; - TypedArray<String> get_configuration_warnings() const override; + void set_debug_color(const Color &p_color); + Color get_debug_color() const; + + PackedStringArray get_configuration_warnings() const override; CollisionShape2D(); }; diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 4523e5dfe9..eece90190b 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -242,8 +242,8 @@ bool CPUParticles2D::get_fractional_delta() const { return fractional_delta; } -TypedArray<String> CPUParticles2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node2D::get_configuration_warnings(); +PackedStringArray CPUParticles2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); CanvasItemMaterial *mat = Object::cast_to<CanvasItemMaterial>(get_material().ptr()); diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index 3fd1c7fd0f..141e5f9139 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -152,8 +152,8 @@ private: Vector2 direction = Vector2(1, 0); real_t spread = 45.0; - real_t parameters_min[PARAM_MAX]; - real_t parameters_max[PARAM_MAX]; + real_t parameters_min[PARAM_MAX] = {}; + real_t parameters_max[PARAM_MAX] = {}; Ref<Curve> curve_parameters[PARAM_MAX]; Color color; @@ -282,7 +282,7 @@ public: void set_gravity(const Vector2 &p_gravity); Vector2 get_gravity() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void restart(); diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index bed68b4ee0..18f709f241 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -296,8 +296,8 @@ bool GPUParticles2D::get_interpolate() const { return interpolate; } -TypedArray<String> GPUParticles2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node2D::get_configuration_warnings(); +PackedStringArray GPUParticles2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); if (RenderingServer::get_singleton()->is_low_end()) { warnings.push_back(RTR("GPU-based particles are not supported by the OpenGL video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles2D\" option for this purpose.")); diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h index 10ae91775f..d613b4ef51 100644 --- a/scene/2d/gpu_particles_2d.h +++ b/scene/2d/gpu_particles_2d.h @@ -145,7 +145,7 @@ public: void set_texture(const Ref<Texture2D> &p_texture); Ref<Texture2D> get_texture() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_sub_emitter(const NodePath &p_path); NodePath get_sub_emitter() const; diff --git a/scene/2d/joint_2d.cpp b/scene/2d/joint_2d.cpp index 89b6f3f9da..6000508f36 100644 --- a/scene/2d/joint_2d.cpp +++ b/scene/2d/joint_2d.cpp @@ -202,8 +202,8 @@ bool Joint2D::get_exclude_nodes_from_collision() const { return exclude_from_collision; } -TypedArray<String> Joint2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node2D::get_configuration_warnings(); +PackedStringArray Joint2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); if (!warning.is_empty()) { warnings.push_back(warning); diff --git a/scene/2d/joint_2d.h b/scene/2d/joint_2d.h index e3cd600cbd..8b145be6ae 100644 --- a/scene/2d/joint_2d.h +++ b/scene/2d/joint_2d.h @@ -62,7 +62,7 @@ protected: _FORCE_INLINE_ bool is_configured() const { return configured; } public: - virtual TypedArray<String> get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; void set_node_a(const NodePath &p_node_a); NodePath get_node_a() const; diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 7eb6b43af7..90402260ed 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -395,8 +395,8 @@ Vector2 PointLight2D::get_texture_offset() const { return texture_offset; } -TypedArray<String> PointLight2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray PointLight2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::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_2d.h b/scene/2d/light_2d.h index 373cfe59fd..29870923aa 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -171,7 +171,7 @@ public: void set_texture_scale(real_t p_scale); real_t get_texture_scale() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; PointLight2D(); }; diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp index 6c171383ca..67e82140e4 100644 --- a/scene/2d/light_occluder_2d.cpp +++ b/scene/2d/light_occluder_2d.cpp @@ -246,8 +246,8 @@ int LightOccluder2D::get_occluder_light_mask() const { return mask; } -TypedArray<String> LightOccluder2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray LightOccluder2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::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/light_occluder_2d.h b/scene/2d/light_occluder_2d.h index b61e23464a..ee4d87e54b 100644 --- a/scene/2d/light_occluder_2d.h +++ b/scene/2d/light_occluder_2d.h @@ -105,7 +105,7 @@ public: void set_as_sdf_collision(bool p_enable); bool is_set_as_sdf_collision() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; LightOccluder2D(); ~LightOccluder2D(); diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index d7f75c63a4..f077f7f5e6 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -178,6 +178,13 @@ NavigationAgent2D::NavigationAgent2D() { set_time_horizon(20.0); set_radius(10.0); set_max_speed(200.0); + + // Preallocate query and result objects to improve performance. + navigation_query = Ref<NavigationPathQueryParameters2D>(); + navigation_query.instantiate(); + + navigation_result = Ref<NavigationPathQueryResult2D>(); + navigation_result.instantiate(); } NavigationAgent2D::~NavigationAgent2D() { @@ -314,6 +321,8 @@ Vector2 NavigationAgent2D::get_target_location() const { Vector2 NavigationAgent2D::get_next_location() { update_navigation(); + + const Vector<Vector2> &navigation_path = navigation_result->get_path(); if (navigation_path.size() == 0) { ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector2(), "The agent has no parent."); return agent_parent->get_global_position(); @@ -322,6 +331,10 @@ Vector2 NavigationAgent2D::get_next_location() { } } +const Vector<Vector2> &NavigationAgent2D::get_nav_path() const { + return navigation_result->get_path(); +} + real_t NavigationAgent2D::distance_to_target() const { ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent."); return agent_parent->get_global_position().distance_to(target_location); @@ -342,6 +355,8 @@ bool NavigationAgent2D::is_navigation_finished() { Vector2 NavigationAgent2D::get_final_location() { update_navigation(); + + const Vector<Vector2> &navigation_path = navigation_result->get_path(); if (navigation_path.size() == 0) { return Vector2(); } @@ -368,8 +383,8 @@ void NavigationAgent2D::_avoidance_done(Vector3 p_new_velocity) { emit_signal(SNAME("velocity_computed"), velocity); } -TypedArray<String> NavigationAgent2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray NavigationAgent2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to<Node2D>(get_parent())) { warnings.push_back(RTR("The NavigationAgent2D can be used only under a Node2D inheriting parent node.")); @@ -391,22 +406,24 @@ void NavigationAgent2D::update_navigation() { update_frame_id = Engine::get_singleton()->get_physics_frames(); - Vector2 o = agent_parent->get_global_position(); + Vector2 origin = agent_parent->get_global_position(); bool reload_path = false; if (NavigationServer2D::get_singleton()->agent_is_map_changed(agent)) { reload_path = true; - } else if (navigation_path.size() == 0) { + } else if (navigation_result->get_path().size() == 0) { reload_path = true; } else { // Check if too far from the navigation path if (nav_path_index > 0) { + const Vector<Vector2> &navigation_path = navigation_result->get_path(); + Vector2 segment[2]; segment[0] = navigation_path[nav_path_index - 1]; segment[1] = navigation_path[nav_path_index]; - Vector2 p = Geometry2D::get_closest_point_to_segment(o, segment); - if (o.distance_to(p) >= path_max_distance) { + Vector2 p = Geometry2D::get_closest_point_to_segment(origin, segment); + if (origin.distance_to(p) >= path_max_distance) { // To faraway, reload path reload_path = true; } @@ -414,24 +431,31 @@ void NavigationAgent2D::update_navigation() { } if (reload_path) { + navigation_query->set_start_position(origin); + navigation_query->set_target_position(target_location); + navigation_query->set_navigation_layers(navigation_layers); + if (map_override.is_valid()) { - navigation_path = NavigationServer2D::get_singleton()->map_get_path(map_override, o, target_location, true, navigation_layers); + navigation_query->set_map(map_override); } else { - navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true, navigation_layers); + navigation_query->set_map(agent_parent->get_world_2d()->get_navigation_map()); } + + NavigationServer2D::get_singleton()->query_path(navigation_query, navigation_result); navigation_finished = false; nav_path_index = 0; emit_signal(SNAME("path_changed")); } - if (navigation_path.size() == 0) { + if (navigation_result->get_path().size() == 0) { return; } // Check if we can advance the navigation path if (navigation_finished == false) { // Advances to the next far away location. - while (o.distance_to(navigation_path[nav_path_index]) < path_desired_distance) { + const Vector<Vector2> &navigation_path = navigation_result->get_path(); + while (origin.distance_to(navigation_path[nav_path_index]) < path_desired_distance) { nav_path_index += 1; if (nav_path_index == navigation_path.size()) { _check_distance_to_target(); @@ -445,7 +469,7 @@ void NavigationAgent2D::update_navigation() { } void NavigationAgent2D::_request_repath() { - navigation_path.clear(); + navigation_result->reset(); target_reached = false; navigation_finished = false; update_frame_id = 0; diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h index 11b845665d..5abd3c0317 100644 --- a/scene/2d/navigation_agent_2d.h +++ b/scene/2d/navigation_agent_2d.h @@ -34,6 +34,8 @@ #include "scene/main/node.h" class Node2D; +class NavigationPathQueryParameters2D; +class NavigationPathQueryResult2D; class NavigationAgent2D : public Node { GDCLASS(NavigationAgent2D, Node); @@ -58,7 +60,8 @@ class NavigationAgent2D : public Node { real_t path_max_distance = 3.0; Vector2 target_location; - Vector<Vector2> navigation_path; + Ref<NavigationPathQueryParameters2D> navigation_query; + Ref<NavigationPathQueryResult2D> navigation_result; int nav_path_index = 0; bool velocity_submitted = false; Vector2 prev_safe_velocity; @@ -138,9 +141,7 @@ public: Vector2 get_next_location(); - Vector<Vector2> get_nav_path() const { - return navigation_path; - } + const Vector<Vector2> &get_nav_path() const; int get_nav_path_index() const { return nav_path_index; @@ -155,7 +156,7 @@ public: void set_velocity(Vector2 p_velocity); void _avoidance_done(Vector3 p_new_velocity); - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; private: void update_navigation(); diff --git a/scene/2d/navigation_link_2d.cpp b/scene/2d/navigation_link_2d.cpp index 38a03aaf97..3f7e10eaea 100644 --- a/scene/2d/navigation_link_2d.cpp +++ b/scene/2d/navigation_link_2d.cpp @@ -113,6 +113,10 @@ void NavigationLink2D::_notification(int p_what) { #ifdef TOOLS_ENABLED Rect2 NavigationLink2D::_edit_get_rect() const { + if (!is_inside_tree()) { + return Rect2(); + } + real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map()); Rect2 rect(get_start_location(), Size2()); @@ -263,8 +267,8 @@ void NavigationLink2D::set_travel_cost(real_t p_travel_cost) { NavigationServer2D::get_singleton()->link_set_travel_cost(link, travel_cost); } -TypedArray<String> NavigationLink2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray NavigationLink2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (start_location.is_equal_approx(end_location)) { warnings.push_back(RTR("NavigationLink2D start location should be different than the end location to be useful.")); diff --git a/scene/2d/navigation_link_2d.h b/scene/2d/navigation_link_2d.h index 5990ea082c..2a5092216d 100644 --- a/scene/2d/navigation_link_2d.h +++ b/scene/2d/navigation_link_2d.h @@ -79,7 +79,7 @@ public: void set_travel_cost(real_t p_travel_cost); real_t get_travel_cost() const { return travel_cost; } - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; NavigationLink2D(); ~NavigationLink2D(); diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index a592d20cba..e46bb79551 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -38,6 +38,9 @@ void NavigationObstacle2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_rid"), &NavigationObstacle2D::get_rid); + ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationObstacle2D::set_navigation_map); + ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationObstacle2D::get_navigation_map); + ClassDB::bind_method(D_METHOD("set_estimate_radius", "estimate_radius"), &NavigationObstacle2D::set_estimate_radius); ClassDB::bind_method(D_METHOD("is_radius_estimated"), &NavigationObstacle2D::is_radius_estimated); ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationObstacle2D::set_radius); @@ -57,28 +60,26 @@ void NavigationObstacle2D::_validate_property(PropertyInfo &p_property) const { void NavigationObstacle2D::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - parent_node2d = Object::cast_to<Node2D>(get_parent()); - reevaluate_agent_radius(); - if (parent_node2d != nullptr) { - // place agent on navigation map first or else the RVO agent callback creation fails silently later - NavigationServer2D::get_singleton()->agent_set_map(get_rid(), parent_node2d->get_world_2d()->get_navigation_map()); - } + case NOTIFICATION_POST_ENTER_TREE: { + set_agent_parent(get_parent()); set_physics_process_internal(true); } break; case NOTIFICATION_EXIT_TREE: { - parent_node2d = nullptr; + set_agent_parent(nullptr); set_physics_process_internal(false); } break; case NOTIFICATION_PARENTED: { - parent_node2d = Object::cast_to<Node2D>(get_parent()); - reevaluate_agent_radius(); + if (is_inside_tree() && (get_parent() != parent_node2d)) { + set_agent_parent(get_parent()); + set_physics_process_internal(true); + } } break; case NOTIFICATION_UNPARENTED: { - parent_node2d = nullptr; + set_agent_parent(nullptr); + set_physics_process_internal(false); } break; case NOTIFICATION_PAUSED: { @@ -119,8 +120,8 @@ NavigationObstacle2D::~NavigationObstacle2D() { agent = RID(); // Pointless } -TypedArray<String> NavigationObstacle2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray NavigationObstacle2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to<Node2D>(get_parent())) { warnings.push_back(RTR("The NavigationObstacle2D only serves to provide collision avoidance to a Node2D object.")); @@ -182,6 +183,35 @@ real_t NavigationObstacle2D::estimate_agent_radius() const { return 1.0; // Never a 0 radius } +void NavigationObstacle2D::set_agent_parent(Node *p_agent_parent) { + if (Object::cast_to<Node2D>(p_agent_parent) != nullptr) { + parent_node2d = Object::cast_to<Node2D>(p_agent_parent); + if (map_override.is_valid()) { + NavigationServer2D::get_singleton()->agent_set_map(get_rid(), map_override); + } else { + NavigationServer2D::get_singleton()->agent_set_map(get_rid(), parent_node2d->get_world_2d()->get_navigation_map()); + } + reevaluate_agent_radius(); + } else { + parent_node2d = nullptr; + NavigationServer2D::get_singleton()->agent_set_map(get_rid(), RID()); + } +} + +void NavigationObstacle2D::set_navigation_map(RID p_navigation_map) { + map_override = p_navigation_map; + NavigationServer2D::get_singleton()->agent_set_map(agent, map_override); +} + +RID NavigationObstacle2D::get_navigation_map() const { + if (map_override.is_valid()) { + return map_override; + } else if (parent_node2d != nullptr) { + return parent_node2d->get_world_2d()->get_navigation_map(); + } + return RID(); +} + void NavigationObstacle2D::set_estimate_radius(bool p_estimate_radius) { estimate_radius = p_estimate_radius; notify_property_list_changed(); diff --git a/scene/2d/navigation_obstacle_2d.h b/scene/2d/navigation_obstacle_2d.h index 5795c6c94f..d4c1df343f 100644 --- a/scene/2d/navigation_obstacle_2d.h +++ b/scene/2d/navigation_obstacle_2d.h @@ -38,8 +38,10 @@ class NavigationObstacle2D : public Node { GDCLASS(NavigationObstacle2D, Node); Node2D *parent_node2d = nullptr; + RID agent; RID map_before_pause; + RID map_override; bool estimate_radius = true; real_t radius = 1.0; @@ -57,6 +59,11 @@ public: return agent; } + void set_agent_parent(Node *p_agent_parent); + + void set_navigation_map(RID p_navigation_map); + RID get_navigation_map() const; + void set_estimate_radius(bool p_estimate_radius); bool is_radius_estimated() const { return estimate_radius; @@ -66,7 +73,7 @@ public: return radius; } - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; private: void initialize_agent(); diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index ffccb95a22..6e8ecb13b1 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -354,10 +354,13 @@ void NavigationPolygon::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines"); } +///////////////////////////// + void NavigationRegion2D::set_enabled(bool p_enabled) { if (enabled == p_enabled) { return; } + enabled = p_enabled; if (!is_inside_tree()) { @@ -384,35 +387,50 @@ bool NavigationRegion2D::is_enabled() const { } void NavigationRegion2D::set_navigation_layers(uint32_t p_navigation_layers) { - NavigationServer2D::get_singleton()->region_set_navigation_layers(region, p_navigation_layers); + if (navigation_layers == p_navigation_layers) { + return; + } + + navigation_layers = p_navigation_layers; + + NavigationServer2D::get_singleton()->region_set_navigation_layers(region, navigation_layers); } uint32_t NavigationRegion2D::get_navigation_layers() const { - return NavigationServer2D::get_singleton()->region_get_navigation_layers(region); + return navigation_layers; } void NavigationRegion2D::set_navigation_layer_value(int p_layer_number, bool p_value) { ERR_FAIL_COND_MSG(p_layer_number < 1, "Navigation layer number must be between 1 and 32 inclusive."); ERR_FAIL_COND_MSG(p_layer_number > 32, "Navigation layer number must be between 1 and 32 inclusive."); + uint32_t _navigation_layers = get_navigation_layers(); + if (p_value) { _navigation_layers |= 1 << (p_layer_number - 1); } else { _navigation_layers &= ~(1 << (p_layer_number - 1)); } + set_navigation_layers(_navigation_layers); } bool NavigationRegion2D::get_navigation_layer_value(int p_layer_number) const { ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Navigation layer number must be between 1 and 32 inclusive."); ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Navigation layer number must be between 1 and 32 inclusive."); + return get_navigation_layers() & (1 << (p_layer_number - 1)); } void NavigationRegion2D::set_enter_cost(real_t p_enter_cost) { ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive."); - enter_cost = MAX(p_enter_cost, 0.0); - NavigationServer2D::get_singleton()->region_set_enter_cost(region, p_enter_cost); + if (Math::is_equal_approx(enter_cost, p_enter_cost)) { + return; + } + + enter_cost = p_enter_cost; + + NavigationServer2D::get_singleton()->region_set_enter_cost(region, enter_cost); } real_t NavigationRegion2D::get_enter_cost() const { @@ -421,7 +439,12 @@ real_t NavigationRegion2D::get_enter_cost() const { void NavigationRegion2D::set_travel_cost(real_t p_travel_cost) { ERR_FAIL_COND_MSG(p_travel_cost < 0.0, "The travel_cost must be positive."); - travel_cost = MAX(p_travel_cost, 0.0); + if (Math::is_equal_approx(travel_cost, p_travel_cost)) { + return; + } + + travel_cost = p_travel_cost; + NavigationServer2D::get_singleton()->region_set_travel_cost(region, travel_cost); } @@ -433,7 +456,6 @@ RID NavigationRegion2D::get_region_rid() const { return region; } -///////////////////////////// #ifdef TOOLS_ENABLED Rect2 NavigationRegion2D::_edit_get_rect() const { return navpoly.is_valid() ? navpoly->_edit_get_rect() : Rect2(); @@ -566,8 +588,8 @@ void NavigationRegion2D::_map_changed(RID p_map) { #endif // DEBUG_ENABLED } -TypedArray<String> NavigationRegion2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node2D::get_configuration_warnings(); +PackedStringArray NavigationRegion2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); if (is_visible_in_tree() && is_inside_tree()) { if (!navpoly.is_valid()) { diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h index 3c9df91fe3..c630e20780 100644 --- a/scene/2d/navigation_region_2d.h +++ b/scene/2d/navigation_region_2d.h @@ -96,10 +96,10 @@ class NavigationRegion2D : public Node2D { bool enabled = true; RID region; - Ref<NavigationPolygon> navpoly; - + uint32_t navigation_layers = 1; real_t enter_cost = 0.0; real_t travel_cost = 1.0; + Ref<NavigationPolygon> navpoly; void _navpoly_changed(); void _map_changed(RID p_RID); @@ -134,7 +134,7 @@ public: void set_navigation_polygon(const Ref<NavigationPolygon> &p_navpoly); Ref<NavigationPolygon> get_navigation_polygon() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; NavigationRegion2D(); ~NavigationRegion2D(); diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 7765533016..2518069b78 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -437,7 +437,7 @@ void Node2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent); ADD_GROUP("Transform", ""); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_less,or_greater,no_slider,suffix:px"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_less,or_greater,hide_slider,suffix:px"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians"), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale", PROPERTY_HINT_LINK), "set_scale", "get_scale"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "skew", PROPERTY_HINT_RANGE, "-89.9,89.9,0.1,radians"), "set_skew", "get_skew"); diff --git a/scene/2d/parallax_background.cpp b/scene/2d/parallax_background.cpp index bd5a01f5a4..f1a28b7852 100644 --- a/scene/2d/parallax_background.cpp +++ b/scene/2d/parallax_background.cpp @@ -102,9 +102,9 @@ void ParallaxBackground::_update_scroll() { } if (ignore_camera_zoom) { - l->set_base_offset_and_scale((ofs + screen_offset * (scale - 1)) / scale, 1.0, screen_offset); + l->set_base_offset_and_scale((ofs + screen_offset * (scale - 1)) / scale, 1.0); } else { - l->set_base_offset_and_scale(ofs, scale, screen_offset); + l->set_base_offset_and_scale(ofs, scale); } } } diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp index f0aad1b8a4..01e4bf19f3 100644 --- a/scene/2d/parallax_layer.cpp +++ b/scene/2d/parallax_layer.cpp @@ -39,7 +39,7 @@ void ParallaxLayer::set_motion_scale(const Size2 &p_scale) { if (pb && is_inside_tree()) { Vector2 ofs = pb->get_final_offset(); real_t scale = pb->get_scroll_scale(); - set_base_offset_and_scale(ofs, scale, screen_offset); + set_base_offset_and_scale(ofs, scale); } } @@ -54,7 +54,7 @@ void ParallaxLayer::set_motion_offset(const Size2 &p_offset) { if (pb && is_inside_tree()) { Vector2 ofs = pb->get_final_offset(); real_t scale = pb->get_scroll_scale(); - set_base_offset_and_scale(ofs, scale, screen_offset); + set_base_offset_and_scale(ofs, scale); } } @@ -111,9 +111,7 @@ void ParallaxLayer::_notification(int p_what) { } } -void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, real_t p_scale, const Point2 &p_screen_offset) { - screen_offset = p_screen_offset; - +void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, real_t p_scale) { if (!is_inside_tree()) { return; } @@ -121,7 +119,7 @@ void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, real_t p_s return; } - Point2 new_ofs = (screen_offset + (p_offset - screen_offset) * motion_scale) + motion_offset * p_scale + orig_offset * p_scale; + Point2 new_ofs = p_offset * motion_scale + motion_offset * p_scale + orig_offset * p_scale; if (mirroring.x) { real_t den = mirroring.x * p_scale; @@ -139,8 +137,8 @@ void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, real_t p_s _update_mirroring(); } -TypedArray<String> ParallaxLayer::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray ParallaxLayer::get_configuration_warnings() const { + PackedStringArray warnings = Node::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/parallax_layer.h b/scene/2d/parallax_layer.h index b4dcf0ea61..6471f56c5c 100644 --- a/scene/2d/parallax_layer.h +++ b/scene/2d/parallax_layer.h @@ -43,8 +43,6 @@ class ParallaxLayer : public Node2D { Vector2 mirroring; void _update_mirroring(); - Point2 screen_offset; - protected: void _notification(int p_what); static void _bind_methods(); @@ -59,9 +57,9 @@ public: void set_mirroring(const Size2 &p_mirroring); Size2 get_mirroring() const; - void set_base_offset_and_scale(const Point2 &p_offset, real_t p_scale, const Point2 &p_screen_offset); + void set_base_offset_and_scale(const Point2 &p_offset, real_t p_scale); - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; ParallaxLayer(); }; diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 90b2e3d460..c1044fdf5b 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -256,8 +256,8 @@ void PathFollow2D::_validate_property(PropertyInfo &p_property) const { } } -TypedArray<String> PathFollow2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray PathFollow2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (is_visible_in_tree() && is_inside_tree()) { if (!Object::cast_to<Path2D>(get_parent())) { diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index 3d66ca1fab..5e436fb9f6 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -106,7 +106,7 @@ public: void set_cubic_interpolation(bool p_enable); bool get_cubic_interpolation() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; PathFollow2D() {} }; diff --git a/scene/2d/physical_bone_2d.cpp b/scene/2d/physical_bone_2d.cpp index e6933b8a40..5ff706ebb7 100644 --- a/scene/2d/physical_bone_2d.cpp +++ b/scene/2d/physical_bone_2d.cpp @@ -106,8 +106,8 @@ void PhysicalBone2D::_find_joint_child() { } } -TypedArray<String> PhysicalBone2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray PhysicalBone2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::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/physical_bone_2d.h b/scene/2d/physical_bone_2d.h index 9fbfa04100..33ac0d9935 100644 --- a/scene/2d/physical_bone_2d.h +++ b/scene/2d/physical_bone_2d.h @@ -79,7 +79,7 @@ public: void set_follow_bone_when_simulating(bool p_follow); bool get_follow_bone_when_simulating() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; PhysicalBone2D(); ~PhysicalBone2D(); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 714d196779..d0e35c2ea2 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -34,8 +34,8 @@ #include "scene/scene_string_names.h" void PhysicsBody2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("move_and_collide", "distance", "test_only", "safe_margin"), &PhysicsBody2D::_move, DEFVAL(false), DEFVAL(0.08)); - ClassDB::bind_method(D_METHOD("test_move", "from", "distance", "collision", "safe_margin"), &PhysicsBody2D::test_move, DEFVAL(Variant()), DEFVAL(0.08)); + ClassDB::bind_method(D_METHOD("move_and_collide", "distance", "test_only", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::_move, DEFVAL(false), DEFVAL(0.08), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("test_move", "from", "distance", "collision", "safe_margin", "recovery_as_collision"), &PhysicsBody2D::test_move, DEFVAL(Variant()), DEFVAL(0.08), DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody2D::get_collision_exceptions); ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody2D::add_collision_exception_with); @@ -54,15 +54,15 @@ PhysicsBody2D::~PhysicsBody2D() { } } -Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_distance, bool p_test_only, real_t p_margin) { +Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_distance, bool p_test_only, real_t p_margin, bool p_recovery_as_collision) { PhysicsServer2D::MotionParameters parameters(get_global_transform(), p_distance, p_margin); - parameters.recovery_as_collision = false; // Don't report collisions generated only from recovery. + parameters.recovery_as_collision = p_recovery_as_collision; PhysicsServer2D::MotionResult result; if (move_and_collide(parameters, result, p_test_only)) { // Create a new instance when the cached reference is invalid or still in use in script. - if (motion_cache.is_null() || motion_cache->reference_get_count() > 1) { + if (motion_cache.is_null() || motion_cache->get_reference_count() > 1) { motion_cache.instantiate(); motion_cache->owner = this; } @@ -128,7 +128,7 @@ bool PhysicsBody2D::move_and_collide(const PhysicsServer2D::MotionParameters &p_ return colliding; } -bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_distance, const Ref<KinematicCollision2D> &r_collision, real_t p_margin) { +bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_distance, const Ref<KinematicCollision2D> &r_collision, real_t p_margin, bool p_recovery_as_collision) { ERR_FAIL_COND_V(!is_inside_tree(), false); PhysicsServer2D::MotionResult *r = nullptr; @@ -141,7 +141,7 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_distan } PhysicsServer2D::MotionParameters parameters(p_from, p_distance, p_margin); - parameters.recovery_as_collision = false; // Don't report collisions generated only from recovery. + parameters.recovery_as_collision = p_recovery_as_collision; return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r); } @@ -262,21 +262,16 @@ void AnimatableBody2D::_update_kinematic_motion() { #endif if (sync_to_physics) { - PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); + PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &AnimatableBody2D::_body_state_changed)); set_only_update_transform_changes(true); set_notify_local_transform(true); } else { - PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), nullptr, nullptr); + PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), Callable()); set_only_update_transform_changes(false); set_notify_local_transform(false); } } -void AnimatableBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) { - AnimatableBody2D *body = static_cast<AnimatableBody2D *>(p_instance); - body->_body_state_changed(p_state); -} - void AnimatableBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) { if (!sync_to_physics) { return; @@ -438,11 +433,6 @@ struct _RigidBody2DInOut { int local_shape = 0; }; -void RigidBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) { - RigidBody2D *body = static_cast<RigidBody2D *>(p_instance); - body->_body_state_changed(p_state); -} - void RigidBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) { set_block_transform_notify(true); // don't want notify (would feedback loop) if (!freeze || freeze_mode != FREEZE_MODE_KINEMATIC) { @@ -921,10 +911,10 @@ void RigidBody2D::_notification(int p_what) { #endif } -TypedArray<String> RigidBody2D::get_configuration_warnings() const { +PackedStringArray RigidBody2D::get_configuration_warnings() const { Transform2D t = get_transform(); - TypedArray<String> warnings = CollisionObject2D::get_configuration_warnings(); + PackedStringArray warnings = CollisionObject2D::get_configuration_warnings(); if (ABS(t.columns[0].length() - 1.0) > 0.05 || ABS(t.columns[1].length() - 1.0) > 0.05) { warnings.push_back(RTR("Size changes to RigidBody2D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); @@ -1079,7 +1069,7 @@ void RigidBody2D::_validate_property(PropertyInfo &p_property) const { RigidBody2D::RigidBody2D() : PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) { - PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); + PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), callable_mp(this, &RigidBody2D::_body_state_changed)); } RigidBody2D::~RigidBody2D() { @@ -1557,7 +1547,7 @@ Ref<KinematicCollision2D> CharacterBody2D::_get_slide_collision(int p_bounce) { } // Create a new instance when the cached reference is invalid or still in use in script. - if (slide_colliders[p_bounce].is_null() || slide_colliders[p_bounce]->reference_get_count() > 1) { + if (slide_colliders[p_bounce].is_null() || slide_colliders[p_bounce]->get_reference_count() > 1) { slide_colliders.write[p_bounce].instantiate(); slide_colliders.write[p_bounce]->owner = this; } diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index eaba9aadad..932ec1de16 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -47,11 +47,11 @@ protected: Ref<KinematicCollision2D> motion_cache; - Ref<KinematicCollision2D> _move(const Vector2 &p_distance, bool p_test_only = false, real_t p_margin = 0.08); + Ref<KinematicCollision2D> _move(const Vector2 &p_distance, bool p_test_only = false, real_t p_margin = 0.08, bool p_recovery_as_collision = false); public: bool move_and_collide(const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true); - bool test_move(const Transform2D &p_from, const Vector2 &p_distance, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08); + bool test_move(const Transform2D &p_from, const Vector2 &p_distance, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08, bool p_recovery_as_collision = false); TypedArray<PhysicsBody2D> get_collision_exceptions(); void add_collision_exception_with(Node *p_node); //must be physicsbody @@ -309,7 +309,7 @@ public: TypedArray<Node2D> get_colliding_bodies() const; //function for script - virtual TypedArray<String> get_configuration_warnings() const override; + virtual PackedStringArray get_configuration_warnings() const override; RigidBody2D(); ~RigidBody2D(); diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp index 6c4bfd58ce..f4343e4c03 100644 --- a/scene/2d/remote_transform_2d.cpp +++ b/scene/2d/remote_transform_2d.cpp @@ -183,8 +183,8 @@ void RemoteTransform2D::force_update_cache() { _update_cache(); } -TypedArray<String> RemoteTransform2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray RemoteTransform2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::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/remote_transform_2d.h b/scene/2d/remote_transform_2d.h index bd352e1054..f98eec75c6 100644 --- a/scene/2d/remote_transform_2d.h +++ b/scene/2d/remote_transform_2d.h @@ -70,7 +70,7 @@ public: void force_update_cache(); - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; RemoteTransform2D(); }; diff --git a/scene/2d/shape_cast_2d.cpp b/scene/2d/shape_cast_2d.cpp index a25d5934ee..6222b0db14 100644 --- a/scene/2d/shape_cast_2d.cpp +++ b/scene/2d/shape_cast_2d.cpp @@ -391,8 +391,8 @@ Array ShapeCast2D::_get_collision_result() const { return ret; } -TypedArray<String> ShapeCast2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node2D::get_configuration_warnings(); +PackedStringArray ShapeCast2D::get_configuration_warnings() const { + PackedStringArray warnings = Node2D::get_configuration_warnings(); if (shape.is_null()) { warnings.push_back(RTR("This node cannot interact with other objects unless a Shape2D is assigned.")); diff --git a/scene/2d/shape_cast_2d.h b/scene/2d/shape_cast_2d.h index 660e52f189..7b55566b01 100644 --- a/scene/2d/shape_cast_2d.h +++ b/scene/2d/shape_cast_2d.h @@ -117,7 +117,7 @@ public: void remove_exception(const CollisionObject2D *p_node); void clear_exceptions(); - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; }; #endif // SHAPE_CAST_2D_H diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 8f0bf22617..b5759c54f7 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -434,8 +434,8 @@ int Bone2D::get_index_in_skeleton() const { return skeleton_index; } -TypedArray<String> Bone2D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray Bone2D::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); if (!skeleton) { if (parent_bone) { warnings.push_back(RTR("This Bone2D chain should end at a Skeleton2D node.")); diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h index 98fb867d99..580aed97ce 100644 --- a/scene/2d/skeleton_2d.h +++ b/scene/2d/skeleton_2d.h @@ -78,7 +78,7 @@ public: void apply_rest(); Transform2D get_skeleton_rest() const; - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; void set_default_length(real_t p_length); real_t get_default_length() const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 129cce93fa..5acf661425 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -34,6 +34,10 @@ #include "scene/resources/world_2d.h" #include "servers/navigation_server_2d.h" +#ifdef DEBUG_ENABLED +#include "servers/navigation_server_3d.h" +#endif // DEBUG_ENABLED + HashMap<Vector2i, TileSet::CellNeighbor> TileMap::TerrainConstraint::get_overlapping_coords_and_peering_bits() const { HashMap<Vector2i, TileSet::CellNeighbor> output; @@ -828,13 +832,13 @@ void TileMap::_update_dirty_quadrants() { // Update the coords cache. for (SelfList<TileMapQuadrant> *q = dirty_quadrant_list.first(); q; q = q->next()) { - q->self()->map_to_world.clear(); - q->self()->world_to_map.clear(); + q->self()->map_to_local.clear(); + q->self()->local_to_map.clear(); for (const Vector2i &E : q->self()->cells) { Vector2i pk = E; - Vector2i pk_world_coords = map_to_world(pk); - q->self()->map_to_world[pk] = pk_world_coords; - q->self()->world_to_map[pk_world_coords] = pk; + Vector2i pk_local_coords = map_to_local(pk); + q->self()->map_to_local[pk] = pk_local_coords; + q->self()->local_to_map[pk_local_coords] = pk; } } @@ -852,7 +856,7 @@ void TileMap::_update_dirty_quadrants() { for (SelfList<TileMapQuadrant> *q = dirty_quadrant_list.first(); q; q = q->next()) { rs->canvas_item_clear(q->self()->debug_canvas_item); Transform2D xform; - xform.set_origin(map_to_world(q->self()->coords * get_effective_quadrant_size(layer))); + xform.set_origin(map_to_local(q->self()->coords * get_effective_quadrant_size(layer))); rs->canvas_item_set_transform(q->self()->debug_canvas_item, xform); _rendering_draw_quadrant_debug(q->self()); @@ -978,10 +982,10 @@ void TileMap::_recompute_rect_cache() { for (unsigned int layer = 0; layer < layers.size(); layer++) { for (const KeyValue<Vector2i, TileMapQuadrant> &E : layers[layer].quadrant_map) { Rect2 r; - r.position = map_to_world(E.key * get_effective_quadrant_size(layer)); - r.expand_to(map_to_world((E.key + Vector2i(1, 0)) * get_effective_quadrant_size(layer))); - r.expand_to(map_to_world((E.key + Vector2i(1, 1)) * get_effective_quadrant_size(layer))); - r.expand_to(map_to_world((E.key + Vector2i(0, 1)) * get_effective_quadrant_size(layer))); + r.position = map_to_local(E.key * get_effective_quadrant_size(layer)); + r.expand_to(map_to_local((E.key + Vector2i(1, 0)) * get_effective_quadrant_size(layer))); + r.expand_to(map_to_local((E.key + Vector2i(1, 1)) * get_effective_quadrant_size(layer))); + r.expand_to(map_to_local((E.key + Vector2i(0, 1)) * get_effective_quadrant_size(layer))); if (first) { r_total = r; first = false; @@ -1003,6 +1007,22 @@ void TileMap::_recompute_rect_cache() { void TileMap::_rendering_notification(int p_what) { switch (p_what) { + case NOTIFICATION_ENTER_CANVAS: { + bool visible = is_visible_in_tree(); + for (int layer = 0; layer < (int)layers.size(); layer++) { + for (KeyValue<Vector2i, TileMapQuadrant> &E_quadrant : layers[layer].quadrant_map) { + TileMapQuadrant &q = E_quadrant.value; + for (const KeyValue<Vector2i, RID> &kv : q.occluders) { + Transform2D xform; + xform.set_origin(map_to_local(kv.key)); + RS::get_singleton()->canvas_light_occluder_attach_to_canvas(kv.value, get_canvas()); + RS::get_singleton()->canvas_light_occluder_set_transform(kv.value, get_global_transform() * xform); + RS::get_singleton()->canvas_light_occluder_set_enabled(kv.value, visible); + } + } + } + } break; + case NOTIFICATION_VISIBILITY_CHANGED: { bool visible = is_visible_in_tree(); for (int layer = 0; layer < (int)layers.size(); layer++) { @@ -1010,11 +1030,11 @@ void TileMap::_rendering_notification(int p_what) { TileMapQuadrant &q = E_quadrant.value; // Update occluders transform. - for (const KeyValue<Vector2i, Vector2i> &E_cell : q.world_to_map) { + for (const KeyValue<Vector2i, Vector2i> &E_cell : q.local_to_map) { Transform2D xform; xform.set_origin(E_cell.key); - for (const RID &occluder : q.occluders) { - RS::get_singleton()->canvas_light_occluder_set_enabled(occluder, visible); + for (const KeyValue<Vector2i, RID> &kv : q.occluders) { + RS::get_singleton()->canvas_light_occluder_set_enabled(kv.value, visible); } } } @@ -1030,12 +1050,10 @@ void TileMap::_rendering_notification(int p_what) { TileMapQuadrant &q = E_quadrant.value; // Update occluders transform. - for (const KeyValue<Vector2i, Vector2i> &E_cell : q.world_to_map) { + for (const KeyValue<Vector2i, RID> &kv : q.occluders) { Transform2D xform; - xform.set_origin(E_cell.key); - for (const RID &occluder : q.occluders) { - RS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform() * xform); - } + xform.set_origin(map_to_local(kv.key)); + RenderingServer::get_singleton()->canvas_light_occluder_set_transform(kv.value, get_global_transform() * xform); } } } @@ -1046,6 +1064,17 @@ void TileMap::_rendering_notification(int p_what) { RenderingServer::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), is_y_sort_enabled()); } } break; + + case NOTIFICATION_EXIT_CANVAS: { + for (int layer = 0; layer < (int)layers.size(); layer++) { + for (KeyValue<Vector2i, TileMapQuadrant> &E_quadrant : layers[layer].quadrant_map) { + TileMapQuadrant &q = E_quadrant.value; + for (const KeyValue<Vector2i, RID> &kv : q.occluders) { + RS::get_singleton()->canvas_light_occluder_attach_to_canvas(kv.value, RID()); + } + } + } + } break; } } @@ -1102,8 +1131,8 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List q.canvas_items.clear(); // Free the occluders. - for (const RID &occluder : q.occluders) { - rs->free(occluder); + for (const KeyValue<Vector2i, RID> &kv : q.occluders) { + rs->free(kv.value); } q.occluders.clear(); @@ -1126,7 +1155,7 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List } // Iterate over the cells of the quadrant. - for (const KeyValue<Vector2i, Vector2i> &E_cell : q.world_to_map) { + for (const KeyValue<Vector2i, Vector2i> &E_cell : q.local_to_map) { TileMapCell c = get_cell(q.layer, E_cell.value, true); TileSetSource *source; @@ -1151,7 +1180,7 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List int z_index = tile_data->get_z_index(); // Quandrant pos. - Vector2 position = map_to_world(q.coords * get_effective_quadrant_size(q.layer)); + Vector2 position = map_to_local(q.coords * get_effective_quadrant_size(q.layer)); if (is_y_sort_enabled() && layers[q.layer].y_sort_enabled) { // When Y-sorting, the quandrant size is sure to be 1, we can thus offset the CanvasItem. position.y += layers[q.layer].y_sort_origin + tile_data->get_y_sort_origin(); @@ -1207,7 +1236,7 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List rs->canvas_light_occluder_set_polygon(occluder_id, tile_data->get_occluder(i)->get_rid()); rs->canvas_light_occluder_attach_to_canvas(occluder_id, get_canvas()); rs->canvas_light_occluder_set_light_mask(occluder_id, tile_set->get_occlusion_layer_light_mask(i)); - q.occluders.push_back(occluder_id); + q.occluders[E_cell.value] = occluder_id; } } } @@ -1223,14 +1252,14 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List int index = -(int64_t)0x80000000; //always must be drawn below children. for (int layer = 0; layer < (int)layers.size(); layer++) { - // Sort the quadrants coords per world coordinates - RBMap<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator> world_to_map; + // Sort the quadrants coords per local coordinates. + RBMap<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator> local_to_map; for (const KeyValue<Vector2i, TileMapQuadrant> &E : layers[layer].quadrant_map) { - world_to_map[map_to_world(E.key)] = E.key; + local_to_map[map_to_local(E.key)] = E.key; } - // Sort the quadrants - for (const KeyValue<Vector2i, Vector2i> &E : world_to_map) { + // Sort the quadrants. + for (const KeyValue<Vector2i, Vector2i> &E : local_to_map) { TileMapQuadrant &q = layers[layer].quadrant_map[E.value]; for (const RID &ci : q.canvas_items) { RS::get_singleton()->canvas_item_set_draw_index(ci, index++); @@ -1255,8 +1284,8 @@ void TileMap::_rendering_cleanup_quadrant(TileMapQuadrant *p_quadrant) { p_quadrant->canvas_items.clear(); // Free the occluders. - for (const RID &occluder : p_quadrant->occluders) { - RenderingServer::get_singleton()->free(occluder); + for (const KeyValue<Vector2i, RID> &kv : p_quadrant->occluders) { + RenderingServer::get_singleton()->free(kv.value); } p_quadrant->occluders.clear(); } @@ -1270,7 +1299,7 @@ void TileMap::_rendering_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { // Draw a placeholder for scenes needing one. RenderingServer *rs = RenderingServer::get_singleton(); - Vector2 quadrant_pos = map_to_world(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); + Vector2 quadrant_pos = map_to_local(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); for (const Vector2i &E_cell : p_quadrant->cells) { const TileMapCell &c = get_cell(p_quadrant->layer, E_cell, true); @@ -1302,7 +1331,7 @@ void TileMap::_rendering_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { // Draw a placeholder tile. Transform2D xform; - xform.set_origin(map_to_world(E_cell) - quadrant_pos); + xform.set_origin(map_to_local(E_cell) - quadrant_pos); rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform); rs->canvas_item_add_circle(p_quadrant->debug_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color); } @@ -1423,7 +1452,7 @@ void TileMap::_physics_notification(int p_what) { for (RID body : q.bodies) { Transform2D xform; - xform.set_origin(map_to_world(bodies_coords[body])); + xform.set_origin(map_to_local(bodies_coords[body])); xform = global_transform * xform; PhysicsServer2D::get_singleton()->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); } @@ -1446,7 +1475,7 @@ void TileMap::_physics_notification(int p_what) { for (RID body : q.bodies) { Transform2D xform; - xform.set_origin(map_to_world(bodies_coords[body])); + xform.set_origin(map_to_local(bodies_coords[body])); xform = new_transform * xform; PhysicsServer2D::get_singleton()->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); @@ -1516,7 +1545,7 @@ void TileMap::_physics_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r ps->body_set_space(body, space); Transform2D xform; - xform.set_origin(map_to_world(E_cell)); + xform.set_origin(map_to_local(E_cell)); xform = global_transform * xform; ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); @@ -1602,7 +1631,7 @@ void TileMap::_physics_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { Vector<Color> color; color.push_back(debug_collision_color); - Vector2 quadrant_pos = map_to_world(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); + Vector2 quadrant_pos = map_to_local(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); Transform2D qudrant_xform; qudrant_xform.set_origin(quadrant_pos); Transform2D global_transform_inv = (get_global_transform() * qudrant_xform).affine_inverse(); @@ -1641,7 +1670,7 @@ void TileMap::_navigation_notification(int p_what) { continue; } Transform2D tile_transform; - tile_transform.set_origin(map_to_world(E_region.key)); + tile_transform.set_origin(map_to_local(E_region.key)); NavigationServer2D::get_singleton()->region_set_transform(region, tilemap_xform * tile_transform); } } @@ -1656,14 +1685,6 @@ void TileMap::_navigation_update_dirty_quadrants(SelfList<TileMapQuadrant>::List ERR_FAIL_COND(!is_inside_tree()); ERR_FAIL_COND(!tile_set.is_valid()); - // Get colors for debug. - SceneTree *st = SceneTree::get_singleton(); - Color debug_navigation_color; - bool debug_navigation = st && st->is_debugging_navigation_hint(); - if (debug_navigation) { - debug_navigation_color = st->get_debug_navigation_color(); - } - Transform2D tilemap_xform = get_global_transform(); SelfList<TileMapQuadrant> *q_list_element = r_dirty_quadrant_list.first(); while (q_list_element) { @@ -1709,7 +1730,7 @@ void TileMap::_navigation_update_dirty_quadrants(SelfList<TileMapQuadrant>::List if (navpoly.is_valid()) { Transform2D tile_transform; - tile_transform.set_origin(map_to_world(E_cell)); + tile_transform.set_origin(map_to_local(E_cell)); RID region = NavigationServer2D::get_singleton()->region_create(); NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map()); @@ -1766,10 +1787,13 @@ void TileMap::_navigation_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { RenderingServer *rs = RenderingServer::get_singleton(); - Color color = get_tree()->get_debug_navigation_color(); + Color color = Color(0.5, 1.0, 1.0, 1.0); +#ifdef DEBUG_ENABLED + color = NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color(); +#endif // DEBUG_ENABLED RandomPCG rand; - Vector2 quadrant_pos = map_to_world(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); + Vector2 quadrant_pos = map_to_local(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); for (const Vector2i &E_cell : p_quadrant->cells) { TileMapCell c = get_cell(p_quadrant->layer, E_cell, true); @@ -1792,7 +1816,7 @@ void TileMap::_navigation_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { } Transform2D xform; - xform.set_origin(map_to_world(E_cell) - quadrant_pos); + xform.set_origin(map_to_local(E_cell) - quadrant_pos); rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform); for (int layer_index = 0; layer_index < tile_set->get_navigation_layers_count(); layer_index++) { @@ -1862,16 +1886,16 @@ void TileMap::_scenes_update_dirty_quadrants(SelfList<TileMapQuadrant>::List &r_ Ref<PackedScene> packed_scene = scenes_collection_source->get_scene_tile_scene(c.alternative_tile); if (packed_scene.is_valid()) { Node *scene = packed_scene->instantiate(); - add_child(scene); Control *scene_as_control = Object::cast_to<Control>(scene); Node2D *scene_as_node2d = Object::cast_to<Node2D>(scene); if (scene_as_control) { - scene_as_control->set_position(map_to_world(E_cell) + scene_as_control->get_position()); + scene_as_control->set_position(map_to_local(E_cell) + scene_as_control->get_position()); } else if (scene_as_node2d) { Transform2D xform; - xform.set_origin(map_to_world(E_cell)); + xform.set_origin(map_to_local(E_cell)); scene_as_node2d->set_transform(xform * scene_as_node2d->get_transform()); } + add_child(scene); q.scenes[E_cell] = scene->get_name(); } } @@ -1903,7 +1927,7 @@ void TileMap::_scenes_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { // Draw a placeholder for scenes needing one. RenderingServer *rs = RenderingServer::get_singleton(); - Vector2 quadrant_pos = map_to_world(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); + Vector2 quadrant_pos = map_to_local(p_quadrant->coords * get_effective_quadrant_size(p_quadrant->layer)); for (const Vector2i &E_cell : p_quadrant->cells) { const TileMapCell &c = get_cell(p_quadrant->layer, E_cell, true); @@ -1933,7 +1957,7 @@ void TileMap::_scenes_draw_quadrant_debug(TileMapQuadrant *p_quadrant) { // Draw a placeholder tile. Transform2D xform; - xform.set_origin(map_to_world(E_cell) - quadrant_pos); + xform.set_origin(map_to_local(E_cell) - quadrant_pos); rs->canvas_item_add_set_transform(p_quadrant->debug_canvas_item, xform); rs->canvas_item_add_circle(p_quadrant->debug_canvas_item, Vector2(), MIN(tile_set->get_tile_size().x, tile_set->get_tile_size().y) / 4.0, color); } @@ -2822,7 +2846,7 @@ void TileMap::_build_runtime_update_tile_data(SelfList<TileMapQuadrant>::List &r while (q_list_element) { TileMapQuadrant &q = *q_list_element->self(); // Iterate over the cells of the quadrant. - for (const KeyValue<Vector2i, Vector2i> &E_cell : q.world_to_map) { + for (const KeyValue<Vector2i, Vector2i> &E_cell : q.local_to_map) { TileMapCell c = get_cell(q.layer, E_cell.value, true); TileSetSource *source; @@ -2981,7 +3005,7 @@ void TileMap::_get_property_list(List<PropertyInfo> *p_list) const { } } -Vector2 TileMap::map_to_world(const Vector2i &p_pos) const { +Vector2 TileMap::map_to_local(const Vector2i &p_pos) const { // SHOULD RETURN THE CENTER OF THE CELL ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2()); @@ -3058,10 +3082,10 @@ Vector2 TileMap::map_to_world(const Vector2i &p_pos) const { return (ret + Vector2(0.5, 0.5)) * tile_set->get_tile_size(); } -Vector2i TileMap::world_to_map(const Vector2 &p_pos) const { +Vector2i TileMap::local_to_map(const Vector2 &p_local_position) const { ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2i()); - Vector2 ret = p_pos; + Vector2 ret = p_local_position; ret /= tile_set->get_tile_size(); TileSet::TileShape tile_shape = tile_set->get_tile_shape(); @@ -3086,7 +3110,7 @@ Vector2i TileMap::world_to_map(const Vector2 &p_pos) const { ret.x /= overlapping_ratio; } - // For each half-offset shape, we check if we are in the corner of the tile, and thus should correct the world position accordingly. + // For each half-offset shape, we check if we are in the corner of the tile, and thus should correct the local position accordingly. if (tile_shape == TileSet::TILE_SHAPE_HALF_OFFSET_SQUARE || tile_shape == TileSet::TILE_SHAPE_HEXAGON || tile_shape == TileSet::TILE_SHAPE_ISOMETRIC) { // Technically, those 3 shapes are equivalent, as they are basically half-offset, but with different levels or overlap. // square = no overlap, hexagon = 0.25 overlap, isometric = 0.5 overlap @@ -3616,7 +3640,7 @@ TypedArray<Vector2i> TileMap::get_used_cells(int p_layer) const { return a; } -Rect2 TileMap::get_used_rect() { // Not const because of cache +Rect2i TileMap::get_used_rect() { // Not const because of cache // Return the rect of the currently used area if (used_rect_cache_dirty) { bool first = true; @@ -3771,7 +3795,7 @@ void TileMap::draw_cells_outline(Control *p_control, RBSet<Vector2i> p_cells, Co TileSet::TileShape shape = tile_set->get_tile_shape(); for (const Vector2i &E : p_cells) { - Vector2 center = map_to_world(E); + Vector2 center = map_to_local(E); #define DRAW_SIDE_IF_NEEDED(side, polygon_index_from, polygon_index_to) \ if (!p_cells.has(get_neighbor_cell(E, side))) { \ @@ -3820,8 +3844,8 @@ void TileMap::draw_cells_outline(Control *p_control, RBSet<Vector2i> p_cells, Co #undef DRAW_SIDE_IF_NEEDED } -TypedArray<String> TileMap::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +PackedStringArray TileMap::get_configuration_warnings() const { + PackedStringArray warnings = Node::get_configuration_warnings(); // Retrieve the set of Z index values with a Y-sorted layer. RBSet<int> y_sorted_z_index; @@ -3901,8 +3925,8 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("get_used_cells", "layer"), &TileMap::get_used_cells); ClassDB::bind_method(D_METHOD("get_used_rect"), &TileMap::get_used_rect); - ClassDB::bind_method(D_METHOD("map_to_world", "map_position"), &TileMap::map_to_world); - ClassDB::bind_method(D_METHOD("world_to_map", "world_position"), &TileMap::world_to_map); + ClassDB::bind_method(D_METHOD("map_to_local", "map_position"), &TileMap::map_to_local); + ClassDB::bind_method(D_METHOD("local_to_map", "local_position"), &TileMap::local_to_map); ClassDB::bind_method(D_METHOD("get_neighbor_cell", "coords", "neighbor"), &TileMap::get_neighbor_cell); diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index ecc6ee1d59..d468675e91 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -40,7 +40,7 @@ class TileSetAtlasSource; struct TileMapQuadrant { struct CoordsWorldComparator { _ALWAYS_INLINE_ bool operator()(const Vector2i &p_a, const Vector2i &p_b) const { - // We sort the cells by their world coords, as it is needed by rendering. + // We sort the cells by their local coords, as it is needed by rendering. if (p_a.y == p_b.y) { return p_a.x > p_b.x; } else { @@ -49,7 +49,7 @@ struct TileMapQuadrant { } }; - // Dirty list element + // Dirty list element. SelfList<TileMapQuadrant> dirty_list_element; // Quadrant layer and coords. @@ -58,17 +58,17 @@ struct TileMapQuadrant { // TileMapCells RBSet<Vector2i> cells; - // We need those two maps to sort by world position for rendering + // We need those two maps to sort by local position for rendering // This is kind of workaround, it would be better to sort the cells directly in the "cells" set instead. - RBMap<Vector2i, Vector2i> map_to_world; - RBMap<Vector2i, Vector2i, CoordsWorldComparator> world_to_map; + RBMap<Vector2i, Vector2i> map_to_local; + RBMap<Vector2i, Vector2i, CoordsWorldComparator> local_to_map; // Debug. RID debug_canvas_item; // Rendering. List<RID> canvas_items; - List<RID> occluders; + HashMap<Vector2i, RID> occluders; // Physics. List<RID> bodies; @@ -368,14 +368,14 @@ public: virtual void set_y_sort_enabled(bool p_enable) override; - Vector2 map_to_world(const Vector2i &p_pos) const; - Vector2i world_to_map(const Vector2 &p_pos) const; + Vector2 map_to_local(const Vector2i &p_pos) const; + Vector2i local_to_map(const Vector2 &p_pos) const; bool is_existing_neighbor(TileSet::CellNeighbor p_cell_neighbor) const; Vector2i get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const; TypedArray<Vector2i> get_used_cells(int p_layer) const; - Rect2 get_used_rect(); // Not const because of cache + Rect2i get_used_rect(); // Not const because of cache // Override some methods of the CanvasItem class to pass the changes to the quadrants CanvasItems virtual void set_light_mask(int p_light_mask) override; @@ -406,7 +406,7 @@ public: GDVIRTUAL3(_tile_data_runtime_update, int, Vector2i, TileData *); // Configuration warnings. - TypedArray<String> get_configuration_warnings() const override; + PackedStringArray get_configuration_warnings() const override; TileMap(); ~TileMap(); |