diff options
Diffstat (limited to 'scene')
62 files changed, 794 insertions, 543 deletions
diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index f39850441b..dfc08583f2 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -105,214 +105,6 @@ Rect2 AnimatedSprite2D::_get_rect() const { return Rect2(ofs, s); } -void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture2D> &p_frame, int p_at_pos) { - Map<StringName, Anim>::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - - if (p_at_pos >= 0 && p_at_pos < E->get().frames.size()) { - E->get().frames.insert(p_at_pos, p_frame); - } else { - E->get().frames.push_back(p_frame); - } - - emit_changed(); -} - -int SpriteFrames::get_frame_count(const StringName &p_anim) const { - const Map<StringName, Anim>::Element *E = animations.find(p_anim); - ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist."); - - return E->get().frames.size(); -} - -void SpriteFrames::remove_frame(const StringName &p_anim, int p_idx) { - Map<StringName, Anim>::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - - E->get().frames.remove(p_idx); - emit_changed(); -} - -void SpriteFrames::clear(const StringName &p_anim) { - Map<StringName, Anim>::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - - E->get().frames.clear(); - emit_changed(); -} - -void SpriteFrames::clear_all() { - animations.clear(); - add_animation("default"); -} - -void SpriteFrames::add_animation(const StringName &p_anim) { - ERR_FAIL_COND_MSG(animations.has(p_anim), "SpriteFrames already has animation '" + p_anim + "'."); - - animations[p_anim] = Anim(); -} - -bool SpriteFrames::has_animation(const StringName &p_anim) const { - return animations.has(p_anim); -} - -void SpriteFrames::remove_animation(const StringName &p_anim) { - animations.erase(p_anim); -} - -void SpriteFrames::rename_animation(const StringName &p_prev, const StringName &p_next) { - ERR_FAIL_COND_MSG(!animations.has(p_prev), "SpriteFrames doesn't have animation '" + String(p_prev) + "'."); - ERR_FAIL_COND_MSG(animations.has(p_next), "Animation '" + String(p_next) + "' already exists."); - - Anim anim = animations[p_prev]; - animations.erase(p_prev); - animations[p_next] = anim; -} - -Vector<String> SpriteFrames::_get_animation_list() const { - Vector<String> ret; - List<StringName> al; - get_animation_list(&al); - for (List<StringName>::Element *E = al.front(); E; E = E->next()) { - ret.push_back(E->get()); - } - - return ret; -} - -void SpriteFrames::get_animation_list(List<StringName> *r_animations) const { - for (const Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) { - r_animations->push_back(E->key()); - } -} - -Vector<String> SpriteFrames::get_animation_names() const { - Vector<String> names; - for (const Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) { - names.push_back(E->key()); - } - names.sort(); - return names; -} - -void SpriteFrames::set_animation_speed(const StringName &p_anim, float p_fps) { - ERR_FAIL_COND_MSG(p_fps < 0, "Animation speed cannot be negative (" + itos(p_fps) + ")."); - Map<StringName, Anim>::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - E->get().speed = p_fps; -} - -float SpriteFrames::get_animation_speed(const StringName &p_anim) const { - const Map<StringName, Anim>::Element *E = animations.find(p_anim); - ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist."); - return E->get().speed; -} - -void SpriteFrames::set_animation_loop(const StringName &p_anim, bool p_loop) { - Map<StringName, Anim>::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - E->get().loop = p_loop; -} - -bool SpriteFrames::get_animation_loop(const StringName &p_anim) const { - const Map<StringName, Anim>::Element *E = animations.find(p_anim); - ERR_FAIL_COND_V_MSG(!E, false, "Animation '" + String(p_anim) + "' doesn't exist."); - return E->get().loop; -} - -void SpriteFrames::_set_frames(const Array &p_frames) { - clear_all(); - Map<StringName, Anim>::Element *E = animations.find(SceneStringNames::get_singleton()->_default); - ERR_FAIL_COND(!E); - - E->get().frames.resize(p_frames.size()); - for (int i = 0; i < E->get().frames.size(); i++) { - E->get().frames.write[i] = p_frames[i]; - } -} - -Array SpriteFrames::_get_frames() const { - return Array(); -} - -Array SpriteFrames::_get_animations() const { - Array anims; - for (Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) { - Dictionary d; - d["name"] = E->key(); - d["speed"] = E->get().speed; - d["loop"] = E->get().loop; - Array frames; - for (int i = 0; i < E->get().frames.size(); i++) { - frames.push_back(E->get().frames[i]); - } - d["frames"] = frames; - anims.push_back(d); - } - - return anims; -} - -void SpriteFrames::_set_animations(const Array &p_animations) { - animations.clear(); - for (int i = 0; i < p_animations.size(); i++) { - Dictionary d = p_animations[i]; - - ERR_CONTINUE(!d.has("name")); - ERR_CONTINUE(!d.has("speed")); - ERR_CONTINUE(!d.has("loop")); - ERR_CONTINUE(!d.has("frames")); - - Anim anim; - anim.speed = d["speed"]; - anim.loop = d["loop"]; - Array frames = d["frames"]; - for (int j = 0; j < frames.size(); j++) { - RES res = frames[j]; - anim.frames.push_back(res); - } - - animations[d["name"]] = anim; - } -} - -void SpriteFrames::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_animation", "anim"), &SpriteFrames::add_animation); - ClassDB::bind_method(D_METHOD("has_animation", "anim"), &SpriteFrames::has_animation); - ClassDB::bind_method(D_METHOD("remove_animation", "anim"), &SpriteFrames::remove_animation); - ClassDB::bind_method(D_METHOD("rename_animation", "anim", "newname"), &SpriteFrames::rename_animation); - - ClassDB::bind_method(D_METHOD("get_animation_names"), &SpriteFrames::get_animation_names); - - ClassDB::bind_method(D_METHOD("set_animation_speed", "anim", "speed"), &SpriteFrames::set_animation_speed); - ClassDB::bind_method(D_METHOD("get_animation_speed", "anim"), &SpriteFrames::get_animation_speed); - - ClassDB::bind_method(D_METHOD("set_animation_loop", "anim", "loop"), &SpriteFrames::set_animation_loop); - ClassDB::bind_method(D_METHOD("get_animation_loop", "anim"), &SpriteFrames::get_animation_loop); - - ClassDB::bind_method(D_METHOD("add_frame", "anim", "frame", "at_position"), &SpriteFrames::add_frame, DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("get_frame_count", "anim"), &SpriteFrames::get_frame_count); - ClassDB::bind_method(D_METHOD("get_frame", "anim", "idx"), &SpriteFrames::get_frame); - ClassDB::bind_method(D_METHOD("set_frame", "anim", "idx", "txt"), &SpriteFrames::set_frame); - ClassDB::bind_method(D_METHOD("remove_frame", "anim", "idx"), &SpriteFrames::remove_frame); - ClassDB::bind_method(D_METHOD("clear", "anim"), &SpriteFrames::clear); - ClassDB::bind_method(D_METHOD("clear_all"), &SpriteFrames::clear_all); - - ClassDB::bind_method(D_METHOD("_set_frames"), &SpriteFrames::_set_frames); - ClassDB::bind_method(D_METHOD("_get_frames"), &SpriteFrames::_get_frames); - - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "frames", PROPERTY_HINT_NONE, "", 0), "_set_frames", "_get_frames"); //compatibility - - ClassDB::bind_method(D_METHOD("_set_animations"), &SpriteFrames::_set_animations); - ClassDB::bind_method(D_METHOD("_get_animations"), &SpriteFrames::_get_animations); - - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations"); //compatibility -} - -SpriteFrames::SpriteFrames() { - add_animation(SceneStringNames::get_singleton()->_default); -} - void AnimatedSprite2D::_validate_property(PropertyInfo &property) const { if (!frames.is_valid()) { return; @@ -590,6 +382,7 @@ bool AnimatedSprite2D::_is_playing() const { } void AnimatedSprite2D::play(const StringName &p_animation, const bool p_backwards) { + ERR_FAIL_NULL_MSG(frames, "Can't play AnimatedSprite2D without a valid SpriteFrames resource."); backwards = p_backwards; if (p_animation) { diff --git a/scene/2d/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h index 5e53a401e2..14ecb18866 100644 --- a/scene/2d/animated_sprite_2d.h +++ b/scene/2d/animated_sprite_2d.h @@ -32,74 +32,9 @@ #define ANIMATED_SPRITE_2D_H #include "scene/2d/node_2d.h" +#include "scene/resources/sprite_frames.h" #include "scene/resources/texture.h" -class SpriteFrames : public Resource { - GDCLASS(SpriteFrames, Resource); - - struct Anim { - float speed = 5.0; - bool loop = true; - Vector<Ref<Texture2D>> frames; - }; - - Map<StringName, Anim> animations; - - Array _get_frames() const; - void _set_frames(const Array &p_frames); - - Array _get_animations() const; - void _set_animations(const Array &p_animations); - - Vector<String> _get_animation_list() const; - -protected: - static void _bind_methods(); - -public: - void add_animation(const StringName &p_anim); - bool has_animation(const StringName &p_anim) const; - void remove_animation(const StringName &p_anim); - void rename_animation(const StringName &p_prev, const StringName &p_next); - - void get_animation_list(List<StringName> *r_animations) const; - Vector<String> get_animation_names() const; - - void set_animation_speed(const StringName &p_anim, float p_fps); - float get_animation_speed(const StringName &p_anim) const; - - void set_animation_loop(const StringName &p_anim, bool p_loop); - bool get_animation_loop(const StringName &p_anim) const; - - void add_frame(const StringName &p_anim, const Ref<Texture2D> &p_frame, int p_at_pos = -1); - int get_frame_count(const StringName &p_anim) const; - _FORCE_INLINE_ Ref<Texture2D> get_frame(const StringName &p_anim, int p_idx) const { - const Map<StringName, Anim>::Element *E = animations.find(p_anim); - ERR_FAIL_COND_V_MSG(!E, Ref<Texture2D>(), "Animation '" + String(p_anim) + "' doesn't exist."); - ERR_FAIL_COND_V(p_idx < 0, Ref<Texture2D>()); - if (p_idx >= E->get().frames.size()) { - return Ref<Texture2D>(); - } - - return E->get().frames[p_idx]; - } - - void set_frame(const StringName &p_anim, int p_idx, const Ref<Texture2D> &p_frame) { - Map<StringName, Anim>::Element *E = animations.find(p_anim); - ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); - ERR_FAIL_COND(p_idx < 0); - if (p_idx >= E->get().frames.size()) { - return; - } - E->get().frames.write[p_idx] = p_frame; - } - void remove_frame(const StringName &p_anim, int p_idx); - void clear(const StringName &p_anim); - void clear_all(); - - SpriteFrames(); -}; - class AnimatedSprite2D : public Node2D { GDCLASS(AnimatedSprite2D, Node2D); diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp index 892ccadfda..c478f03356 100644 --- a/scene/2d/line_builder.cpp +++ b/scene/2d/line_builder.cpp @@ -375,7 +375,7 @@ void LineBuilder::build() { } if (intersection_result != SEGMENT_INTERSECT) { - // In this case the joint is too corrputed to be re-used, + // In this case the joint is too corrupted to be re-used, // start again the strip with fallback points strip_begin(pos_up0, pos_down0, color1, uvx1); } @@ -485,7 +485,7 @@ void LineBuilder::strip_add_tri(Vector2 up, Orientation orientation) { if (texture_mode != Line2D::LINE_TEXTURE_NONE) { // UVs are just one slice of the texture all along - // (otherwise we can't share the bottom vertice) + // (otherwise we can't share the bottom vertex) uvs.push_back(uvs[_last_index[opposite_orientation]]); } @@ -520,7 +520,7 @@ void LineBuilder::strip_add_arc(Vector2 center, float angle_delta, Orientation o strip_add_tri(rpos, orientation); } - // Last arc vertice + // Last arc vertex rpos = center + Vector2(Math::cos(end_angle), Math::sin(end_angle)) * radius; strip_add_tri(rpos, orientation); } @@ -569,7 +569,7 @@ void LineBuilder::new_arc(Vector2 center, Vector2 vbegin, float angle_delta, Col } } - // Last arc vertice + // Last arc vertex Vector2 sc = Vector2(Math::cos(end_angle), Math::sin(end_angle)); rpos = center + sc * radius; vertices.push_back(rpos); diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index 794993f892..8be8c8db4a 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -364,8 +364,10 @@ void NavigationRegion2D::set_enabled(bool p_enabled) { if (!enabled) { NavigationServer2D::get_singleton()->region_set_map(region, RID()); + NavigationServer2D::get_singleton()->disconnect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed)); } else { NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map()); + NavigationServer2D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed)); } if (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) { @@ -401,6 +403,7 @@ void NavigationRegion2D::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { if (enabled) { NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map()); + NavigationServer2D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed)); } } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -408,12 +411,14 @@ void NavigationRegion2D::_notification(int p_what) { } break; case NOTIFICATION_EXIT_TREE: { NavigationServer2D::get_singleton()->region_set_map(region, RID()); + if (enabled) { + NavigationServer2D::get_singleton()->disconnect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed)); + } } break; case NOTIFICATION_DRAW: { if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) && navpoly.is_valid()) { Vector<Vector2> verts = navpoly->get_vertices(); - int vsize = verts.size(); - if (vsize < 3) { + if (verts.size() < 3) { return; } @@ -423,33 +428,47 @@ void NavigationRegion2D::_notification(int p_what) { } else { color = get_tree()->get_debug_navigation_disabled_color(); } - Vector<Color> colors; - Vector<Vector2> vertices; - vertices.resize(vsize); - colors.resize(vsize); - { - const Vector2 *vr = verts.ptr(); - for (int i = 0; i < vsize; i++) { - vertices.write[i] = vr[i]; - colors.write[i] = color; - } - } + Color doors_color = color.lightened(0.2); - Vector<int> indices; + RandomPCG rand; for (int i = 0; i < navpoly->get_polygon_count(); i++) { + // An array of vertices for this polygon. Vector<int> polygon = navpoly->get_polygon(i); - - for (int j = 2; j < polygon.size(); j++) { - int kofs[3] = { 0, j - 1, j }; - for (int k = 0; k < 3; k++) { - int idx = polygon[kofs[k]]; - ERR_FAIL_INDEX(idx, vsize); - indices.push_back(idx); - } + Vector<Vector2> vertices; + vertices.resize(polygon.size()); + for (int j = 0; j < polygon.size(); j++) { + ERR_FAIL_INDEX(polygon[j], verts.size()); + vertices.write[j] = verts[polygon[j]]; } + + // Generate the polygon color, slightly randomly modified from the settings one. + Color random_variation_color; + random_variation_color.set_hsv(color.get_h() + rand.random(-1.0, 1.0) * 0.05, color.get_s(), color.get_v() + rand.random(-1.0, 1.0) * 0.1); + random_variation_color.a = color.a; + Vector<Color> colors; + colors.push_back(random_variation_color); + + RS::get_singleton()->canvas_item_add_polygon(get_canvas_item(), vertices, colors); + } + + // Draw the region + Transform2D xform = get_global_transform(); + const NavigationServer2D *ns = NavigationServer2D::get_singleton(); + float radius = ns->map_get_edge_connection_margin(get_world_2d()->get_navigation_map()) / 2.0; + for (int i = 0; i < ns->region_get_connections_count(region); i++) { + // Two main points + Vector2 a = ns->region_get_connection_pathway_start(region, i); + a = xform.affine_inverse().xform(a); + Vector2 b = ns->region_get_connection_pathway_end(region, i); + b = xform.affine_inverse().xform(b); + draw_line(a, b, doors_color); + + // Draw a circle to illustrate the margins. + float angle = (b - a).angle(); + draw_arc(a, radius, angle + Math_PI / 2.0, angle - Math_PI / 2.0 + Math_TAU, 10, doors_color); + draw_arc(b, radius, angle - Math_PI / 2.0, angle + Math_PI / 2.0, 10, doors_color); } - RS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, vertices, colors); } } break; } @@ -484,6 +503,11 @@ void NavigationRegion2D::_navpoly_changed() { update(); } } +void NavigationRegion2D::_map_changed(RID p_map) { + if (enabled && get_world_2d()->get_navigation_map() == p_map) { + update(); + } +} String NavigationRegion2D::get_configuration_warning() const { if (!is_visible_in_tree() || !is_inside_tree()) { diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h index 7b471bd555..58f04599be 100644 --- a/scene/2d/navigation_region_2d.h +++ b/scene/2d/navigation_region_2d.h @@ -99,6 +99,7 @@ class NavigationRegion2D : public Node2D { Ref<NavigationPolygon> navpoly; void _navpoly_changed(); + void _map_changed(RID p_RID); protected: void _notification(int p_what); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 96d8fb609b..a615d96687 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -411,13 +411,13 @@ void RigidBody2D::_direct_state_changed(Object *p_state) { } } - //process remotions + //process removals for (int i = 0; i < toremove_count; i++) { _body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape); } - //process aditions + //process additions for (int i = 0; i < toadd_count; i++) { _body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape); diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 5728230a8c..e028b5f5b7 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -184,7 +184,7 @@ void Skeleton2D::_update_bone_setup() { bone_setup_dirty = false; RS::get_singleton()->skeleton_allocate_data(skeleton, bones.size(), true); - bones.sort(); //sorty so they are always in the same order/index + bones.sort(); //sorting so that they are always in the same order/index for (int i = 0; i < bones.size(); i++) { bones.write[i].rest_inverse = bones[i].bone->get_skeleton_rest().affine_inverse(); //bind pose diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp index 31040020dd..7c93edbff9 100644 --- a/scene/2d/sprite_2d.cpp +++ b/scene/2d/sprite_2d.cpp @@ -77,14 +77,14 @@ Rect2 Sprite2D::get_anchorable_rect() const { return get_rect(); } -void Sprite2D::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const { +void Sprite2D::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip_enabled) const { Rect2 base_rect; - if (region) { - r_filter_clip = region_filter_clip; + if (region_enabled) { + r_filter_clip_enabled = region_filter_clip_enabled; base_rect = region_rect; } else { - r_filter_clip = false; + r_filter_clip_enabled = false; base_rect = Rect2(0, 0, texture->get_width(), texture->get_height()); } @@ -129,10 +129,10 @@ void Sprite2D::_notification(int p_what) { */ Rect2 src_rect, dst_rect; - bool filter_clip; - _get_rects(src_rect, dst_rect, filter_clip); + bool filter_clip_enabled; + _get_rects(src_rect, dst_rect, filter_clip_enabled); - texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, filter_clip); + texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, filter_clip_enabled); } break; } } @@ -199,18 +199,18 @@ bool Sprite2D::is_flipped_v() const { return vflip; } -void Sprite2D::set_region(bool p_region) { - if (p_region == region) { +void Sprite2D::set_region_enabled(bool p_region_enabled) { + if (p_region_enabled == region_enabled) { return; } - region = p_region; + region_enabled = p_region_enabled; update(); notify_property_list_changed(); } -bool Sprite2D::is_region() const { - return region; +bool Sprite2D::is_region_enabled() const { + return region_enabled; } void Sprite2D::set_region_rect(const Rect2 &p_region_rect) { @@ -220,7 +220,7 @@ void Sprite2D::set_region_rect(const Rect2 &p_region_rect) { region_rect = p_region_rect; - if (region) { + if (region_enabled) { item_rect_changed(); } } @@ -229,13 +229,13 @@ Rect2 Sprite2D::get_region_rect() const { return region_rect; } -void Sprite2D::set_region_filter_clip(bool p_enable) { - region_filter_clip = p_enable; +void Sprite2D::set_region_filter_clip_enabled(bool p_region_filter_clip_enabled) { + region_filter_clip_enabled = p_region_filter_clip_enabled; update(); } bool Sprite2D::is_region_filter_clip_enabled() const { - return region_filter_clip; + return region_filter_clip_enabled; } void Sprite2D::set_frame(int p_frame) { @@ -299,8 +299,8 @@ bool Sprite2D::is_pixel_opaque(const Point2 &p_point) const { } Rect2 src_rect, dst_rect; - bool filter_clip; - _get_rects(src_rect, dst_rect, filter_clip); + bool filter_clip_enabled; + _get_rects(src_rect, dst_rect, filter_clip_enabled); dst_rect.size = dst_rect.size.abs(); if (!dst_rect.has_point(p_point)) { @@ -350,7 +350,7 @@ Rect2 Sprite2D::get_rect() const { Size2i s; - if (region) { + if (region_enabled) { s = region_rect.size; } else { s = texture->get_size(); @@ -385,7 +385,7 @@ void Sprite2D::_validate_property(PropertyInfo &property) const { property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; } - if (!region && (property.name == "region_rect" || property.name == "region_filter_clip")) { + if (!region_enabled && (property.name == "region_rect" || property.name == "region_filter_clip")) { property.usage = PROPERTY_USAGE_NOEDITOR; } } @@ -414,15 +414,15 @@ void Sprite2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_flip_v", "flip_v"), &Sprite2D::set_flip_v); ClassDB::bind_method(D_METHOD("is_flipped_v"), &Sprite2D::is_flipped_v); - ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite2D::set_region); - ClassDB::bind_method(D_METHOD("is_region"), &Sprite2D::is_region); + ClassDB::bind_method(D_METHOD("set_region_enabled", "enabled"), &Sprite2D::set_region_enabled); + ClassDB::bind_method(D_METHOD("is_region_enabled"), &Sprite2D::is_region_enabled); ClassDB::bind_method(D_METHOD("is_pixel_opaque", "pos"), &Sprite2D::is_pixel_opaque); ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite2D::set_region_rect); ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite2D::get_region_rect); - ClassDB::bind_method(D_METHOD("set_region_filter_clip", "enabled"), &Sprite2D::set_region_filter_clip); + ClassDB::bind_method(D_METHOD("set_region_filter_clip_enabled", "enabled"), &Sprite2D::set_region_filter_clip_enabled); ClassDB::bind_method(D_METHOD("is_region_filter_clip_enabled"), &Sprite2D::is_region_filter_clip_enabled); ClassDB::bind_method(D_METHOD("set_frame", "frame"), &Sprite2D::set_frame); @@ -455,9 +455,9 @@ void Sprite2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); ADD_GROUP("Region", "region_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_filter_clip"), "set_region_filter_clip", "is_region_filter_clip_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_filter_clip_enabled"), "set_region_filter_clip_enabled", "is_region_filter_clip_enabled"); } Sprite2D::Sprite2D() { diff --git a/scene/2d/sprite_2d.h b/scene/2d/sprite_2d.h index fa765f457d..f6e9b4cde2 100644 --- a/scene/2d/sprite_2d.h +++ b/scene/2d/sprite_2d.h @@ -46,16 +46,16 @@ class Sprite2D : public Node2D { bool hflip = false; bool vflip = false; - bool region = false; + bool region_enabled = false; Rect2 region_rect; - bool region_filter_clip = false; + bool region_filter_clip_enabled = false; int frame = 0; int vframes = 1; int hframes = 1; - void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const; + void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip_enabled) const; void _texture_changed(); @@ -97,10 +97,10 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; - void set_region(bool p_region); - bool is_region() const; + void set_region_enabled(bool p_enabled); + bool is_region_enabled() const; - void set_region_filter_clip(bool p_enable); + void set_region_filter_clip_enabled(bool p_enabled); bool is_region_filter_clip_enabled() const; void set_region_rect(const Rect2 &p_region_rect); diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index 23eda379be..749cf4ff9d 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -211,7 +211,7 @@ void Area3D::_clear_monitoring() { Object *obj = ObjectDB::get_instance(E->key()); Node *node = Object::cast_to<Node>(obj); - if (!node) { //node may have been deleted in previous frame or at other legiminate point + if (!node) { //node may have been deleted in previous frame or at other legitimate point continue; } //ERR_CONTINUE(!node); @@ -240,7 +240,7 @@ void Area3D::_clear_monitoring() { Object *obj = ObjectDB::get_instance(E->key()); Node *node = Object::cast_to<Node>(obj); - if (!node) { //node may have been deleted in previous frame or at other legiminate point + if (!node) { //node may have been deleted in previous frame or at other legitimate point continue; } //ERR_CONTINUE(!node); diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index 402e2b8f40..95ffbe48c1 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -449,7 +449,7 @@ int32_t BakedLightmap::_compute_bsp_tree(const Vector<Vector3> &p_points, const ERR_FAIL_COND_V(p_simplex_indices.size() <= 1, 0); //should not happen, this is a bug // Failed to separate the tetrahedrons using planes - // this means Delaunay borked at some point. + // this means Delaunay broke at some point. // Luckily, because we are using tetrahedrons, we can resort to // less precise but still working ways to generate the separating plane // this will most likely look bad when interpolating, but at least it will not crash. @@ -511,7 +511,7 @@ int32_t BakedLightmap::_compute_bsp_tree(const Vector<Vector3> &p_points, const node.plane = best_plane; if (indices_under.size() == 0) { - //noting to do here + //nothing to do here node.under = BSPNode::EMPTY_LEAF; } else if (indices_under.size() == 1) { node.under = -(indices_under[0] + 1); @@ -520,7 +520,7 @@ int32_t BakedLightmap::_compute_bsp_tree(const Vector<Vector3> &p_points, const } if (indices_over.size() == 0) { - //noting to do here + //nothing to do here node.over = BSPNode::EMPTY_LEAF; } else if (indices_over.size() == 1) { node.over = -(indices_over[0] + 1); @@ -660,7 +660,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_d } // create mesh data for insert - //get the base material textures, help compute altlas size and bounds + //get the base material textures, help compute atlas size and bounds for (int m_i = 0; m_i < meshes_found.size(); m_i++) { if (p_bake_step) { float p = (float)(m_i) / meshes_found.size(); @@ -974,7 +974,7 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_d for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) { images.push_back(lightmapper->get_bake_texture(i)); } - //we assume they are all the same, so lets create a large one for saving + //we assume they are all the same, so let's create a large one for saving Ref<Image> large_image; large_image.instance(); diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index f0623c625e..cd8d02233b 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -102,7 +102,7 @@ void Camera3D::_update_camera() { void Camera3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_WORLD: { - // Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD + // Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD // and Spatial will handle it first, including clearing its reference to the Viewport, // therefore making it impossible to subclasses to access it viewport = get_viewport(); @@ -715,7 +715,7 @@ void ClippedCamera3D::_notification(int p_what) { Vector3 ray_from = parent_plane.project(cam_pos); - clip_offset = 0; //reset by defau;t + clip_offset = 0; //reset by default { //check if points changed Vector<Vector3> local_points = get_near_plane_points(); diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 849ef7a2bf..39880db29c 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -30,6 +30,7 @@ #include "collision_object_3d.h" +#include "core/config/engine.h" #include "mesh_instance_3d.h" #include "scene/scene_string_names.h" #include "servers/physics_server_3d.h" @@ -139,7 +140,7 @@ void CollisionObject3D::_update_debug_shapes() { } void CollisionObject3D::_update_shape_data(uint32_t p_owner) { - if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) { + if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint()) { if (debug_shapes_to_update.is_empty()) { call_deferred("_update_debug_shapes"); } diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index 17a61b3e4d..e2cfc2ed87 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -348,7 +348,7 @@ void GPUParticles3D::_notification(int p_what) { } } - // Use internal process when emitting and one_shot are on so that when + // Use internal process when emitting and one_shot is on so that when // the shot ends the editor can properly update if (p_what == NOTIFICATION_INTERNAL_PROCESS) { if (one_shot && !is_emitting()) { diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index 4575716f7a..ba0f8cc870 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -48,7 +48,7 @@ a) If above is invalid, don't keep invalidating upwards 2) If a node sets a GLOBAL, it is converted to LOCAL (and forces validation of everything pending below) - drawback: setting/reading globals is useful and used very very often, and using affine inverses is slow + drawback: setting/reading globals is useful and used very often, and using affine inverses is slow --- diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 6d135c8283..e225c1f22d 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -416,13 +416,13 @@ void RigidBody3D::_direct_state_changed(Object *p_state) { } } - //process remotions + //process removals for (int i = 0; i < toremove_count; i++) { _body_inout(0, toremove[i].body_id, toremove[i].pair.body_shape, toremove[i].pair.local_shape); } - //process aditions + //process additions for (int i = 0; i < toadd_count; i++) { _body_inout(1, toadd[i].id, toadd[i].shape, toadd[i].local_shape); diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp index 465de2cb47..66f3e539a2 100644 --- a/scene/3d/ray_cast_3d.cpp +++ b/scene/3d/ray_cast_3d.cpp @@ -428,10 +428,10 @@ void RayCast3D::_update_debug_shape_material(bool p_check_collision) { if (p_check_collision) { if ((color.get_h() < 0.055 || color.get_h() > 0.945) && color.get_s() > 0.5 && color.get_v() > 0.5) { - // If base color is already quite reddish, hightlight collision with green color + // If base color is already quite reddish, highlight collision with green color color = Color(0.0, 1.0, 0.0, color.a); } else { - // Else, hightlight collision with red color + // Else, highlight collision with red color color = Color(1.0, 0, 0, color.a); } } diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp index 18c831e83d..85da546430 100644 --- a/scene/3d/skeleton_ik_3d.cpp +++ b/scene/3d/skeleton_ik_3d.cpp @@ -120,7 +120,7 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain if (p_force_simple_chain) { // NOTE: - // This is an "hack" that force to create only one tip per chain since the solver of multi tip (end effector) + // This is a "hack" that force to create only one tip per chain since the solver of multi tip (end effector) // is not yet created. // Remove this code when this is done break; @@ -268,6 +268,10 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove p_task->skeleton->set_bone_global_pose_override(p_task->chain.tips[i].chain_item->bone, Transform(), 0.0, true); } + // Update the initial root transform + p_task->chain.chain_root.initial_transform = p_task->skeleton->get_bone_global_pose(p_task->chain.chain_root.bone); + p_task->chain.chain_root.current_pos = p_task->chain.chain_root.initial_transform.origin; + make_goal(p_task, p_task->skeleton->get_global_transform().affine_inverse(), blending_delta); if (p_use_magnet && p_task->chain.middle_chain_item) { diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 2d8f22ab37..3fde4d6ef3 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -37,7 +37,6 @@ #include "scene/3d/collision_object_3d.h" #include "scene/3d/physics_body_3d.h" #include "scene/3d/skeleton_3d.h" -#include "servers/physics_server_3d.h" SoftBodyRenderingServerHandler::SoftBodyRenderingServerHandler() {} @@ -48,27 +47,28 @@ void SoftBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) { mesh = p_mesh; surface = p_surface; -#ifndef _MSC_VER -#warning Softbody is not working, needs to be redone considering that these functions no longer exist -#endif -#if 0 - const uint32_t surface_format = RS::get_singleton()->mesh_surface_get_format(mesh, surface); - const int surface_vertex_len = RS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface); - const int surface_index_len = RS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface); + + RS::SurfaceData surface_data = RS::get_singleton()->mesh_get_surface(mesh, surface); + uint32_t surface_offsets[RS::ARRAY_MAX]; + uint32_t vertex_stride; + uint32_t attrib_stride; + uint32_t skin_stride; + RS::get_singleton()->mesh_surface_make_offsets_from_format(surface_data.format, surface_data.vertex_count, surface_data.index_count, surface_offsets, vertex_stride, attrib_stride, skin_stride); - buffer = RS::get_singleton()->mesh_surface_get_array(mesh, surface); - stride = RS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets); + buffer = surface_data.vertex_data; + stride = vertex_stride; offset_vertices = surface_offsets[RS::ARRAY_VERTEX]; offset_normal = surface_offsets[RS::ARRAY_NORMAL]; -#endif } void SoftBodyRenderingServerHandler::clear() { - if (mesh.is_valid()) { - buffer.resize(0); - } + buffer.resize(0); + stride = 0; + offset_vertices = 0; + offset_normal = 0; + surface = 0; mesh = RID(); } @@ -77,7 +77,7 @@ void SoftBodyRenderingServerHandler::open() { } void SoftBodyRenderingServerHandler::close() { - //write_buffer.release(); + write_buffer = nullptr; } void SoftBodyRenderingServerHandler::commit_changes() { @@ -309,6 +309,8 @@ void SoftBody3D::_notification(int p_what) { } void SoftBody3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_physics_rid"), &SoftBody3D::get_physics_rid); + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftBody3D::set_collision_mask); ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftBody3D::get_collision_mask); @@ -337,18 +339,9 @@ void SoftBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftBody3D::set_linear_stiffness); ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftBody3D::get_linear_stiffness); - ClassDB::bind_method(D_METHOD("set_angular_stiffness", "angular_stiffness"), &SoftBody3D::set_angular_stiffness); - ClassDB::bind_method(D_METHOD("get_angular_stiffness"), &SoftBody3D::get_angular_stiffness); - - ClassDB::bind_method(D_METHOD("set_volume_stiffness", "volume_stiffness"), &SoftBody3D::set_volume_stiffness); - ClassDB::bind_method(D_METHOD("get_volume_stiffness"), &SoftBody3D::get_volume_stiffness); - ClassDB::bind_method(D_METHOD("set_pressure_coefficient", "pressure_coefficient"), &SoftBody3D::set_pressure_coefficient); ClassDB::bind_method(D_METHOD("get_pressure_coefficient"), &SoftBody3D::get_pressure_coefficient); - ClassDB::bind_method(D_METHOD("set_pose_matching_coefficient", "pose_matching_coefficient"), &SoftBody3D::set_pose_matching_coefficient); - ClassDB::bind_method(D_METHOD("get_pose_matching_coefficient"), &SoftBody3D::get_pose_matching_coefficient); - ClassDB::bind_method(D_METHOD("set_damping_coefficient", "damping_coefficient"), &SoftBody3D::set_damping_coefficient); ClassDB::bind_method(D_METHOD("get_damping_coefficient"), &SoftBody3D::get_damping_coefficient); @@ -366,12 +359,9 @@ void SoftBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "simulation_precision", PROPERTY_HINT_RANGE, "1,100,1"), "set_simulation_precision", "get_simulation_precision"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_mass", PROPERTY_HINT_RANGE, "0.01,10000,1"), "set_total_mass", "get_total_mass"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_linear_stiffness", "get_linear_stiffness"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_angular_stiffness", "get_angular_stiffness"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_stiffness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_volume_stiffness", "get_volume_stiffness"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pressure_coefficient"), "set_pressure_coefficient", "get_pressure_coefficient"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_damping_coefficient", "get_damping_coefficient"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drag_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_coefficient", "get_drag_coefficient"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pose_matching_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_pose_matching_coefficient", "get_pose_matching_coefficient"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ray_pickable"), "set_ray_pickable", "is_ray_pickable"); } @@ -612,34 +602,10 @@ real_t SoftBody3D::get_linear_stiffness() { return PhysicsServer3D::get_singleton()->soft_body_get_linear_stiffness(physics_rid); } -void SoftBody3D::set_angular_stiffness(real_t p_angular_stiffness) { - PhysicsServer3D::get_singleton()->soft_body_set_angular_stiffness(physics_rid, p_angular_stiffness); -} - -real_t SoftBody3D::get_angular_stiffness() { - return PhysicsServer3D::get_singleton()->soft_body_get_angular_stiffness(physics_rid); -} - -void SoftBody3D::set_volume_stiffness(real_t p_volume_stiffness) { - PhysicsServer3D::get_singleton()->soft_body_set_volume_stiffness(physics_rid, p_volume_stiffness); -} - -real_t SoftBody3D::get_volume_stiffness() { - return PhysicsServer3D::get_singleton()->soft_body_get_volume_stiffness(physics_rid); -} - real_t SoftBody3D::get_pressure_coefficient() { return PhysicsServer3D::get_singleton()->soft_body_get_pressure_coefficient(physics_rid); } -void SoftBody3D::set_pose_matching_coefficient(real_t p_pose_matching_coefficient) { - PhysicsServer3D::get_singleton()->soft_body_set_pose_matching_coefficient(physics_rid, p_pose_matching_coefficient); -} - -real_t SoftBody3D::get_pose_matching_coefficient() { - return PhysicsServer3D::get_singleton()->soft_body_get_pose_matching_coefficient(physics_rid); -} - void SoftBody3D::set_pressure_coefficient(real_t p_pressure_coefficient) { PhysicsServer3D::get_singleton()->soft_body_set_pressure_coefficient(physics_rid, p_pressure_coefficient); } @@ -768,7 +734,9 @@ void SoftBody3D::_reset_points_offsets() { PinnedPoint *w = pinned_points.ptrw(); for (int i = pinned_points.size() - 1; 0 <= i; --i) { if (!r[i].spatial_attachment) { - w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(r[i].spatial_attachment_path)); + if (!r[i].spatial_attachment_path.is_empty() && has_node(r[i].spatial_attachment_path)) { + w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(r[i].spatial_attachment_path)); + } } if (!r[i].spatial_attachment) { diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h index 6e24a530bd..f98df39209 100644 --- a/scene/3d/soft_body_3d.h +++ b/scene/3d/soft_body_3d.h @@ -32,10 +32,11 @@ #define SOFT_PHYSICS_BODY_H #include "scene/3d/mesh_instance_3d.h" +#include "servers/physics_server_3d.h" class SoftBody3D; -class SoftBodyRenderingServerHandler { +class SoftBodyRenderingServerHandler : public RenderingServerHandler { friend class SoftBody3D; RID mesh; @@ -57,9 +58,9 @@ private: void commit_changes(); public: - void set_vertex(int p_vertex_id, const void *p_vector3); - void set_normal(int p_vertex_id, const void *p_vector3); - void set_aabb(const AABB &p_aabb); + void set_vertex(int p_vertex_id, const void *p_vector3) override; + void set_normal(int p_vertex_id, const void *p_vector3) override; + void set_aabb(const AABB &p_aabb) override; }; class SoftBody3D : public MeshInstance3D { @@ -122,6 +123,8 @@ public: void prepare_physics_server(); void become_mesh_owner(); + RID get_physics_rid() const { return physics_rid; } + void set_collision_mask(uint32_t p_mask); uint32_t get_collision_mask() const; @@ -149,18 +152,9 @@ public: void set_linear_stiffness(real_t p_linear_stiffness); real_t get_linear_stiffness(); - void set_angular_stiffness(real_t p_angular_stiffness); - real_t get_angular_stiffness(); - - void set_volume_stiffness(real_t p_volume_stiffness); - real_t get_volume_stiffness(); - void set_pressure_coefficient(real_t p_pressure_coefficient); real_t get_pressure_coefficient(); - void set_pose_matching_coefficient(real_t p_pose_matching_coefficient); - real_t get_pose_matching_coefficient(); - void set_damping_coefficient(real_t p_damping_coefficient); real_t get_damping_coefficient(); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index b7a3135bd5..0be54e7243 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -366,7 +366,7 @@ void Sprite3D::_draw() { } Rect2 base_rect; - if (region) { + if (region_enabled) { base_rect = region_rect; } else { base_rect = Rect2(0, 0, texture->get_width(), texture->get_height()); @@ -511,24 +511,24 @@ Ref<Texture2D> Sprite3D::get_texture() const { return texture; } -void Sprite3D::set_region(bool p_region) { - if (p_region == region) { +void Sprite3D::set_region_enabled(bool p_region_enabled) { + if (p_region_enabled == region_enabled) { return; } - region = p_region; + region_enabled = p_region_enabled; _queue_update(); notify_property_list_changed(); } -bool Sprite3D::is_region() const { - return region; +bool Sprite3D::is_region_enabled() const { + return region_enabled; } void Sprite3D::set_region_rect(const Rect2 &p_region_rect) { bool changed = region_rect != p_region_rect; region_rect = p_region_rect; - if (region && changed) { + if (region_enabled && changed) { _queue_update(); } } @@ -595,7 +595,7 @@ Rect2 Sprite3D::get_item_rect() const { Size2i s; - if (region) { + if (region_enabled) { s = region_rect.size; } else { s = texture->get_size(); @@ -625,7 +625,7 @@ void Sprite3D::_validate_property(PropertyInfo &property) const { property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; } - if (!region && property.name == "region_rect") { + if (!region_enabled && property.name == "region_rect") { property.usage = PROPERTY_USAGE_NOEDITOR; } } @@ -634,8 +634,8 @@ void Sprite3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite3D::set_texture); ClassDB::bind_method(D_METHOD("get_texture"), &Sprite3D::get_texture); - ClassDB::bind_method(D_METHOD("set_region", "enabled"), &Sprite3D::set_region); - ClassDB::bind_method(D_METHOD("is_region"), &Sprite3D::is_region); + ClassDB::bind_method(D_METHOD("set_region_enabled", "enabled"), &Sprite3D::set_region_enabled); + ClassDB::bind_method(D_METHOD("is_region_enabled"), &Sprite3D::is_region_enabled); ClassDB::bind_method(D_METHOD("set_region_rect", "rect"), &Sprite3D::set_region_rect); ClassDB::bind_method(D_METHOD("get_region_rect"), &Sprite3D::get_region_rect); @@ -659,14 +659,14 @@ void Sprite3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); ADD_GROUP("Region", "region_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); ADD_SIGNAL(MethodInfo("frame_changed")); } Sprite3D::Sprite3D() { - region = false; + region_enabled = false; frame = 0; vframes = 1; hframes = 1; @@ -692,7 +692,7 @@ void AnimatedSprite3D::_draw() { Ref<Texture2D> texture = frames->get_frame(animation, frame); if (!texture.is_valid()) { - return; //no texuture no life + return; //no texture no life } Vector2 tsize = texture->get_size(); if (tsize.x == 0 || tsize.y == 0) { diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index a9ce2d8eee..b48660eb2d 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -31,8 +31,8 @@ #ifndef SPRITE_3D_H #define SPRITE_3D_H -#include "scene/2d/animated_sprite_2d.h" #include "scene/3d/visual_instance_3d.h" +#include "scene/resources/sprite_frames.h" class SpriteBase3D : public GeometryInstance3D { GDCLASS(SpriteBase3D, GeometryInstance3D); @@ -107,8 +107,8 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; - void set_region(bool p_region); - bool is_region() const; + void set_region_enabled(bool p_region_enabled); + bool is_region_enabled() const; void set_region_rect(const Rect2 &p_region_rect); Rect2 get_region_rect() const; @@ -147,7 +147,7 @@ class Sprite3D : public SpriteBase3D { GDCLASS(Sprite3D, SpriteBase3D); Ref<Texture2D> texture; - bool region; + bool region_enabled; Rect2 region_rect; int frame; @@ -167,8 +167,8 @@ public: void set_texture(const Ref<Texture2D> &p_texture); Ref<Texture2D> get_texture() const; - void set_region(bool p_region); - bool is_region() const; + void set_region_enabled(bool p_region_enabled); + bool is_region_enabled() const; void set_region_rect(const Rect2 &p_region_rect); Rect2 get_region_rect() const; diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index 8b774444b9..5b0b3b89d3 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -563,7 +563,7 @@ void VehicleBody3D::_resolve_single_bilateral(PhysicsDirectBodyState3D *s, const b2invmass); // FIXME: rel_vel assignment here is overwritten by the following assignment. - // What seems to be intended in the next next assignment is: rel_vel = normal.dot(rel_vel); + // What seems to be intended in the next assignment is: rel_vel = normal.dot(rel_vel); // Investigate why. real_t rel_vel = jac.getRelativeVelocity( s->get_linear_velocity(), diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index 17c8596e8f..16718b956f 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -151,7 +151,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co Vector2 uv; Vector3 lnormal; get_uv_and_normal(intersection, p_vtx, p_uv, p_normal, uv, lnormal); - if (lnormal == Vector3()) { //just in case normal as nor provided + if (lnormal == Vector3()) { //just in case normal is not provided lnormal = normal; } @@ -183,7 +183,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co Vector3 lnormal; Vector2 uv; get_uv_and_normal(inters, p_vtx, p_uv, p_normal, uv, normal); - if (lnormal == Vector3()) { //just in case normal as nor provided + if (lnormal == Vector3()) { //just in case normal is not provided lnormal = normal; } diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 2c19307c52..0c1798a876 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -605,7 +605,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float } if (p_seeked) { - //find whathever should be playing + //find whatever should be playing int idx = a->track_find_key(i, p_time); if (idx < 0) { continue; @@ -634,7 +634,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float nc->audio_playing = true; playing_caches.insert(nc); - if (len && end_ofs > 0) { //force a end at a time + if (len && end_ofs > 0) { //force an end at a time nc->audio_len = len - start_ofs - end_ofs; } else { nc->audio_len = 0; @@ -665,7 +665,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float nc->audio_playing = true; playing_caches.insert(nc); - if (len && end_ofs > 0) { //force a end at a time + if (len && end_ofs > 0) { //force an end at a time nc->audio_len = len - start_ofs - end_ofs; } else { nc->audio_len = 0; @@ -1343,7 +1343,7 @@ void AnimationPlayer::_stop_playing_caches() { } void AnimationPlayer::_node_removed(Node *p_node) { - clear_caches(); // nodes contained here ar being removed, clear the caches + clear_caches(); // nodes contained here are being removed, clear the caches } void AnimationPlayer::clear_caches() { diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 26a13f33c9..4b4d3943c9 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -1009,7 +1009,7 @@ void AnimationTree::_process_graph(float p_delta) { TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track); if (seeked) { - //find whathever should be playing + //find whatever should be playing int idx = a->track_find_key(i, time); if (idx < 0) { continue; @@ -1038,7 +1038,7 @@ void AnimationTree::_process_graph(float p_delta) { t->playing = true; playing_caches.insert(t); - if (len && end_ofs > 0) { //force a end at a time + if (len && end_ofs > 0) { //force an end at a time t->len = len - start_ofs - end_ofs; } else { t->len = 0; @@ -1069,7 +1069,7 @@ void AnimationTree::_process_graph(float p_delta) { t->playing = true; playing_caches.insert(t); - if (len && end_ofs > 0) { //force a end at a time + if (len && end_ofs > 0) { //force an end at a time t->len = len - start_ofs - end_ofs; } else { t->len = 0; @@ -1337,6 +1337,7 @@ void AnimationTree::_tree_changed() { } void AnimationTree::_update_properties_for_node(const String &p_base_path, Ref<AnimationNode> node) { + ERR_FAIL_COND(node.is_null()); if (!property_parent_map.has(p_base_path)) { property_parent_map[p_base_path] = HashMap<StringName, StringName>(); } diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index eb35979a47..2030808724 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -1115,7 +1115,7 @@ real_t Tween::tell() const { // For each interpolation... for (const List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) { - // Get the data and figure out if it's position is further along than the previous ones + // Get the data and figure out if its position is further along than the previous ones const InterpolateData &data = E->get(); if (data.elapsed > pos) { // Save it if so diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index 2853a8b9d9..1478cbf69e 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -171,7 +171,7 @@ void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) { if (active.is_set() && stream_playback.is_valid() && !stream_paused) { //changing streams out of the blue is not a great idea, but at least - //lets try to somehow avoid a click + //let's try to somehow avoid a click AudioFrame *buffer = fadeout_buffer.ptrw(); int buffer_size = fadeout_buffer.size(); diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index 4dbe3cc1c4..a1d4adcd41 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -487,7 +487,7 @@ void LiveEditor::_send_tree() { } Array arr; - // Encoded as a flat list depth fist. + // Encoded as a flat list depth first. SceneDebuggerTree tree(scene_tree->root); tree.serialize(arr); EngineDebugger::get_singleton()->send_message("scene:scene_tree", arr); diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index c570438b6a..7407ad5b8f 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -313,7 +313,7 @@ BoxContainer::AlignMode BoxContainer::get_alignment() const { return align; } -void BoxContainer::add_spacer(bool p_begin) { +Control *BoxContainer::add_spacer(bool p_begin) { Control *c = memnew(Control); c->set_mouse_filter(MOUSE_FILTER_PASS); //allow spacer to pass mouse events @@ -327,6 +327,8 @@ void BoxContainer::add_spacer(bool p_begin) { if (p_begin) { move_child(c, 0); } + + return c; } BoxContainer::BoxContainer(bool p_vertical) { diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h index 31050d1feb..23feea565c 100644 --- a/scene/gui/box_container.h +++ b/scene/gui/box_container.h @@ -55,7 +55,7 @@ protected: static void _bind_methods(); public: - void add_spacer(bool p_begin = false); + Control *add_spacer(bool p_begin = false); void set_alignment(AlignMode p_align); AlignMode get_alignment() const; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index f188e63743..c13bce5e0c 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -96,6 +96,7 @@ void Control::_edit_set_state(const Dictionary &p_state) { void Control::_edit_set_position(const Point2 &p_position) { #ifdef TOOLS_ENABLED + ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins."); set_position(p_position, CanvasItemEditor::get_singleton()->is_anchors_mode_enabled() && Object::cast_to<Control>(data.parent)); #else // Unlikely to happen. TODO: enclose all _edit_ functions into TOOLS_ENABLED @@ -117,6 +118,7 @@ Size2 Control::_edit_get_scale() const { void Control::_edit_set_rect(const Rect2 &p_edit_rect) { #ifdef TOOLS_ENABLED + ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins."); set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1)), CanvasItemEditor::get_singleton()->is_anchors_mode_enabled()); set_size(p_edit_rect.size.snapped(Vector2(1, 1)), CanvasItemEditor::get_singleton()->is_anchors_mode_enabled()); #else @@ -584,7 +586,7 @@ void Control::_notification(int p_notification) { } break; case NOTIFICATION_MOVED_IN_PARENT: { - // some parents need to know the order of the childrens to draw (like TabContainer) + // some parents need to know the order of the children to draw (like TabContainer) // update if necessary if (data.parent) { data.parent->update(); @@ -1782,7 +1784,7 @@ void Control::add_theme_icon_override(const StringName &p_name, const Ref<Textur data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed)); } - // clear if "null" is passed instead of a icon + // clear if "null" is passed instead of an icon if (p_icon.is_null()) { data.icon_override.erase(p_name); } else { diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 2882c4286b..7ad4ac80c9 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -731,9 +731,9 @@ FileDialog::Access FileDialog::get_access() const { } void FileDialog::_make_dir_confirm() { - Error err = dir_access->make_dir(makedirname->get_text()); + Error err = dir_access->make_dir(makedirname->get_text().strip_edges()); if (err == OK) { - dir_access->change_dir(makedirname->get_text()); + dir_access->change_dir(makedirname->get_text().strip_edges()); invalidate(); update_filters(); update_dir(); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 331f0380c5..71d31434d4 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -180,7 +180,12 @@ void GraphEditMinimap::_gui_input(const Ref<InputEvent> &p_ev) { accept_event(); } else if (mm.is_valid() && is_pressing) { if (is_resizing) { - ge->set_minimap_size(ge->get_minimap_size() - mm->get_relative()); + // Prevent setting minimap wider than GraphEdit + Vector2 new_minimap_size; + new_minimap_size.x = MIN(get_size().x - mm->get_relative().x, ge->get_size().x - 2.0 * minimap_padding.x); + new_minimap_size.y = MIN(get_size().y - mm->get_relative().y, ge->get_size().y - 2.0 * minimap_padding.y); + ge->set_minimap_size(new_minimap_size); + update(); } else { Vector2 click_position = _convert_to_graph_position(mm->get_position() - minimap_padding) - graph_padding; @@ -1312,25 +1317,17 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { minimap->update(); } - if (b->get_button_index() == BUTTON_WHEEL_UP && b->is_pressed()) { - //too difficult to get right - //set_zoom(zoom*ZOOM_SCALE); - } - - if (b->get_button_index() == BUTTON_WHEEL_DOWN && b->is_pressed()) { - //too difficult to get right - //set_zoom(zoom/ZOOM_SCALE); - } - if (b->get_button_index() == BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + set_zoom(zoom * ZOOM_SCALE); + } else if (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + set_zoom(zoom / ZOOM_SCALE); + } else if (b->get_button_index() == BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8); - } - if (b->get_button_index() == BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + } else if (b->get_button_index() == BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8); - } - if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + } else if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b->get_factor() / 8); - } - if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + } else if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b->get_factor() / 8); } } diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index b615cdb266..c80fc516e8 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -32,6 +32,12 @@ #include "core/string/translation.h" +struct _MinSizeCache { + int min_size; + bool will_stretch; + int final_size; +}; + bool GraphNode::_set(const StringName &p_name, const Variant &p_value) { String str = p_name; if (str.begins_with("opentype_features/")) { @@ -171,15 +177,23 @@ void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const { } void GraphNode::_resort() { - int sep = get_theme_constant("separation"); + /** First pass, determine minimum size AND amount of stretchable elements */ + + Size2i new_size = get_size(); Ref<StyleBox> sb = get_theme_stylebox("frame"); - bool first = true; - Size2 minsize; + int sep = get_theme_constant("separation"); + + bool first = true; + int children_count = 0; + int stretch_min = 0; + int stretch_avail = 0; + float stretch_ratio_total = 0; + Map<Control *, _MinSizeCache> min_size_cache; for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) { + if (!c || !c->is_visible_in_tree()) { continue; } if (c->is_set_as_top_level()) { @@ -187,38 +201,120 @@ void GraphNode::_resort() { } Size2i size = c->get_combined_minimum_size(); + _MinSizeCache msc; - minsize.y += size.y; - minsize.x = MAX(minsize.x, size.x); + stretch_min += size.height; + msc.min_size = size.height; + msc.will_stretch = c->get_v_size_flags() & SIZE_EXPAND; - if (first) { - first = false; - } else { - minsize.y += sep; + if (msc.will_stretch) { + stretch_avail += msc.min_size; + stretch_ratio_total += c->get_stretch_ratio(); } + msc.final_size = msc.min_size; + min_size_cache[c] = msc; + children_count++; } - int vofs = 0; - int w = get_size().x - sb->get_minimum_size().x; + if (children_count == 0) { + return; + } + + int stretch_max = new_size.height - (children_count - 1) * sep; + int stretch_diff = stretch_max - stretch_min; + if (stretch_diff < 0) { + //avoid negative stretch space + stretch_diff = 0; + } + + stretch_avail += stretch_diff - sb->get_margin(SIDE_BOTTOM) - sb->get_margin(SIDE_TOP); //available stretch space. + /** Second, pass sucessively to discard elements that can't be stretched, this will run while stretchable + elements exist */ + + while (stretch_ratio_total > 0) { // first of all, don't even be here if no stretchable objects exist + bool refit_successful = true; //assume refit-test will go well + + for (int i = 0; i < get_child_count(); i++) { + Control *c = Object::cast_to<Control>(get_child(i)); + if (!c || !c->is_visible_in_tree()) { + continue; + } + if (c->is_set_as_top_level()) { + continue; + } + ERR_FAIL_COND(!min_size_cache.has(c)); + _MinSizeCache &msc = min_size_cache[c]; + + if (msc.will_stretch) { //wants to stretch + //let's see if it can really stretch + + int final_pixel_size = stretch_avail * c->get_stretch_ratio() / stretch_ratio_total; + if (final_pixel_size < msc.min_size) { + //if available stretching area is too small for widget, + //then remove it from stretching area + msc.will_stretch = false; + stretch_ratio_total -= c->get_stretch_ratio(); + refit_successful = false; + stretch_avail -= msc.min_size; + msc.final_size = msc.min_size; + break; + } else { + msc.final_size = final_pixel_size; + } + } + } + + if (refit_successful) { //uf refit went well, break + break; + } + } + + /** Final pass, draw and stretch elements **/ + + int ofs = sb->get_margin(SIDE_TOP); + + first = true; + int idx = 0; cache_y.clear(); + int w = new_size.width - sb->get_minimum_size().x; + for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) { + if (!c || !c->is_visible_in_tree()) { continue; } if (c->is_set_as_top_level()) { continue; } - Size2i size = c->get_combined_minimum_size(); + _MinSizeCache &msc = min_size_cache[c]; + + if (first) { + first = false; + } else { + ofs += sep; + } - Rect2 r(sb->get_margin(SIDE_LEFT), sb->get_margin(SIDE_TOP) + vofs, w, size.y); + int from = ofs; + int to = ofs + msc.final_size; - fit_child_in_rect(c, r); - cache_y.push_back(vofs + size.y * 0.5); + if (msc.will_stretch && idx == children_count - 1) { + //adjust so the last one always fits perfect + //compensating for numerical imprecision - vofs += size.y + sep; + to = new_size.height - sb->get_margin(SIDE_BOTTOM); + } + + int size = to - from; + + Rect2 rect(sb->get_margin(SIDE_LEFT), from, w, size); + + fit_child_in_rect(c, rect); + cache_y.push_back(from - sb->get_margin(SIDE_TOP) + size * 0.5); + + ofs = to; + idx++; } update(); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 7afc04c51c..fa72599fb3 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -768,7 +768,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { } } } else if (p_event->is_action("ui_accept")) { - search_string = ""; //any mousepress cance + search_string = ""; //any mousepress cancels if (current >= 0 && current < items.size()) { emit_signal("item_activated", current); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index f674e717f3..ce371e3b56 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -809,7 +809,7 @@ void LineEdit::_notification(int p_what) { } } else { { - // IME intermidiet text range. + // IME intermediate text range. Vector<Vector2> sel = TS->shaped_text_get_selection(text_rid, cursor_pos, cursor_pos + ime_text.length()); for (int i = 0; i < sel.size(); i++) { Rect2 rect = Rect2(sel[i].x + ofs.x, ofs.y, sel[i].y - sel[i].x, text_height); @@ -1436,7 +1436,7 @@ void LineEdit::set_cursor_position(int p_pos) { ofs_max -= r_icon->get_width(); } - // Note: Use too coordinates to fit IME input range. + // Note: Use two coordinates to fit IME input range. Vector2i primary_catret_offset = get_cursor_pixel_pos(); if (MIN(primary_catret_offset.x, primary_catret_offset.y) <= x_ofs) { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index f237f79be1..fb9e2647ee 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -222,7 +222,7 @@ void PopupMenu::_activate_submenu(int p_over) { submenu_popup->set_close_on_parent_focus(false); submenu_popup->set_position(submenu_pos); - submenu_popup->set_as_minsize(); // Shrink the popup size to it's contents. + submenu_popup->set_as_minsize(); // Shrink the popup size to its contents. submenu_popup->popup(); // Set autohide areas @@ -722,6 +722,7 @@ void PopupMenu::_notification(int p_what) { for (int i = 0; i < items.size(); i++) { items.write[i].xl_text = tr(items[i].text); items.write[i].dirty = true; + _shape_item(i); } child_controls_changed(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index ed319f9fd0..bce30e7cd3 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -147,7 +147,7 @@ RichTextLabel::Item *RichTextLabel::_get_item_at_pos(RichTextLabel::Item *p_item case ITEM_TEXT: { ItemText *t = (ItemText *)it; offset += t->text.length(); - if (offset >= p_position) { + if (offset > p_position) { return it; } } break; @@ -588,7 +588,8 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> offset.x += table->columns[column].width + hseparation + frame->padding.size.x; row_height = MAX(yofs, row_height); - if (column == col_count - 1) { + // Add row height after last column of the row or last cell of the table. + if (column == col_count - 1 || E->next() == nullptr) { offset.x = 0; row_height += vseparation; table->total_height += row_height; @@ -1117,7 +1118,8 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item Point2 ofs = text_rect.get_position() + Vector2(0, main->lines[from_line].offset.y - vofs); while (ofs.y < size.height && from_line < main->lines.size()) { - ofs.y += _find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, p_click, r_click_frame, r_click_line, r_click_item, r_click_char); + _find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, p_click, r_click_frame, r_click_line, r_click_item, r_click_char); + ofs.y += main->lines[from_line].text_buf->get_size().y; if (((r_click_item != nullptr) && ((*r_click_item) != nullptr)) || ((r_click_frame != nullptr) && ((*r_click_frame) != nullptr))) { if (r_outside != nullptr) { *r_outside = false; @@ -1244,8 +1246,19 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V if (r_click_item != nullptr) { Item *it = p_frame->lines[p_line].from; Item *it_to = (p_line + 1 < p_frame->lines.size()) ? p_frame->lines[p_line + 1].from : nullptr; - it = _get_item_at_pos(it, it_to, char_pos); - *r_click_item = it; + if (char_pos == p_frame->lines[p_line].char_count) { + // Selection after the end of line, select last item. + if (it_to != nullptr) { + *r_click_item = _get_prev_item(it_to); + } else { + for (Item *i = it; i && i != it_to; i = _get_next_item(i)) { + *r_click_item = i; + } + } + } else { + // Selection in the line. + *r_click_item = _get_item_at_pos(it, it_to, char_pos); + } } if (r_click_frame != nullptr) { diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index e3e3f549de..3bf163f670 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -645,7 +645,7 @@ int TabContainer::_get_tab_width(int p_index) const { // Get the width of the text displayed on the tab. Ref<Font> font = get_theme_font("font"); int font_size = get_theme_font_size("font_size"); - String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(control->get_name()); + String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(tr(control->get_name())); int width = font->get_string_size(text, font_size).width; // Add space for a tab icon. @@ -1023,6 +1023,7 @@ void TabContainer::set_tab_title(int p_tab, const String &p_title) { Control *child = _get_tab(p_tab); ERR_FAIL_COND(!child); child->set_meta("_tab_name", p_title); + _refresh_texts(); update(); } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 5c17f929bc..cf3978ca41 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -808,7 +808,7 @@ void TextEdit::_notification(int p_what) { // Get the highlighted words. String highlighted_text = get_selection_text(); - // Check if highlighted words contains only whitespaces (tabs or spaces). + // Check if highlighted words contain only whitespaces (tabs or spaces). bool only_whitespaces_highlighted = highlighted_text.strip_edges() == String(); int cursor_wrap_index = get_cursor_wrap_index(); @@ -1057,7 +1057,7 @@ void TextEdit::_notification(int p_what) { } if (str.length() == 0) { - // Draw line background if empty as we won't loop at at all. + // Draw line background if empty as we won't loop at all. if (line == cursor.line && cursor_wrap_index == line_wrap_index && highlight_current_line) { if (rtl) { RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - ofs_x - xmargin_end, ofs_y, xmargin_end, row_height), cache.current_line_color); @@ -1442,7 +1442,7 @@ void TextEdit::_notification(int p_what) { } } else { { - // IME intermidiet text range. + // IME Intermediate text range. Vector<Vector2> sel = TS->shaped_text_get_selection(rid, cursor.column, cursor.column + ime_text.length()); for (int j = 0; j < sel.size(); j++) { Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, text_height); @@ -1557,7 +1557,7 @@ void TextEdit::_notification(int p_what) { completion_rect.position.x = rect_left_border_x; } - if (cursor_pos.y + row_height + total_height > get_size().height) { + if (cursor_pos.y + row_height + total_height > get_size().height && cursor_pos.y > total_height) { // Completion panel above the cursor line completion_rect.position.y = cursor_pos.y - total_height; } else { @@ -2009,7 +2009,7 @@ void TextEdit::indent_selected_lines_right() { // We don't really care where selection is - we just need to know indentation level at the beginning of the line. int left = _find_first_non_whitespace_column_of_line(line_text); int spaces_to_add = _calculate_spaces_till_next_right_indent(left); - // Since we will add this much spaces we want move whole selection and cursor by this much. + // Since we will add these many spaces, we want to move the whole selection and cursor by this much. selection_offset = spaces_to_add; for (int j = 0; j < spaces_to_add; j++) { line_text = ' ' + line_text; @@ -2034,7 +2034,7 @@ void TextEdit::indent_selected_lines_left() { int end_line; // Moving cursor and selection after unindenting can get tricky because - // changing content of line can move cursor and selection on it's own (if new line ends before previous position of either), + // changing content of line can move cursor and selection on its own (if new line ends before previous position of either), // therefore we just remember initial values and at the end of the operation offset them by number of removed characters. int removed_characters = 0; int initial_selection_end_column = selection.to_column; @@ -2454,7 +2454,7 @@ void TextEdit::_move_cursor_to_line_start(bool p_select) { row_start_col += rows[i].length(); } if (cursor.column == row_start_col || wi == 0) { - // Compute whitespace symbols seq length. + // Compute whitespace symbols sequence length. int current_line_whitespace_len = 0; while (current_line_whitespace_len < text[cursor.line].length()) { char32_t c = text[cursor.line][current_line_whitespace_len]; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6ac4d7fd2f..0445e5f345 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -410,6 +410,14 @@ bool TreeItem::is_collapsed() { return collapsed; } +void TreeItem::uncollapse_tree() { + TreeItem *t = this; + while (t) { + t->set_collapsed(false); + t = t->parent; + } +} + void TreeItem::set_custom_minimum_height(int p_height) { custom_min_height = p_height; _changed_notify(); @@ -842,6 +850,8 @@ void TreeItem::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collapsed", "enable"), &TreeItem::set_collapsed); ClassDB::bind_method(D_METHOD("is_collapsed"), &TreeItem::is_collapsed); + ClassDB::bind_method(D_METHOD("uncollapse_tree"), &TreeItem::uncollapse_tree); + ClassDB::bind_method(D_METHOD("set_custom_minimum_height", "height"), &TreeItem::set_custom_minimum_height); ClassDB::bind_method(D_METHOD("get_custom_minimum_height"), &TreeItem::get_custom_minimum_height); @@ -3506,9 +3516,13 @@ int Tree::get_column_width(int p_column) const { return columns[p_column].min_width; } + int expand_area = get_size().width; + Ref<StyleBox> bg = cache.bg; - int expand_area = get_size().width - (bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT)); + if (bg.is_valid()) { + expand_area -= bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT); + } if (v_scroll->is_visible_in_tree()) { expand_area -= v_scroll->get_combined_minimum_size().width; diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 1be21cb4a4..d1407e24d4 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -229,6 +229,8 @@ public: void set_collapsed(bool p_collapsed); bool is_collapsed(); + void uncollapse_tree(); + void set_custom_minimum_height(int p_height); int get_custom_minimum_height() const; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 71c372aec2..e4ed5c6e6c 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -335,7 +335,7 @@ bool HTTPRequest::_update_connection() { call_deferred("_request_done", RESULT_CHUNKED_BODY_SIZE_MISMATCH, response_code, response_headers, PackedByteArray()); return true; - // Request migh have been done + // Request might have been done } else { // Did not request yet, do request diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 4c6bcb10b2..933f67db68 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -428,7 +428,7 @@ void Node::set_process_mode(ProcessMode p_mode) { _propagate_process_owner(data.process_owner, pause_notification); #ifdef TOOLS_ENABLED // This is required for the editor to update the visibility of disabled nodes - // Its very expensive during runtime to change, so editor-only + // It's very expensive during runtime to change, so editor-only if (Engine::get_singleton()->is_editor_hint()) { get_tree()->emit_signal("tree_process_mode_changed"); } @@ -1130,7 +1130,7 @@ String increase_numeric_string(const String &s) { void Node::_generate_serial_child_name(const Node *p_child, StringName &name) const { if (name == StringName()) { - //no name and a new nade is needed, create one. + //no name and a new name is needed, create one. name = p_child->get_class(); // Adjust casing according to project setting. The current type name is expected to be in PascalCase. @@ -1156,7 +1156,7 @@ void Node::_generate_serial_child_name(const Node *p_child, StringName &name) co bool exists = false; for (int i = 0; i < cc; i++) { - if (children_ptr[i] == p_child) { //exclude self in renaming if its already a child + if (children_ptr[i] == p_child) { //exclude self in renaming if it's already a child continue; } if (children_ptr[i]->data.name == name) { @@ -1945,7 +1945,7 @@ void Node::set_editable_instance(Node *p_node, bool p_editable) { if (!p_editable) { p_node->data.editable_instance = false; // Avoid this flag being needlessly saved; - // also give more visual feedback if editable children is re-enabled + // also give more visual feedback if editable children are re-enabled set_display_folded(false); } else { p_node->data.editable_instance = true; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 9aaddfd373..66f3a2ebde 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -389,6 +389,7 @@ void SceneTree::set_group(const StringName &p_group, const String &p_name, const } void SceneTree::initialize() { + ERR_FAIL_COND(!root); initialized = true; root->_set_tree(this); MainLoop::initialize(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 40b85e6d7b..e4cda4b96f 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1163,7 +1163,7 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) { if (p_world_2d.is_valid()) { world_2d = p_world_2d; } else { - WARN_PRINT("Invalid world_3d"); + WARN_PRINT("Invalid world_2d"); world_2d = Ref<World2D>(memnew(World2D)); } @@ -2201,7 +2201,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { embedder = this; viewport_pos = mpos; } else { - //not an embeder, but may be a subwindow of an embedder + //not an embedder, but may be a subwindow of an embedder Window *w = Object::cast_to<Window>(this); if (w) { if (w->is_embedded()) { @@ -2393,7 +2393,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { //keyboard focus //if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) { Ref<InputEventKey> k = p_event; - //need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/righ/etc> is handled here when it shouldn't be. + //need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/right/etc> is handled here when it shouldn't be. bool mods = k.is_valid() && (k->get_control() || k->get_alt() || k->get_shift() || k->get_metakey()); if (from && p_event->is_pressed()) { @@ -2672,7 +2672,7 @@ void Viewport::_post_gui_grab_click_focus() { Ref<InputEventMouseButton> mb; mb.instance(); - //send unclic + //send unclick mb->set_position(click); mb->set_button_index(i + 1); @@ -2690,7 +2690,7 @@ void Viewport::_post_gui_grab_click_focus() { Ref<InputEventMouseButton> mb; mb.instance(); - //send clic + //send click mb->set_position(click); mb->set_button_index(i + 1); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 8f3e82ad73..bacb0030bb 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -897,12 +897,13 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) { } if (exclusive_child != nullptr) { + /* Window *focus_target = exclusive_child; focus_target->grab_focus(); while (focus_target->exclusive_child != nullptr) { focus_target = focus_target->exclusive_child; focus_target->grab_focus(); - } + }*/ if (!is_embedding_subwindows()) { //not embedding, no need for event return; diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index cc1dafd0db..6f64ac6d04 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -2738,7 +2738,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1); if (d > pd.length() * p_alowed_linear_err) { - return false; //beyond allowed error for colinearity + return false; //beyond allowed error for collinearity } if (p_norm != Vector3() && Math::acos(pd.normalized().dot(p_norm)) > p_alowed_angular_err) { @@ -2828,7 +2828,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1); if (d > pd.length() * p_alowed_linear_err) { - return false; //beyond allowed error for colinearity + return false; //beyond allowed error for collinearity } t[2] = (d1 - d0) / (d2 - d0); diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index 8ffc7b4b4c..3cc1af59ae 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -285,7 +285,7 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) +---+---+ | 4 | | +---+---+ - this normally go RIGHT, but if its coming from RIGHT, it should go LEFT + this normally go RIGHT, but if it's coming from RIGHT, it should go LEFT */ if (case6s.has(Point2i(curx, cury))) { //found, so we go left, and delete from case6s; diff --git a/scene/resources/concave_polygon_shape_3d.cpp b/scene/resources/concave_polygon_shape_3d.cpp index f067695d7d..3fed700383 100644 --- a/scene/resources/concave_polygon_shape_3d.cpp +++ b/scene/resources/concave_polygon_shape_3d.cpp @@ -35,13 +35,12 @@ Vector<Vector3> ConcavePolygonShape3D::get_debug_mesh_lines() const { Set<DrawEdge> edges; - Vector<Vector3> data = get_faces(); - int datalen = data.size(); - ERR_FAIL_COND_V((datalen % 3) != 0, Vector<Vector3>()); + int index_count = faces.size(); + ERR_FAIL_COND_V((index_count % 3) != 0, Vector<Vector3>()); - const Vector3 *r = data.ptr(); + const Vector3 *r = faces.ptr(); - for (int i = 0; i < datalen; i += 3) { + for (int i = 0; i < index_count; i += 3) { for (int j = 0; j < 3; j++) { DrawEdge de(r[i + j], r[i + ((j + 1) % 3)]); edges.insert(de); @@ -71,22 +70,46 @@ real_t ConcavePolygonShape3D::get_enclosing_radius() const { } void ConcavePolygonShape3D::_update_shape() { + Dictionary d; + d["faces"] = faces; + d["backface_collision"] = backface_collision; + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); + Shape3D::_update_shape(); } void ConcavePolygonShape3D::set_faces(const Vector<Vector3> &p_faces) { - PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), p_faces); + faces = p_faces; + _update_shape(); notify_change_to_owners(); } Vector<Vector3> ConcavePolygonShape3D::get_faces() const { - return PhysicsServer3D::get_singleton()->shape_get_data(get_shape()); + return faces; +} + +void ConcavePolygonShape3D::set_backface_collision_enabled(bool p_enabled) { + backface_collision = p_enabled; + + if (!faces.is_empty()) { + _update_shape(); + notify_change_to_owners(); + } +} + +bool ConcavePolygonShape3D::is_backface_collision_enabled() const { + return backface_collision; } void ConcavePolygonShape3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_faces", "faces"), &ConcavePolygonShape3D::set_faces); ClassDB::bind_method(D_METHOD("get_faces"), &ConcavePolygonShape3D::get_faces); + + ClassDB::bind_method(D_METHOD("set_backface_collision_enabled", "enabled"), &ConcavePolygonShape3D::set_backface_collision_enabled); + ClassDB::bind_method(D_METHOD("is_backface_collision_enabled"), &ConcavePolygonShape3D::is_backface_collision_enabled); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_faces", "get_faces"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "backface_collision"), "set_backface_collision_enabled", "is_backface_collision_enabled"); } ConcavePolygonShape3D::ConcavePolygonShape3D() : diff --git a/scene/resources/concave_polygon_shape_3d.h b/scene/resources/concave_polygon_shape_3d.h index 391459a3d7..bb28359dcc 100644 --- a/scene/resources/concave_polygon_shape_3d.h +++ b/scene/resources/concave_polygon_shape_3d.h @@ -36,6 +36,9 @@ class ConcavePolygonShape3D : public Shape3D { GDCLASS(ConcavePolygonShape3D, Shape3D); + Vector<Vector3> faces; + bool backface_collision = false; + struct DrawEdge { Vector3 a; Vector3 b; @@ -65,6 +68,9 @@ public: void set_faces(const Vector<Vector3> &p_faces); Vector<Vector3> get_faces() const; + void set_backface_collision_enabled(bool p_enabled); + bool is_backface_collision_enabled() const; + virtual Vector<Vector3> get_debug_mesh_lines() const override; virtual real_t get_enclosing_radius() const override; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 9931757cc4..0d02bde90d 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -1703,7 +1703,7 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const { property.usage = PROPERTY_USAGE_NOEDITOR; } - // you can only enable anti-aliasing (in mataerials) on alpha scissor and alpha hash + // you can only enable anti-aliasing (in materials) on alpha scissor and alpha hash const bool can_select_aa = (transparency == TRANSPARENCY_ALPHA_SCISSOR || transparency == TRANSPARENCY_ALPHA_HASH); // alpha anti aliasiasing is only enabled when you can select aa const bool alpha_aa_enabled = (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) && can_select_aa; @@ -1722,7 +1722,7 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const { property.usage = 0; } - // we cant choose an antialiasing mode if alpha isnt possible + // we can't choose an antialiasing mode if alpha isn't possible if (property.name == "alpha_antialiasing_edge" && !alpha_aa_enabled) { property.usage = 0; } diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 167540eb77..a0f4bf9409 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -1075,7 +1075,7 @@ ParticlesMaterial::SubEmitterMode ParticlesMaterial::get_sub_emitter_mode() cons void ParticlesMaterial::set_sub_emitter_frequency(float p_frequency) { sub_emitter_frequency = p_frequency; - RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_frequency, 1.0 / p_frequency); //pas delta instead of frequency, since its easier to compute + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_frequency, 1.0 / p_frequency); //pass delta instead of frequency, since its easier to compute } float ParticlesMaterial::get_sub_emitter_frequency() const { return sub_emitter_frequency; diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index f292140d6b..536318ed16 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -77,7 +77,7 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> outside_point.x += 20.451 + Math::randf() * 10.2039; outside_point.y += 21.193 + Math::randf() * 12.5412; - //insert edges (which are also connetions) + //insert edges (which are also connections) for (int i = 0; i < p_connections.size(); i += 2) { Edge e(p_connections[i], p_connections[i + 1]); @@ -335,7 +335,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector //oh this was visited already, can we win the cost? if (p.distance > distance) { - p.prev = least_cost_point; //reasign previous + p.prev = least_cost_point; //reassign previous p.distance = distance; } } else { diff --git a/scene/resources/ray_shape_2d.cpp b/scene/resources/ray_shape_2d.cpp index d2125445fa..fb8f4b9985 100644 --- a/scene/resources/ray_shape_2d.cpp +++ b/scene/resources/ray_shape_2d.cpp @@ -42,17 +42,33 @@ void RayShape2D::_update_shape() { } void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) { - Vector2 tip = Vector2(0, get_length()); - RS::get_singleton()->canvas_item_add_line(p_to_rid, Vector2(), tip, p_color, 3); + const Vector2 target_position = Vector2(0, get_length()); + + const float max_arrow_size = 6; + const float line_width = 1.4; + bool no_line = target_position.length() < line_width; + float arrow_size = CLAMP(target_position.length() * 2 / 3, line_width, max_arrow_size); + + if (no_line) { + arrow_size = target_position.length(); + } else { + RS::get_singleton()->canvas_item_add_line(p_to_rid, Vector2(), target_position - target_position.normalized() * arrow_size, p_color, line_width); + } + + Transform2D xf; + xf.rotate(target_position.angle()); + xf.translate(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0)); + Vector<Vector2> pts; - float tsize = 4.0; - pts.push_back(tip + Vector2(0, tsize)); - pts.push_back(tip + Vector2(Math_SQRT12 * tsize, 0)); - pts.push_back(tip + Vector2(-Math_SQRT12 * tsize, 0)); + pts.push_back(xf.xform(Vector2(arrow_size, 0))); + pts.push_back(xf.xform(Vector2(0, 0.5 * arrow_size))); + pts.push_back(xf.xform(Vector2(0, -0.5 * arrow_size))); + Vector<Color> cols; for (int i = 0; i < 3; i++) { cols.push_back(p_color); } + RS::get_singleton()->canvas_item_add_primitive(p_to_rid, pts, cols, Vector<Point2>(), RID()); } diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index 7ca532e1d6..f2751b7604 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -1321,7 +1321,7 @@ String ResourceFormatLoaderText::get_resource_type(const String &p_path) const { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { - return ""; //could not rwead + return ""; //could not read } ResourceLoaderText loader; diff --git a/scene/resources/sprite_frames.cpp b/scene/resources/sprite_frames.cpp new file mode 100644 index 0000000000..90c702081b --- /dev/null +++ b/scene/resources/sprite_frames.cpp @@ -0,0 +1,241 @@ +/*************************************************************************/ +/* sprite_frames.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "sprite_frames.h" + +#include "scene/scene_string_names.h" + +void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture2D> &p_frame, int p_at_pos) { + Map<StringName, Anim>::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + + if (p_at_pos >= 0 && p_at_pos < E->get().frames.size()) { + E->get().frames.insert(p_at_pos, p_frame); + } else { + E->get().frames.push_back(p_frame); + } + + emit_changed(); +} + +int SpriteFrames::get_frame_count(const StringName &p_anim) const { + const Map<StringName, Anim>::Element *E = animations.find(p_anim); + ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist."); + + return E->get().frames.size(); +} + +void SpriteFrames::remove_frame(const StringName &p_anim, int p_idx) { + Map<StringName, Anim>::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + + E->get().frames.remove(p_idx); + emit_changed(); +} + +void SpriteFrames::clear(const StringName &p_anim) { + Map<StringName, Anim>::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + + E->get().frames.clear(); + emit_changed(); +} + +void SpriteFrames::clear_all() { + animations.clear(); + add_animation("default"); +} + +void SpriteFrames::add_animation(const StringName &p_anim) { + ERR_FAIL_COND_MSG(animations.has(p_anim), "SpriteFrames already has animation '" + p_anim + "'."); + + animations[p_anim] = Anim(); +} + +bool SpriteFrames::has_animation(const StringName &p_anim) const { + return animations.has(p_anim); +} + +void SpriteFrames::remove_animation(const StringName &p_anim) { + animations.erase(p_anim); +} + +void SpriteFrames::rename_animation(const StringName &p_prev, const StringName &p_next) { + ERR_FAIL_COND_MSG(!animations.has(p_prev), "SpriteFrames doesn't have animation '" + String(p_prev) + "'."); + ERR_FAIL_COND_MSG(animations.has(p_next), "Animation '" + String(p_next) + "' already exists."); + + Anim anim = animations[p_prev]; + animations.erase(p_prev); + animations[p_next] = anim; +} + +Vector<String> SpriteFrames::_get_animation_list() const { + Vector<String> ret; + List<StringName> al; + get_animation_list(&al); + for (List<StringName>::Element *E = al.front(); E; E = E->next()) { + ret.push_back(E->get()); + } + + return ret; +} + +void SpriteFrames::get_animation_list(List<StringName> *r_animations) const { + for (const Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) { + r_animations->push_back(E->key()); + } +} + +Vector<String> SpriteFrames::get_animation_names() const { + Vector<String> names; + for (const Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) { + names.push_back(E->key()); + } + names.sort(); + return names; +} + +void SpriteFrames::set_animation_speed(const StringName &p_anim, float p_fps) { + ERR_FAIL_COND_MSG(p_fps < 0, "Animation speed cannot be negative (" + itos(p_fps) + ")."); + Map<StringName, Anim>::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + E->get().speed = p_fps; +} + +float SpriteFrames::get_animation_speed(const StringName &p_anim) const { + const Map<StringName, Anim>::Element *E = animations.find(p_anim); + ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist."); + return E->get().speed; +} + +void SpriteFrames::set_animation_loop(const StringName &p_anim, bool p_loop) { + Map<StringName, Anim>::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + E->get().loop = p_loop; +} + +bool SpriteFrames::get_animation_loop(const StringName &p_anim) const { + const Map<StringName, Anim>::Element *E = animations.find(p_anim); + ERR_FAIL_COND_V_MSG(!E, false, "Animation '" + String(p_anim) + "' doesn't exist."); + return E->get().loop; +} + +void SpriteFrames::_set_frames(const Array &p_frames) { + clear_all(); + Map<StringName, Anim>::Element *E = animations.find(SceneStringNames::get_singleton()->_default); + ERR_FAIL_COND(!E); + + E->get().frames.resize(p_frames.size()); + for (int i = 0; i < E->get().frames.size(); i++) { + E->get().frames.write[i] = p_frames[i]; + } +} + +Array SpriteFrames::_get_frames() const { + return Array(); +} + +Array SpriteFrames::_get_animations() const { + Array anims; + for (Map<StringName, Anim>::Element *E = animations.front(); E; E = E->next()) { + Dictionary d; + d["name"] = E->key(); + d["speed"] = E->get().speed; + d["loop"] = E->get().loop; + Array frames; + for (int i = 0; i < E->get().frames.size(); i++) { + frames.push_back(E->get().frames[i]); + } + d["frames"] = frames; + anims.push_back(d); + } + + return anims; +} + +void SpriteFrames::_set_animations(const Array &p_animations) { + animations.clear(); + for (int i = 0; i < p_animations.size(); i++) { + Dictionary d = p_animations[i]; + + ERR_CONTINUE(!d.has("name")); + ERR_CONTINUE(!d.has("speed")); + ERR_CONTINUE(!d.has("loop")); + ERR_CONTINUE(!d.has("frames")); + + Anim anim; + anim.speed = d["speed"]; + anim.loop = d["loop"]; + Array frames = d["frames"]; + for (int j = 0; j < frames.size(); j++) { + RES res = frames[j]; + anim.frames.push_back(res); + } + + animations[d["name"]] = anim; + } +} + +void SpriteFrames::_bind_methods() { + ClassDB::bind_method(D_METHOD("add_animation", "anim"), &SpriteFrames::add_animation); + ClassDB::bind_method(D_METHOD("has_animation", "anim"), &SpriteFrames::has_animation); + ClassDB::bind_method(D_METHOD("remove_animation", "anim"), &SpriteFrames::remove_animation); + ClassDB::bind_method(D_METHOD("rename_animation", "anim", "newname"), &SpriteFrames::rename_animation); + + ClassDB::bind_method(D_METHOD("get_animation_names"), &SpriteFrames::get_animation_names); + + ClassDB::bind_method(D_METHOD("set_animation_speed", "anim", "speed"), &SpriteFrames::set_animation_speed); + ClassDB::bind_method(D_METHOD("get_animation_speed", "anim"), &SpriteFrames::get_animation_speed); + + ClassDB::bind_method(D_METHOD("set_animation_loop", "anim", "loop"), &SpriteFrames::set_animation_loop); + ClassDB::bind_method(D_METHOD("get_animation_loop", "anim"), &SpriteFrames::get_animation_loop); + + ClassDB::bind_method(D_METHOD("add_frame", "anim", "frame", "at_position"), &SpriteFrames::add_frame, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("get_frame_count", "anim"), &SpriteFrames::get_frame_count); + ClassDB::bind_method(D_METHOD("get_frame", "anim", "idx"), &SpriteFrames::get_frame); + ClassDB::bind_method(D_METHOD("set_frame", "anim", "idx", "txt"), &SpriteFrames::set_frame); + ClassDB::bind_method(D_METHOD("remove_frame", "anim", "idx"), &SpriteFrames::remove_frame); + ClassDB::bind_method(D_METHOD("clear", "anim"), &SpriteFrames::clear); + ClassDB::bind_method(D_METHOD("clear_all"), &SpriteFrames::clear_all); + + ClassDB::bind_method(D_METHOD("_set_frames"), &SpriteFrames::_set_frames); + ClassDB::bind_method(D_METHOD("_get_frames"), &SpriteFrames::_get_frames); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "frames", PROPERTY_HINT_NONE, "", 0), "_set_frames", "_get_frames"); //compatibility + + ClassDB::bind_method(D_METHOD("_set_animations"), &SpriteFrames::_set_animations); + ClassDB::bind_method(D_METHOD("_get_animations"), &SpriteFrames::_get_animations); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_animations", "_get_animations"); //compatibility +} + +SpriteFrames::SpriteFrames() { + add_animation(SceneStringNames::get_singleton()->_default); +} diff --git a/scene/resources/sprite_frames.h b/scene/resources/sprite_frames.h new file mode 100644 index 0000000000..282c5f20ab --- /dev/null +++ b/scene/resources/sprite_frames.h @@ -0,0 +1,102 @@ +/*************************************************************************/ +/* sprite_frames.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SPRITE_FRAMES_H +#define SPRITE_FRAMES_H + +#include "scene/resources/texture.h" + +class SpriteFrames : public Resource { + GDCLASS(SpriteFrames, Resource); + + struct Anim { + float speed = 5.0; + bool loop = true; + Vector<Ref<Texture2D>> frames; + }; + + Map<StringName, Anim> animations; + + Array _get_frames() const; + void _set_frames(const Array &p_frames); + + Array _get_animations() const; + void _set_animations(const Array &p_animations); + + Vector<String> _get_animation_list() const; + +protected: + static void _bind_methods(); + +public: + void add_animation(const StringName &p_anim); + bool has_animation(const StringName &p_anim) const; + void remove_animation(const StringName &p_anim); + void rename_animation(const StringName &p_prev, const StringName &p_next); + + void get_animation_list(List<StringName> *r_animations) const; + Vector<String> get_animation_names() const; + + void set_animation_speed(const StringName &p_anim, float p_fps); + float get_animation_speed(const StringName &p_anim) const; + + void set_animation_loop(const StringName &p_anim, bool p_loop); + bool get_animation_loop(const StringName &p_anim) const; + + void add_frame(const StringName &p_anim, const Ref<Texture2D> &p_frame, int p_at_pos = -1); + int get_frame_count(const StringName &p_anim) const; + _FORCE_INLINE_ Ref<Texture2D> get_frame(const StringName &p_anim, int p_idx) const { + const Map<StringName, Anim>::Element *E = animations.find(p_anim); + ERR_FAIL_COND_V_MSG(!E, Ref<Texture2D>(), "Animation '" + String(p_anim) + "' doesn't exist."); + ERR_FAIL_COND_V(p_idx < 0, Ref<Texture2D>()); + if (p_idx >= E->get().frames.size()) { + return Ref<Texture2D>(); + } + + return E->get().frames[p_idx]; + } + + void set_frame(const StringName &p_anim, int p_idx, const Ref<Texture2D> &p_frame) { + Map<StringName, Anim>::Element *E = animations.find(p_anim); + ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist."); + ERR_FAIL_COND(p_idx < 0); + if (p_idx >= E->get().frames.size()) { + return; + } + E->get().frames.write[p_idx] = p_frame; + } + void remove_frame(const StringName &p_anim, int p_idx); + void clear(const StringName &p_anim); + void clear_all(); + + SpriteFrames(); +}; + +#endif // SPRITE_FRAMES_H diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 47933bd69a..3d3900ecc5 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -1059,6 +1059,10 @@ void SurfaceTool::set_material(const Ref<Material> &p_material) { material = p_material; } +Ref<Material> SurfaceTool::get_material() const { + return material; +} + void SurfaceTool::clear() { begun = false; primitive = Mesh::PRIMITIVE_LINES; @@ -1088,6 +1092,10 @@ void SurfaceTool::set_custom_format(int p_index, CustomFormat p_format) { ERR_FAIL_COND(begun); last_custom_format[p_index] = p_format; } + +Mesh::PrimitiveType SurfaceTool::get_primitive() const { + return primitive; +} SurfaceTool::CustomFormat SurfaceTool::get_custom_format(int p_index) const { ERR_FAIL_INDEX_V(p_index, RS::ARRAY_CUSTOM_COUNT, CUSTOM_MAX); return last_custom_format[p_index]; @@ -1174,6 +1182,7 @@ void SurfaceTool::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_lod", "nd_threshold", "target_index_count"), &SurfaceTool::generate_lod, DEFVAL(3)); ClassDB::bind_method(D_METHOD("set_material", "material"), &SurfaceTool::set_material); + ClassDB::bind_method(D_METHOD("get_primitive"), &SurfaceTool::get_primitive); ClassDB::bind_method(D_METHOD("clear"), &SurfaceTool::clear); diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index 17efdcba71..28addf2245 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -143,6 +143,8 @@ public: void set_custom_format(int p_index, CustomFormat p_format); CustomFormat get_custom_format(int p_index) const; + Mesh::PrimitiveType get_primitive() const; + void begin(Mesh::PrimitiveType p_primitive); void set_color(Color p_color); @@ -171,6 +173,7 @@ public: Vector<int> generate_lod(float p_threshold, int p_target_index_count = 3); void set_material(const Ref<Material> &p_material); + Ref<Material> get_material() const; void clear(); diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index a064ade362..ccdc5bebd0 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -368,7 +368,7 @@ World2D::World2D() { navigation_map = NavigationServer2D::get_singleton()->map_create(); NavigationServer2D::get_singleton()->map_set_active(navigation_map, true); NavigationServer2D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/2d/default_cell_size", 10)); - NavigationServer2D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/2d/default_edge_connection_margin", 100)); + NavigationServer2D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/2d/default_edge_connection_margin", 5)); indexer = memnew(SpatialIndexer2D); } |