diff options
Diffstat (limited to 'scene')
114 files changed, 1788 insertions, 1052 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp index 5982556c18..4865858b7d 100644 --- a/scene/2d/animated_sprite.cpp +++ b/scene/2d/animated_sprite.cpp @@ -247,16 +247,16 @@ SpriteFrames::SpriteFrames() { add_animation(SceneStringNames::get_singleton()->_default); } -void AnimatedSprite::edit_set_pivot(const Point2 &p_pivot) { +void AnimatedSprite::_edit_set_pivot(const Point2 &p_pivot) { set_offset(p_pivot); } -Point2 AnimatedSprite::edit_get_pivot() const { +Point2 AnimatedSprite::_edit_get_pivot() const { return get_offset(); } -bool AnimatedSprite::edit_has_pivot() const { +bool AnimatedSprite::_edit_use_pivot() const { return true; } @@ -509,17 +509,17 @@ bool AnimatedSprite::is_flipped_v() const { return vflip; } -Rect2 AnimatedSprite::get_item_rect() const { +Rect2 AnimatedSprite::_edit_get_rect() const { if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { - return Node2D::get_item_rect(); + return Node2D::_edit_get_rect(); } Ref<Texture> t; if (animation) t = frames->get_frame(animation, frame); if (t.is_null()) - return Node2D::get_item_rect(); + return Node2D::_edit_get_rect(); Size2i s = t->get_size(); Point2 ofs = offset; diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h index 6c660d0381..a8d0db021a 100644 --- a/scene/2d/animated_sprite.h +++ b/scene/2d/animated_sprite.h @@ -149,9 +149,9 @@ protected: virtual void _validate_property(PropertyInfo &property) const; public: - virtual void edit_set_pivot(const Point2 &p_pivot); - virtual Point2 edit_get_pivot() const; - virtual bool edit_has_pivot() const; + virtual void _edit_set_pivot(const Point2 &p_pivot); + virtual Point2 _edit_get_pivot() const; + virtual bool _edit_use_pivot() const; void set_sprite_frames(const Ref<SpriteFrames> &p_frames); Ref<SpriteFrames> get_sprite_frames() const; @@ -181,7 +181,7 @@ public: void set_modulate(const Color &p_color); Color get_modulate() const; - virtual Rect2 get_item_rect() const; + virtual Rect2 _edit_get_rect() const; virtual String get_configuration_warning() const; AnimatedSprite(); diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp index 2858ddaad5..e4f52a227a 100644 --- a/scene/2d/back_buffer_copy.cpp +++ b/scene/2d/back_buffer_copy.cpp @@ -49,7 +49,7 @@ void BackBufferCopy::_update_copy_mode() { } } -Rect2 BackBufferCopy::get_item_rect() const { +Rect2 BackBufferCopy::_edit_get_rect() const { return rect; } diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h index 2424dd7b19..cfd632d755 100644 --- a/scene/2d/back_buffer_copy.h +++ b/scene/2d/back_buffer_copy.h @@ -52,14 +52,14 @@ protected: static void _bind_methods(); public: + Rect2 _edit_get_rect() const; + void set_rect(const Rect2 &p_rect); Rect2 get_rect() const; void set_copy_mode(CopyMode p_mode); CopyMode get_copy_mode() const; - Rect2 get_item_rect() const; - BackBufferCopy(); ~BackBufferCopy(); }; diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index b41ba7f590..66abe1baa8 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -178,6 +178,12 @@ CanvasItemMaterial::LightMode CanvasItemMaterial::get_light_mode() const { void CanvasItemMaterial::_validate_property(PropertyInfo &property) const { } +RID CanvasItemMaterial::get_shader_rid() const { + + ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); + return shader_map[current_key].shader; +} + void CanvasItemMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &CanvasItemMaterial::set_blend_mode); @@ -300,22 +306,7 @@ void CanvasItem::hide() { _change_notify("visible"); } -Variant CanvasItem::edit_get_state() const { - - return Variant(); -} -void CanvasItem::edit_set_state(const Variant &p_state) { -} - -void CanvasItem::edit_set_rect(const Rect2 &p_edit_rect) { - - //used by editors, implement at will -} - -void CanvasItem::edit_rotate(float p_rot) { -} - -Size2 CanvasItem::edit_get_minimum_size() const { +Size2 CanvasItem::_edit_get_minimum_size() const { return Size2(-1, -1); //no limit } @@ -935,15 +926,22 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("_toplevel_raise_self"), &CanvasItem::_toplevel_raise_self); ClassDB::bind_method(D_METHOD("_update_callback"), &CanvasItem::_update_callback); - - ClassDB::bind_method(D_METHOD("edit_set_state", "state"), &CanvasItem::edit_set_state); - ClassDB::bind_method(D_METHOD("edit_get_state"), &CanvasItem::edit_get_state); - ClassDB::bind_method(D_METHOD("edit_set_rect", "rect"), &CanvasItem::edit_set_rect); - ClassDB::bind_method(D_METHOD("edit_rotate", "degrees"), &CanvasItem::edit_rotate); - - ClassDB::bind_method(D_METHOD("get_item_rect"), &CanvasItem::get_item_rect); - ClassDB::bind_method(D_METHOD("get_item_and_children_rect"), &CanvasItem::get_item_and_children_rect); - //ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform); + ClassDB::bind_method(D_METHOD("_edit_set_state", "state"), &CanvasItem::_edit_set_state); + ClassDB::bind_method(D_METHOD("_edit_get_state"), &CanvasItem::_edit_get_state); + + ClassDB::bind_method(D_METHOD("_edit_set_position", "position"), &CanvasItem::_edit_set_position); + ClassDB::bind_method(D_METHOD("_edit_get_position"), &CanvasItem::_edit_get_position); + ClassDB::bind_method(D_METHOD("_edit_use_position"), &CanvasItem::_edit_use_position); + ClassDB::bind_method(D_METHOD("_edit_set_rect", "rect"), &CanvasItem::_edit_set_rect); + ClassDB::bind_method(D_METHOD("_edit_get_rect"), &CanvasItem::_edit_get_rect); + ClassDB::bind_method(D_METHOD("_edit_use_rect"), &CanvasItem::_edit_use_rect); + ClassDB::bind_method(D_METHOD("_edit_get_item_and_children_rect"), &CanvasItem::_edit_get_item_and_children_rect); + ClassDB::bind_method(D_METHOD("_edit_set_rotation", "degrees"), &CanvasItem::_edit_set_rotation); + ClassDB::bind_method(D_METHOD("_edit_get_rotation"), &CanvasItem::_edit_get_rotation); + ClassDB::bind_method(D_METHOD("_edit_use_rotation"), &CanvasItem::_edit_use_rotation); + ClassDB::bind_method(D_METHOD("_edit_set_pivot", "pivot"), &CanvasItem::_edit_set_pivot); + ClassDB::bind_method(D_METHOD("_edit_get_pivot"), &CanvasItem::_edit_get_pivot); + ClassDB::bind_method(D_METHOD("_edit_use_pivot"), &CanvasItem::_edit_use_pivot); ClassDB::bind_method(D_METHOD("get_canvas_item"), &CanvasItem::get_canvas_item); @@ -1113,14 +1111,14 @@ int CanvasItem::get_canvas_layer() const { return 0; } -Rect2 CanvasItem::get_item_and_children_rect() const { +Rect2 CanvasItem::_edit_get_item_and_children_rect() const { - Rect2 rect = get_item_rect(); + Rect2 rect = _edit_get_rect(); for (int i = 0; i < get_child_count(); i++) { CanvasItem *c = Object::cast_to<CanvasItem>(get_child(i)); if (c) { - Rect2 sir = c->get_transform().xform(c->get_item_and_children_rect()); + Rect2 sir = c->get_transform().xform(c->_edit_get_item_and_children_rect()); rect = rect.merge(sir); } } diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 1afbd150a2..c877a94755 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -121,6 +121,8 @@ public: static void finish_shaders(); static void flush_changes(); + RID get_shader_rid() const; + CanvasItemMaterial(); virtual ~CanvasItemMaterial(); }; @@ -214,11 +216,31 @@ public: /* EDITOR */ - virtual Variant edit_get_state() const; - virtual void edit_set_state(const Variant &p_state); - virtual void edit_set_rect(const Rect2 &p_edit_rect); - virtual void edit_rotate(float p_rot); - virtual Size2 edit_get_minimum_size() const; + virtual void _edit_set_state(const Dictionary &p_state){}; + virtual Dictionary _edit_get_state() const { return Dictionary(); }; + + // Used to move/select the node + virtual void _edit_set_position(const Point2 &p_position){}; + virtual Point2 _edit_get_position() const { return Point2(); }; + virtual bool _edit_use_position() const { return false; }; + + // Used to resize/move/select the node + virtual void _edit_set_rect(const Rect2 &p_rect){}; + virtual Rect2 _edit_get_rect() const { return Rect2(-32, -32, 64, 64); }; + Rect2 _edit_get_item_and_children_rect() const; + virtual bool _edit_use_rect() const { return false; }; + + // Used to rotate the node + virtual void _edit_set_rotation(float p_rotation){}; + virtual float _edit_get_rotation() const { return 0.0; }; + virtual bool _edit_use_rotation() const { return false; }; + + // Used to set a pivot + virtual void _edit_set_pivot(const Point2 &p_pivot){}; + virtual Point2 _edit_get_pivot() const { return Point2(); }; + virtual bool _edit_use_pivot() const { return false; }; + + virtual Size2 _edit_get_minimum_size() const; /* VISIBILITY */ @@ -248,7 +270,7 @@ public: void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color); void draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture> &p_normal_map = Ref<Texture>()); void draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()); - void draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true); + void draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = false); void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect); void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture> p_texture = Ref<Texture>(), float p_width = 1, const Ref<Texture> &p_normal_map = Ref<Texture>()); void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>(), const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_antialiased = false); @@ -270,14 +292,11 @@ public: CanvasItem *get_parent_item() const; - virtual Rect2 get_item_rect() const = 0; virtual Transform2D get_transform() const = 0; virtual Transform2D get_global_transform() const; virtual Transform2D get_global_transform_with_canvas() const; - Rect2 get_item_and_children_rect() const; - CanvasItem *get_toplevel() const; _FORCE_INLINE_ RID get_canvas_item() const { return canvas_item; } diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index a840744c78..92855299ae 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -243,7 +243,7 @@ CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const { return build_mode; } -Rect2 CollisionPolygon2D::get_item_rect() const { +Rect2 CollisionPolygon2D::_edit_get_rect() const { return aabb; } diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index c9ec860e36..2fb08a4599 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -69,7 +69,7 @@ public: void set_polygon(const Vector<Point2> &p_polygon); Vector<Point2> get_polygon() const; - virtual Rect2 get_item_rect() const; + virtual Rect2 _edit_get_rect() const; virtual String get_configuration_warning() const; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 0758f4a9bf..f7cb5473e3 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -158,7 +158,7 @@ Ref<Shape2D> CollisionShape2D::get_shape() const { return shape; } -Rect2 CollisionShape2D::get_item_rect() const { +Rect2 CollisionShape2D::_edit_get_rect() const { return rect; } diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h index 04203a75b4..4745c659c8 100644 --- a/scene/2d/collision_shape_2d.h +++ b/scene/2d/collision_shape_2d.h @@ -51,9 +51,10 @@ protected: static void _bind_methods(); public: + virtual Rect2 _edit_get_rect() const; + void set_shape(const Ref<Shape2D> &p_shape); Ref<Shape2D> get_shape() const; - virtual Rect2 get_item_rect() const; void set_disabled(bool p_disabled); bool is_disabled() const; diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 516acefe2a..d2b987e037 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -32,21 +32,21 @@ #include "engine.h" #include "servers/visual_server.h" -void Light2D::edit_set_pivot(const Point2 &p_pivot) { +void Light2D::_edit_set_pivot(const Point2 &p_pivot) { set_texture_offset(p_pivot); } -Point2 Light2D::edit_get_pivot() const { +Point2 Light2D::_edit_get_pivot() const { return get_texture_offset(); } -bool Light2D::edit_has_pivot() const { +bool Light2D::_edit_use_pivot() const { return true; } -Rect2 Light2D::get_item_rect() const { +Rect2 Light2D::_edit_get_rect() const { if (texture.is_null()) return Rect2(0, 0, 1, 1); diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index f6bc943adb..9b9da8379f 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -84,9 +84,10 @@ protected: static void _bind_methods(); public: - virtual void edit_set_pivot(const Point2 &p_pivot); - virtual Point2 edit_get_pivot() const; - virtual bool edit_has_pivot() const; + virtual void _edit_set_pivot(const Point2 &p_pivot); + virtual Point2 _edit_get_pivot() const; + virtual bool _edit_use_pivot() const; + virtual Rect2 _edit_get_rect() const; void set_enabled(bool p_enabled); bool is_enabled() const; @@ -151,8 +152,6 @@ public: void set_shadow_smooth(float p_amount); float get_shadow_smooth() const; - virtual Rect2 get_item_rect() const; - String get_configuration_warning() const; Light2D(); diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index e62b59dd4d..36fbf5fda6 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -34,45 +34,39 @@ #include "scene/main/viewport.h" #include "servers/visual_server.h" -void Node2D::edit_set_pivot(const Point2 &p_pivot) { -} - -Point2 Node2D::edit_get_pivot() const { - - return Point2(); -} -bool Node2D::edit_has_pivot() const { - - return false; -} - -Variant Node2D::edit_get_state() const { +Dictionary Node2D::_edit_get_state() const { - Array state; - state.push_back(get_position()); - state.push_back(get_rotation()); - state.push_back(get_scale()); + Dictionary state; + state["position"] = get_position(); + state["rotation"] = get_rotation(); + state["scale"] = get_scale(); return state; } -void Node2D::edit_set_state(const Variant &p_state) { +void Node2D::_edit_set_state(const Dictionary &p_state) { - Array state = p_state; - ERR_FAIL_COND(state.size() != 3); + Dictionary state = p_state; + pos = state["position"]; + angle = state["rotation"]; + _scale = state["scale"]; - pos = state[0]; - angle = state[1]; - _scale = state[2]; _update_transform(); _change_notify("rotation"); - _change_notify("rotation_deg"); + _change_notify("rotation_degrees"); _change_notify("scale"); _change_notify("position"); } -void Node2D::edit_set_rect(const Rect2 &p_edit_rect) { +void Node2D::_edit_set_position(const Point2 &p_position) { + pos = p_position; +} + +Point2 Node2D::_edit_get_position() const { + return pos; +} - Rect2 r = get_item_rect(); +void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) { + Rect2 r = _edit_get_rect(); Vector2 zero_offset; if (r.size.x != 0) @@ -101,12 +95,23 @@ void Node2D::edit_set_rect(const Rect2 &p_edit_rect) { _change_notify("position"); } -void Node2D::edit_rotate(float p_rot) { +bool Node2D::_edit_use_rect() const { + return true; +} - angle += p_rot; +void Node2D::_edit_set_rotation(float p_rotation) { + angle = p_rotation; _update_transform(); _change_notify("rotation"); - _change_notify("rotation_deg"); + _change_notify("rotation_degrees"); +} + +float Node2D::_edit_get_rotation() const { + return angle; +} + +bool Node2D::_edit_use_rotation() const { + return true; } void Node2D::_update_xform_values() { @@ -147,22 +152,14 @@ void Node2D::set_rotation(float p_radians) { angle = p_radians; _update_transform(); _change_notify("rotation"); - _change_notify("rotation_deg"); + _change_notify("rotation_degrees"); } -void Node2D::set_rotation_in_degrees(float p_degrees) { +void Node2D::set_rotation_degrees(float p_degrees) { set_rotation(Math::deg2rad(p_degrees)); } -// Kept for compatibility after rename to set_rotd. -// Could be removed after a couple releases. -void Node2D::_set_rotd(float p_degrees) { - - WARN_PRINT("Deprecated method Node2D._set_rotd(): This method was renamed to set_rotd. Please adapt your code accordingly, as the old method will be obsoleted."); - set_rotation_in_degrees(p_degrees); -} - void Node2D::set_scale(const Size2 &p_scale) { if (_xform_dirty) @@ -182,23 +179,19 @@ Point2 Node2D::get_position() const { ((Node2D *)this)->_update_xform_values(); return pos; } + float Node2D::get_rotation() const { if (_xform_dirty) ((Node2D *)this)->_update_xform_values(); return angle; } -float Node2D::get_rotation_in_degrees() const { + +float Node2D::get_rotation_degrees() const { return Math::rad2deg(get_rotation()); } -// Kept for compatibility after rename to get_rotd. -// Could be removed after a couple releases. -float Node2D::_get_rotd() const { - WARN_PRINT("Deprecated method Node2D._get_rotd(): This method was renamed to get_rotd. Please adapt your code accordingly, as the old method will be obsoleted."); - return get_rotation_in_degrees(); -} Size2 Node2D::get_scale() const { if (_xform_dirty) ((Node2D *)this)->_update_xform_values(); @@ -217,17 +210,6 @@ Transform2D Node2D::get_transform() const { return _mat; } -Rect2 Node2D::get_item_rect() const { - - if (get_script_instance()) { - Variant::CallError err; - Rect2 r = get_script_instance()->call("_get_item_rect", NULL, 0, err); - if (err.error == Variant::CallError::CALL_OK) - return r; - } - return Rect2(Point2(-32, -32), Size2(64, 64)); -} - void Node2D::rotate(float p_radians) { set_rotation(get_rotation() + p_radians); @@ -299,12 +281,12 @@ void Node2D::set_global_rotation(float p_radians) { } } -float Node2D::get_global_rotation_in_degrees() const { +float Node2D::get_global_rotation_degrees() const { return Math::rad2deg(get_global_rotation()); } -void Node2D::set_global_rotation_in_degrees(float p_degrees) { +void Node2D::set_global_rotation_degrees(float p_degrees) { set_global_rotation(Math::deg2rad(p_degrees)); } @@ -410,18 +392,14 @@ Point2 Node2D::to_global(Point2 p_local) const { void Node2D::_bind_methods() { - // TODO: Obsolete those two methods (old name) properly (GH-4397) - ClassDB::bind_method(D_METHOD("_get_rotd"), &Node2D::_get_rotd); - ClassDB::bind_method(D_METHOD("_set_rotd", "degrees"), &Node2D::_set_rotd); - ClassDB::bind_method(D_METHOD("set_position", "position"), &Node2D::set_position); ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Node2D::set_rotation); - ClassDB::bind_method(D_METHOD("set_rotation_in_degrees", "degrees"), &Node2D::set_rotation_in_degrees); + ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Node2D::set_rotation_degrees); ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Node2D::set_scale); ClassDB::bind_method(D_METHOD("get_position"), &Node2D::get_position); ClassDB::bind_method(D_METHOD("get_rotation"), &Node2D::get_rotation); - ClassDB::bind_method(D_METHOD("get_rotation_in_degrees"), &Node2D::get_rotation_in_degrees); + ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Node2D::get_rotation_degrees); ClassDB::bind_method(D_METHOD("get_scale"), &Node2D::get_scale); ClassDB::bind_method(D_METHOD("rotate", "radians"), &Node2D::rotate); @@ -435,8 +413,8 @@ void Node2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_global_position"), &Node2D::get_global_position); ClassDB::bind_method(D_METHOD("set_global_rotation", "radians"), &Node2D::set_global_rotation); ClassDB::bind_method(D_METHOD("get_global_rotation"), &Node2D::get_global_rotation); - ClassDB::bind_method(D_METHOD("set_global_rotation_in_degrees", "degrees"), &Node2D::set_global_rotation_in_degrees); - ClassDB::bind_method(D_METHOD("get_global_rotation_in_degrees"), &Node2D::get_global_rotation_in_degrees); + ClassDB::bind_method(D_METHOD("set_global_rotation_degrees", "degrees"), &Node2D::set_global_rotation_degrees); + ClassDB::bind_method(D_METHOD("get_global_rotation_degrees"), &Node2D::get_global_rotation_degrees); ClassDB::bind_method(D_METHOD("set_global_scale", "scale"), &Node2D::set_global_scale); ClassDB::bind_method(D_METHOD("get_global_scale"), &Node2D::get_global_scale); @@ -455,20 +433,20 @@ void Node2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_z_as_relative", "enable"), &Node2D::set_z_as_relative); ClassDB::bind_method(D_METHOD("is_z_relative"), &Node2D::is_z_relative); - ClassDB::bind_method(D_METHOD("edit_set_pivot", "pivot"), &Node2D::edit_set_pivot); + ClassDB::bind_method(D_METHOD("_edit_set_pivot", "pivot"), &Node2D::_edit_set_pivot); ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent); ADD_GROUP("Transform", ""); ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position"); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_rotation", "get_rotation"); - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rotation_deg", PROPERTY_HINT_RANGE, "-1440,1440,0.1", PROPERTY_USAGE_EDITOR), "set_rotation_in_degrees", "get_rotation_in_degrees"); + ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rotation_degrees", PROPERTY_HINT_RANGE, "-1440,1440,0.1", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees"); ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "", 0), "set_transform", "get_transform"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_position", PROPERTY_HINT_NONE, "", 0), "set_global_position", "get_global_position"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_rotation", PROPERTY_HINT_NONE, "", 0), "set_global_rotation", "get_global_rotation"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_rotation_deg", PROPERTY_HINT_NONE, "", 0), "set_global_rotation_in_degrees", "get_global_rotation_in_degrees"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_rotation_degrees", PROPERTY_HINT_NONE, "", 0), "set_global_rotation_degrees", "get_global_rotation_degrees"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_scale", PROPERTY_HINT_NONE, "", 0), "set_global_scale", "get_global_scale"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform"); diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index 19aafc81ff..e1e07f2895 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -48,10 +48,6 @@ class Node2D : public CanvasItem { void _update_transform(); - // Deprecated, should be removed in a future version. - void _set_rotd(float p_degrees); - float _get_rotd() const; - void _update_xform_values(); protected: @@ -60,17 +56,20 @@ protected: static void _bind_methods(); public: - virtual Variant edit_get_state() const; - virtual void edit_set_state(const Variant &p_state); - virtual void edit_set_rect(const Rect2 &p_edit_rect); - virtual void edit_rotate(float p_rot); - virtual void edit_set_pivot(const Point2 &p_pivot); - virtual Point2 edit_get_pivot() const; - virtual bool edit_has_pivot() const; + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + + virtual void _edit_set_position(const Point2 &p_position); + virtual Point2 _edit_get_position() const; + virtual void _edit_set_rect(const Rect2 &p_edit_rect); + virtual bool _edit_use_rect() const; + virtual void _edit_set_rotation(float p_rotation); + virtual float _edit_get_rotation() const; + virtual bool _edit_use_rotation() const; void set_position(const Point2 &p_pos); void set_rotation(float p_radians); - void set_rotation_in_degrees(float p_degrees); + void set_rotation_degrees(float p_degrees); void set_scale(const Size2 &p_scale); void rotate(float p_radians); @@ -82,20 +81,19 @@ public: Point2 get_position() const; float get_rotation() const; - float get_rotation_in_degrees() const; + float get_rotation_degrees() const; Size2 get_scale() const; Point2 get_global_position() const; float get_global_rotation() const; - float get_global_rotation_in_degrees() const; + float get_global_rotation_degrees() const; Size2 get_global_scale() const; - virtual Rect2 get_item_rect() const; void set_transform(const Transform2D &p_transform); void set_global_transform(const Transform2D &p_transform); void set_global_position(const Point2 &p_pos); void set_global_rotation(float p_radians); - void set_global_rotation_in_degrees(float p_degrees); + void set_global_rotation_degrees(float p_degrees); void set_global_scale(const Size2 &p_scale); void set_z(int p_z); diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index c146ac08c2..aee5d89150 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -77,7 +77,7 @@ void Particles2D::set_randomness_ratio(float p_ratio) { void Particles2D::set_visibility_rect(const Rect2 &p_aabb) { visibility_rect = p_aabb; - Rect3 aabb; + AABB aabb; aabb.position.x = p_aabb.position.x; aabb.position.y = p_aabb.position.y; aabb.size.x = p_aabb.size.x; @@ -223,7 +223,7 @@ String Particles2D::get_configuration_warning() const { Rect2 Particles2D::capture_rect() const { - Rect3 aabb = VS::get_singleton()->particles_get_current_aabb(particles); + AABB aabb = VS::get_singleton()->particles_get_current_aabb(particles); Rect2 r; r.position.x = aabb.position.x; r.position.y = aabb.position.y; @@ -378,7 +378,7 @@ void Particles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); ADD_GROUP("Drawing", ""); - ADD_PROPERTY(PropertyInfo(Variant::RECT3, "visibility_rect"), "set_visibility_rect", "get_visibility_rect"); + ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_rect"), "set_visibility_rect", "get_visibility_rect"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates"); ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime"), "set_draw_order", "get_draw_order"); ADD_GROUP("Process Material", "process_"); diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 8413be1ca9..55c055e34f 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -107,28 +107,39 @@ void PathFollow2D::_update_transform() { if (!c.is_valid()) return; + if (delta_offset == 0) { + return; + } + float o = offset; if (loop) o = Math::fposmod(o, c->get_baked_length()); Vector2 pos = c->interpolate_baked(o, cubic); + Vector2 offset = Vector2(h_offset, v_offset); + + Transform2D t = get_transform(); + t.set_origin(pos); + if (rotate) { - Vector2 n = (c->interpolate_baked(o + lookahead, cubic) - pos).normalized(); - Vector2 t = -n.tangent(); - pos += n * h_offset; - pos += t * v_offset; + Vector2 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized(); + Vector2 t_cur = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized(); + + float dot = t_prev.dot(t_cur); + float angle = Math::acos(CLAMP(dot, -1, 1)); + + t.rotate(angle); - set_rotation(t.angle()); + t.translate(offset); } else { - pos.x += h_offset; - pos.y += v_offset; + t.set_origin(t.get_origin() + offset); } - set_position(pos); + set_transform(t); } void PathFollow2D::_notification(int p_what) { @@ -176,8 +187,6 @@ bool PathFollow2D::_set(const StringName &p_name, const Variant &p_value) { set_cubic_interpolation(p_value); } else if (String(p_name) == "loop") { set_loop(p_value); - } else if (String(p_name) == "lookahead") { - set_lookahead(p_value); } else return false; @@ -200,8 +209,6 @@ bool PathFollow2D::_get(const StringName &p_name, Variant &r_ret) const { r_ret = cubic; } else if (String(p_name) == "loop") { r_ret = loop; - } else if (String(p_name) == "lookahead") { - r_ret = lookahead; } else return false; @@ -219,7 +226,6 @@ void PathFollow2D::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::BOOL, "rotate")); p_list->push_back(PropertyInfo(Variant::BOOL, "cubic_interp")); p_list->push_back(PropertyInfo(Variant::BOOL, "loop")); - p_list->push_back(PropertyInfo(Variant::REAL, "lookahead", PROPERTY_HINT_RANGE, "0.001,1024.0,0.001")); } String PathFollow2D::get_configuration_warning() const { @@ -259,7 +265,7 @@ void PathFollow2D::_bind_methods() { } void PathFollow2D::set_offset(float p_offset) { - + delta_offset = p_offset - offset; offset = p_offset; if (path) _update_transform(); @@ -310,16 +316,6 @@ float PathFollow2D::get_unit_offset() const { return 0; } -void PathFollow2D::set_lookahead(float p_lookahead) { - - lookahead = p_lookahead; -} - -float PathFollow2D::get_lookahead() const { - - return lookahead; -} - void PathFollow2D::set_rotate(bool p_rotate) { rotate = p_rotate; @@ -344,11 +340,11 @@ bool PathFollow2D::has_loop() const { PathFollow2D::PathFollow2D() { offset = 0; + delta_offset = 0; h_offset = 0; v_offset = 0; path = NULL; rotate = true; cubic = true; loop = true; - lookahead = 4; } diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index 88a0abdea9..f5ba3a3d32 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -60,9 +60,9 @@ public: private: Path2D *path; real_t offset; + real_t delta_offset; // change in offset since last _update_transform real_t h_offset; real_t v_offset; - real_t lookahead; bool cubic; bool loop; bool rotate; @@ -90,9 +90,6 @@ public: void set_unit_offset(float p_unit_offset); float get_unit_offset() const; - void set_lookahead(float p_lookahead); - float get_lookahead() const; - void set_loop(bool p_loop); bool has_loop() const; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index f0ee64a53f..1f6127e6eb 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -133,8 +133,9 @@ bool PhysicsBody2D::get_collision_layer_bit(int p_bit) const { } PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) - : CollisionObject2D(Physics2DServer::get_singleton()->body_create(p_mode), false) { + : CollisionObject2D(Physics2DServer::get_singleton()->body_create(), false) { + Physics2DServer::get_singleton()->body_set_mode(get_rid(), p_mode); collision_layer = 1; collision_mask = 1; set_pickable(false); @@ -1027,7 +1028,10 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const on_floor = true; floor_velocity = collision.collider_vel; - if (collision.travel.length() < 1 && ABS((lv.x - floor_velocity.x)) < p_slope_stop_min_velocity) { + Vector2 rel_v = lv - floor_velocity; + Vector2 hv = rel_v - p_floor_direction * p_floor_direction.dot(rel_v); + + if (collision.travel.length() < 1 && hv.length() < p_slope_stop_min_velocity) { Transform2D gt = get_global_transform(); gt.elements[2] -= collision.travel; set_global_transform(gt); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 197c74352e..3f2ad19e51 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "polygon_2d.h" -Rect2 Polygon2D::get_item_rect() const { +Rect2 Polygon2D::_edit_get_rect() const { if (rect_cache_dirty) { int l = polygon.size(); @@ -49,16 +49,16 @@ Rect2 Polygon2D::get_item_rect() const { return item_rect; } -void Polygon2D::edit_set_pivot(const Point2 &p_pivot) { +void Polygon2D::_edit_set_pivot(const Point2 &p_pivot) { set_offset(p_pivot); } -Point2 Polygon2D::edit_get_pivot() const { +Point2 Polygon2D::_edit_get_pivot() const { return get_offset(); } -bool Polygon2D::edit_has_pivot() const { +bool Polygon2D::_edit_use_pivot() const { return true; } @@ -264,11 +264,11 @@ float Polygon2D::get_texture_rotation() const { return tex_rot; } -void Polygon2D::_set_texture_rotationd(float p_rot) { +void Polygon2D::set_texture_rotation_degrees(float p_rot) { set_texture_rotation(Math::deg2rad(p_rot)); } -float Polygon2D::_get_texture_rotationd() const { +float Polygon2D::get_texture_rotation_degrees() const { return Math::rad2deg(get_texture_rotation()); } @@ -348,8 +348,8 @@ void Polygon2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture_rotation", "texture_rotation"), &Polygon2D::set_texture_rotation); ClassDB::bind_method(D_METHOD("get_texture_rotation"), &Polygon2D::get_texture_rotation); - ClassDB::bind_method(D_METHOD("_set_texture_rotationd", "texture_rotation"), &Polygon2D::_set_texture_rotationd); - ClassDB::bind_method(D_METHOD("_get_texture_rotationd"), &Polygon2D::_get_texture_rotationd); + ClassDB::bind_method(D_METHOD("set_texture_rotation_degrees", "texture_rotation"), &Polygon2D::set_texture_rotation_degrees); + ClassDB::bind_method(D_METHOD("get_texture_rotation_degrees"), &Polygon2D::get_texture_rotation_degrees); ClassDB::bind_method(D_METHOD("set_texture_scale", "texture_scale"), &Polygon2D::set_texture_scale); ClassDB::bind_method(D_METHOD("get_texture_scale"), &Polygon2D::get_texture_scale); @@ -377,7 +377,7 @@ void Polygon2D::_bind_methods() { ADD_GROUP("Texture", "texture_"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_offset"), "set_texture_offset", "get_texture_offset"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_scale"), "set_texture_scale", "get_texture_scale"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_rotation", PROPERTY_HINT_RANGE, "-1440,1440,0.1"), "_set_texture_rotationd", "_get_texture_rotationd"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_rotation", PROPERTY_HINT_RANGE, "-1440,1440,0.1"), "set_texture_rotation_degrees", "get_texture_rotation_degrees"); ADD_GROUP("Invert", "invert_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_enable"), "set_invert", "get_invert"); diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h index 20c3324a50..d09e22f5ff 100644 --- a/scene/2d/polygon_2d.h +++ b/scene/2d/polygon_2d.h @@ -53,9 +53,6 @@ class Polygon2D : public Node2D { mutable bool rect_cache_dirty; mutable Rect2 item_rect; - void _set_texture_rotationd(float p_rot); - float _get_texture_rotationd() const; - protected: void _notification(int p_what); static void _bind_methods(); @@ -82,6 +79,9 @@ public: void set_texture_rotation(float p_rot); float get_texture_rotation() const; + void set_texture_rotation_degrees(float p_rot); + float get_texture_rotation_degrees() const; + void set_texture_scale(const Size2 &p_scale); Size2 get_texture_scale() const; @@ -99,11 +99,11 @@ public: //editor stuff - virtual void edit_set_pivot(const Point2 &p_pivot); - virtual Point2 edit_get_pivot() const; - virtual bool edit_has_pivot() const; + virtual void _edit_set_pivot(const Point2 &p_pivot); + virtual Point2 _edit_get_pivot() const; + virtual bool _edit_use_pivot() const; - virtual Rect2 get_item_rect() const; + virtual Rect2 _edit_get_rect() const; Polygon2D(); }; diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp index cde665d422..1e729bc179 100644 --- a/scene/2d/position_2d.cpp +++ b/scene/2d/position_2d.cpp @@ -38,7 +38,7 @@ void Position2D::_draw_cross() { draw_line(Point2(0, -10), Point2(0, +10), Color(0.5, 1, 0.5)); } -Rect2 Position2D::get_item_rect() const { +Rect2 Position2D::_edit_get_rect() const { return Rect2(Point2(-10, -10), Size2(20, 20)); } diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h index af54fb919a..5961e447df 100644 --- a/scene/2d/position_2d.h +++ b/scene/2d/position_2d.h @@ -42,7 +42,7 @@ protected: void _notification(int p_what); public: - virtual Rect2 get_item_rect() const; + virtual Rect2 _edit_get_rect() const; Position2D(); }; diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp index bf7c5a3ba4..d5fcda90d5 100644 --- a/scene/2d/screen_button.cpp +++ b/scene/2d/screen_button.cpp @@ -133,7 +133,7 @@ void TouchScreenButton::_notification(int p_what) { return; if (shape.is_valid()) { Color draw_col = get_tree()->get_debug_collisions_color(); - Vector2 pos = shape_centered ? get_item_rect().size * 0.5f : Vector2(); + Vector2 pos = shape_centered ? _edit_get_rect().size * 0.5f : Vector2(); draw_set_transform_matrix(get_canvas_transform().translated(pos)); shape->draw(get_canvas_item(), draw_col); } @@ -251,7 +251,7 @@ void TouchScreenButton::_input(const Ref<InputEvent> &p_event) { bool TouchScreenButton::_is_point_inside(const Point2 &p_point) { Point2 coord = (get_global_transform_with_canvas()).affine_inverse().xform(p_point); - Rect2 item_rect = get_item_rect(); + Rect2 item_rect = _edit_get_rect(); bool touched = false; bool check_rect = true; @@ -322,13 +322,13 @@ void TouchScreenButton::_release(bool p_exiting_tree) { } } -Rect2 TouchScreenButton::get_item_rect() const { +Rect2 TouchScreenButton::_edit_get_rect() const { if (texture.is_null()) return Rect2(0, 0, 1, 1); /* if (texture.is_null()) - return CanvasItem::get_item_rect(); + return CanvasItem::_edit_get_rect(); */ return Rect2(Size2(), texture->get_size()); diff --git a/scene/2d/screen_button.h b/scene/2d/screen_button.h index 7647070b26..2e674c20b4 100644 --- a/scene/2d/screen_button.h +++ b/scene/2d/screen_button.h @@ -102,7 +102,7 @@ public: bool is_pressed() const; - Rect2 get_item_rect() const; + Rect2 _edit_get_rect() const; TouchScreenButton(); }; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index c53faab5f9..df2265aae9 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -33,16 +33,16 @@ #include "scene/main/viewport.h" #include "scene/scene_string_names.h" -void Sprite::edit_set_pivot(const Point2 &p_pivot) { +void Sprite::_edit_set_pivot(const Point2 &p_pivot) { set_offset(p_pivot); } -Point2 Sprite::edit_get_pivot() const { +Point2 Sprite::_edit_get_pivot() const { return get_offset(); } -bool Sprite::edit_has_pivot() const { +bool Sprite::_edit_use_pivot() const { return true; } @@ -257,13 +257,13 @@ int Sprite::get_hframes() const { return hframes; } -Rect2 Sprite::get_item_rect() const { +Rect2 Sprite::_edit_get_rect() const { if (texture.is_null()) return Rect2(0, 0, 1, 1); /* if (texture.is_null()) - return CanvasItem::get_item_rect(); + return CanvasItem::_edit_get_rect(); */ Size2i s; @@ -368,224 +368,3 @@ Sprite::Sprite() { vframes = 1; hframes = 1; } - -//////////////////////////// VPSPRITE -/// -/// -/// - -#if 0 -void ViewportSprite::edit_set_pivot(const Point2& p_pivot) { - - set_offset(p_pivot); -} - -Point2 ViewportSprite::edit_get_pivot() const { - - return get_offset(); -} -bool ViewportSprite::edit_has_pivot() const { - - return true; -} - -void ViewportSprite::_notification(int p_what) { - - switch(p_what) { - - case NOTIFICATION_ENTER_TREE: { - - if (!viewport_path.is_empty()) { - - Node *n = get_node(viewport_path); - ERR_FAIL_COND(!n); - Viewport *vp=Object::cast_to<Viewport>(n); - ERR_FAIL_COND(!vp); - - Ref<RenderTargetTexture> rtt = vp->get_render_target_texture(); - texture=rtt; - texture->connect("changed",this,"update"); - item_rect_changed(); - } - } break; - case NOTIFICATION_EXIT_TREE: { - - if (texture.is_valid()) { - - texture->disconnect("changed",this,"update"); - texture=Ref<Texture>(); - } - } break; - case NOTIFICATION_DRAW: { - - if (texture.is_null()) - return; - - RID ci = get_canvas_item(); - - /* - texture->draw(ci,Point2()); - break; - */ - - Size2i s; - Rect2i src_rect; - - s = texture->get_size(); - - src_rect.size=s; - - Point2 ofs=offset; - if (centered) - ofs-=s/2; - - if (OS::get_singleton()->get_use_pixel_snap()) { - ofs=ofs.floor(); - } - Rect2 dst_rect(ofs,s); - texture->draw_rect_region(ci,dst_rect,src_rect,modulate); - - } break; - } -} - -void ViewportSprite::set_viewport_path(const NodePath& p_viewport) { - - viewport_path=p_viewport; - update(); - if (!is_inside_tree()) - return; - - if (texture.is_valid()) { - texture->disconnect("changed",this,"update"); - texture=Ref<Texture>(); - } - - if (viewport_path.is_empty()) - return; - - - Node *n = get_node(viewport_path); - ERR_FAIL_COND(!n); - Viewport *vp=Object::cast_to<Viewport>(n); - ERR_FAIL_COND(!vp); - - Ref<RenderTargetTexture> rtt = vp->get_render_target_texture(); - texture=rtt; - - if (texture.is_valid()) { - texture->connect("changed",this,"update"); - } - - item_rect_changed(); - -} - -NodePath ViewportSprite::get_viewport_path() const { - - return viewport_path; -} - -void ViewportSprite::set_centered(bool p_center) { - - centered=p_center; - update(); - item_rect_changed(); -} - -bool ViewportSprite::is_centered() const { - - return centered; -} - -void ViewportSprite::set_offset(const Point2& p_offset) { - - offset=p_offset; - update(); - item_rect_changed(); -} -Point2 ViewportSprite::get_offset() const { - - return offset; -} -void ViewportSprite::set_modulate(const Color& p_color) { - - modulate=p_color; - update(); -} - -Color ViewportSprite::get_modulate() const{ - - return modulate; -} - - -Rect2 ViewportSprite::get_item_rect() const { - - if (texture.is_null()) - return Rect2(0,0,1,1); - /* - if (texture.is_null()) - return CanvasItem::get_item_rect(); - */ - - Size2i s; - - s = texture->get_size(); - Point2 ofs=offset; - if (centered) - ofs-=s/2; - - if (s==Size2(0,0)) - s=Size2(1,1); - - return Rect2(ofs,s); -} - -String ViewportSprite::get_configuration_warning() const { - - if (!has_node(viewport_path) || !Object::cast_to<Viewport>(get_node(viewport_path))) { - return TTR("Path property must point to a valid Viewport node to work. Such Viewport must be set to 'render target' mode."); - } else { - - Node *n = get_node(viewport_path); - if (n) { - Viewport *vp = Object::cast_to<Viewport>(n); - if (!vp->is_set_as_render_target()) { - - return TTR("The Viewport set in the path property must be set as 'render target' in order for this sprite to work."); - } - } - } - - return String(); - -} - -void ViewportSprite::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_viewport_path","path"),&ViewportSprite::set_viewport_path); - ClassDB::bind_method(D_METHOD("get_viewport_path"),&ViewportSprite::get_viewport_path); - - ClassDB::bind_method(D_METHOD("set_centered","centered"),&ViewportSprite::set_centered); - ClassDB::bind_method(D_METHOD("is_centered"),&ViewportSprite::is_centered); - - ClassDB::bind_method(D_METHOD("set_offset","offset"),&ViewportSprite::set_offset); - ClassDB::bind_method(D_METHOD("get_offset"),&ViewportSprite::get_offset); - - ClassDB::bind_method(D_METHOD("set_modulate","modulate"),&ViewportSprite::set_modulate); - ClassDB::bind_method(D_METHOD("get_modulate"),&ViewportSprite::get_modulate); - - ADD_PROPERTYNZ( PropertyInfo( Variant::NODE_PATH, "viewport"), "set_viewport_path","get_viewport_path"); - ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), "set_centered","is_centered"); - ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), "set_offset","get_offset"); - ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), "set_modulate","get_modulate"); - -} - -ViewportSprite::ViewportSprite() { - - centered=true; - modulate=Color(1,1,1,1); -} -#endif diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h index 64d30325f2..1bef73c0a5 100644 --- a/scene/2d/sprite.h +++ b/scene/2d/sprite.h @@ -62,9 +62,10 @@ protected: virtual void _validate_property(PropertyInfo &property) const; public: - virtual void edit_set_pivot(const Point2 &p_pivot); - virtual Point2 edit_get_pivot() const; - virtual bool edit_has_pivot() const; + virtual void _edit_set_pivot(const Point2 &p_pivot); + virtual Point2 _edit_get_pivot() const; + virtual bool _edit_use_pivot() const; + virtual Rect2 _edit_get_rect() const; void set_texture(const Ref<Texture> &p_texture); Ref<Texture> get_texture() const; @@ -102,53 +103,7 @@ public: void set_hframes(int p_amount); int get_hframes() const; - virtual Rect2 get_item_rect() const; - Sprite(); }; -#if 0 -class ViewportSprite : public Node2D { - - GDCLASS( ViewportSprite, Node2D ); - - Ref<Texture> texture; - NodePath viewport_path; - - bool centered; - Point2 offset; - Color modulate; - -protected: - - void _notification(int p_what); - - static void _bind_methods(); - -public: - - virtual void edit_set_pivot(const Point2& p_pivot); - virtual Point2 edit_get_pivot() const; - virtual bool edit_has_pivot() const; - - void set_viewport_path(const NodePath& p_viewport); - NodePath get_viewport_path() const; - - void set_centered(bool p_center); - bool is_centered() const; - - void set_offset(const Point2& p_offset); - Point2 get_offset() const; - - void set_modulate(const Color& p_color); - Color get_modulate() const; - - virtual Rect2 get_item_rect() const; - - virtual String get_configuration_warning() const; - - ViewportSprite(); -}; - -#endif #endif // SPRITE_H diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 4286d88ab1..f067b5a187 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -448,21 +448,20 @@ void TileMap::_update_dirty_quadrants() { if (r == Rect2()) { tex->draw_rect(canvas_item, rect, false, modulate, c.transpose, normal_map); } else { - tex->draw_rect_region(canvas_item, rect, r, modulate, c.transpose, normal_map); + tex->draw_rect_region(canvas_item, rect, r, modulate, c.transpose, normal_map, clip_uv); } Vector<TileSet::ShapeData> shapes = tile_set->tile_get_shapes(c.id); for (int i = 0; i < shapes.size(); i++) { - Ref<Shape2D> shape = shapes[i].shape; if (shape.is_valid()) { Transform2D xform; xform.set_origin(offset.floor()); - _fix_cell_transform(xform, c, center_ofs, s); + Vector2 shape_ofs = tile_set->tile_get_shape_offset(c.id, i); - xform *= shapes[i].shape_transform; + _fix_cell_transform(xform, c, shape_ofs + center_ofs, s); if (debug_canvas_item.is_valid()) { vs->canvas_item_add_set_transform(debug_canvas_item, xform); @@ -587,7 +586,9 @@ Map<TileMap::PosKey, TileMap::Quadrant>::Element *TileMap::_create_quadrant(cons xform.set_origin(q.pos); //q.canvas_item = VisualServer::get_singleton()->canvas_item_create(); - q.body = Physics2DServer::get_singleton()->body_create(use_kinematic ? Physics2DServer::BODY_MODE_KINEMATIC : Physics2DServer::BODY_MODE_STATIC); + q.body = Physics2DServer::get_singleton()->body_create(); + Physics2DServer::get_singleton()->body_set_mode(q.body, use_kinematic ? Physics2DServer::BODY_MODE_KINEMATIC : Physics2DServer::BODY_MODE_STATIC); + Physics2DServer::get_singleton()->body_attach_object_instance_id(q.body, get_instance_id()); Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer); Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask); @@ -882,7 +883,7 @@ PoolVector<int> TileMap::_get_tile_data() const { return data; } -Rect2 TileMap::get_item_rect() const { +Rect2 TileMap::_edit_get_rect() const { const_cast<TileMap *>(this)->_update_dirty_quadrants(); return rect_cache; @@ -1234,6 +1235,21 @@ void TileMap::set_light_mask(int p_light_mask) { } } +void TileMap::set_clip_uv(bool p_enable) { + + if (clip_uv == p_enable) + return; + + _clear_quadrants(); + clip_uv = p_enable; + _recreate_quadrants(); +} + +bool TileMap::get_clip_uv() const { + + return clip_uv; +} + void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_tileset", "tileset"), &TileMap::set_tileset); @@ -1266,6 +1282,9 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_center_y", "enable"), &TileMap::set_center_y); ClassDB::bind_method(D_METHOD("get_center_y"), &TileMap::get_center_y); + ClassDB::bind_method(D_METHOD("set_clip_uv", "enable"), &TileMap::set_clip_uv); + ClassDB::bind_method(D_METHOD("get_clip_uv"), &TileMap::get_clip_uv); + ClassDB::bind_method(D_METHOD("set_y_sort_mode", "enable"), &TileMap::set_y_sort_mode); ClassDB::bind_method(D_METHOD("is_y_sort_mode_enabled"), &TileMap::is_y_sort_mode_enabled); @@ -1327,6 +1346,7 @@ void TileMap::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_half_offset", PROPERTY_HINT_ENUM, "Offset X,Offset Y,Disabled"), "set_half_offset", "get_half_offset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_tile_origin", PROPERTY_HINT_ENUM, "Top Left,Center,Bottom Left"), "set_tile_origin", "get_tile_origin"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_y_sort"), "set_y_sort_mode", "is_y_sort_mode_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cell_clip_uv"), "set_clip_uv", "get_clip_uv"); ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_kinematic", PROPERTY_HINT_NONE, ""), "set_collision_use_kinematic", "get_collision_use_kinematic"); @@ -1377,6 +1397,7 @@ TileMap::TileMap() { navigation = NULL; y_sort_mode = false; occluder_light_mask = 1; + clip_uv = false; fp_adjust = 0.00001; tile_origin = TILE_ORIGIN_TOP_LEFT; diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index c9d14e09d1..9e14ec838a 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -161,6 +161,7 @@ private: bool used_size_cache_dirty; bool quadrant_order_dirty; bool y_sort_mode; + bool clip_uv; float fp_adjust; float friction; float bounce; @@ -228,7 +229,7 @@ public: void set_cellv(const Vector2 &p_pos, int p_tile, bool p_flip_x = false, bool p_flip_y = false, bool p_transpose = false); int get_cellv(const Vector2 &p_pos) const; - Rect2 get_item_rect() const; + Rect2 _edit_get_rect() const; void set_collision_layer(uint32_t p_layer); uint32_t get_collision_layer() const; @@ -285,6 +286,9 @@ public: virtual void set_use_parent_material(bool p_use_parent_material); + void set_clip_uv(bool p_enable); + bool get_clip_uv() const; + void clear(); TileMap(); diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index b0fd57baf5..298bc2649e 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -83,7 +83,7 @@ void VisibilityNotifier2D::set_rect(const Rect2 &p_rect) { _change_notify("rect"); } -Rect2 VisibilityNotifier2D::get_item_rect() const { +Rect2 VisibilityNotifier2D::_edit_get_rect() const { return rect; } diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h index ee5152978b..6e06833912 100644 --- a/scene/2d/visibility_notifier_2d.h +++ b/scene/2d/visibility_notifier_2d.h @@ -54,13 +54,13 @@ protected: static void _bind_methods(); public: + virtual Rect2 _edit_get_rect() const; + void set_rect(const Rect2 &p_rect); Rect2 get_rect() const; bool is_on_screen() const; - virtual Rect2 get_item_rect() const; - VisibilityNotifier2D(); }; diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp index 382cbb8f38..a6d812efec 100644 --- a/scene/3d/collision_polygon.cpp +++ b/scene/3d/collision_polygon.cpp @@ -117,7 +117,7 @@ Vector<Point2> CollisionPolygon::get_polygon() const { return polygon; } -Rect3 CollisionPolygon::get_item_rect() const { +AABB CollisionPolygon::get_item_rect() const { return aabb; } @@ -176,7 +176,7 @@ void CollisionPolygon::_bind_methods() { CollisionPolygon::CollisionPolygon() { - aabb = Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2)); + aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); depth = 1.0; set_notify_local_transform(true); parent = NULL; diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h index dbed1d7154..14d8c3aba6 100644 --- a/scene/3d/collision_polygon.h +++ b/scene/3d/collision_polygon.h @@ -40,7 +40,7 @@ class CollisionPolygon : public Spatial { protected: float depth; - Rect3 aabb; + AABB aabb; Vector<Point2> polygon; uint32_t owner_id; @@ -64,7 +64,7 @@ public: void set_disabled(bool p_disabled); bool is_disabled() const; - virtual Rect3 get_item_rect() const; + virtual AABB get_item_rect() const; String get_configuration_warning() const; diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index c0ca358717..05d5d52d28 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -31,12 +31,12 @@ #include "mesh_instance.h" -void GIProbeData::set_bounds(const Rect3 &p_bounds) { +void GIProbeData::set_bounds(const AABB &p_bounds) { VS::get_singleton()->gi_probe_set_bounds(probe, p_bounds); } -Rect3 GIProbeData::get_bounds() const { +AABB GIProbeData::get_bounds() const { return VS::get_singleton()->gi_probe_get_bounds(probe); } @@ -180,7 +180,7 @@ void GIProbeData::_bind_methods() { ClassDB::bind_method(D_METHOD("set_compress", "compress"), &GIProbeData::set_compress); ClassDB::bind_method(D_METHOD("is_compressed"), &GIProbeData::is_compressed); - ADD_PROPERTY(PropertyInfo(Variant::RECT3, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds"); + ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_size", "get_cell_size"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "to_cell_xform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_to_cell_xform", "get_to_cell_xform"); @@ -410,7 +410,7 @@ static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) { rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ if (min > rad || max < -rad) return false; -/*======================== Z-tests ========================*/ + /*======================== Z-tests ========================*/ #define AXISTEST_Z12(a, b, fa, fb) \ p1 = a * v1.x - b * v1.y; \ @@ -542,7 +542,7 @@ static _FORCE_INLINE_ Vector2 get_uv(const Vector3 &p_pos, const Vector3 *p_vtx, return p_uv[0] * u + p_uv[1] * v + p_uv[2] * w; } -void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const Baker::MaterialCache &p_material, const Rect3 &p_aabb, Baker *p_baker) { +void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const Baker::MaterialCache &p_material, const AABB &p_aabb, Baker *p_baker) { if (p_level == p_baker->cell_subdiv - 1) { //plot the face by guessing it's albedo and emission value @@ -702,7 +702,7 @@ void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, cons int half = (1 << (p_baker->cell_subdiv - 1)) >> (p_level + 1); for (int i = 0; i < 8; i++) { - Rect3 aabb = p_aabb; + AABB aabb = p_aabb; aabb.size *= 0.5; int nx = p_x; @@ -726,7 +726,7 @@ void GIProbe::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, cons continue; { - Rect3 test_aabb = aabb; + AABB test_aabb = aabb; //test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test @@ -891,7 +891,7 @@ void GIProbe::_fixup_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, Bak } } -Vector<Color> GIProbe::_get_bake_texture(Ref<Image> p_image, const Color &p_color) { +Vector<Color> GIProbe::_get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add) { Vector<Color> ret; @@ -899,7 +899,7 @@ Vector<Color> GIProbe::_get_bake_texture(Ref<Image> p_image, const Color &p_colo ret.resize(bake_texture_size * bake_texture_size); for (int i = 0; i < bake_texture_size * bake_texture_size; i++) { - ret[i] = p_color; + ret[i] = p_color_add; } return ret; @@ -919,9 +919,10 @@ Vector<Color> GIProbe::_get_bake_texture(Ref<Image> p_image, const Color &p_colo for (int i = 0; i < bake_texture_size * bake_texture_size; i++) { Color c; - c.r = (r[i * 4 + 0] / 255.0) * p_color.r; - c.g = (r[i * 4 + 1] / 255.0) * p_color.g; - c.b = (r[i * 4 + 2] / 255.0) * p_color.b; + c.r = (r[i * 4 + 0] / 255.0) * p_color_mul.r + p_color_add.r; + c.g = (r[i * 4 + 1] / 255.0) * p_color_mul.g + p_color_add.g; + c.b = (r[i * 4 + 2] / 255.0) * p_color_mul.b + p_color_add.b; + c.a = r[i * 4 + 3] / 255.0; ret[i] = c; @@ -951,17 +952,15 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_mater if (albedo_tex.is_valid()) { img_albedo = albedo_tex->get_data(); + mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo(), Color(0, 0, 0)); // albedo texture, color is multiplicative } else { + mc.albedo = _get_bake_texture(img_albedo, Color(1, 1, 1), mat->get_albedo()); // no albedo texture, color is additive } - mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo()); - - Ref<ImageTexture> emission_tex = mat->get_texture(SpatialMaterial::TEXTURE_EMISSION); + Ref<Texture> emission_tex = mat->get_texture(SpatialMaterial::TEXTURE_EMISSION); Color emission_col = mat->get_emission(); - emission_col.r *= mat->get_emission_energy(); - emission_col.g *= mat->get_emission_energy(); - emission_col.b *= mat->get_emission_energy(); + float emission_energy = mat->get_emission_energy(); Ref<Image> img_emission; @@ -970,13 +969,17 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_mater img_emission = emission_tex->get_data(); } - mc.emission = _get_bake_texture(img_emission, emission_col); + if (mat->get_emission_operator() == SpatialMaterial::EMISSION_OP_ADD) { + mc.emission = _get_bake_texture(img_emission, Color(1, 1, 1) * emission_energy, emission_col * emission_energy); + } else { + mc.emission = _get_bake_texture(img_emission, emission_col * emission_energy, Color(0, 0, 0)); + } } else { Ref<Image> empty; - mc.albedo = _get_bake_texture(empty, Color(0.7, 0.7, 0.7)); - mc.emission = _get_bake_texture(empty, Color(0, 0, 0)); + mc.albedo = _get_bake_texture(empty, Color(0, 0, 0), Color(1, 1, 1)); + mc.emission = _get_bake_texture(empty, Color(0, 0, 0), Color(0, 0, 0)); } p_baker->material_cache[p_material] = mc; @@ -1080,11 +1083,11 @@ void GIProbe::_find_meshes(Node *p_at_node, Baker *p_baker) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { - Rect3 aabb = mesh->get_aabb(); + AABB aabb = mesh->get_aabb(); Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform(); - if (Rect3(-extents, extents * 2).intersects(xf.xform(aabb))) { + if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { Baker::PlotMesh pm; pm.local_xform = xf; pm.mesh = mesh; @@ -1110,11 +1113,11 @@ void GIProbe::_find_meshes(Node *p_at_node, Baker *p_baker) { if (!mesh.is_valid()) continue; - Rect3 aabb = mesh->get_aabb(); + AABB aabb = mesh->get_aabb(); Transform xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf); - if (Rect3(-extents, extents * 2).intersects(xf.xform(aabb))) { + if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { Baker::PlotMesh pm; pm.local_xform = xf; pm.mesh = mesh; @@ -1148,7 +1151,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { baker.bake_cells.resize(1); //find out the actual real bounds, power of 2, which gets the highest subdivision - baker.po2_bounds = Rect3(-extents, extents * 2.0); + baker.po2_bounds = AABB(-extents, extents * 2.0); int longest_axis = baker.po2_bounds.get_longest_axis_index(); baker.axis_cell_size[longest_axis] = (1 << (baker.cell_subdiv - 1)); baker.leaf_voxel_count = 0; @@ -1283,7 +1286,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { Ref<GIProbeData> probe_data; probe_data.instance(); - probe_data->set_bounds(Rect3(-extents, extents * 2.0)); + probe_data->set_bounds(AABB(-extents, extents * 2.0)); probe_data->set_cell_size(baker.po2_bounds.size[longest_axis] / baker.axis_cell_size[longest_axis]); probe_data->set_dynamic_data(data); probe_data->set_dynamic_range(dynamic_range); @@ -1303,7 +1306,7 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { } } -void GIProbe::_debug_mesh(int p_idx, int p_level, const Rect3 &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, Baker *p_baker) { +void GIProbe::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, Baker *p_baker) { if (p_level == p_baker->cell_subdiv - 1) { @@ -1325,7 +1328,7 @@ void GIProbe::_debug_mesh(int p_idx, int p_level, const Rect3 &p_aabb, Ref<Multi if (p_baker->bake_cells[p_idx].childs[i] == Baker::CHILD_EMPTY) continue; - Rect3 aabb = p_aabb; + AABB aabb = p_aabb; aabb.size *= 0.5; if (i & 1) @@ -1437,9 +1440,9 @@ void GIProbe::_debug_bake() { bake(NULL, true); } -Rect3 GIProbe::get_aabb() const { +AABB GIProbe::get_aabb() const { - return Rect3(-extents, extents * 2); + return AABB(-extents, extents * 2); } PoolVector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const { diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h index 50d0c33d4f..324ff8e917 100644 --- a/scene/3d/gi_probe.h +++ b/scene/3d/gi_probe.h @@ -43,8 +43,8 @@ protected: static void _bind_methods(); public: - void set_bounds(const Rect3 &p_bounds); - Rect3 get_bounds() const; + void set_bounds(const AABB &p_bounds); + AABB get_bounds() const; void set_cell_size(float p_size); float get_cell_size() const; @@ -146,7 +146,7 @@ private: MaterialCache _get_material_cache(Ref<Material> p_material); int leaf_voxel_count; - Rect3 po2_bounds; + AABB po2_bounds; int axis_cell_size[3]; struct PlotMesh { @@ -178,14 +178,14 @@ private: int color_scan_cell_width; int bake_texture_size; - Vector<Color> _get_bake_texture(Ref<Image> p_image, const Color &p_color); + Vector<Color> _get_bake_texture(Ref<Image> p_image, const Color &p_color_mul, const Color &p_color_add); Baker::MaterialCache _get_material_cache(Ref<Material> p_material, Baker *p_baker); - void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const Baker::MaterialCache &p_material, const Rect3 &p_aabb, Baker *p_baker); + void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector2 *p_uv, const Baker::MaterialCache &p_material, const AABB &p_aabb, Baker *p_baker); void _plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, Baker *p_baker, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material); void _find_meshes(Node *p_at_node, Baker *p_baker); void _fixup_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, Baker *p_baker); - void _debug_mesh(int p_idx, int p_level, const Rect3 &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, Baker *p_baker); + void _debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, Baker *p_baker); void _create_debug_mesh(Baker *p_baker); void _debug_bake(); @@ -230,7 +230,7 @@ public: void bake(Node *p_from_node = NULL, bool p_create_visual_debug = false); - virtual Rect3 get_aabb() const; + virtual AABB get_aabb() const; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; GIProbe(); diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp index 11f7efe066..092ed8f0b2 100644 --- a/scene/3d/immediate_geometry.cpp +++ b/scene/3d/immediate_geometry.cpp @@ -85,7 +85,7 @@ void ImmediateGeometry::clear() { cached_textures.clear(); } -Rect3 ImmediateGeometry::get_aabb() const { +AABB ImmediateGeometry::get_aabb() const { return aabb; } diff --git a/scene/3d/immediate_geometry.h b/scene/3d/immediate_geometry.h index 93ef726c6d..1ff4e05e82 100644 --- a/scene/3d/immediate_geometry.h +++ b/scene/3d/immediate_geometry.h @@ -42,7 +42,7 @@ class ImmediateGeometry : public GeometryInstance { // in VisualServer from becoming invalid if the texture is no longer used List<Ref<Texture> > cached_textures; bool empty; - Rect3 aabb; + AABB aabb; protected: static void _bind_methods(); @@ -62,7 +62,7 @@ public: void add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv = true); - virtual Rect3 get_aabb() const; + virtual AABB get_aabb() const; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; ImmediateGeometry(); diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index 02d10523e7..126c07f0be 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -117,24 +117,24 @@ bool Light::get_shadow_reverse_cull_face() const { return reverse_cull; } -Rect3 Light::get_aabb() const { +AABB Light::get_aabb() const { if (type == VisualServer::LIGHT_DIRECTIONAL) { - return Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2)); + return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); } else if (type == VisualServer::LIGHT_OMNI) { - return Rect3(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]); + return AABB(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]); } else if (type == VisualServer::LIGHT_SPOT) { float len = param[PARAM_RANGE]; float size = Math::tan(Math::deg2rad(param[PARAM_SPOT_ANGLE])) * len; - return Rect3(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); + return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); } - return Rect3(); + return AABB(); } PoolVector<Face3> Light::get_faces(uint32_t p_usage_flags) const { @@ -222,6 +222,7 @@ void Light::_bind_methods() { ADD_GROUP("Light", "light_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_color", "get_color"); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_ENERGY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_param", "get_param", PARAM_INDIRECT_ENERGY); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative"); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR); ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); @@ -236,6 +237,7 @@ void Light::_bind_methods() { ADD_GROUP("", ""); BIND_ENUM_CONSTANT(PARAM_ENERGY); + BIND_ENUM_CONSTANT(PARAM_INDIRECT_ENERGY); BIND_ENUM_CONSTANT(PARAM_SPECULAR); BIND_ENUM_CONSTANT(PARAM_RANGE); BIND_ENUM_CONSTANT(PARAM_ATTENUATION); @@ -255,7 +257,13 @@ void Light::_bind_methods() { Light::Light(VisualServer::LightType p_type) { type = p_type; - light = VisualServer::get_singleton()->light_create(p_type); + switch (p_type) { + case VS::LIGHT_DIRECTIONAL: light = VisualServer::get_singleton()->directional_light_create(); break; + case VS::LIGHT_OMNI: light = VisualServer::get_singleton()->omni_light_create(); break; + case VS::LIGHT_SPOT: light = VisualServer::get_singleton()->spot_light_create(); break; + default: {}; + } + VS::get_singleton()->instance_set_base(get_instance(), light); reverse_cull = false; @@ -267,6 +275,7 @@ Light::Light(VisualServer::LightType p_type) { set_cull_mask(0xFFFFFFFF); set_param(PARAM_ENERGY, 1); + set_param(PARAM_INDIRECT_ENERGY, 1); set_param(PARAM_SPECULAR, 0.5); set_param(PARAM_RANGE, 5); set_param(PARAM_ATTENUATION, 1); diff --git a/scene/3d/light.h b/scene/3d/light.h index 2f3ac8a5e7..8514b429ec 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -46,6 +46,7 @@ class Light : public VisualInstance { public: enum Param { PARAM_ENERGY = VS::LIGHT_PARAM_ENERGY, + PARAM_INDIRECT_ENERGY = VS::LIGHT_PARAM_INDIRECT_ENERGY, PARAM_SPECULAR = VS::LIGHT_PARAM_SPECULAR, PARAM_RANGE = VS::LIGHT_PARAM_RANGE, PARAM_ATTENUATION = VS::LIGHT_PARAM_ATTENUATION, @@ -113,7 +114,7 @@ public: void set_shadow_reverse_cull_face(bool p_enable); bool get_shadow_reverse_cull_face() const; - virtual Rect3 get_aabb() const; + virtual AABB get_aabb() const; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; Light(); diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index c8215971c4..1e52ccc6e0 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -165,12 +165,12 @@ NodePath MeshInstance::get_skeleton_path() { return skeleton_path; } -Rect3 MeshInstance::get_aabb() const { +AABB MeshInstance::get_aabb() const { if (!mesh.is_null()) return mesh->get_aabb(); - return Rect3(); + return AABB(); } PoolVector<Face3> MeshInstance::get_faces(uint32_t p_usage_flags) const { diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h index 8e8c12a592..970a10aaf3 100644 --- a/scene/3d/mesh_instance.h +++ b/scene/3d/mesh_instance.h @@ -85,7 +85,7 @@ public: void create_debug_tangents(); - virtual Rect3 get_aabb() const; + virtual AABB get_aabb() const; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; MeshInstance(); diff --git a/scene/3d/multimesh_instance.cpp b/scene/3d/multimesh_instance.cpp index f90489f1f0..ce7b97be7f 100644 --- a/scene/3d/multimesh_instance.cpp +++ b/scene/3d/multimesh_instance.cpp @@ -55,10 +55,10 @@ PoolVector<Face3> MultiMeshInstance::get_faces(uint32_t p_usage_flags) const { return PoolVector<Face3>(); } -Rect3 MultiMeshInstance::get_aabb() const { +AABB MultiMeshInstance::get_aabb() const { if (multimesh.is_null()) - return Rect3(); + return AABB(); else return multimesh->get_aabb(); } diff --git a/scene/3d/multimesh_instance.h b/scene/3d/multimesh_instance.h index cd0e7b463c..9b2b1ff9a7 100644 --- a/scene/3d/multimesh_instance.h +++ b/scene/3d/multimesh_instance.h @@ -52,7 +52,7 @@ public: void set_multimesh(const Ref<MultiMesh> &p_multimesh); Ref<MultiMesh> get_multimesh() const; - virtual Rect3 get_aabb() const; + virtual AABB get_aabb() const; MultiMeshInstance(); ~MultiMeshInstance(); diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index 4e19214c59..915a10328b 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -31,9 +31,9 @@ #include "scene/resources/surface_tool.h" #include "servers/visual_server.h" -Rect3 Particles::get_aabb() const { +AABB Particles::get_aabb() const { - return Rect3(); + return AABB(); } PoolVector<Face3> Particles::get_faces(uint32_t p_usage_flags) const { @@ -82,7 +82,7 @@ void Particles::set_randomness_ratio(float p_ratio) { randomness_ratio = p_ratio; VS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio); } -void Particles::set_visibility_aabb(const Rect3 &p_aabb) { +void Particles::set_visibility_aabb(const AABB &p_aabb) { visibility_aabb = p_aabb; VS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb); @@ -140,7 +140,7 @@ float Particles::get_randomness_ratio() const { return randomness_ratio; } -Rect3 Particles::get_visibility_aabb() const { +AABB Particles::get_visibility_aabb() const { return visibility_aabb; } @@ -252,7 +252,7 @@ void Particles::restart() { VisualServer::get_singleton()->particles_restart(particles); } -Rect3 Particles::capture_aabb() const { +AABB Particles::capture_aabb() const { return VS::get_singleton()->particles_get_current_aabb(particles); } @@ -335,7 +335,7 @@ void Particles::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); ADD_GROUP("Drawing", ""); - ADD_PROPERTY(PropertyInfo(Variant::RECT3, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb"); + ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates"); ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,View Depth"), "set_draw_order", "get_draw_order"); ADD_GROUP("Process Material", ""); @@ -367,7 +367,7 @@ Particles::Particles() { set_pre_process_time(0); set_explosiveness_ratio(0); set_randomness_ratio(0); - set_visibility_aabb(Rect3(Vector3(-4, -4, -4), Vector3(8, 8, 8))); + set_visibility_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8))); set_use_local_coordinates(true); set_draw_passes(1); set_draw_order(DRAW_ORDER_INDEX); @@ -642,7 +642,7 @@ void ParticlesMaterial::_update_shader() { code += " float angle1 = (rand_from_seed(alt_seed)*2.0-1.0)*spread/180.0*3.1416;\n"; code += " vec3 rot = vec3( cos(angle1), sin(angle1),0.0 );\n"; - code += " VELOCITY = (rot*initial_linear_velocity+rot*initial_linear_velocity_random*rand_from_seed(alt_seed));\n"; + code += " VELOCITY = rot*initial_linear_velocity*mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } else { //initiate velocity spread in 3D @@ -650,7 +650,7 @@ void ParticlesMaterial::_update_shader() { code += " float angle2 = rand_from_seed(alt_seed)*20.0*3.1416; // make it more random like\n"; code += " vec3 rot_xz = vec3( sin(angle1), 0.0, cos(angle1) );\n"; code += " vec3 rot = vec3( cos(angle2)*rot_xz.x,sin(angle2)*rot_xz.x, rot_xz.z);\n"; - code += " VELOCITY = (rot*initial_linear_velocity+rot*initial_linear_velocity_random*rand_from_seed(alt_seed));\n"; + code += " VELOCITY = rot*initial_linear_velocity*mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } code += " float base_angle = (initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n"; @@ -761,11 +761,11 @@ void ParticlesMaterial::_update_shader() { code += " force += length(diff) > 0.0 ? normalize(diff) * (radial_accel+tex_radial_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random) : vec3(0.0);\n"; code += " //apply tangential acceleration;\n"; if (flags[FLAG_DISABLE_Z]) { - code += " force += length(diff.yx) > 0.0 ? vec3(normalize(diff.yx * vec2(-1.0,1.0)),0.0) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random)) : vec3(0.0);\n"; + code += " force += length(diff.yx) > 0.0 ? vec3(normalize(diff.yx * vec2(-1.0,1.0)),0.0) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),tangent_accel_random)) : vec3(0.0);\n"; } else { code += " vec3 crossDiff = cross(normalize(diff),normalize(gravity));\n"; - code += " force += length(crossDiff) > 0.0 ? normalize(crossDiff) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random)) : vec3(0.0);\n"; + code += " force += length(crossDiff) > 0.0 ? normalize(crossDiff) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),tangent_accel_random)) : vec3(0.0);\n"; } code += " //apply attractor forces\n"; code += " VELOCITY += force * DELTA;\n"; diff --git a/scene/3d/particles.h b/scene/3d/particles.h index e3109f470f..30080360bb 100644 --- a/scene/3d/particles.h +++ b/scene/3d/particles.h @@ -65,7 +65,7 @@ private: float explosiveness_ratio; float randomness_ratio; float speed_scale; - Rect3 visibility_aabb; + AABB visibility_aabb; bool local_coords; int fixed_fps; bool fractional_delta; @@ -82,7 +82,7 @@ protected: virtual void _validate_property(PropertyInfo &property) const; public: - Rect3 get_aabb() const; + AABB get_aabb() const; PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; void set_emitting(bool p_emitting); @@ -92,7 +92,7 @@ public: void set_pre_process_time(float p_time); void set_explosiveness_ratio(float p_ratio); void set_randomness_ratio(float p_ratio); - void set_visibility_aabb(const Rect3 &p_aabb); + void set_visibility_aabb(const AABB &p_aabb); void set_use_local_coordinates(bool p_enable); void set_process_material(const Ref<Material> &p_material); void set_speed_scale(float p_scale); @@ -104,7 +104,7 @@ public: float get_pre_process_time() const; float get_explosiveness_ratio() const; float get_randomness_ratio() const; - Rect3 get_visibility_aabb() const; + AABB get_visibility_aabb() const; bool get_use_local_coordinates() const; Ref<Material> get_process_material() const; float get_speed_scale() const; @@ -128,7 +128,7 @@ public: void restart(); - Rect3 capture_aabb() const; + AABB capture_aabb() const; Particles(); ~Particles(); }; diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 4c661e6a88..4e06b272e2 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -938,7 +938,7 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_colli Transform gt = get_global_transform(); PhysicsServer::MotionResult result; - bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, margin, &result); + bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, &result); if (colliding) { r_collision.collider_metadata = result.collider_metadata; @@ -988,12 +988,15 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve on_floor = true; floor_velocity = collision.collider_vel; - /*if (collision.travel.length() < 0.01 && ABS((lv.x - floor_velocity.x)) < p_slope_stop_min_velocity) { + Vector3 rel_v = lv - floor_velocity; + Vector3 hv = rel_v - p_floor_direction * p_floor_direction.dot(rel_v); + + if (collision.travel.length() < 0.05 && hv.length() < p_slope_stop_min_velocity) { Transform gt = get_global_transform(); - gt.elements[2] -= collision.travel; + gt.origin -= collision.travel; set_global_transform(gt); - return Vector3(); - }*/ + return floor_velocity - p_floor_direction * p_floor_direction.dot(floor_velocity); + } } else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle)) { //ceiling on_ceiling = true; } else { @@ -1041,12 +1044,13 @@ bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion) ERR_FAIL_COND_V(!is_inside_tree(), false); - return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, margin); + return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion); } void KinematicBody::set_safe_margin(float p_margin) { margin = p_margin; + PhysicsServer::get_singleton()->body_set_kinematic_safe_margin(get_rid(), margin); } float KinematicBody::get_safe_margin() const { diff --git a/scene/3d/portal.cpp b/scene/3d/portal.cpp index 6c14f7dbc9..4fde29aab9 100644 --- a/scene/3d/portal.cpp +++ b/scene/3d/portal.cpp @@ -98,7 +98,7 @@ void Portal::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::REAL, "connect_range", PROPERTY_HINT_RANGE, "0.1,4096,0.01")); } -Rect3 Portal::get_aabb() const { +AABB Portal::get_aabb() const { return aabb; } diff --git a/scene/3d/portal.h b/scene/3d/portal.h index 6de3df8553..4ea208a718 100644 --- a/scene/3d/portal.h +++ b/scene/3d/portal.h @@ -53,7 +53,7 @@ class Portal : public VisualInstance { Color disabled_color; float connect_range; - Rect3 aabb; + AABB aabb; protected: bool _set(const StringName &p_name, const Variant &p_value); @@ -63,7 +63,7 @@ protected: static void _bind_methods(); public: - virtual Rect3 get_aabb() const; + virtual AABB get_aabb() const; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; void set_enabled(bool p_enabled); diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index 46b105cd21..0e575ec152 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -178,9 +178,9 @@ ReflectionProbe::UpdateMode ReflectionProbe::get_update_mode() const { return update_mode; } -Rect3 ReflectionProbe::get_aabb() const { +AABB ReflectionProbe::get_aabb() const { - Rect3 aabb; + AABB aabb; aabb.position = -origin_offset; aabb.size = origin_offset + extents; return aabb; diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h index 7c328a8f16..26f17fdcf9 100644 --- a/scene/3d/reflection_probe.h +++ b/scene/3d/reflection_probe.h @@ -101,7 +101,7 @@ public: void set_update_mode(UpdateMode p_mode); UpdateMode get_update_mode() const; - virtual Rect3 get_aabb() const; + virtual AABB get_aabb() const; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; ReflectionProbe(); diff --git a/scene/3d/room_instance.cpp b/scene/3d/room_instance.cpp index 439b6bfdf8..47a7b8bfb9 100644 --- a/scene/3d/room_instance.cpp +++ b/scene/3d/room_instance.cpp @@ -66,12 +66,12 @@ void Room::_notification(int p_what) { } } -Rect3 Room::get_aabb() const { +AABB Room::get_aabb() const { if (room.is_null()) - return Rect3(); + return AABB(); - return Rect3(); + return AABB(); } PoolVector<Face3> Room::get_faces(uint32_t p_usage_flags) const { diff --git a/scene/3d/room_instance.h b/scene/3d/room_instance.h index b9a64b6670..3069ea2eba 100644 --- a/scene/3d/room_instance.h +++ b/scene/3d/room_instance.h @@ -71,7 +71,7 @@ public: NOTIFICATION_AREA_CHANGED = 60 }; - virtual Rect3 get_aabb() const; + virtual AABB get_aabb() const; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; void set_room(const Ref<RoomBounds> &p_room); diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 0dfd80ca90..588aa2881a 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -233,7 +233,7 @@ void Spatial::set_transform(const Transform &p_transform) { data.dirty |= DIRTY_VECTORS; _change_notify("translation"); _change_notify("rotation"); - _change_notify("rotation_deg"); + _change_notify("rotation_degrees"); _change_notify("scale"); _propagate_transform_changed(this); if (data.notify_local_transform) { @@ -327,17 +327,11 @@ void Spatial::set_rotation(const Vector3 &p_euler_rad) { } } -void Spatial::set_rotation_in_degrees(const Vector3 &p_euler_deg) { +void Spatial::set_rotation_degrees(const Vector3 &p_euler_deg) { set_rotation(p_euler_deg * Math_PI / 180.0); } -void Spatial::_set_rotation_deg(const Vector3 &p_euler_deg) { - - WARN_PRINT("Deprecated method Spatial._set_rotation_deg(): This method was renamed to set_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted."); - set_rotation_in_degrees(p_euler_deg); -} - void Spatial::set_scale(const Vector3 &p_scale) { if (data.dirty & DIRTY_VECTORS) { @@ -370,19 +364,11 @@ Vector3 Spatial::get_rotation() const { return data.rotation; } -Vector3 Spatial::get_rotation_in_degrees() const { +Vector3 Spatial::get_rotation_degrees() const { return get_rotation() * 180.0 / Math_PI; } -// Kept for compatibility after rename to set_rotd. -// Could be removed after a couple releases. -Vector3 Spatial::_get_rotation_deg() const { - - WARN_PRINT("Deprecated method Spatial._get_rotation_deg(): This method was renamed to get_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted."); - return get_rotation_in_degrees(); -} - Vector3 Spatial::get_scale() const { if (data.dirty & DIRTY_VECTORS) { @@ -691,10 +677,10 @@ void Spatial::_bind_methods() { ClassDB::bind_method(D_METHOD("get_transform"), &Spatial::get_transform); ClassDB::bind_method(D_METHOD("set_translation", "translation"), &Spatial::set_translation); ClassDB::bind_method(D_METHOD("get_translation"), &Spatial::get_translation); - ClassDB::bind_method(D_METHOD("set_rotation", "rotation_rad"), &Spatial::set_rotation); + ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Spatial::set_rotation); ClassDB::bind_method(D_METHOD("get_rotation"), &Spatial::get_rotation); - ClassDB::bind_method(D_METHOD("set_rotation_deg", "rotation_deg"), &Spatial::set_rotation_in_degrees); - ClassDB::bind_method(D_METHOD("get_rotation_deg"), &Spatial::get_rotation_in_degrees); + ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Spatial::set_rotation_degrees); + ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Spatial::get_rotation_degrees); ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Spatial::set_scale); ClassDB::bind_method(D_METHOD("get_scale"), &Spatial::get_scale); ClassDB::bind_method(D_METHOD("set_global_transform", "global"), &Spatial::set_global_transform); @@ -705,10 +691,6 @@ void Spatial::_bind_methods() { ClassDB::bind_method(D_METHOD("is_set_as_toplevel"), &Spatial::is_set_as_toplevel); ClassDB::bind_method(D_METHOD("get_world"), &Spatial::get_world); - // TODO: Obsolete those two methods (old name) properly (GH-4397) - ClassDB::bind_method(D_METHOD("_set_rotation_deg", "rotation_deg"), &Spatial::_set_rotation_deg); - ClassDB::bind_method(D_METHOD("_get_rotation_deg"), &Spatial::_get_rotation_deg); - #ifdef TOOLS_ENABLED ClassDB::bind_method(D_METHOD("_update_gizmo"), &Spatial::_update_gizmo); #endif @@ -764,7 +746,7 @@ void Spatial::_bind_methods() { ADD_PROPERTYNZ(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform"); ADD_PROPERTYNZ(PropertyInfo(Variant::TRANSFORM, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "translation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_translation", "get_translation"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_deg", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_deg", "get_rotation_deg"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_NONE, "", 0), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale"); ADD_GROUP("Visibility", ""); diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index b912d1f906..8f53b4a066 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -106,10 +106,6 @@ class Spatial : public Node { void _notify_dirty(); void _propagate_transform_changed(Spatial *p_origin); - // Deprecated, should be removed in a future version. - void _set_rotation_deg(const Vector3 &p_euler_deg); - Vector3 _get_rotation_deg() const; - void _propagate_visibility_changed(); protected: @@ -136,12 +132,12 @@ public: void set_translation(const Vector3 &p_translation); void set_rotation(const Vector3 &p_euler_rad); - void set_rotation_in_degrees(const Vector3 &p_euler_deg); + void set_rotation_degrees(const Vector3 &p_euler_deg); void set_scale(const Vector3 &p_scale); Vector3 get_translation() const; Vector3 get_rotation() const; - Vector3 get_rotation_in_degrees() const; + Vector3 get_rotation_degrees() const; Vector3 get_scale() const; void set_transform(const Transform &p_transform); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 49a3205f21..18ebc22c8b 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -188,7 +188,7 @@ void SpriteBase3D::_queue_update() { call_deferred(SceneStringNames::get_singleton()->_im_update); } -Rect3 SpriteBase3D::get_aabb() const { +AABB SpriteBase3D::get_aabb() const { return aabb; } @@ -407,7 +407,7 @@ void Sprite3D::_draw() { } } - Rect3 aabb; + AABB aabb; for (int i = 0; i < 4; i++) { VS::get_singleton()->immediate_normal(immediate, normal); @@ -698,7 +698,7 @@ void AnimatedSprite3D::_draw() { } } - Rect3 aabb; + AABB aabb; for (int i = 0; i < 4; i++) { VS::get_singleton()->immediate_normal(immediate, normal); diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 1165392cb2..d18553a504 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -71,7 +71,7 @@ private: Vector3::Axis axis; float pixel_size; - Rect3 aabb; + AABB aabb; RID immediate; @@ -87,7 +87,7 @@ protected: void _notification(int p_what); static void _bind_methods(); virtual void _draw() = 0; - _FORCE_INLINE_ void set_aabb(const Rect3 &p_aabb) { aabb = p_aabb; } + _FORCE_INLINE_ void set_aabb(const AABB &p_aabb) { aabb = p_aabb; } _FORCE_INLINE_ RID &get_immediate() { return immediate; } void _queue_update(); @@ -130,7 +130,7 @@ public: virtual Rect2 get_item_rect() const = 0; - virtual Rect3 get_aabb() const; + virtual AABB get_aabb() const; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; SpriteBase3D(); diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp index e60b32a92a..47144c4b78 100644 --- a/scene/3d/visibility_notifier.cpp +++ b/scene/3d/visibility_notifier.cpp @@ -60,7 +60,7 @@ void VisibilityNotifier::_exit_camera(Camera *p_camera) { } } -void VisibilityNotifier::set_aabb(const Rect3 &p_aabb) { +void VisibilityNotifier::set_aabb(const AABB &p_aabb) { if (aabb == p_aabb) return; @@ -74,7 +74,7 @@ void VisibilityNotifier::set_aabb(const Rect3 &p_aabb) { update_gizmo(); } -Rect3 VisibilityNotifier::get_aabb() const { +AABB VisibilityNotifier::get_aabb() const { return aabb; } @@ -108,7 +108,7 @@ void VisibilityNotifier::_bind_methods() { ClassDB::bind_method(D_METHOD("get_aabb"), &VisibilityNotifier::get_aabb); ClassDB::bind_method(D_METHOD("is_on_screen"), &VisibilityNotifier::is_on_screen); - ADD_PROPERTY(PropertyInfo(Variant::RECT3, "aabb"), "set_aabb", "get_aabb"); + ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb"), "set_aabb", "get_aabb"); ADD_SIGNAL(MethodInfo("camera_entered", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"))); ADD_SIGNAL(MethodInfo("camera_exited", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"))); @@ -118,7 +118,7 @@ void VisibilityNotifier::_bind_methods() { VisibilityNotifier::VisibilityNotifier() { - aabb = Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2)); + aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); set_notify_transform(true); } diff --git a/scene/3d/visibility_notifier.h b/scene/3d/visibility_notifier.h index 0b83e0534e..fc06cf5aec 100644 --- a/scene/3d/visibility_notifier.h +++ b/scene/3d/visibility_notifier.h @@ -39,7 +39,7 @@ class VisibilityNotifier : public Spatial { Set<Camera *> cameras; - Rect3 aabb; + AABB aabb; protected: virtual void _screen_enter() {} @@ -53,8 +53,8 @@ protected: void _exit_camera(Camera *p_camera); public: - void set_aabb(const Rect3 &p_aabb); - Rect3 get_aabb() const; + void set_aabb(const AABB &p_aabb); + AABB get_aabb() const; bool is_on_screen() const; VisibilityNotifier(); diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index fa35d982eb..b92e7ead04 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -33,7 +33,7 @@ #include "servers/visual_server.h" #include "skeleton.h" -Rect3 VisualInstance::get_transformed_aabb() const { +AABB VisualInstance::get_transformed_aabb() const { return get_global_transform().xform(get_aabb()); } diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index c405236d2c..5827f1e1fb 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -62,10 +62,10 @@ public: }; RID get_instance() const; - virtual Rect3 get_aabb() const = 0; + virtual AABB get_aabb() const = 0; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const = 0; - virtual Rect3 get_transformed_aabb() const; // helper + virtual AABB get_transformed_aabb() const; // helper void set_base(const RID &p_base); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 80b7748078..6be3ff88d9 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -545,7 +545,14 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, f } else { - next_pos = Math::fposmod(next_pos, len); + float looped_next_pos = Math::fposmod(next_pos, len); + if (looped_next_pos == 0 && next_pos != 0) { + // Loop multiples of the length to it, rather than 0 + // so state at time=length is previewable in the editor + next_pos = len; + } else { + next_pos = looped_next_pos; + } } cd.pos = next_pos; diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index e0508cf147..40d06dc756 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -416,10 +416,10 @@ Variant Tween::_run_equation(InterpolateData &p_data) { result = r; } break; - case Variant::RECT3: { - Rect3 i = initial_val; - Rect3 d = delta_val; - Rect3 r; + case Variant::AABB: { + AABB i = initial_val; + AABB d = delta_val; + AABB r; APPLY_EQUATION(position.x); APPLY_EQUATION(position.y); @@ -956,10 +956,10 @@ bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final case Variant::QUAT: delta_val = final_val.operator Quat() - initial_val.operator Quat(); break; - case Variant::RECT3: { - Rect3 i = initial_val; - Rect3 f = final_val; - delta_val = Rect3(f.position - i.position, f.size - i.size); + case Variant::AABB: { + AABB i = initial_val; + AABB f = final_val; + delta_val = AABB(f.position - i.position, f.size - i.size); } break; case Variant::TRANSFORM: { Transform i = initial_val; diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp index 058b162e83..08b01c6a4c 100644 --- a/scene/audio/audio_player.cpp +++ b/scene/audio/audio_player.cpp @@ -31,20 +31,7 @@ #include "engine.h" -void AudioStreamPlayer::_mix_audio() { - - if (!stream_playback.is_valid()) { - return; - } - - if (!active) { - return; - } - - if (setseek >= 0.0) { - stream_playback->start(setseek); - setseek = -1.0; //reset seek - } +void AudioStreamPlayer::_mix_internal(bool p_fadeout) { int bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus); @@ -52,19 +39,24 @@ void AudioStreamPlayer::_mix_audio() { AudioFrame *buffer = mix_buffer.ptr(); int buffer_size = mix_buffer.size(); + if (p_fadeout) { + buffer_size = MIN(buffer_size, 16); //short fadeout ramp + } + //mix stream_playback->mix(buffer, 1.0, buffer_size); //multiply volume interpolating to avoid clicks if this changes + float target_volume = p_fadeout ? -80.0 : volume_db; float vol = Math::db2linear(mix_volume_db); - float vol_inc = (Math::db2linear(volume_db) - vol) / float(buffer_size); + float vol_inc = (Math::db2linear(target_volume) - vol) / float(buffer_size); for (int i = 0; i < buffer_size; i++) { buffer[i] *= vol; vol += vol_inc; } //set volume for next mix - mix_volume_db = volume_db; + mix_volume_db = target_volume; AudioFrame *targets[4] = { NULL, NULL, NULL, NULL }; @@ -95,6 +87,30 @@ void AudioStreamPlayer::_mix_audio() { } } +void AudioStreamPlayer::_mix_audio() { + + if (!stream_playback.is_valid()) { + return; + } + + if (!active) { + return; + } + + if (setseek >= 0.0) { + if (stream_playback->is_playing()) { + + //fade out to avoid pops + _mix_internal(true); + } + stream_playback->start(setseek); + setseek = -1.0; //reset seek + mix_volume_db = volume_db; //reset ramp + } + + _mix_internal(false); +} + void AudioStreamPlayer::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { @@ -163,7 +179,7 @@ float AudioStreamPlayer::get_volume_db() const { void AudioStreamPlayer::play(float p_from_pos) { if (stream_playback.is_valid()) { - mix_volume_db = volume_db; //reset volume ramp + //mix_volume_db = volume_db; do not reset volume ramp here, can cause clicks setseek = p_from_pos; active = true; set_process_internal(true); diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h index 4bfc44730d..6e9d623433 100644 --- a/scene/audio/audio_player.h +++ b/scene/audio/audio_player.h @@ -59,6 +59,7 @@ private: MixTarget mix_target; + void _mix_internal(bool p_fadeout); void _mix_audio(); static void _mix_audios(void *self) { reinterpret_cast<AudioStreamPlayer *>(self)->_mix_audio(); } diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp index e68159e27f..77fdedd5e5 100644 --- a/scene/gui/check_button.cpp +++ b/scene/gui/check_button.cpp @@ -32,6 +32,23 @@ #include "print_string.h" #include "servers/visual_server.h" +Size2 CheckButton::get_minimum_size() const { + + Size2 minsize = Button::get_minimum_size(); + + Ref<Texture> on = Control::get_icon("on"); + Ref<Texture> off = Control::get_icon("off"); + Size2 tex_size = Size2(0, 0); + if (!on.is_null()) + tex_size = Size2(on->get_width(), on->get_height()); + if (!off.is_null()) + tex_size = Size2(MAX(tex_size.width, off->get_width()), MAX(tex_size.height, off->get_height())); + minsize += Size2(tex_size.width + get_constant("hseparation"), 0); + minsize.height = MAX(minsize.height, tex_size.height); + + return get_stylebox("normal")->get_minimum_size() + minsize; +} + void CheckButton::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { @@ -41,9 +58,11 @@ void CheckButton::_notification(int p_what) { Ref<Texture> on = Control::get_icon("on"); Ref<Texture> off = Control::get_icon("off"); + Ref<StyleBox> sb = get_stylebox("normal"); + Size2 sb_ofs = Size2(sb->get_margin(MARGIN_RIGHT), sb->get_margin(MARGIN_TOP)); Vector2 ofs; - ofs.x = get_size().width - on->get_width(); - ofs.y = int((get_size().height - on->get_height()) / 2); + ofs.x = get_minimum_size().width - (on->get_width() + sb_ofs.width); + ofs.y = sb_ofs.height; if (is_pressed()) on->draw(ci, ofs); diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h index af3b80fe04..eb68943fe7 100644 --- a/scene/gui/check_button.h +++ b/scene/gui/check_button.h @@ -39,6 +39,7 @@ class CheckButton : public Button { GDCLASS(CheckButton, Button); protected: + virtual Size2 get_minimum_size() const; void _notification(int p_what); public: diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 54a58159ac..adca78d1d4 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -45,7 +45,7 @@ #endif #include <stdio.h> -Variant Control::edit_get_state() const { +Dictionary Control::_edit_get_state() const { Dictionary s; s["rect"] = get_rect(); @@ -59,22 +59,78 @@ Variant Control::edit_get_state() const { s["anchors"] = anchors; return s; } -void Control::edit_set_state(const Variant &p_state) { +void Control::_edit_set_state(const Dictionary &p_state) { - Dictionary s = p_state; + Dictionary state = p_state; - Rect2 state = s["rect"]; - set_position(state.position); - set_size(state.size); - set_rotation(s["rotation"]); - set_scale(s["scale"]); - Array anchors = s["anchors"]; + Rect2 rect = state["rect"]; + set_position(rect.position); + set_size(rect.size); + set_rotation(state["rotation"]); + set_scale(state["scale"]); + Array anchors = state["anchors"]; set_anchor(MARGIN_LEFT, anchors[0]); set_anchor(MARGIN_TOP, anchors[1]); set_anchor(MARGIN_RIGHT, anchors[2]); set_anchor(MARGIN_BOTTOM, anchors[3]); } +void Control::_edit_set_position(const Point2 &p_position) { + set_position(p_position); +}; + +Point2 Control::_edit_get_position() const { + return get_position(); +}; + +void Control::_edit_set_rect(const Rect2 &p_edit_rect) { + + Transform2D xform = _get_internal_transform(); + + Vector2 new_pos = xform.basis_xform(p_edit_rect.position); + + Vector2 pos = get_position() + new_pos; + + Rect2 new_rect = get_rect(); + new_rect.position = pos.snapped(Vector2(1, 1)); + new_rect.size = p_edit_rect.size.snapped(Vector2(1, 1)); + + set_position(new_rect.position); + set_size(new_rect.size); +} + +Rect2 Control::_edit_get_rect() const { + return Rect2(Point2(), get_size()); +} + +bool Control::_edit_use_rect() const { + return true; +} + +void Control::_edit_set_rotation(float p_rotation) { + set_rotation(p_rotation); +} + +float Control::_edit_get_rotation() const { + return get_rotation(); +} + +bool Control::_edit_use_rotation() const { + return true; +} + +void Control::_edit_set_pivot(const Point2 &p_pivot) { + set_pivot_offset(p_pivot); +} + +Point2 Control::_edit_get_pivot() const { + return get_pivot_offset(); +} + +bool Control::_edit_use_pivot() const { + return true; +} + void Control::set_custom_minimum_size(const Size2 &p_custom) { if (p_custom == data.custom_minimum_size) @@ -96,7 +152,7 @@ Size2 Control::get_combined_minimum_size() const { return minsize; } -Size2 Control::edit_get_minimum_size() const { +Size2 Control::_edit_get_minimum_size() const { return get_combined_minimum_size(); } @@ -110,23 +166,6 @@ Transform2D Control::_get_internal_transform() const { return offset.affine_inverse() * (rot_scale * offset); } -void Control::edit_set_rect(const Rect2 &p_edit_rect) { - - Transform2D xform = _get_internal_transform(); - - // xform[2] += get_position(); - - Vector2 new_pos = xform.basis_xform(p_edit_rect.position); - - Vector2 pos = get_position() + new_pos; - - Rect2 new_rect = get_rect(); - new_rect.position = pos.snapped(Vector2(1, 1)); - new_rect.size = p_edit_rect.size.snapped(Vector2(1, 1)); - - set_position(new_rect.position); - set_size(new_rect.size); -} bool Control::_set(const StringName &p_name, const Variant &p_value) { @@ -1210,7 +1249,7 @@ Size2 Control::get_parent_area_size() const { if (data.parent_canvas_item) { - parent_size = data.parent_canvas_item->get_item_rect().size; + parent_size = data.parent_canvas_item->_edit_get_rect().size; } else { parent_size = get_viewport()->get_visible_rect().size; @@ -1289,7 +1328,7 @@ float Control::_get_parent_range(int p_idx) const { } if (data.parent_canvas_item) { - return data.parent_canvas_item->get_item_rect().size[p_idx & 1]; + return data.parent_canvas_item->_edit_get_rect().size[p_idx & 1]; } else { return get_viewport()->get_visible_rect().size[p_idx & 1]; } @@ -1751,11 +1790,6 @@ Rect2 Control::get_rect() const { return Rect2(get_position(), get_size()); } -Rect2 Control::get_item_rect() const { - - return Rect2(Point2(), get_size()); -} - void Control::add_icon_override(const StringName &p_name, const Ref<Texture> &p_icon) { ERR_FAIL_COND(p_icon.is_null()); @@ -1847,6 +1881,25 @@ Control *Control::find_next_valid_focus() const { while (true) { + // If the focus property is manually overwritten, attempt to use it. + + if (!data.focus_next.is_empty()) { + Node *n = get_node(data.focus_next); + if (n) { + from = Object::cast_to<Control>(n); + + if (!from) { + + ERR_EXPLAIN("Next focus node is not a control: " + n->get_name()); + ERR_FAIL_V(NULL); + } + } else { + return NULL; + } + if (from->is_visible() && from->get_focus_mode() != FOCUS_NONE) + return from; + } + // find next child Control *next_child = NULL; @@ -1926,6 +1979,25 @@ Control *Control::find_prev_valid_focus() const { while (true) { + // If the focus property is manually overwritten, attempt to use it. + + if (!data.focus_prev.is_empty()) { + Node *n = get_node(data.focus_prev); + if (n) { + from = Object::cast_to<Control>(n); + + if (!from) { + + ERR_EXPLAIN("Prev focus node is not a control: " + n->get_name()); + ERR_FAIL_V(NULL); + } + } else { + return NULL; + } + if (from->is_visible() && from->get_focus_mode() != FOCUS_NONE) + return from; + } + // find prev child Control *prev_child = NULL; @@ -2157,6 +2229,26 @@ NodePath Control::get_focus_neighbour(Margin p_margin) const { return data.focus_neighbour[p_margin]; } +void Control::set_focus_next(const NodePath &p_next) { + + data.focus_next = p_next; +} + +NodePath Control::get_focus_next() const { + + return data.focus_next; +} + +void Control::set_focus_previous(const NodePath &p_prev) { + + data.focus_prev = p_prev; +} + +NodePath Control::get_focus_previous() const { + + return data.focus_prev; +} + #define MAX_NEIGHBOUR_SEARCH_COUNT 512 Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) { @@ -2172,7 +2264,7 @@ Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) { if (!c) { - ERR_EXPLAIN("Next focus node is not a control: " + n->get_name()); + ERR_EXPLAIN("Neighbour focus node is not a control: " + n->get_name()); ERR_FAIL_V(NULL); } } else { @@ -2196,7 +2288,7 @@ Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) { Point2 points[4]; Transform2D xform = get_global_transform(); - Rect2 rect = get_item_rect(); + Rect2 rect = _edit_get_rect(); points[0] = xform.xform(rect.position); points[1] = xform.xform(rect.position + Point2(rect.size.x, 0)); @@ -2255,7 +2347,7 @@ void Control::_window_find_focus_neighbour(const Vector2 &p_dir, Node *p_at, con Point2 points[4]; Transform2D xform = c->get_global_transform(); - Rect2 rect = c->get_item_rect(); + Rect2 rect = c->_edit_get_rect(); points[0] = xform.xform(rect.position); points[1] = xform.xform(rect.position + Point2(rect.size.x, 0)); @@ -2416,24 +2508,14 @@ float Control::get_rotation() const { return data.rotation; } -void Control::set_rotation_deg(float p_degrees) { +void Control::set_rotation_degrees(float p_degrees) { set_rotation(Math::deg2rad(p_degrees)); } -float Control::get_rotation_deg() const { +float Control::get_rotation_degrees() const { return Math::rad2deg(get_rotation()); } -// Kept for compatibility after rename to {s,g}et_rotation_deg. -// Could be removed after a couple releases. -void Control::_set_rotation_deg(float p_degrees) { - WARN_PRINT("Deprecated method Control._set_rotation_deg(): This method was renamed to set_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted."); - set_rotation_deg(p_degrees); -} -float Control::_get_rotation_deg() const { - WARN_PRINT("Deprecated method Control._get_rotation_deg(): This method was renamed to get_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted."); - return get_rotation_deg(); -} //needed to update the control if the font changes.. void Control::_ref_font(Ref<Font> p_sc) { @@ -2606,9 +2688,7 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_custom_minimum_size", "size"), &Control::set_custom_minimum_size); ClassDB::bind_method(D_METHOD("set_global_position", "position"), &Control::set_global_position); ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Control::set_rotation); - ClassDB::bind_method(D_METHOD("set_rotation_deg", "degrees"), &Control::set_rotation_deg); - // TODO: Obsolete this method (old name) properly (GH-4397) - ClassDB::bind_method(D_METHOD("_set_rotation_deg", "degrees"), &Control::_set_rotation_deg); + ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Control::set_rotation_degrees); ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale); ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset); ClassDB::bind_method(D_METHOD("get_margin", "margin"), &Control::get_margin); @@ -2617,9 +2697,7 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("get_position"), &Control::get_position); ClassDB::bind_method(D_METHOD("get_size"), &Control::get_size); ClassDB::bind_method(D_METHOD("get_rotation"), &Control::get_rotation); - ClassDB::bind_method(D_METHOD("get_rotation_deg"), &Control::get_rotation_deg); - // TODO: Obsolete this method (old name) properly (GH-4397) - ClassDB::bind_method(D_METHOD("_get_rotation_deg"), &Control::_get_rotation_deg); + ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Control::get_rotation_degrees); ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale); ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset); ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size); @@ -2691,6 +2769,12 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_focus_neighbour", "margin", "neighbour"), &Control::set_focus_neighbour); ClassDB::bind_method(D_METHOD("get_focus_neighbour", "margin"), &Control::get_focus_neighbour); + ClassDB::bind_method(D_METHOD("set_focus_next", "next"), &Control::set_focus_next); + ClassDB::bind_method(D_METHOD("get_focus_next"), &Control::get_focus_next); + + ClassDB::bind_method(D_METHOD("set_focus_previous", "previous"), &Control::set_focus_previous); + ClassDB::bind_method(D_METHOD("get_focus_previous"), &Control::get_focus_previous); + ClassDB::bind_method(D_METHOD("force_drag", "data", "preview"), &Control::force_drag); ClassDB::bind_method(D_METHOD("set_mouse_filter", "filter"), &Control::set_mouse_filter); @@ -2738,7 +2822,7 @@ void Control::_bind_methods() { ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_size", "get_size"); ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size"); - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_deg", "get_rotation_deg"); + ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_degrees", "get_rotation_degrees"); ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale"); ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset"); ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); @@ -2751,6 +2835,8 @@ void Control::_bind_methods() { ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_top"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_TOP); ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_right"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_RIGHT); ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_bottom"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_BOTTOM); + ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_next"), "set_focus_next", "get_focus_next"); + ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_previous"), "set_focus_previous", "get_focus_previous"); ADD_GROUP("Mouse", "mouse_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter"); diff --git a/scene/gui/control.h b/scene/gui/control.h index 5b146b4454..92d1c969fc 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -191,6 +191,8 @@ private: ObjectID modal_prev_focus_owner; NodePath focus_neighbour[4]; + NodePath focus_next; + NodePath focus_prev; HashMap<StringName, Ref<Texture>, StringNameHasher> icon_override; HashMap<StringName, Ref<Shader>, StringNameHasher> shader_override; @@ -226,10 +228,6 @@ private: void _size_changed(); String _get_tooltip() const; - // Deprecated, should be removed in a future version. - void _set_rotation_deg(float p_degrees); - float _get_rotation_deg() const; - void _ref_font(Ref<Font> p_sc); void _unref_font(Ref<Font> p_sc); void _font_changed(); @@ -273,10 +271,25 @@ public: }; - virtual Variant edit_get_state() const; - virtual void edit_set_state(const Variant &p_state); - virtual void edit_set_rect(const Rect2 &p_edit_rect); - virtual Size2 edit_get_minimum_size() const; + virtual Dictionary _edit_get_state() const; + virtual void _edit_set_state(const Dictionary &p_state); + + virtual void _edit_set_position(const Point2 &p_position); + virtual Point2 _edit_get_position() const; + + virtual void _edit_set_rect(const Rect2 &p_edit_rect); + virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; + + virtual void _edit_set_rotation(float p_rotation); + virtual float _edit_get_rotation() const; + virtual bool _edit_use_rotation() const; + + virtual void _edit_set_pivot(const Point2 &p_pivot); + virtual Point2 _edit_get_pivot() const; + virtual bool _edit_use_pivot() const; + + virtual Size2 _edit_get_minimum_size() const; void accept_event(); @@ -332,9 +345,9 @@ public: Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the visual server void set_rotation(float p_radians); - void set_rotation_deg(float p_degrees); + void set_rotation_degrees(float p_degrees); float get_rotation() const; - float get_rotation_deg() const; + float get_rotation_degrees() const; void set_h_grow_direction(GrowDirection p_direction); GrowDirection get_h_grow_direction() const; @@ -378,6 +391,11 @@ public: void set_focus_neighbour(Margin p_margin, const NodePath &p_neighbour); NodePath get_focus_neighbour(Margin p_margin) const; + void set_focus_next(const NodePath &p_next); + NodePath get_focus_next() const; + void set_focus_previous(const NodePath &p_prev); + NodePath get_focus_previous() const; + Control *get_focus_owner() const; void set_mouse_filter(MouseFilter p_filter); @@ -424,7 +442,6 @@ public: CursorShape get_default_cursor_shape() const; virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const; - virtual Rect2 get_item_rect() const; virtual Transform2D get_transform() const; bool is_toplevel_control() const; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 623a110263..e9e9dcc859 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -754,7 +754,7 @@ void ItemList::_notification(int p_what) { int width = size.width - bg->get_minimum_size().width; if (scroll_bar->is_visible()) { - width -= mw + bg->get_margin(MARGIN_RIGHT); + width -= mw; } draw_style_box(bg, Rect2(Point2(), size)); @@ -1107,7 +1107,7 @@ void ItemList::_notification(int p_what) { } for (int i = 0; i < separators.size(); i++) { - draw_line(Vector2(bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), Vector2(size.width - bg->get_margin(MARGIN_RIGHT), base_ofs.y + separators[i]), guide_color); + draw_line(Vector2(bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), Vector2(width, base_ofs.y + separators[i]), guide_color); } } } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 40e2dba6c2..f7bf1cd9ea 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -48,7 +48,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { if (b.is_valid()) { - if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT) { + if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT && context_menu_enabled) { menu->set_position(get_global_transform().xform(get_local_mouse_position())); menu->set_size(Vector2(1, 1)); menu->popup(); @@ -1286,6 +1286,14 @@ void LineEdit::menu_option(int p_option) { } } +void LineEdit::set_context_menu_enabled(bool p_enable) { + context_menu_enabled = p_enable; +} + +bool LineEdit::is_context_menu_enabled() { + return context_menu_enabled; +} + PopupMenu *LineEdit::get_menu() const { return menu; } @@ -1301,6 +1309,7 @@ void LineEdit::set_expand_to_text_length(bool p_enabled) { expand_to_text_length = p_enabled; minimum_size_changed(); + set_window_pos(0); } bool LineEdit::get_expand_to_text_length() const { @@ -1395,6 +1404,8 @@ void LineEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("select", "from", "to"), &LineEdit::select, DEFVAL(0), DEFVAL(-1)); ClassDB::bind_method(D_METHOD("menu_option", "option"), &LineEdit::menu_option); ClassDB::bind_method(D_METHOD("get_menu"), &LineEdit::get_menu); + ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enable"), &LineEdit::set_context_menu_enabled); + ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &LineEdit::is_context_menu_enabled); ADD_SIGNAL(MethodInfo("text_changed", PropertyInfo(Variant::STRING, "text"))); ADD_SIGNAL(MethodInfo("text_entered", PropertyInfo(Variant::STRING, "text"))); @@ -1418,7 +1429,7 @@ void LineEdit::_bind_methods() { ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "max_length"), "set_max_length", "get_max_length"); ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "editable"), "set_editable", "is_editable"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "secret"), "set_secret", "is_secret"); - ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "expand_to_len"), "set_expand_to_text_length", "get_expand_to_text_length"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "expand_to_text_length"), "set_expand_to_text_length", "get_expand_to_text_length"); ADD_PROPERTY(PropertyInfo(Variant::INT, "focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_focus_mode", "get_focus_mode"); ADD_GROUP("Placeholder", "placeholder_"); ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "placeholder_text"), "set_placeholder", "get_placeholder"); @@ -1426,6 +1437,7 @@ void LineEdit::_bind_methods() { ADD_GROUP("Caret", "caret_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "cursor_set_blink_enabled", "cursor_get_blink_enabled"); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.1"), "cursor_set_blink_speed", "cursor_get_blink_speed"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled"); } LineEdit::LineEdit() { @@ -1455,6 +1467,7 @@ LineEdit::LineEdit() { caret_blink_timer->connect("timeout", this, "_toggle_draw_caret"); cursor_set_blink_enabled(false); + context_menu_enabled = true; menu = memnew(PopupMenu); add_child(menu); menu->add_item(TTR("Cut"), MENU_CUT, KEY_MASK_CMD | KEY_X); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index bece29a37d..c3a299c2f5 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -74,6 +74,7 @@ private: String ime_text; Point2 ime_selection; + bool context_menu_enabled; PopupMenu *menu; int cursor_pos; @@ -150,6 +151,8 @@ public: virtual void drop_data(const Point2 &p_point, const Variant &p_data); void menu_option(int p_option); + void set_context_menu_enabled(bool p_enable); + bool is_context_menu_enabled(); PopupMenu *get_menu() const; void select_all(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 798acb9d52..71e02cb2f7 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -877,11 +877,13 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { if (main->first_invalid_line < main->lines.size()) return; + int line = 0; + Item *item = NULL; + bool outside; + _find_click(main, m->get_position(), &item, &line, &outside); + if (selection.click) { - int line = 0; - Item *item = NULL; - _find_click(main, m->get_position(), &item, &line); if (!item) return; // do not update @@ -912,6 +914,22 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { selection.active = true; update(); } + + Variant meta; + if (item && !outside && _find_meta(item, &meta)) { + if (meta_hovering != item) { + if (meta_hovering) { + emit_signal("meta_hover_ended", current_meta); + } + meta_hovering = static_cast<ItemMeta *>(item); + current_meta = meta; + emit_signal("meta_hover_started", meta); + } + } else if (meta_hovering) { + emit_signal("meta_hover_ended", current_meta); + meta_hovering = NULL; + current_meta = false; + } } } @@ -1968,6 +1986,8 @@ void RichTextLabel::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color"); ADD_SIGNAL(MethodInfo("meta_clicked", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); + ADD_SIGNAL(MethodInfo("meta_hover_started", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); + ADD_SIGNAL(MethodInfo("meta_hover_ended", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); BIND_ENUM_CONSTANT(ALIGN_LEFT); BIND_ENUM_CONSTANT(ALIGN_CENTER); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index f9e37b1094..1096e3f650 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -225,6 +225,9 @@ private: Align default_align; + ItemMeta *meta_hovering; + Variant current_meta; + void _invalidate_current_line(ItemFrame *p_frame); void _validate_line_caches(ItemFrame *p_frame); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 1ad1e3f638..9022d67a4a 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -347,12 +347,11 @@ void ScrollContainer::update_scrollbars() { } else { v_scroll->show(); + v_scroll->set_max(min.height); + v_scroll->set_page(size.height - hmin.height); scroll.y = v_scroll->get_value(); } - v_scroll->set_max(min.height); - v_scroll->set_page(size.height - hmin.height); - if (!scroll_h || min.width <= size.width - vmin.width) { h_scroll->hide(); diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index 49823e18fc..1fb0f84223 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -142,91 +142,107 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (rb_pressing && mb.is_valid() && - !mb->is_pressed() && - mb->get_button_index() == BUTTON_LEFT) { + if (mb.is_valid()) { - if (rb_hover != -1) { - //pressed - emit_signal("right_button_pressed", rb_hover); + if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) { + + if (scrolling_enabled && buttons_visible) { + if (offset > 0) { + offset--; + update(); + } + } } - rb_pressing = false; - update(); - } + if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) { + if (scrolling_enabled && buttons_visible) { + if (missing_right) { + offset++; + update(); + } + } + } + + if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - if (cb_pressing && mb.is_valid() && - !mb->is_pressed() && - mb->get_button_index() == BUTTON_LEFT) { + if (rb_hover != -1) { + //pressed + emit_signal("right_button_pressed", rb_hover); + } - if (cb_hover != -1) { - //pressed - emit_signal("tab_close", cb_hover); + rb_pressing = false; + update(); } - cb_pressing = false; - update(); - } + if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - if (mb.is_valid() && - mb->is_pressed() && - mb->get_button_index() == BUTTON_LEFT) { + if (cb_hover != -1) { + //pressed + emit_signal("tab_close", cb_hover); + } - // clicks - Point2 pos(mb->get_position().x, mb->get_position().y); + cb_pressing = false; + update(); + } - if (buttons_visible) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - Ref<Texture> incr = get_icon("increment"); - Ref<Texture> decr = get_icon("decrement"); + // clicks + Point2 pos(mb->get_position().x, mb->get_position().y); - int limit = get_size().width - incr->get_width() - decr->get_width(); + if (buttons_visible) { - if (pos.x > limit + decr->get_width()) { - if (missing_right) { - offset++; - update(); - } - return; - } else if (pos.x > limit) { - if (offset > 0) { - offset--; - update(); + Ref<Texture> incr = get_icon("increment"); + Ref<Texture> decr = get_icon("decrement"); + + int limit = get_size().width - incr->get_width() - decr->get_width(); + + if (pos.x > limit + decr->get_width()) { + if (missing_right) { + offset++; + update(); + } + return; + } else if (pos.x > limit) { + if (offset > 0) { + offset--; + update(); + } + return; } - return; } - } - int found = -1; - for (int i = 0; i < tabs.size(); i++) { + int found = -1; + for (int i = 0; i < tabs.size(); i++) { - if (i < offset) - continue; + if (i < offset) + continue; - if (tabs[i].rb_rect.has_point(pos)) { - rb_pressing = true; - update(); - return; - } + if (tabs[i].rb_rect.has_point(pos)) { + rb_pressing = true; + update(); + return; + } - if (tabs[i].cb_rect.has_point(pos)) { - cb_pressing = true; - update(); - return; - } + if (tabs[i].cb_rect.has_point(pos)) { + cb_pressing = true; + update(); + return; + } - if (pos.x >= tabs[i].ofs_cache && pos.x < tabs[i].ofs_cache + tabs[i].size_cache) { - if (!tabs[i].disabled) { - found = i; + if (pos.x >= tabs[i].ofs_cache && pos.x < tabs[i].ofs_cache + tabs[i].size_cache) { + if (!tabs[i].disabled) { + found = i; + } + break; } - break; } - } - if (found != -1) { + if (found != -1) { - set_current_tab(found); - emit_signal("tab_clicked", found); + set_current_tab(found); + emit_signal("tab_clicked", found); + } } } } @@ -440,6 +456,14 @@ int Tabs::get_hovered_tab() const { return hover; } +int Tabs::get_tab_offset() const { + return offset; +} + +bool Tabs::get_offset_buttons_visible() const { + return buttons_visible; +} + void Tabs::set_tab_title(int p_tab, const String &p_title) { ERR_FAIL_INDEX(p_tab, tabs.size()); @@ -484,6 +508,7 @@ void Tabs::set_tab_right_button(int p_tab, const Ref<Texture> &p_right_button) { ERR_FAIL_INDEX(p_tab, tabs.size()); tabs[p_tab].right_button = p_right_button; + _update_cache(); update(); minimum_size_changed(); } @@ -783,6 +808,14 @@ void Tabs::set_min_width(int p_width) { min_width = p_width; } +void Tabs::set_scrolling_enabled(bool p_enabled) { + scrolling_enabled = p_enabled; +} + +bool Tabs::get_scrolling_enabled() const { + return scrolling_enabled; +} + void Tabs::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &Tabs::_gui_input); @@ -799,11 +832,15 @@ void Tabs::_bind_methods() { ClassDB::bind_method(D_METHOD("add_tab", "title", "icon"), &Tabs::add_tab, DEFVAL(""), DEFVAL(Ref<Texture>())); ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &Tabs::set_tab_align); ClassDB::bind_method(D_METHOD("get_tab_align"), &Tabs::get_tab_align); + ClassDB::bind_method(D_METHOD("get_tab_offset"), &Tabs::get_tab_offset); + ClassDB::bind_method(D_METHOD("get_offset_buttons_visible"), &Tabs::get_offset_buttons_visible); ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &Tabs::ensure_tab_visible); ClassDB::bind_method(D_METHOD("get_tab_rect", "tab_idx"), &Tabs::get_tab_rect); ClassDB::bind_method(D_METHOD("move_tab", "from", "to"), &Tabs::move_tab); ClassDB::bind_method(D_METHOD("set_tab_close_display_policy", "policy"), &Tabs::set_tab_close_display_policy); ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &Tabs::get_tab_close_display_policy); + ClassDB::bind_method(D_METHOD("set_scrolling_enabled", "enabled"), &Tabs::set_scrolling_enabled); + ClassDB::bind_method(D_METHOD("get_scrolling_enabled"), &Tabs::get_scrolling_enabled); ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab"))); ADD_SIGNAL(MethodInfo("right_button_pressed", PropertyInfo(Variant::INT, "tab"))); @@ -814,6 +851,7 @@ void Tabs::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab"); ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled"); BIND_ENUM_CONSTANT(ALIGN_LEFT); BIND_ENUM_CONSTANT(ALIGN_CENTER); @@ -841,4 +879,5 @@ Tabs::Tabs() { max_drawn_tab = 0; min_width = 0; + scrolling_enabled = true; } diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h index 73fa40bbb8..4eb6be3435 100644 --- a/scene/gui/tabs.h +++ b/scene/gui/tabs.h @@ -88,6 +88,7 @@ private: int hover; // hovered tab int min_width; + bool scrolling_enabled; int get_tab_width(int p_idx) const; void _ensure_no_over_offset(); @@ -131,10 +132,16 @@ public: int get_current_tab() const; int get_hovered_tab() const; + int get_tab_offset() const; + bool get_offset_buttons_visible() const; + void remove_tab(int p_idx); void clear_tabs(); + void set_scrolling_enabled(bool p_enabled); + bool get_scrolling_enabled() const; + void ensure_tab_visible(int p_idx); void set_min_width(int p_width); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 7d200a799b..c9af7eed0d 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -274,6 +274,7 @@ void TextEdit::Text::insert(int p_at, const String &p_text) { Line line; line.marked = false; line.breakpoint = false; + line.hidden = false; line.width_cache = -1; line.data = p_text; text.insert(p_at, line); @@ -297,9 +298,11 @@ void TextEdit::_update_scrollbars() { int hscroll_rows = ((hmin.height - 1) / get_row_height()) + 1; int visible_rows = get_visible_rows(); - int total_rows = text.size(); + int num_rows = MAX(visible_rows, num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(visible_rows, text.size() - 1 - cursor.line_ofs))); + + int total_rows = (is_hiding_enabled() ? get_total_unhidden_rows() : text.size()); if (scroll_past_end_of_file_enabled) { - total_rows += get_visible_rows() - 1; + total_rows += visible_rows - 1; } int vscroll_pixels = v_scroll->get_combined_minimum_size().width; @@ -313,6 +316,10 @@ void TextEdit::_update_scrollbars() { total_width += cache.breakpoint_gutter_width; } + if (draw_fold_gutter) { + total_width += cache.fold_gutter_width; + } + bool use_hscroll = true; bool use_vscroll = true; @@ -347,12 +354,11 @@ void TextEdit::_update_scrollbars() { v_scroll->set_step(1); } - if (fabs(v_scroll->get_value() - (double)cursor.line_ofs) >= 1) { - v_scroll->set_value(cursor.line_ofs); - } - + update_line_scroll_pos(); } else { cursor.line_ofs = 0; + line_scroll_pos = 0; + v_scroll->set_value(0); v_scroll->hide(); } @@ -551,6 +557,13 @@ void TextEdit::_notification(int p_what) { cache.breakpoint_gutter_width = 0; } + if (draw_fold_gutter) { + fold_gutter_width = (get_row_height() * 55) / 100; + cache.fold_gutter_width = fold_gutter_width; + } else { + cache.fold_gutter_width = 0; + } + int line_number_char_count = 0; { @@ -573,7 +586,7 @@ void TextEdit::_notification(int p_what) { RID ci = get_canvas_item(); VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true); - int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width; + int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width; int xmargin_end = cache.size.width - cache.style_normal->get_margin(MARGIN_RIGHT); //let's do it easy for now: cache.style_normal->draw(ci, Rect2(Point2(), cache.size)); @@ -780,10 +793,22 @@ void TextEdit::_notification(int p_what) { String highlighted_text = get_selection_text(); String line_num_padding = line_numbers_zero_padded ? "0" : " "; + update_line_scroll_pos(); + int line = cursor.line_ofs - 1; for (int i = 0; i < visible_rows; i++) { - int line = i + cursor.line_ofs; + line++; + + if (line < 0 || line >= (int)text.size()) + continue; + + while (is_line_hidden(line)) { + line++; + if (line < 0 || line >= (int)text.size()) { + break; + } + } if (line < 0 || line >= (int)text.size()) continue; @@ -794,7 +819,7 @@ void TextEdit::_notification(int p_what) { int char_ofs = 0; int ofs_y = (i * get_row_height() + cache.line_spacing / 2); if (smooth_scroll_enabled) { - ofs_y -= (v_scroll->get_value() - cursor.line_ofs) * get_row_height(); + ofs_y -= (v_scroll->get_value() - get_line_scroll_pos()) * get_row_height(); } bool prev_is_char = false; @@ -857,6 +882,21 @@ void TextEdit::_notification(int p_what) { } } + // draw fold markers + if (draw_fold_gutter) { + int horizontal_gap = (cache.fold_gutter_width * 30) / 100; + int gutter_left = cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + cache.line_number_w; + if (is_folded(line)) { + int xofs = horizontal_gap - (cache.can_fold_icon->get_width()) / 2; + int yofs = (get_row_height() - cache.folded_icon->get_height()) / 2; + cache.folded_icon->draw(ci, Point2(gutter_left + xofs, ofs_y + yofs), Color(0.8f, 0.8f, 0.8f, 0.8f)); + } else if (can_fold(line)) { + int xofs = -cache.can_fold_icon->get_width() / 2 - horizontal_gap + 3; + int yofs = (get_row_height() - cache.can_fold_icon->get_height()) / 2; + cache.can_fold_icon->draw(ci, Point2(gutter_left + xofs, ofs_y + yofs), Color(0.8f, 0.8f, 0.8f, 0.8f)); + } + } + if (cache.line_number_w) { String fc = String::num(line + 1); while (fc.length() < line_number_char_count) { @@ -894,17 +934,18 @@ void TextEdit::_notification(int p_what) { is_hex_notation = false; } - // check for dot or 'x' for hex notation in floating point number - if ((str[j] == '.' || str[j] == 'x') && !in_word && prev_is_number && !is_number) { + // check for dot or underscore or 'x' for hex notation in floating point number + if ((str[j] == '.' || str[j] == 'x' || str[j] == '_') && !in_word && prev_is_number && !is_number) { is_number = true; is_symbol = false; + is_char = false; if (str[j] == 'x' && str[j - 1] == '0') { is_hex_notation = true; } } - if (!in_word && _is_char(str[j])) { + if (!in_word && _is_char(str[j]) && !is_number) { in_word = true; } @@ -1195,6 +1236,10 @@ void TextEdit::_notification(int p_what) { } char_ofs += char_w; + + if (j == str.length() - 1 && is_folded(line)) { + cache.folded_eol_icon->draw(ci, Point2(char_ofs + char_margin, ofs_y), Color(1, 1, 1, 1), true); + } } if (cursor.column == str.length() && cursor.line == line && (char_ofs + char_margin) >= xmargin_beg) { @@ -1537,6 +1582,12 @@ void TextEdit::backspace_at_cursor() { int prev_line = cursor.column ? cursor.line : cursor.line - 1; int prev_column = cursor.column ? (cursor.column - 1) : (text[cursor.line - 1].length()); + + if (is_line_hidden(cursor.line)) + set_line_as_hidden(prev_line, true); + if (is_line_set_as_breakpoint(cursor.line)) + set_line_as_breakpoint(prev_line, true); + if (auto_brace_completion_enabled && cursor.column > 0 && _is_pair_left_symbol(text[cursor.line][cursor.column - 1])) { @@ -1576,7 +1627,7 @@ void TextEdit::backspace_at_cursor() { } } - cursor_set_line(prev_line); + cursor_set_line(prev_line, true, true); cursor_set_column(prev_column); } @@ -1650,10 +1701,18 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co float rows = p_mouse.y; rows -= cache.style_normal->get_margin(MARGIN_TOP); rows /= get_row_height(); - int row = cursor.line_ofs + (rows + (v_scroll->get_value() - cursor.line_ofs)); + int lsp = get_line_scroll_pos(true); + int row = cursor.line_ofs + (rows + (v_scroll->get_value() - lsp)); + + if (is_hiding_enabled()) { + // row will be offset by the hidden rows + int f_ofs = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(rows + 1, text.size() - cursor.line_ofs)) - 1; + row = cursor.line_ofs + (f_ofs + (v_scroll->get_value() - lsp)); + row = CLAMP(row, 0, text.size() - num_lines_from(text.size() - 1, -1)); + } if (row < 0) - row = 0; + row = 0; //todo int col = 0; @@ -1663,7 +1722,7 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co col = text[row].size(); } else { - col = p_mouse.x - (cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width); + col = p_mouse.x - (cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width); col += cursor.x_ofs; col = get_char_pos_for(col, get_line(row)); } @@ -1716,10 +1775,11 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (mb->is_pressed()) { if (mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) { + float scroll_factor = 3 * mb->get_factor(); if (scrolling) { - target_v_scroll = (target_v_scroll - (3 * mb->get_factor())); + target_v_scroll = (target_v_scroll - scroll_factor); } else { - target_v_scroll = (v_scroll->get_value() - (3 * mb->get_factor())); + target_v_scroll = (v_scroll->get_value() - scroll_factor); } if (smooth_scroll_enabled) { @@ -1733,16 +1793,18 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } } if (mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) { + float scroll_factor = 3 * mb->get_factor(); if (scrolling) { - target_v_scroll = (target_v_scroll + (3 * mb->get_factor())); + target_v_scroll = (target_v_scroll + scroll_factor); } else { - target_v_scroll = (v_scroll->get_value() + (3 * mb->get_factor())); + target_v_scroll = (v_scroll->get_value() + scroll_factor); } if (smooth_scroll_enabled) { - int max_v_scroll = get_line_count() - 1; + int max_v_scroll = get_total_unhidden_rows(); if (!scroll_past_end_of_file_enabled) { - max_v_scroll -= get_visible_rows() - 1; + max_v_scroll -= get_visible_rows(); + max_v_scroll = CLAMP(max_v_scroll, 0, get_total_unhidden_rows()); } if (target_v_scroll > max_v_scroll) { @@ -1765,6 +1827,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { _reset_caret_blink_timer(); int row, col; + update_line_scroll_pos(); _get_mouse_pos(Point2i(mb->get_position().x, mb->get_position().y), row, col); if (mb->get_command() && highlighted_word != String()) { @@ -1783,10 +1846,35 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } } + // toggle fold on gutter click if can + if (draw_fold_gutter) { + + int left_margin = cache.style_normal->get_margin(MARGIN_LEFT); + int gutter_left = left_margin + cache.breakpoint_gutter_width + cache.line_number_w; + if (mb->get_position().x > gutter_left - 6 && mb->get_position().x <= gutter_left + cache.fold_gutter_width - 3) { + if (is_folded(row)) { + unfold_line(row); + } else if (can_fold(row)) { + fold_line(row); + } + return; + } + } + + // unfold on folded icon click + if (is_folded(row)) { + int line_width = text.get_line_width(row); + line_width += cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width - cursor.x_ofs; + if (mb->get_position().x > line_width - 3 && mb->get_position().x <= line_width + cache.folded_eol_icon->get_width() + 3) { + unfold_line(row); + return; + } + } + int prev_col = cursor.column; int prev_line = cursor.line; - cursor_set_line(row); + cursor_set_line(row, true, false); cursor_set_column(col); if (mb->get_shift() && (cursor.column != prev_col || cursor.line != prev_line)) { @@ -2025,17 +2113,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { return; } - if (k->get_scancode() == KEY_DOWN) { - - if (completion_index < completion_options.size() - 1) { - completion_index++; - completion_current = completion_options[completion_index]; - update(); - } - accept_event(); - return; - } - if (k->get_scancode() == KEY_KP_ENTER || k->get_scancode() == KEY_ENTER || k->get_scancode() == KEY_TAB) { _confirm_completion(); @@ -2189,7 +2266,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { selection.active = false; update(); _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - cursor_set_line(selection.from_line); + cursor_set_line(selection.from_line, true, false); cursor_set_column(selection.from_column); update(); } @@ -2239,6 +2316,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } } + if (is_folded(cursor.line)) + unfold_line(cursor.line); + bool brace_indent = false; // no need to indent if we are going upwards. @@ -2389,6 +2469,8 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { cursor_set_column(column); } else { + if (cursor.line > 0 && is_line_hidden(cursor.line - 1)) + unfold_line(cursor.line - 1); backspace_at_cursor(); } @@ -2447,7 +2529,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } else if (cursor.column == 0) { if (cursor.line > 0) { - cursor_set_line(cursor.line - 1); + cursor_set_line(cursor.line - num_lines_from(CLAMP(cursor.line - 1, 0, text.size() - 1), -1)); cursor_set_column(text[cursor.line].length()); } } else { @@ -2510,7 +2592,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } else if (cursor.column == text[cursor.line].length()) { if (cursor.line < text.size() - 1) { - cursor_set_line(cursor.line + 1); + cursor_set_line(cursor_get_line() + num_lines_from(CLAMP(cursor.line + 1, 0, text.size() - 1), 1), true, false); cursor_set_column(0); } } else { @@ -2551,7 +2633,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { cursor_set_line(0); else #endif - cursor_set_line(cursor_get_line() - 1); + cursor_set_line(cursor_get_line() - num_lines_from(CLAMP(cursor.line - 1, 0, text.size() - 1), -1)); if (k->get_shift()) _post_shift_selection(); @@ -2585,10 +2667,10 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } if (k->get_command()) - cursor_set_line(text.size() - 1); + cursor_set_line(text.size() - 1, true, false); else #endif - cursor_set_line(cursor_get_line() + 1); + cursor_set_line(cursor_get_line() + num_lines_from(CLAMP(cursor.line + 1, 0, text.size() - 1), 1), true, false); if (k->get_shift()) _post_shift_selection(); @@ -2735,7 +2817,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (k->get_shift()) _pre_shift_selection(); - cursor_set_line(text.size() - 1); + cursor_set_line(text.size() - 1, true, false); if (k->get_shift()) _post_shift_selection(); @@ -2750,7 +2832,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { _pre_shift_selection(); if (k->get_command()) - cursor_set_line(text.size() - 1); + cursor_set_line(text.size() - 1, true, false); cursor_set_column(text[cursor.line].length()); if (k->get_shift()) @@ -2775,7 +2857,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (k->get_shift()) _pre_shift_selection(); - cursor_set_line(cursor_get_line() - get_visible_rows()); + cursor_set_line(cursor_get_line() - num_lines_from(cursor.line, -get_visible_rows()), true, false); if (k->get_shift()) _post_shift_selection(); @@ -2796,7 +2878,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (k->get_shift()) _pre_shift_selection(); - cursor_set_line(cursor_get_line() + get_visible_rows()); + cursor_set_line(cursor_get_line() + num_lines_from(cursor.line, get_visible_rows()), true, false); if (k->get_shift()) _post_shift_selection(); @@ -3014,8 +3096,9 @@ void TextEdit::_scroll_lines_up() { } // adjust the cursor - if (cursor_get_line() >= (get_visible_rows() + get_v_scroll()) && !selection.active) { - cursor_set_line((get_visible_rows() + get_v_scroll()) - 1, false); + int num_lines = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), get_visible_rows()) - 1; + if (cursor.line >= cursor.line_ofs + num_lines && !selection.active) { + cursor_set_line(cursor.line_ofs + num_lines, false, false); } } @@ -3023,9 +3106,10 @@ void TextEdit::_scroll_lines_down() { scrolling = false; // calculate the maximum vertical scroll position - int max_v_scroll = get_line_count() - 1; + int max_v_scroll = get_total_unhidden_rows(); if (!scroll_past_end_of_file_enabled) { - max_v_scroll -= get_visible_rows() - 1; + max_v_scroll -= get_visible_rows(); + max_v_scroll = CLAMP(max_v_scroll, 0, get_total_unhidden_rows()); } // adjust the vertical scroll @@ -3034,8 +3118,8 @@ void TextEdit::_scroll_lines_down() { } // adjust the cursor - if ((cursor_get_line()) <= get_v_scroll() - 1 && !selection.active) { - cursor_set_line(get_v_scroll(), false); + if (cursor.line <= cursor.line_ofs - 1 && !selection.active) { + cursor_set_line(cursor.line_ofs, false, false); } } @@ -3080,6 +3164,15 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i } } + // if we are just making a new empty line, reset breakpoints and hidden status + if (p_char == 0 && p_text.replace("\r", "") == "\n") { + + text.set_breakpoint(p_line + 1, text.is_breakpoint(p_line)); + text.set_hidden(p_line + 1, text.is_hidden(p_line)); + text.set_breakpoint(p_line, false); + text.set_hidden(p_line, false); + } + r_end_line = p_line + substrings.size() - 1; r_end_column = text[r_end_line].length() - postinsert_text.length(); @@ -3278,6 +3371,7 @@ Size2 TextEdit::get_minimum_size() const { return cache.style_normal->get_minimum_size(); } + int TextEdit::get_visible_rows() const { int total = cache.size.height; @@ -3285,31 +3379,81 @@ int TextEdit::get_visible_rows() const { total /= get_row_height(); return total; } + +int TextEdit::get_total_unhidden_rows() const { + if (!is_hiding_enabled()) + return text.size(); + + int total_unhidden = 0; + for (int i = 0; i < text.size(); i++) { + if (!text.is_hidden(i)) + total_unhidden++; + } + return total_unhidden; +} + +double TextEdit::get_line_scroll_pos(bool p_recalculate) const { + + if (!is_hiding_enabled()) + return cursor.line_ofs; + if (!p_recalculate) + return line_scroll_pos; + + // count num unhidden lines to the cursor line ofs + double new_line_scroll_pos = 0; + int to = CLAMP(cursor.line_ofs, 0, text.size() - 1); + for (int i = 0; i < to; i++) { + if (!text.is_hidden(i)) + new_line_scroll_pos++; + } + return new_line_scroll_pos; +} + +void TextEdit::update_line_scroll_pos() { + + if (!is_hiding_enabled()) { + line_scroll_pos = cursor.line_ofs; + return; + } + + // count num unhidden lines to the cursor line ofs + double new_line_scroll_pos = 0; + int to = CLAMP(cursor.line_ofs, 0, text.size() - 1); + for (int i = 0; i < to; i++) { + if (!text.is_hidden(i)) + new_line_scroll_pos++; + } + line_scroll_pos = new_line_scroll_pos; +} + void TextEdit::adjust_viewport_to_cursor() { scrolling = false; - if (cursor.line_ofs > cursor.line) + if (cursor.line_ofs > cursor.line) { cursor.line_ofs = cursor.line; + } - int visible_width = cache.size.width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width; + int visible_width = cache.size.width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width; if (v_scroll->is_visible_in_tree()) visible_width -= v_scroll->get_combined_minimum_size().width; visible_width -= 20; // give it a little more space - //printf("rowofs %i, visrows %i, cursor.line %i\n",cursor.line_ofs,get_visible_rows(),cursor.line); - int visible_rows = get_visible_rows(); if (h_scroll->is_visible_in_tree()) visible_rows -= ((h_scroll->get_combined_minimum_size().height - 1) / get_row_height()); + int num_rows = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(visible_rows, text.size() - 1 - cursor.line_ofs)); - if (cursor.line >= (cursor.line_ofs + visible_rows)) - cursor.line_ofs = cursor.line - visible_rows; - if (cursor.line < cursor.line_ofs) + // if the cursor is off the screen + if (cursor.line >= (cursor.line_ofs + MAX(num_rows, visible_rows))) { + cursor.line_ofs = cursor.line - (num_lines_from(CLAMP(cursor.line, 0, text.size() - 1), -visible_rows) - 1); + } + if (cursor.line < cursor.line_ofs) { cursor.line_ofs = cursor.line; + } - if (cursor.line_ofs + visible_rows > text.size() && !scroll_past_end_of_file_enabled) { - cursor.line_ofs = text.size() - visible_rows; - v_scroll->set_value(text.size() - visible_rows); + // fixes deleting lines from moving the line ofs in a bad way + if (!scroll_past_end_of_file_enabled && get_total_unhidden_rows() > visible_rows && num_rows < visible_rows) { + cursor.line_ofs = text.size() - 1 - (num_lines_from(text.size() - 1, -visible_rows) - 1); } int cursor_x = get_column_x_offset(cursor.column, text[cursor.line]); @@ -3320,6 +3464,8 @@ void TextEdit::adjust_viewport_to_cursor() { if (cursor_x < cursor.x_ofs) cursor.x_ofs = cursor_x; + update_line_scroll_pos(); + v_scroll->set_value(get_line_scroll_pos() + 1); update(); /* get_range()->set_max(text.size()); @@ -3336,7 +3482,10 @@ void TextEdit::center_viewport_to_cursor() { if (cursor.line_ofs > cursor.line) cursor.line_ofs = cursor.line; - int visible_width = cache.size.width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width; + if (is_line_hidden(cursor.line)) + unfold_line(cursor.line); + + int visible_width = cache.size.width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width; if (v_scroll->is_visible_in_tree()) visible_width -= v_scroll->get_combined_minimum_size().width; visible_width -= 20; // give it a little more space @@ -3345,9 +3494,8 @@ void TextEdit::center_viewport_to_cursor() { if (h_scroll->is_visible_in_tree()) visible_rows -= ((h_scroll->get_combined_minimum_size().height - 1) / get_row_height()); - int max_ofs = text.size() - (scroll_past_end_of_file_enabled ? 1 : visible_rows); - cursor.line_ofs = CLAMP(cursor.line - (visible_rows / 2), 0, max_ofs); - + int max_ofs = text.size() - (scroll_past_end_of_file_enabled ? 1 : num_lines_from(text.size() - 1, -visible_rows)); + cursor.line_ofs = CLAMP(cursor.line - num_lines_from(cursor.line - visible_rows / 2, -visible_rows / 2), 0, max_ofs); int cursor_x = get_column_x_offset(cursor.column, text[cursor.line]); if (cursor_x > (cursor.x_ofs + visible_width)) @@ -3356,6 +3504,9 @@ void TextEdit::center_viewport_to_cursor() { if (cursor_x < cursor.x_ofs) cursor.x_ofs = cursor_x; + update_line_scroll_pos(); + v_scroll->set_value(get_line_scroll_pos()); + update(); } @@ -3380,7 +3531,7 @@ void TextEdit::cursor_set_column(int p_col, bool p_adjust_viewport) { } } -void TextEdit::cursor_set_line(int p_row, bool p_adjust_viewport) { +void TextEdit::cursor_set_line(int p_row, bool p_adjust_viewport, bool p_can_be_hidden) { if (setting_row) return; @@ -3392,6 +3543,21 @@ void TextEdit::cursor_set_line(int p_row, bool p_adjust_viewport) { if (p_row >= (int)text.size()) p_row = (int)text.size() - 1; + if (!p_can_be_hidden) { + if (is_line_hidden(CLAMP(p_row, 0, text.size() - 1))) { + int move_down = num_lines_from(p_row, 1) - 1; + if (p_row + move_down <= text.size() - 1 && !is_line_hidden(p_row + move_down)) { + p_row += move_down; + } else { + int move_up = num_lines_from(p_row, -1) - 1; + if (p_row - move_up > 0 && !is_line_hidden(p_row - move_up)) { + p_row -= move_up; + } else { + WARN_PRINTS(("Cursor set to hidden line " + itos(p_row) + " and there are no nonhidden lines.")); + } + } + } + } cursor.line = p_row; cursor.column = get_char_pos_for(cursor.last_fit_x, get_line(cursor.line)); @@ -3461,8 +3627,11 @@ void TextEdit::_scroll_moved(double p_to_val) { if (h_scroll->is_visible_in_tree()) cursor.x_ofs = h_scroll->get_value(); - if (v_scroll->is_visible_in_tree()) - cursor.line_ofs = v_scroll->get_value(); + if (v_scroll->is_visible_in_tree()) { + double val = v_scroll->get_value(); + cursor.line_ofs = num_lines_from(0, (int)floor(val)) - 1; + line_scroll_pos = (int)floor(val); + } update(); } @@ -3551,10 +3720,43 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { if (highlighted_word != String()) return CURSOR_POINTING_HAND; - int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width; - if ((completion_active && completion_rect.has_point(p_pos)) || p_pos.x < gutter) { + int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width; + if ((completion_active && completion_rect.has_point(p_pos))) { return CURSOR_ARROW; } + if (p_pos.x < gutter) { + + int row, col; + _get_mouse_pos(p_pos, row, col); + int left_margin = cache.style_normal->get_margin(MARGIN_LEFT); + + // breakpoint icon + if (draw_breakpoint_gutter && p_pos.x > left_margin && p_pos.x <= left_margin + cache.breakpoint_gutter_width + 3) { + return CURSOR_POINTING_HAND; + } + + // fold icon + int gutter_left = left_margin + cache.breakpoint_gutter_width + cache.line_number_w; + if (draw_fold_gutter && p_pos.x > gutter_left - 6 && p_pos.x <= gutter_left + cache.fold_gutter_width - 3) { + if (is_folded(row) || can_fold(row)) + return CURSOR_POINTING_HAND; + else + return CURSOR_ARROW; + } + return CURSOR_ARROW; + } else { + int row, col; + _get_mouse_pos(p_pos, row, col); + // eol fold icon + if (is_folded(row)) { + int line_width = text.get_line_width(row); + line_width += cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width - cursor.x_ofs; + if (p_pos.x > line_width - 3 && p_pos.x <= line_width + cache.folded_eol_icon->get_width() + 3) { + return CURSOR_POINTING_HAND; + } + } + } + return CURSOR_IBEAM; } @@ -3568,6 +3770,7 @@ void TextEdit::set_text(String p_text) { cursor.line = 0; cursor.x_ofs = 0; cursor.line_ofs = 0; + line_scroll_pos = 0; cursor.last_fit_x = 0; cursor_set_line(0); cursor_set_column(0); @@ -3653,6 +3856,7 @@ void TextEdit::_clear() { cursor.line = 0; cursor.x_ofs = 0; cursor.line_ofs = 0; + line_scroll_pos = 0; cursor.last_fit_x = 0; } @@ -3668,6 +3872,11 @@ void TextEdit::set_readonly(bool p_readonly) { readonly = p_readonly; } +bool TextEdit::is_readonly() const { + + return readonly; +} + void TextEdit::set_wrap(bool p_wrap) { wrap = p_wrap; @@ -3726,6 +3935,9 @@ void TextEdit::_update_caches() { cache.line_spacing = get_constant("line_spacing"); cache.row_height = cache.font->get_height() + cache.line_spacing; cache.tab_icon = get_icon("tab"); + cache.folded_icon = get_icon("GuiTreeArrowRight", "EditorIcons"); + cache.can_fold_icon = get_icon("GuiTreeArrowDown", "EditorIcons"); + cache.folded_eol_icon = get_icon("GuiTabMenu", "EditorIcons"); text.set_font(cache.font); } @@ -3900,7 +4112,12 @@ void TextEdit::select(int p_from_line, int p_from_column, int p_to_line, int p_t update(); } - +void TextEdit::swap_lines(int line1, int line2) { + String tmp = get_line(line1); + String tmp2 = get_line(line2); + set_line(line2, tmp); + set_line(line1, tmp2); +} bool TextEdit::is_selection_active() const { return selection.active; @@ -4167,6 +4384,198 @@ void TextEdit::get_breakpoints(List<int> *p_breakpoints) const { } } +void TextEdit::set_line_as_hidden(int p_line, bool p_hidden) { + + ERR_FAIL_INDEX(p_line, text.size()); + if (is_hiding_enabled() || !p_hidden) + text.set_hidden(p_line, p_hidden); + update(); +} + +bool TextEdit::is_line_hidden(int p_line) const { + + ERR_FAIL_INDEX_V(p_line, text.size(), false); + return text.is_hidden(p_line); +} + +void TextEdit::fold_all_lines() { + + for (int i = 0; i < text.size(); i++) { + fold_line(i); + } + _update_scrollbars(); + update(); +} + +void TextEdit::unhide_all_lines() { + + for (int i = 0; i < text.size(); i++) { + text.set_hidden(i, false); + } + _update_scrollbars(); + update(); +} + +int TextEdit::num_lines_from(int p_line_from, int unhidden_amount) const { + + // returns the number of hidden and unhidden lines from p_line_from to p_line_from + amount of visible lines + ERR_FAIL_INDEX_V(p_line_from, text.size(), ABS(unhidden_amount)); + + if (!is_hiding_enabled()) + return unhidden_amount; + int num_visible = 0; + int num_total = 0; + if (unhidden_amount >= 0) { + for (int i = p_line_from; i < text.size(); i++) { + num_total++; + if (!is_line_hidden(i)) + num_visible++; + if (num_visible >= unhidden_amount) + break; + } + } else { + unhidden_amount = ABS(unhidden_amount); + for (int i = p_line_from; i >= 0; i--) { + num_total++; + if (!is_line_hidden(i)) + num_visible++; + if (num_visible >= unhidden_amount) + break; + } + } + return num_total; +} + +int TextEdit::get_whitespace_level(int p_line) const { + + ERR_FAIL_INDEX_V(p_line, text.size(), 0); + + // counts number of tabs and spaces before line starts + int whitespace_count = 0; + int line_length = text[p_line].size(); + for (int i = 0; i < line_length - 1; i++) { + if (text[p_line][i] == '\t') { + whitespace_count++; + } else if (text[p_line][i] == ' ') { + whitespace_count++; + } else if (text[p_line][i] == '#') { + break; + } else { + break; + } + } + return whitespace_count; +} + +bool TextEdit::can_fold(int p_line) const { + + ERR_FAIL_INDEX_V(p_line, text.size(), false); + if (!is_hiding_enabled()) + return false; + if (p_line + 1 >= text.size()) + return false; + if (text[p_line].size() == 0) + return false; + if (is_folded(p_line)) + return false; + if (is_line_hidden(p_line)) + return false; + + int start_indent = get_whitespace_level(p_line); + + for (int i = p_line + 1; i < text.size(); i++) { + if (text[i].size() == 0) + continue; + int next_indent = get_whitespace_level(i); + if (next_indent > start_indent) + return true; + else + return false; + } + + return false; +} + +bool TextEdit::is_folded(int p_line) const { + + ERR_FAIL_INDEX_V(p_line, text.size(), false); + if (p_line + 1 >= text.size() - 1) + return false; + if (!is_line_hidden(p_line) && is_line_hidden(p_line + 1)) + return true; + return false; +} + +void TextEdit::fold_line(int p_line) { + + ERR_FAIL_INDEX(p_line, text.size()); + if (!is_hiding_enabled()) + return; + if (!can_fold(p_line)) + return; + + // hide lines below this one + int start_indent = get_whitespace_level(p_line); + for (int i = p_line + 1; i < text.size(); i++) { + int cur_indent = get_whitespace_level(i); + if (text[i].size() == 0 || cur_indent > start_indent) { + set_line_as_hidden(i, true); + } else { + // exclude trailing empty lines + for (int trail_i = i - 1; trail_i > p_line; trail_i--) { + if (text[trail_i].size() == 0) + set_line_as_hidden(trail_i, false); + else + break; + } + break; + } + } + + // fix selection + if (is_selection_active()) { + if (is_line_hidden(selection.from_line) && is_line_hidden(selection.to_line)) { + deselect(); + } else if (is_line_hidden(selection.from_line)) { + select(p_line, 9999, selection.to_line, selection.to_column); + } else if (is_line_hidden(selection.to_line)) { + select(selection.from_line, selection.from_column, p_line, 9999); + } + } + + // reset cursor + if (is_line_hidden(cursor.line)) { + cursor_set_line(p_line, false, false); + cursor_set_column(get_line(p_line).length(), false); + } + _update_scrollbars(); + update(); +} + +void TextEdit::unfold_line(int p_line) { + + ERR_FAIL_INDEX(p_line, text.size()); + + if (!is_folded(p_line) && !is_line_hidden(p_line)) + return; + int fold_start = p_line; + for (fold_start = p_line; fold_start > 0; fold_start--) { + if (is_folded(fold_start)) + break; + } + fold_start = is_folded(fold_start) ? fold_start : p_line; + + for (int i = fold_start + 1; i < text.size(); i++) { + if (is_line_hidden(i)) { + set_line_as_hidden(i, false); + } else { + break; + } + } + _update_scrollbars(); + update(); +} + int TextEdit::get_line_count() const { return text.size(); @@ -4393,12 +4802,14 @@ void TextEdit::set_v_scroll(int p_scroll) { p_scroll = 0; } if (!scroll_past_end_of_file_enabled) { - if (p_scroll + get_visible_rows() > get_line_count()) { - p_scroll = get_line_count() - get_visible_rows(); + if (p_scroll + get_visible_rows() > get_total_unhidden_rows()) { + int num_rows = num_lines_from(CLAMP(p_scroll, 0, text.size() - 1), MIN(get_visible_rows(), text.size() - 1 - p_scroll)); + p_scroll = text.size() - num_rows; } } v_scroll->set_value(p_scroll); - cursor.line_ofs = p_scroll; + cursor.line_ofs = num_lines_from(0, p_scroll); + line_scroll_pos = p_scroll; } int TextEdit::get_h_scroll() const { @@ -4760,7 +5171,7 @@ void TextEdit::set_line(int line, String new_text) { void TextEdit::insert_at(const String &p_text, int at) { cursor_set_column(0); - cursor_set_line(at); + cursor_set_line(at, false, true); _insert_text(at, 0, p_text + "\n"); } @@ -4808,6 +5219,35 @@ int TextEdit::get_breakpoint_gutter_width() const { return cache.breakpoint_gutter_width; } +void TextEdit::set_draw_fold_gutter(bool p_draw) { + draw_fold_gutter = p_draw; + update(); +} + +bool TextEdit::is_drawing_fold_gutter() const { + return draw_fold_gutter; +} + +void TextEdit::set_fold_gutter_width(int p_gutter_width) { + fold_gutter_width = p_gutter_width; + update(); +} + +int TextEdit::get_fold_gutter_width() const { + return cache.fold_gutter_width; +} + +void TextEdit::set_hiding_enabled(int p_enabled) { + if (!p_enabled) + unhide_all_lines(); + hiding_enabled = p_enabled; + update(); +} + +int TextEdit::is_hiding_enabled() const { + return hiding_enabled; +} + void TextEdit::set_highlight_current_line(bool p_enabled) { highlight_current_line = p_enabled; update(); @@ -4866,6 +5306,10 @@ void TextEdit::set_context_menu_enabled(bool p_enable) { context_menu_enabled = p_enable; } +bool TextEdit::is_context_menu_enabled() { + return context_menu_enabled; +} + PopupMenu *TextEdit::get_menu() const { return menu; } @@ -4898,7 +5342,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_line", "line"), &TextEdit::get_line); ClassDB::bind_method(D_METHOD("cursor_set_column", "column", "adjust_viewport"), &TextEdit::cursor_set_column, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("cursor_set_line", "line", "adjust_viewport"), &TextEdit::cursor_set_line, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("cursor_set_line", "line", "adjust_viewport", "can_be_hidden"), &TextEdit::cursor_set_line, DEFVAL(true), DEFVAL(true)); ClassDB::bind_method(D_METHOD("cursor_get_column"), &TextEdit::cursor_get_column); ClassDB::bind_method(D_METHOD("cursor_get_line"), &TextEdit::cursor_get_line); @@ -4910,8 +5354,12 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("cursor_is_block_mode"), &TextEdit::cursor_is_block_mode); ClassDB::bind_method(D_METHOD("set_readonly", "enable"), &TextEdit::set_readonly); + ClassDB::bind_method(D_METHOD("is_readonly"), &TextEdit::is_readonly); + ClassDB::bind_method(D_METHOD("set_wrap", "enable"), &TextEdit::set_wrap); ClassDB::bind_method(D_METHOD("set_max_chars", "amount"), &TextEdit::set_max_chars); + ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enable"), &TextEdit::set_context_menu_enabled); + ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &TextEdit::is_context_menu_enabled); ClassDB::bind_method(D_METHOD("cut"), &TextEdit::cut); ClassDB::bind_method(D_METHOD("copy"), &TextEdit::copy); @@ -4935,6 +5383,17 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_show_line_numbers", "enable"), &TextEdit::set_show_line_numbers); ClassDB::bind_method(D_METHOD("is_show_line_numbers_enabled"), &TextEdit::is_show_line_numbers_enabled); + ClassDB::bind_method(D_METHOD("set_hiding_enabled", "enable"), &TextEdit::set_hiding_enabled); + ClassDB::bind_method(D_METHOD("is_hiding_enabled"), &TextEdit::is_hiding_enabled); + ClassDB::bind_method(D_METHOD("set_line_as_hidden", "line", "enable"), &TextEdit::set_line_as_hidden); + ClassDB::bind_method(D_METHOD("is_line_hidden"), &TextEdit::is_line_hidden); + ClassDB::bind_method(D_METHOD("fold_all_lines"), &TextEdit::fold_all_lines); + ClassDB::bind_method(D_METHOD("unhide_all_lines"), &TextEdit::unhide_all_lines); + ClassDB::bind_method(D_METHOD("fold_line", "line"), &TextEdit::fold_line); + ClassDB::bind_method(D_METHOD("unfold_line", "line"), &TextEdit::unfold_line); + ClassDB::bind_method(D_METHOD("can_fold", "line"), &TextEdit::can_fold); + ClassDB::bind_method(D_METHOD("is_folded", "line"), &TextEdit::is_folded); + ClassDB::bind_method(D_METHOD("set_highlight_all_occurrences", "enable"), &TextEdit::set_highlight_all_occurrences); ClassDB::bind_method(D_METHOD("is_highlight_all_occurrences_enabled"), &TextEdit::is_highlight_all_occurrences_enabled); @@ -4958,13 +5417,17 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option); ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "readonly"), "set_readonly", "is_readonly"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), "set_syntax_coloring", "is_syntax_coloring_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_scrolling"), "set_smooth_scroll_enable", "is_smooth_scroll_enabled"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_scroll_speed"), "set_v_scroll_speed", "get_v_scroll_speed"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hiding_enabled"), "set_hiding_enabled", "is_hiding_enabled"); ADD_GROUP("Caret", "caret_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_block_mode"), "cursor_set_block_mode", "cursor_is_block_mode"); @@ -5006,6 +5469,8 @@ TextEdit::TextEdit() { cache.line_number_w = 1; cache.breakpoint_gutter_width = 0; breakpoint_gutter_width = 0; + cache.fold_gutter_width = 0; + fold_gutter_width = 0; indent_size = 4; text.set_indent_size(indent_size); @@ -5075,6 +5540,8 @@ TextEdit::TextEdit() { line_length_guideline = false; line_length_guideline_col = 80; draw_breakpoint_gutter = false; + draw_fold_gutter = false; + hiding_enabled = false; next_operation_is_complex = false; scroll_past_end_of_file_enabled = false; auto_brace_completion_enabled = false; diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 81310b7c10..b1c7b14e58 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -73,6 +73,9 @@ class TextEdit : public Control { struct Cache { Ref<Texture> tab_icon; + Ref<Texture> can_fold_icon; + Ref<Texture> folded_icon; + Ref<Texture> folded_eol_icon; Ref<StyleBox> style_normal; Ref<StyleBox> style_focus; Ref<Font> font; @@ -105,6 +108,7 @@ class TextEdit : public Control { int line_spacing; int line_number_w; int breakpoint_gutter_width; + int fold_gutter_width; Size2 size; } cache; @@ -136,6 +140,7 @@ class TextEdit : public Control { int width_cache : 24; bool marked : 1; bool breakpoint : 1; + bool hidden : 1; Map<int, ColorRegionInfo> region_info; String data; }; @@ -160,6 +165,8 @@ class TextEdit : public Control { bool is_marked(int p_line) const { return text[p_line].marked; } void set_breakpoint(int p_line, bool p_breakpoint) { text[p_line].breakpoint = p_breakpoint; } bool is_breakpoint(int p_line) const { return text[p_line].breakpoint; } + void set_hidden(int p_line, bool p_hidden) { text[p_line].hidden = p_hidden; } + bool is_hidden(int p_line) const { return text[p_line].hidden; } void insert(int p_at, const String &p_text); void remove(int p_at); int size() const { return text.size(); } @@ -251,6 +258,9 @@ class TextEdit : public Control { int line_length_guideline_col; bool draw_breakpoint_gutter; int breakpoint_gutter_width; + bool draw_fold_gutter; + int fold_gutter_width; + bool hiding_enabled; bool highlight_all_occurrences; bool scroll_past_end_of_file_enabled; @@ -293,9 +303,14 @@ class TextEdit : public Control { int search_result_line; int search_result_col; + double line_scroll_pos; + bool context_menu_enabled; int get_visible_rows() const; + int get_total_unhidden_rows() const; + double get_line_scroll_pos(bool p_recalculate = false) const; + void update_line_scroll_pos(); int get_char_count(); @@ -303,6 +318,7 @@ class TextEdit : public Control { int get_column_x_offset(int p_char, String p_str); void adjust_viewport_to_cursor(); + double get_scroll_line_diff() const; void _scroll_moved(double); void _update_scrollbars(); void _v_scroll_input(); @@ -405,6 +421,18 @@ public: void set_line_as_breakpoint(int p_line, bool p_breakpoint); bool is_line_set_as_breakpoint(int p_line) const; void get_breakpoints(List<int> *p_breakpoints) const; + + void set_line_as_hidden(int p_line, bool p_hidden); + bool is_line_hidden(int p_line) const; + void fold_all_lines(); + void unhide_all_lines(); + int num_lines_from(int p_line_from, int unhidden_amount) const; + int get_whitespace_level(int p_line) const; + bool can_fold(int p_line) const; + bool is_folded(int p_line) const; + void fold_line(int p_line); + void unfold_line(int p_line); + String get_text(); String get_line(int line) const; void set_line(int line, String new_text); @@ -433,7 +461,7 @@ public: void center_viewport_to_cursor(); void cursor_set_column(int p_col, bool p_adjust_viewport = true); - void cursor_set_line(int p_row, bool p_adjust_viewport = true); + void cursor_set_line(int p_row, bool p_adjust_viewport = true, bool p_can_be_hidden = true); int cursor_get_column() const; int cursor_get_line() const; @@ -448,6 +476,7 @@ public: bool cursor_is_block_mode() const; void set_readonly(bool p_readonly); + bool is_readonly() const; void set_max_chars(int p_max_chars); void set_wrap(bool p_wrap); @@ -463,6 +492,7 @@ public: void select_all(); void select(int p_from_line, int p_from_column, int p_to_line, int p_to_column); void deselect(); + void swap_lines(int line1, int line2); void set_search_text(const String &p_search_text); void set_search_flags(uint32_t p_flags); @@ -536,6 +566,15 @@ public: void set_breakpoint_gutter_width(int p_gutter_width); int get_breakpoint_gutter_width() const; + void set_draw_fold_gutter(bool p_draw); + bool is_drawing_fold_gutter() const; + + void set_fold_gutter_width(int p_gutter_width); + int get_fold_gutter_width() const; + + void set_hiding_enabled(int p_enabled); + int is_hiding_enabled() const; + void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata); void set_completion(bool p_enabled, const Vector<String> &p_prefixes); @@ -547,6 +586,8 @@ public: bool is_selecting_identifiers_on_hover_enabled() const; void set_context_menu_enabled(bool p_enable); + bool is_context_menu_enabled(); + PopupMenu *get_menu() const; String get_text_for_completion(); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index f2e5919b5f..749ff51f57 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -28,6 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "tree.h" +#include <limits.h> #include "os/input.h" #include "os/keyboard.h" @@ -154,8 +155,17 @@ void TreeItem::set_text(int p_column, String p_text) { if (cells[p_column].mode == TreeItem::CELL_MODE_RANGE || cells[p_column].mode == TreeItem::CELL_MODE_RANGE_EXPRESSION) { - cells[p_column].min = 0; - cells[p_column].max = p_text.get_slice_count(","); + Vector<String> strings = p_text.split(","); + cells[p_column].min = INT_MAX; + cells[p_column].max = INT_MIN; + for (int i = 0; i < strings.size(); i++) { + int value = i; + if (!strings[i].get_slicec(':', 1).empty()) { + value = strings[i].get_slicec(':', 1).to_int(); + } + cells[p_column].min = MIN(cells[p_column].min, value); + cells[p_column].max = MAX(cells[p_column].max, value); + } cells[p_column].step = 0; } _changed_notify(p_column); @@ -1231,8 +1241,18 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 int option = (int)p_item->cells[i].val; - String s = p_item->cells[i].text; - s = s.get_slicec(',', option); + String s = RTR("(Other)"); + Vector<String> strings = p_item->cells[i].text.split(","); + for (int i = 0; i < strings.size(); i++) { + int value = i; + if (!strings[i].get_slicec(':', 1).empty()) { + value = strings[i].get_slicec(':', 1).to_int(); + } + if (option == value) { + s = strings[i].get_slicec(':', 0); + break; + } + } if (p_item->cells[i].suffix != String()) s += " " + p_item->cells[i].suffix; @@ -1776,7 +1796,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool for (int i = 0; i < c.text.get_slice_count(","); i++) { String s = c.text.get_slicec(',', i); - popup_menu->add_item(s, i); + popup_menu->add_item(s.get_slicec(':', 0), s.get_slicec(':', 1).empty() ? i : s.get_slicec(':', 1).to_int()); } popup_menu->set_size(Size2(col_width, 0)); @@ -2634,7 +2654,7 @@ bool Tree::edit_selected() { for (int i = 0; i < c.text.get_slice_count(","); i++) { String s = c.text.get_slicec(',', i); - popup_menu->add_item(s, i); + popup_menu->add_item(s.get_slicec(':', 0), s.get_slicec(':', 1).empty() ? i : s.get_slicec(':', 1).to_int()); } popup_menu->set_size(Size2(rect.size.width, 0)); diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index 190ccd50d5..1b6bd30b58 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -42,44 +42,127 @@ void VideoPlayer::sp_set_mix_rate(int p_rate) { server_mix_rate = p_rate; } -bool VideoPlayer::sp_mix(int32_t *p_buffer, int p_frames) { - - if (resampler.is_ready()) { +bool VideoPlayer::mix(AudioFrame *p_buffer, int p_frames) { + + // Check the amount resampler can really handle. + // If it cannot, wait "wait_resampler_phase_limit" times. + // This mechanism contributes to smoother pause/unpause operation. + if (p_frames <= resampler.get_num_of_ready_frames() || + wait_resampler_limit <= wait_resampler) { + wait_resampler = 0; return resampler.mix(p_buffer, p_frames); } - + wait_resampler++; return false; } -int VideoPlayer::_audio_mix_callback(void *p_udata, const int16_t *p_data, int p_frames) { +// Called from main thread (eg VideoStreamPlaybackWebm::update) +int VideoPlayer::_audio_mix_callback(void *p_udata, const float *p_data, int p_frames) { VideoPlayer *vp = (VideoPlayer *)p_udata; - int todo = MIN(vp->resampler.get_todo(), p_frames); + int todo = MIN(vp->resampler.get_writer_space(), p_frames); - int16_t *wb = vp->resampler.get_write_buffer(); + float *wb = vp->resampler.get_write_buffer(); int c = vp->resampler.get_channel_count(); for (int i = 0; i < todo * c; i++) { wb[i] = p_data[i]; } vp->resampler.write(todo); + return todo; } +// Called from audio thread +void VideoPlayer::_mix_audio() { + + if (!stream.is_valid()) { + return; + } + if (!playback.is_valid() || !playback->is_playing() || playback->is_paused()) { + return; + } + + AudioFrame *buffer = mix_buffer.ptr(); + int buffer_size = mix_buffer.size(); + + // Resample + if (!mix(buffer, buffer_size)) + return; + + AudioFrame vol = AudioFrame(volume, volume); + + // Copy to server's audio buffer + switch (AudioServer::get_singleton()->get_speaker_mode()) { + + case AudioServer::SPEAKER_MODE_STEREO: { + AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 0); + + for (int j = 0; j < buffer_size; j++) { + + target[j] += buffer[j] * vol; + } + + } break; + case AudioServer::SPEAKER_SURROUND_51: { + + AudioFrame *targets[2] = { + AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 1), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 2), + }; + + for (int j = 0; j < buffer_size; j++) { + + AudioFrame frame = buffer[j] * vol; + targets[0][j] = frame; + targets[1][j] = frame; + } + } break; + case AudioServer::SPEAKER_SURROUND_71: { + + AudioFrame *targets[3] = { + AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 1), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 2), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus_index, 3) + }; + + for (int j = 0; j < buffer_size; j++) { + + AudioFrame frame = buffer[j] * vol; + targets[0][j] += frame; + targets[1][j] += frame; + targets[2][j] += frame; + } + + } break; + } +} + void VideoPlayer::_notification(int p_notification) { switch (p_notification) { case NOTIFICATION_ENTER_TREE: { + AudioServer::get_singleton()->add_callback(_mix_audios, this); + if (stream.is_valid() && autoplay && !Engine::get_singleton()->is_editor_hint()) { play(); } + + } break; + + case NOTIFICATION_EXIT_TREE: { + + AudioServer::get_singleton()->remove_callback(_mix_audios, this); + } break; case NOTIFICATION_INTERNAL_PROCESS: { + bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus); + if (stream.is_null()) return; if (paused) @@ -87,10 +170,11 @@ void VideoPlayer::_notification(int p_notification) { if (!playback->is_playing()) return; - double audio_time = USEC_TO_SEC(OS::get_singleton()->get_ticks_usec()); //AudioServer::get_singleton()->get_mix_time(); + double audio_time = USEC_TO_SEC(OS::get_singleton()->get_ticks_usec()); double delta = last_audio_time == 0 ? 0 : audio_time - last_audio_time; last_audio_time = audio_time; + if (delta == 0) return; @@ -135,6 +219,9 @@ bool VideoPlayer::has_expand() const { void VideoPlayer::set_stream(const Ref<VideoStream> &p_stream) { stop(); + AudioServer::get_singleton()->lock(); + mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size()); + AudioServer::get_singleton()->unlock(); stream = p_stream; if (stream.is_valid()) { @@ -309,6 +396,40 @@ bool VideoPlayer::has_autoplay() const { return autoplay; }; +void VideoPlayer::set_bus(const StringName &p_bus) { + + //if audio is active, must lock this + AudioServer::get_singleton()->lock(); + bus = p_bus; + AudioServer::get_singleton()->unlock(); +} + +StringName VideoPlayer::get_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == bus) { + return bus; + } + } + return "Master"; +} + +void VideoPlayer::_validate_property(PropertyInfo &property) const { + + if (property.name == "bus") { + + String options; + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (i > 0) + options += ","; + String name = AudioServer::get_singleton()->get_bus_name(i); + options += name; + } + + property.hint_string = options; + } +} + void VideoPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_stream", "stream"), &VideoPlayer::set_stream); @@ -345,6 +466,9 @@ void VideoPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_buffering_msec", "msec"), &VideoPlayer::set_buffering_msec); ClassDB::bind_method(D_METHOD("get_buffering_msec"), &VideoPlayer::get_buffering_msec); + ClassDB::bind_method(D_METHOD("set_bus", "bus"), &VideoPlayer::set_bus); + ClassDB::bind_method(D_METHOD("get_bus"), &VideoPlayer::get_bus); + ClassDB::bind_method(D_METHOD("get_video_texture"), &VideoPlayer::get_video_texture); ADD_PROPERTY(PropertyInfo(Variant::INT, "audio_track", PROPERTY_HINT_RANGE, "0,128,1"), "set_audio_track", "get_audio_track"); @@ -354,6 +478,7 @@ void VideoPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "has_autoplay"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_paused", "is_paused"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand"), "set_expand", "has_expand"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); } VideoPlayer::VideoPlayer() { @@ -372,6 +497,9 @@ VideoPlayer::VideoPlayer() { // internal_stream.player=this; // stream_rid=AudioServer::get_singleton()->audio_stream_create(&internal_stream); last_audio_time = 0; + + wait_resampler = 0; + wait_resampler_limit = 2; }; VideoPlayer::~VideoPlayer() { diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h index f04e90365f..74e2f14e58 100644 --- a/scene/gui/video_player.h +++ b/scene/gui/video_player.h @@ -33,17 +33,24 @@ #include "scene/gui/control.h" #include "scene/resources/video_stream.h" #include "servers/audio/audio_rb_resampler.h" +#include "servers/audio_server.h" class VideoPlayer : public Control { GDCLASS(VideoPlayer, Control); + struct Output { + + AudioFrame vol; + int bus_index; + Viewport *viewport; //pointer only used for reference to previous mix + }; Ref<VideoStreamPlayback> playback; Ref<VideoStream> stream; int sp_get_channel_count() const; void sp_set_mix_rate(int p_rate); //notify the stream of the mix rate - bool sp_mix(int32_t *p_buffer, int p_frames); + bool mix(AudioFrame *p_buffer, int p_frames); RID stream_rid; @@ -51,6 +58,8 @@ class VideoPlayer : public Control { Ref<Image> last_frame; AudioRBResampler resampler; + Vector<AudioFrame> mix_buffer; + int wait_resampler, wait_resampler_limit; bool paused; bool autoplay; @@ -61,12 +70,18 @@ class VideoPlayer : public Control { int buffering_ms; int server_mix_rate; int audio_track; + int bus_index; + + StringName bus; - static int _audio_mix_callback(void *p_udata, const int16_t *p_data, int p_frames); + void _mix_audio(); + static int _audio_mix_callback(void *p_udata, const float *p_data, int p_frames); + static void _mix_audios(void *self) { reinterpret_cast<VideoPlayer *>(self)->_mix_audio(); } protected: static void _bind_methods(); void _notification(int p_notification); + void _validate_property(PropertyInfo &property) const; public: Size2 get_minimum_size() const; @@ -104,6 +119,9 @@ public: void set_buffering_msec(int p_msec); int get_buffering_msec() const; + void set_bus(const StringName &p_bus); + StringName get_bus() const; + VideoPlayer(); ~VideoPlayer(); }; diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index ce8714e574..5a3814ef35 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -105,30 +105,16 @@ real_t CanvasLayer::get_rotation() const { return rot; } -void CanvasLayer::set_rotationd(real_t p_degrees) { +void CanvasLayer::set_rotation_degrees(real_t p_degrees) { set_rotation(Math::deg2rad(p_degrees)); } -real_t CanvasLayer::get_rotationd() const { +real_t CanvasLayer::get_rotation_degrees() const { return Math::rad2deg(get_rotation()); } -// Kept for compatibility after rename to {s,g}et_rotationd. -// Could be removed after a couple releases. -void CanvasLayer::_set_rotationd(real_t p_degrees) { - - WARN_PRINT("Deprecated method CanvasLayer._set_rotationd(): This method was renamed to set_rotationd. Please adapt your code accordingly, as the old method will be obsoleted."); - set_rotationd(p_degrees); -} - -real_t CanvasLayer::_get_rotationd() const { - - WARN_PRINT("Deprecated method CanvasLayer._get_rotationd(): This method was renamed to get_rotationd. Please adapt your code accordingly, as the old method will be obsoleted."); - return get_rotationd(); -} - void CanvasLayer::set_scale(const Vector2 &p_scale) { if (locrotscale_dirty) @@ -252,12 +238,8 @@ void CanvasLayer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &CanvasLayer::set_rotation); ClassDB::bind_method(D_METHOD("get_rotation"), &CanvasLayer::get_rotation); - ClassDB::bind_method(D_METHOD("set_rotationd", "degrees"), &CanvasLayer::set_rotationd); - ClassDB::bind_method(D_METHOD("get_rotationd"), &CanvasLayer::get_rotationd); - - // TODO: Obsolete those two methods (old name) properly (GH-4397) - ClassDB::bind_method(D_METHOD("_set_rotationd", "degrees"), &CanvasLayer::_set_rotationd); - ClassDB::bind_method(D_METHOD("_get_rotationd"), &CanvasLayer::_get_rotationd); + ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &CanvasLayer::set_rotation_degrees); + ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &CanvasLayer::get_rotation_degrees); ClassDB::bind_method(D_METHOD("set_scale", "scale"), &CanvasLayer::set_scale); ClassDB::bind_method(D_METHOD("get_scale"), &CanvasLayer::get_scale); @@ -271,7 +253,7 @@ void CanvasLayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "layer", PROPERTY_HINT_RANGE, "-128,128,1"), "set_layer", "get_layer"); //ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"transform",PROPERTY_HINT_RANGE),"set_transform","get_transform") ; ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "rotation"), "set_rotationd", "get_rotationd"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "rotation"), "set_rotation_degrees", "get_rotation_degrees"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale"); } diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h index fbee87f487..db2c8e1273 100644 --- a/scene/main/canvas_layer.h +++ b/scene/main/canvas_layer.h @@ -54,10 +54,6 @@ class CanvasLayer : public Node { int sort_index; - // Deprecated, should be removed in a future version. - void _set_rotationd(real_t p_degrees); - real_t _get_rotationd() const; - void _update_xform(); void _update_locrotscale(); @@ -78,8 +74,8 @@ public: void set_rotation(real_t p_radians); real_t get_rotation() const; - void set_rotationd(real_t p_degrees); - real_t get_rotationd() const; + void set_rotation_degrees(real_t p_degrees); + real_t get_rotation_degrees() const; void set_scale(const Size2 &p_scale); Size2 get_scale() const; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index e6e11de177..253084dd99 100755 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2067,7 +2067,7 @@ int Node::get_position_in_parent() const { return data.pos; } -Node *Node::_duplicate(int p_flags) const { +Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const { Node *node = NULL; @@ -2084,7 +2084,12 @@ Node *Node::_duplicate(int p_flags) const { Ref<PackedScene> res = ResourceLoader::load(get_filename()); ERR_FAIL_COND_V(res.is_null(), NULL); - node = res->instance(); + PackedScene::GenEditState ges = PackedScene::GEN_EDIT_STATE_DISABLED; +#ifdef TOOLS_ENABLED + if (p_flags & DUPLICATE_FROM_EDITOR) + ges = PackedScene::GEN_EDIT_STATE_INSTANCE; +#endif + node = res->instance(ges); ERR_FAIL_COND_V(!node, NULL); instanced = true; @@ -2099,10 +2104,6 @@ Node *Node::_duplicate(int p_flags) const { ERR_FAIL_COND_V(!node, NULL); } - if (get_filename() != "") { //an instance - node->set_filename(get_filename()); - } - List<PropertyInfo> plist; get_property_list(&plist); @@ -2138,18 +2139,25 @@ Node *Node::_duplicate(int p_flags) const { node->set_name(get_name()); +#ifdef TOOLS_ENABLED + if ((p_flags & DUPLICATE_FROM_EDITOR) && r_duplimap) + r_duplimap->insert(this, node); +#endif + if (p_flags & DUPLICATE_GROUPS) { List<GroupInfo> gi; get_groups(&gi); for (List<GroupInfo>::Element *E = gi.front(); E; E = E->next()) { +#ifdef TOOLS_ENABLED + if ((p_flags & DUPLICATE_FROM_EDITOR) && !E->get().persistent) + continue; +#endif + node->add_to_group(E->get().name, E->get().persistent); } } - if (p_flags & DUPLICATE_SIGNALS) - _duplicate_signals(this, node); - for (int i = 0; i < get_child_count(); i++) { if (get_child(i)->data.parent_owned) @@ -2157,7 +2165,7 @@ Node *Node::_duplicate(int p_flags) const { if (instanced && get_child(i)->data.owner == this) continue; //part of instance - Node *dup = get_child(i)->duplicate(p_flags); + Node *dup = get_child(i)->_duplicate(p_flags, r_duplimap); if (!dup) { memdelete(node); @@ -2181,6 +2189,20 @@ Node *Node::duplicate(int p_flags) const { return dupe; } +#ifdef TOOLS_ENABLED +Node *Node::duplicate_from_editor(Map<const Node *, Node *> &r_duplimap) const { + + Node *dupe = _duplicate(DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANCING | DUPLICATE_FROM_EDITOR, &r_duplimap); + + // Duplication of signals must happen after all the node descendants have been copied, + // because re-targeting of connections from some descendant to another is not possible + // if the emitter node comes later in tree order than the receiver + _duplicate_signals(this, dupe); + + return dupe; +} +#endif + void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p_reown_map) const { if (get_owner() != get_parent()->get_owner()) @@ -2251,6 +2273,9 @@ void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p } } +// Duplication of signals must happen after all the node descendants have been copied, +// because re-targeting of connections from some descendant to another is not possible +// if the emitter node comes later in tree order than the receiver void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const { if (this != p_original && (get_owner() != p_original && get_owner() != p_original->get_owner())) @@ -2273,6 +2298,12 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const { NodePath ptarget = p_original->get_path_to(target); Node *copytarget = p_copy->get_node(ptarget); + // Cannot find a path to the duplicate target, so it seems it's not part + // of the duplicated and not yet parented hierarchy, so at least try to connect + // to the same target as the original + if (!copytarget) + copytarget = target; + if (copy && copytarget) { copy->connect(E->get().signal, copytarget, E->get().method, E->get().binds, CONNECT_PERSIST); } @@ -2319,6 +2350,9 @@ Node *Node::duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const { get_child(i)->_duplicate_and_reown(node, p_reown_map); } + // Duplication of signals must happen after all the node descendants have been copied, + // because re-targeting of connections from some descendant to another is not possible + // if the emitter node comes later in tree order than the receiver _duplicate_signals(this, node); return node; } @@ -2422,7 +2456,9 @@ void Node::_replace_connections_target(Node *p_new_target) { if (c.flags & CONNECT_PERSIST) { c.source->disconnect(c.signal, this, c.method); - ERR_CONTINUE(!p_new_target->has_method(c.method)); + bool valid = p_new_target->has_method(c.method) || p_new_target->get_script().is_null() || Ref<Script>(p_new_target->get_script())->has_method(c.method); + ERR_EXPLAIN("Attempt to connect signal \'" + c.source->get_class() + "." + c.signal + "\' to nonexistent method \'" + c.target->get_class() + "." + c.method + "\'"); + ERR_CONTINUE(!valid); c.source->connect(c.signal, p_new_target, c.method, c.binds, c.flags); } } diff --git a/scene/main/node.h b/scene/main/node.h index c43e96063f..bd0b18c87a 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -58,7 +58,10 @@ public: DUPLICATE_SIGNALS = 1, DUPLICATE_GROUPS = 2, DUPLICATE_SCRIPTS = 4, - DUPLICATE_USE_INSTANCING = 8 + DUPLICATE_USE_INSTANCING = 8, +#ifdef TOOLS_ENABLED + DUPLICATE_FROM_EDITOR = 16, +#endif }; enum RPCMode { @@ -169,7 +172,7 @@ private: void _duplicate_signals(const Node *p_original, Node *p_copy) const; void _duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p_reown_map) const; - Node *_duplicate(int p_flags) const; + Node *_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap = NULL) const; Array _get_children() const; Array _get_groups() const; @@ -326,6 +329,9 @@ public: Node *duplicate(int p_flags = DUPLICATE_GROUPS | DUPLICATE_SIGNALS | DUPLICATE_SCRIPTS) const; Node *duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const; +#ifdef TOOLS_ENABLED + Node *duplicate_from_editor(Map<const Node *, Node *> &r_duplimap) const; +#endif //Node *clone_tree() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index eaa16069cf..c99bc3c9ef 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -83,10 +83,10 @@ #include "scene/gui/link_button.h" #include "scene/gui/margin_container.h" #include "scene/gui/menu_button.h" +#include "scene/gui/nine_patch_rect.h" #include "scene/gui/option_button.h" #include "scene/gui/panel.h" #include "scene/gui/panel_container.h" -#include "scene/gui/nine_patch_rect.h" #include "scene/gui/popup_menu.h" #include "scene/gui/progress_bar.h" #include "scene/gui/reference_rect.h" diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 21e4a85cd1..8192074c17 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -1125,14 +1125,14 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a return a.cubic_slerp(b, pa, pb, p_c); } break; - case Variant::RECT3: { + case Variant::AABB: { - Rect3 a = p_a; - Rect3 b = p_b; - Rect3 pa = p_pre_a; - Rect3 pb = p_post_b; + AABB a = p_a; + AABB b = p_b; + AABB pa = p_pre_a; + AABB pb = p_post_b; - return Rect3( + return AABB( a.position.cubic_interpolate(b.position, pa.position, pb.position, p_c), a.size.cubic_interpolate(b.size, pa.size, pb.size, p_c)); } break; diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index fdc3b79db6..f81f460521 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -31,17 +31,23 @@ void AudioStreamPlaybackSample::start(float p_from_pos) { - for (int i = 0; i < 2; i++) { - ima_adpcm[i].step_index = 0; - ima_adpcm[i].predictor = 0; - ima_adpcm[i].loop_step_index = 0; - ima_adpcm[i].loop_predictor = 0; - ima_adpcm[i].last_nibble = -1; - ima_adpcm[i].loop_pos = 0x7FFFFFFF; - ima_adpcm[i].window_ofs = 0; + if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) { + //no seeking in IMA_ADPCM + for (int i = 0; i < 2; i++) { + ima_adpcm[i].step_index = 0; + ima_adpcm[i].predictor = 0; + ima_adpcm[i].loop_step_index = 0; + ima_adpcm[i].loop_predictor = 0; + ima_adpcm[i].last_nibble = -1; + ima_adpcm[i].loop_pos = 0x7FFFFFFF; + ima_adpcm[i].window_ofs = 0; + } + + offset = 0; + } else { + seek(p_from_pos); } - seek(p_from_pos); sign = 1; active = true; } @@ -373,6 +379,14 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in dst_buff += target; } + + if (todo) { + //bit was missing from mix + int todo_ofs = p_frames - todo; + for (int i = todo_ofs; i < p_frames; i++) { + p_buffer[i] = AudioFrame(0, 0); + } + } } float AudioStreamPlaybackSample::get_length() const { diff --git a/scene/resources/box_shape.cpp b/scene/resources/box_shape.cpp index bbc85ce0f6..4b9843f3f5 100644 --- a/scene/resources/box_shape.cpp +++ b/scene/resources/box_shape.cpp @@ -33,7 +33,7 @@ Vector<Vector3> BoxShape::_gen_debug_mesh_lines() { Vector<Vector3> lines; - Rect3 aabb; + AABB aabb; aabb.position = -get_extents(); aabb.size = aabb.position * -2; diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp index 56a09bc3bf..912150b939 100644 --- a/scene/resources/capsule_shape_2d.cpp +++ b/scene/resources/capsule_shape_2d.cpp @@ -98,7 +98,7 @@ void CapsuleShape2D::_bind_methods() { } CapsuleShape2D::CapsuleShape2D() - : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CAPSULE)) { + : Shape2D(Physics2DServer::get_singleton()->capsule_shape_create()) { radius = 10; height = 20; diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp index ecfc98ea60..287bde4bfb 100644 --- a/scene/resources/circle_shape_2d.cpp +++ b/scene/resources/circle_shape_2d.cpp @@ -77,7 +77,7 @@ void CircleShape2D::draw(const RID &p_to_rid, const Color &p_color) { } CircleShape2D::CircleShape2D() - : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CIRCLE)) { + : Shape2D(Physics2DServer::get_singleton()->circle_shape_create()) { radius = 10; _update_shape(); diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp index 7f4abf7ae0..bb91e33ec2 100644 --- a/scene/resources/concave_polygon_shape_2d.cpp +++ b/scene/resources/concave_polygon_shape_2d.cpp @@ -85,5 +85,5 @@ void ConcavePolygonShape2D::_bind_methods() { } ConcavePolygonShape2D::ConcavePolygonShape2D() - : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CONCAVE_POLYGON)) { + : Shape2D(Physics2DServer::get_singleton()->concave_polygon_shape_create()) { } diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp index 7588909d90..a76b6a7cf4 100644 --- a/scene/resources/convex_polygon_shape_2d.cpp +++ b/scene/resources/convex_polygon_shape_2d.cpp @@ -87,7 +87,7 @@ Rect2 ConvexPolygonShape2D::get_rect() const { } ConvexPolygonShape2D::ConvexPolygonShape2D() - : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CONVEX_POLYGON)) { + : Shape2D(Physics2DServer::get_singleton()->convex_polygon_shape_create()) { int pcount = 3; for (int i = 0; i < pcount; i++) diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index ce439fece6..cd28c9d203 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -836,39 +836,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("autohide", "HSplitContainer", 1 * scale); theme->set_constant("autohide", "VSplitContainer", 1 * scale); - // HButtonArray - theme->set_stylebox("normal", "HButtonArray", sb_button_normal); - theme->set_stylebox("selected", "HButtonArray", sb_button_pressed); - theme->set_stylebox("hover", "HButtonArray", sb_button_hover); - - theme->set_font("font", "HButtonArray", default_font); - theme->set_font("font_selected", "HButtonArray", default_font); - - theme->set_color("font_color", "HButtonArray", control_font_color_low); - theme->set_color("font_color_selected", "HButtonArray", control_font_color_hover); - - theme->set_constant("icon_separator", "HButtonArray", 2 * scale); - theme->set_constant("button_separator", "HButtonArray", 4 * scale); - - theme->set_stylebox("focus", "HButtonArray", focus); - - // VButtonArray - - theme->set_stylebox("normal", "VButtonArray", sb_button_normal); - theme->set_stylebox("selected", "VButtonArray", sb_button_pressed); - theme->set_stylebox("hover", "VButtonArray", sb_button_hover); - - theme->set_font("font", "VButtonArray", default_font); - theme->set_font("font_selected", "VButtonArray", default_font); - - theme->set_color("font_color", "VButtonArray", control_font_color_low); - theme->set_color("font_color_selected", "VButtonArray", control_font_color_hover); - - theme->set_constant("icon_separator", "VButtonArray", 2 * scale); - theme->set_constant("button_separator", "VButtonArray", 4 * scale); - - theme->set_stylebox("focus", "VButtonArray", focus); - // ReferenceRect Ref<StyleBoxTexture> ttnc = make_stylebox(full_panel_bg_png, 8, 8, 8, 8); diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 1ee76a4216..48c6add586 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -571,7 +571,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { wr[ofs + 0] = 255; //grayscale as 1 wr[ofs + 1] = slot->bitmap.buffer[i * slot->bitmap.pitch + j]; break; - // TODO: FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_BGRA + // TODO: FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_BGRA default: ERR_EXPLAIN("Font uses unsupported pixel format: " + itos(slot->bitmap.pixel_mode)); ERR_FAIL(); diff --git a/scene/resources/dynamic_font_stb.cpp b/scene/resources/dynamic_font_stb.cpp index 91263fb125..4aa47cb664 100644 --- a/scene/resources/dynamic_font_stb.cpp +++ b/scene/resources/dynamic_font_stb.cpp @@ -333,8 +333,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { //blit to image and texture { - - Image img(tex.texture_size, tex.texture_size, 0, Image::FORMAT_LA8, tex.imgdata); + Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, Image::FORMAT_LA8, tex.imgdata)); if (tex.texture.is_null()) { tex.texture.instance(); @@ -518,7 +517,7 @@ bool ResourceFormatLoaderDynamicFont::handles_type(const String &p_type) const { String ResourceFormatLoaderDynamicFont::get_resource_type(const String &p_path) const { - String el = p_path.extension().to_lower(); + String el = p_path.get_extension().to_lower(); if (el == "ttf") return "DynamicFontData"; return ""; diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 232f690074..fe59450f2e 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -1184,7 +1184,8 @@ Environment::Environment() { bg_energy = 1.0; bg_canvas_max_layer = 0; ambient_energy = 1.0; - ambient_sky_contribution = 1.0; + //ambient_sky_contribution = 1.0; + set_ambient_light_sky_contribution(1.0); tone_mapper = TONE_MAPPER_LINEAR; tonemap_exposure = 1.0; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 12434b39fa..286840656b 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -723,7 +723,11 @@ void SpatialMaterial::_update_shader() { } else { code += "\tvec3 emission_tex = texture(texture_emission,base_uv).rgb;\n"; } - code += "\tEMISSION = (emission.rgb+emission_tex)*emission_energy;\n"; + if (emission_op == EMISSION_OP_ADD) { + code += "\tEMISSION = (emission.rgb+emission_tex)*emission_energy;\n"; + } else { + code += "\tEMISSION = (emission.rgb*emission_tex)*emission_energy;\n"; + } } if (features[FEATURE_REFRACTION] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //refraction not supported with triplanar @@ -1635,6 +1639,19 @@ float SpatialMaterial::get_distance_fade_min_distance() const { return distance_fade_min_distance; } +void SpatialMaterial::set_emission_operator(EmissionOperator p_op) { + + if (emission_op == p_op) + return; + emission_op = p_op; + _queue_shader_change(); +} + +SpatialMaterial::EmissionOperator SpatialMaterial::get_emission_operator() const { + + return emission_op; +} + RID SpatialMaterial::get_shader_rid() const { ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); @@ -1769,6 +1786,9 @@ void SpatialMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_grow", "amount"), &SpatialMaterial::set_grow); ClassDB::bind_method(D_METHOD("get_grow"), &SpatialMaterial::get_grow); + ClassDB::bind_method(D_METHOD("set_emission_operator", "operator"), &SpatialMaterial::set_emission_operator); + ClassDB::bind_method(D_METHOD("get_emission_operator"), &SpatialMaterial::get_emission_operator); + ClassDB::bind_method(D_METHOD("set_ao_light_affect", "amount"), &SpatialMaterial::set_ao_light_affect); ClassDB::bind_method(D_METHOD("get_ao_light_affect"), &SpatialMaterial::get_ao_light_affect); @@ -1854,6 +1874,7 @@ void SpatialMaterial::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_enabled"), "set_feature", "get_feature", FEATURE_EMISSION); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_emission_energy", "get_emission_energy"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_operator", PROPERTY_HINT_ENUM, "Add,Multiply"), "set_emission_operator", "get_emission_operator"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_EMISSION); ADD_GROUP("NormalMap", "normal_"); @@ -2022,6 +2043,9 @@ void SpatialMaterial::_bind_methods() { BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_BLUE); BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_ALPHA); BIND_ENUM_CONSTANT(TEXTURE_CHANNEL_GRAYSCALE); + + BIND_ENUM_CONSTANT(EMISSION_OP_ADD); + BIND_ENUM_CONSTANT(EMISSION_OP_MULTIPLY); } SpatialMaterial::SpatialMaterial() @@ -2057,6 +2081,7 @@ SpatialMaterial::SpatialMaterial() set_particles_anim_v_frames(1); set_particles_anim_loop(false); set_alpha_scissor_threshold(0.98); + emission_op = EMISSION_OP_ADD; proximity_fade_enabled = false; distance_fade_enabled = false; diff --git a/scene/resources/material.h b/scene/resources/material.h index 2425f1a174..877d4dfd41 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -215,6 +215,11 @@ public: TEXTURE_CHANNEL_GRAYSCALE }; + enum EmissionOperator { + EMISSION_OP_ADD, + EMISSION_OP_MULTIPLY + }; + private: union MaterialKey { @@ -234,6 +239,7 @@ private: uint64_t grow : 1; uint64_t proximity_fade : 1; uint64_t distance_fade : 1; + uint64_t emission_op : 1; }; uint64_t key; @@ -278,6 +284,7 @@ private: mk.grow = grow_enabled; mk.proximity_fade = proximity_fade_enabled; mk.distance_fade = distance_fade_enabled; + mk.emission_op = emission_op; return mk; } @@ -394,6 +401,7 @@ private: SpecularMode specular_mode; DiffuseMode diffuse_mode; BillboardMode billboard_mode; + EmissionOperator emission_op; TextureChannel metallic_texture_channel; TextureChannel roughness_texture_channel; @@ -571,6 +579,9 @@ public: void set_distance_fade_min_distance(float p_distance); float get_distance_fade_min_distance() const; + void set_emission_operator(EmissionOperator p_op); + EmissionOperator get_emission_operator() const; + void set_metallic_texture_channel(TextureChannel p_channel); TextureChannel get_metallic_texture_channel() const; void set_roughness_texture_channel(TextureChannel p_channel); @@ -603,6 +614,7 @@ VARIANT_ENUM_CAST(SpatialMaterial::DiffuseMode) VARIANT_ENUM_CAST(SpatialMaterial::SpecularMode) VARIANT_ENUM_CAST(SpatialMaterial::BillboardMode) VARIANT_ENUM_CAST(SpatialMaterial::TextureChannel) +VARIANT_ENUM_CAST(SpatialMaterial::EmissionOperator) ////////////////////// diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index db5d87d703..0a886c25b1 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -574,7 +574,6 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { ERR_FAIL_COND_V(!d.has("format"), false); uint32_t format = d["format"]; - ERR_FAIL_COND_V(!d.has("primitive"), false); uint32_t primitive = d["primitive"]; ERR_FAIL_COND_V(!d.has("vertex_count"), false); @@ -595,11 +594,11 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { } ERR_FAIL_COND_V(!d.has("aabb"), false); - Rect3 aabb = d["aabb"]; + AABB aabb = d["aabb"]; - Vector<Rect3> bone_aabb; - if (d.has("bone_aabb")) { - Array baabb = d["bone_aabb"]; + Vector<AABB> bone_aabb; + if (d.has("skeleton_aabb")) { + Array baabb = d["skeleton_aabb"]; bone_aabb.resize(baabb.size()); for (int i = 0; i < baabb.size(); i++) { @@ -677,7 +676,7 @@ bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { d["format"] = VS::get_singleton()->mesh_surface_get_format(mesh, idx); d["aabb"] = VS::get_singleton()->mesh_surface_get_aabb(mesh, idx); - Vector<Rect3> skel_aabb = VS::get_singleton()->mesh_surface_get_skeleton_aabb(mesh, idx); + Vector<AABB> skel_aabb = VS::get_singleton()->mesh_surface_get_skeleton_aabb(mesh, idx); Array arr; for (int i = 0; i < skel_aabb.size(); i++) { arr[i] = skel_aabb[i]; @@ -726,13 +725,13 @@ void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const { } } - p_list->push_back(PropertyInfo(Variant::RECT3, "custom_aabb/custom_aabb")); + p_list->push_back(PropertyInfo(Variant::AABB, "custom_aabb/custom_aabb")); } void ArrayMesh::_recompute_aabb() { // regenerate AABB - aabb = Rect3(); + aabb = AABB(); for (int i = 0; i < surfaces.size(); i++) { @@ -743,7 +742,7 @@ void ArrayMesh::_recompute_aabb() { } } -void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<Rect3> &p_bone_aabbs) { +void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabbs) { Surface s; s.aabb = p_aabb; @@ -773,7 +772,7 @@ void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array & const Vector3 *vtx = r.ptr(); // check AABB - Rect3 aabb; + AABB aabb; for (int i = 0; i < len; i++) { if (i == 0) @@ -921,7 +920,13 @@ String ArrayMesh::surface_get_name(int p_idx) const { return surfaces[p_idx].name; } -void ArrayMesh::surface_set_custom_aabb(int p_idx, const Rect3 &p_aabb) { +void ArrayMesh::surface_update_region(int p_surface, int p_offset, const PoolVector<uint8_t> &p_data) { + + ERR_FAIL_INDEX(p_surface, surfaces.size()); + VS::get_singleton()->mesh_surface_update_region(mesh, p_surface, p_offset, p_data); +} + +void ArrayMesh::surface_set_custom_aabb(int p_idx, const AABB &p_aabb) { ERR_FAIL_INDEX(p_idx, surfaces.size()); surfaces[p_idx].aabb = p_aabb; @@ -937,7 +942,7 @@ Ref<Material> ArrayMesh::surface_get_material(int p_idx) const { void ArrayMesh::add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data) { VisualServer::get_singleton()->mesh_add_surface_from_mesh_data(mesh, p_mesh_data); - Rect3 aabb; + AABB aabb; for (int i = 0; i < p_mesh_data.vertices.size(); i++) { if (i == 0) @@ -965,18 +970,18 @@ RID ArrayMesh::get_rid() const { return mesh; } -Rect3 ArrayMesh::get_aabb() const { +AABB ArrayMesh::get_aabb() const { return aabb; } -void ArrayMesh::set_custom_aabb(const Rect3 &p_custom) { +void ArrayMesh::set_custom_aabb(const AABB &p_custom) { custom_aabb = p_custom; VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); } -Rect3 ArrayMesh::get_custom_aabb() const { +AABB ArrayMesh::get_custom_aabb() const { return custom_aabb; } @@ -1042,6 +1047,7 @@ void ArrayMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); ClassDB::bind_method(D_METHOD("get_surface_count"), &ArrayMesh::get_surface_count); ClassDB::bind_method(D_METHOD("surface_remove", "surf_idx"), &ArrayMesh::surface_remove); + ClassDB::bind_method(D_METHOD("surface_update_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_region); ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len); ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &ArrayMesh::surface_get_array_index_len); ClassDB::bind_method(D_METHOD("surface_get_format", "surf_idx"), &ArrayMesh::surface_get_format); @@ -1090,6 +1096,16 @@ void ArrayMesh::_bind_methods() { BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX); } +void ArrayMesh::reload_from_file() { + VisualServer::get_singleton()->mesh_clear(mesh); + surfaces.clear(); + clear_blend_shapes(); + + Resource::reload_from_file(); + + _change_notify(); +} + ArrayMesh::ArrayMesh() { mesh = VisualServer::get_singleton()->mesh_create(); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index f4edb258b6..b85a6a84af 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -95,6 +95,7 @@ public: ARRAY_FLAG_USE_2D_VERTICES = ARRAY_COMPRESS_INDEX << 1, ARRAY_FLAG_USE_16_BIT_BONES = ARRAY_COMPRESS_INDEX << 2, + ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3, ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_VERTEX | ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 | ARRAY_COMPRESS_WEIGHTS @@ -135,7 +136,7 @@ public: Ref<Mesh> create_outline(float p_margin) const; - virtual Rect3 get_aabb() const = 0; + virtual AABB get_aabb() const = 0; Mesh(); }; @@ -148,16 +149,16 @@ class ArrayMesh : public Mesh { private: struct Surface { String name; - Rect3 aabb; + AABB aabb; Ref<Material> material; bool is_2d; }; Vector<Surface> surfaces; RID mesh; - Rect3 aabb; + AABB aabb; BlendShapeMode blend_shape_mode; Vector<StringName> blend_shapes; - Rect3 custom_aabb; + AABB custom_aabb; void _recompute_aabb(); @@ -172,7 +173,7 @@ protected: public: void add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), uint32_t p_flags = ARRAY_COMPRESS_DEFAULT); - void add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const Rect3 &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<Rect3> &p_bone_aabbs = Vector<Rect3>()); + void add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()); Array surface_get_arrays(int p_surface) const; Array surface_get_blend_shape_arrays(int p_surface) const; @@ -185,10 +186,12 @@ public: void set_blend_shape_mode(BlendShapeMode p_mode); BlendShapeMode get_blend_shape_mode() const; + void surface_update_region(int p_surface, int p_offset, const PoolVector<uint8_t> &p_data); + int get_surface_count() const; void surface_remove(int p_idx); - void surface_set_custom_aabb(int p_idx, const Rect3 &p_aabb); //only recognized by driver + void surface_set_custom_aabb(int p_idx, const AABB &p_aabb); //only recognized by driver int surface_get_array_len(int p_idx) const; int surface_get_array_index_len(int p_idx) const; @@ -204,15 +207,17 @@ public: void add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data); - void set_custom_aabb(const Rect3 &p_custom); - Rect3 get_custom_aabb() const; + void set_custom_aabb(const AABB &p_custom); + AABB get_custom_aabb() const; - Rect3 get_aabb() const; + AABB get_aabb() const; virtual RID get_rid() const; void center_geometry(); void regen_normalmaps(); + virtual void reload_from_file(); + ArrayMesh(); ~ArrayMesh(); diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp index 15f1e15542..ee6efa6e85 100644 --- a/scene/resources/multimesh.cpp +++ b/scene/resources/multimesh.cpp @@ -155,7 +155,7 @@ Color MultiMesh::get_instance_color(int p_instance) const { return VisualServer::get_singleton()->multimesh_instance_get_color(multimesh, p_instance); } -Rect3 MultiMesh::get_aabb() const { +AABB MultiMesh::get_aabb() const { return VisualServer::get_singleton()->multimesh_get_aabb(multimesh); } diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h index 7ca66b0b46..0a5310f641 100644 --- a/scene/resources/multimesh.h +++ b/scene/resources/multimesh.h @@ -84,7 +84,7 @@ public: void set_instance_color(int p_instance, const Color &p_color); Color get_instance_color(int p_instance) const; - virtual Rect3 get_aabb() const; + virtual AABB get_aabb() const; virtual RID get_rid() const; diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index ba356d89b1..3b80db291c 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -42,7 +42,7 @@ void PrimitiveMesh::_update() const { PoolVector<Vector3> points = arr[VS::ARRAY_VERTEX]; - aabb = Rect3(); + aabb = AABB(); int pc = points.size(); ERR_FAIL_COND(pc == 0); @@ -141,7 +141,7 @@ StringName PrimitiveMesh::get_blend_shape_name(int p_index) const { return StringName(); } -Rect3 PrimitiveMesh::get_aabb() const { +AABB PrimitiveMesh::get_aabb() const { if (pending_request) { _update(); } @@ -1299,14 +1299,16 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const { tangents.resize(4 * 4); uvs.resize(4); - for (int i = 0; i < 4; i++) { + Vector2 _size = Vector2(size.x / 2.0f, size.y / 2.0f); - static const Vector3 quad_faces[4] = { - Vector3(-1, -1, 0), - Vector3(-1, 1, 0), - Vector3(1, 1, 0), - Vector3(1, -1, 0), - }; + Vector3 quad_faces[4] = { + Vector3(-_size.x, -_size.y, 0), + Vector3(-_size.x, _size.y, 0), + Vector3(_size.x, _size.y, 0), + Vector3(_size.x, -_size.y, 0), + }; + + for (int i = 0; i < 4; i++) { faces.set(i, quad_faces[i]); normals.set(i, Vector3(0, 0, 1)); @@ -1325,18 +1327,30 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const { uvs.set(i, quad_uv[i]); } - p_arr[ARRAY_VERTEX] = faces; - p_arr[ARRAY_NORMAL] = normals; - p_arr[ARRAY_TANGENT] = tangents; - p_arr[ARRAY_TEX_UV] = uvs; + p_arr[VS::ARRAY_VERTEX] = faces; + p_arr[VS::ARRAY_NORMAL] = normals; + p_arr[VS::ARRAY_TANGENT] = tangents; + p_arr[VS::ARRAY_TEX_UV] = uvs; }; void QuadMesh::_bind_methods() { - // nothing here yet... + ClassDB::bind_method(D_METHOD("set_size", "size"), &QuadMesh::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &QuadMesh::get_size); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); } QuadMesh::QuadMesh() { primitive_type = PRIMITIVE_TRIANGLE_FAN; + size = Size2(1.0, 1.0); +} + +void QuadMesh::set_size(const Size2 &p_size) { + size = p_size; + _request_update(); +} + +Size2 QuadMesh::get_size() const { + return size; } /** diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index 38a5695883..b38c247827 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -47,7 +47,7 @@ class PrimitiveMesh : public Mesh { private: RID mesh; - mutable Rect3 aabb; + mutable AABB aabb; Ref<Material> material; @@ -73,7 +73,7 @@ public: virtual Ref<Material> surface_get_material(int p_idx) const; virtual int get_blend_shape_count() const; virtual StringName get_blend_shape_name(int p_index) const; - virtual Rect3 get_aabb() const; + virtual AABB get_aabb() const; virtual RID get_rid() const; void set_material(const Ref<Material> &p_material); @@ -263,7 +263,7 @@ class QuadMesh : public PrimitiveMesh { GDCLASS(QuadMesh, PrimitiveMesh) private: - // nothing? really? Maybe add size some day atleast... :) + Size2 size; protected: static void _bind_methods(); @@ -271,6 +271,9 @@ protected: public: QuadMesh(); + + void set_size(const Size2 &p_size); + Size2 get_size() const; }; /** diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp index 507dbce861..69dbb76744 100644 --- a/scene/resources/rectangle_shape_2d.cpp +++ b/scene/resources/rectangle_shape_2d.cpp @@ -67,7 +67,7 @@ void RectangleShape2D::_bind_methods() { } RectangleShape2D::RectangleShape2D() - : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_RECTANGLE)) { + : Shape2D(Physics2DServer::get_singleton()->rectangle_shape_create()) { extents = Vector2(10, 10); _update_shape(); diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index f0304bfaa5..fe23fbf6b3 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -33,7 +33,7 @@ #include "project_settings.h" #include "version.h" -//version 2: changed names for basis, rect3, poolvectors, etc. +//version 2: changed names for basis, aabb, poolvectors, etc. #define FORMAT_VERSION 2 #include "os/dir_access.h" diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp index 1171db5c02..7c7ec0d112 100644 --- a/scene/resources/segment_shape_2d.cpp +++ b/scene/resources/segment_shape_2d.cpp @@ -87,7 +87,7 @@ void SegmentShape2D::_bind_methods() { } SegmentShape2D::SegmentShape2D() - : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_SEGMENT)) { + : Shape2D(Physics2DServer::get_singleton()->segment_shape_create()) { a = Vector2(); b = Vector2(0, 10); @@ -146,7 +146,7 @@ real_t RayShape2D::get_length() const { } RayShape2D::RayShape2D() - : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_RAY)) { + : Shape2D(Physics2DServer::get_singleton()->ray_shape_create()) { length = 20; _update_shape(); diff --git a/scene/resources/shape_line_2d.cpp b/scene/resources/shape_line_2d.cpp index 4dcc5ac981..d046ce876c 100644 --- a/scene/resources/shape_line_2d.cpp +++ b/scene/resources/shape_line_2d.cpp @@ -96,7 +96,7 @@ void LineShape2D::_bind_methods() { } LineShape2D::LineShape2D() - : Shape2D(Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_LINE)) { + : Shape2D(Physics2DServer::get_singleton()->line_shape_create()) { normal = Vector2(0, -1); d = 0; diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 50e8c28c22..29ac7852bf 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -57,11 +57,9 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { tile_set_region(id, p_value); else if (what == "shape") tile_set_shape(id, 0, p_value); - else if (what == "shape_offset") { - Transform2D xform = tile_get_shape_transform(id, 0); - xform.set_origin(p_value); - tile_set_shape_transform(id, 0, xform); - } else if (what == "shape_transform") + else if (what == "shape_offset") + tile_set_shape_offset(id, 0, p_value); + else if (what == "shape_transform") tile_set_shape_transform(id, 0, p_value); else if (what == "shape_one_way") tile_set_shape_one_way(id, 0, p_value); @@ -110,7 +108,7 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { else if (what == "shape") r_ret = tile_get_shape(id, 0); else if (what == "shape_offset") - r_ret = tile_get_shape_transform(id, 0).get_origin(); + r_ret = tile_get_shape_offset(id, 0); else if (what == "shape_transform") r_ret = tile_get_shape_transform(id, 0); else if (what == "shape_one_way") @@ -313,6 +311,16 @@ Transform2D TileSet::tile_get_shape_transform(int p_id, int p_shape_id) const { return Transform2D(); } +void TileSet::tile_set_shape_offset(int p_id, int p_shape_id, const Vector2 &p_offset) { + Transform2D transform = tile_get_shape_transform(p_id, p_shape_id); + transform.set_origin(p_offset); + tile_set_shape_transform(p_id, p_shape_id, transform); +} + +Vector2 TileSet::tile_get_shape_offset(int p_id, int p_shape_id) const { + return tile_get_shape_transform(p_id, p_shape_id).get_origin(); +} + void TileSet::tile_set_shape_one_way(int p_id, int p_shape_id, const bool p_one_way) { ERR_FAIL_COND(!tile_map.has(p_id)); diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index fe782ff987..3ef3f00cef 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -108,6 +108,9 @@ public: void tile_set_shape_transform(int p_id, int p_shape_id, const Transform2D &p_offset); Transform2D tile_get_shape_transform(int p_id, int p_shape_id) const; + void tile_set_shape_offset(int p_id, int p_shape_id, const Vector2 &p_offset); + Vector2 tile_get_shape_offset(int p_id, int p_shape_id) const; + void tile_set_shape_one_way(int p_id, int p_shape_id, bool p_one_way); bool tile_get_shape_one_way(int p_id, int p_shape_id) const; diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h index 3f79858056..fbe52909e7 100644 --- a/scene/resources/video_stream.h +++ b/scene/resources/video_stream.h @@ -40,7 +40,7 @@ protected: static void _bind_methods(); public: - typedef int (*AudioMixCallback)(void *p_udata, const int16_t *p_data, int p_frames); + typedef int (*AudioMixCallback)(void *p_udata, const float *p_data, int p_frames); virtual void stop() = 0; virtual void play() = 0; @@ -48,7 +48,7 @@ public: virtual bool is_playing() const = 0; virtual void set_paused(bool p_paused) = 0; - virtual bool is_paused(bool p_paused) const = 0; + virtual bool is_paused() const = 0; virtual void set_loop(bool p_enable) = 0; virtual bool has_loop() const = 0; diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp index af159975ca..86b32a5cdd 100644 --- a/scene/resources/world.cpp +++ b/scene/resources/world.cpp @@ -41,7 +41,7 @@ struct SpatialIndexer { struct NotifierData { - Rect3 aabb; + AABB aabb; OctreeElementID id; }; @@ -63,7 +63,7 @@ struct SpatialIndexer { uint64_t pass; uint64_t last_frame; - void _notifier_add(VisibilityNotifier *p_notifier, const Rect3 &p_rect) { + void _notifier_add(VisibilityNotifier *p_notifier, const AABB &p_rect) { ERR_FAIL_COND(notifiers.has(p_notifier)); notifiers[p_notifier].aabb = p_rect; @@ -71,7 +71,7 @@ struct SpatialIndexer { changed = true; } - void _notifier_update(VisibilityNotifier *p_notifier, const Rect3 &p_rect) { + void _notifier_update(VisibilityNotifier *p_notifier, const AABB &p_rect) { Map<VisibilityNotifier *, NotifierData>::Element *E = notifiers.find(p_notifier); ERR_FAIL_COND(!E); @@ -229,14 +229,14 @@ void World::_remove_camera(Camera *p_camera) { #endif } -void World::_register_notifier(VisibilityNotifier *p_notifier, const Rect3 &p_rect) { +void World::_register_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect) { #ifndef _3D_DISABLED indexer->_notifier_add(p_notifier, p_rect); #endif } -void World::_update_notifier(VisibilityNotifier *p_notifier, const Rect3 &p_rect) { +void World::_update_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect) { #ifndef _3D_DISABLED indexer->_notifier_update(p_notifier, p_rect); diff --git a/scene/resources/world.h b/scene/resources/world.h index 767d1b5b6e..e0f1de1fd0 100644 --- a/scene/resources/world.h +++ b/scene/resources/world.h @@ -60,8 +60,8 @@ protected: void _update_camera(Camera *p_camera); void _remove_camera(Camera *p_camera); - void _register_notifier(VisibilityNotifier *p_notifier, const Rect3 &p_rect); - void _update_notifier(VisibilityNotifier *p_notifier, const Rect3 &p_rect); + void _register_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect); + void _update_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect); void _remove_notifier(VisibilityNotifier *p_notifier); friend class Viewport; void _update(uint64_t p_frame); diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index d9770ec3f3..52b8e35d5e 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -143,7 +143,7 @@ SceneStringNames::SceneStringNames() { v_offset = StaticCString::create("v_offset"); transform_pos = StaticCString::create("position"); - transform_rot = StaticCString::create("rotation_deg"); + transform_rot = StaticCString::create("rotation_degrees"); transform_scale = StaticCString::create("scale"); _update_remote = StaticCString::create("_update_remote"); |