summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/animated_sprite.cpp12
-rw-r--r--scene/2d/animated_sprite.h8
-rw-r--r--scene/2d/back_buffer_copy.cpp2
-rw-r--r--scene/2d/back_buffer_copy.h4
-rw-r--r--scene/2d/canvas_item.cpp54
-rw-r--r--scene/2d/canvas_item.h37
-rw-r--r--scene/2d/collision_polygon_2d.cpp2
-rw-r--r--scene/2d/collision_polygon_2d.h2
-rw-r--r--scene/2d/collision_shape_2d.cpp2
-rw-r--r--scene/2d/collision_shape_2d.h3
-rw-r--r--scene/2d/light_2d.cpp8
-rw-r--r--scene/2d/light_2d.h9
-rw-r--r--scene/2d/node_2d.cpp118
-rw-r--r--scene/2d/node_2d.h30
-rw-r--r--scene/2d/particles_2d.cpp6
-rw-r--r--scene/2d/path_2d.cpp46
-rw-r--r--scene/2d/path_2d.h5
-rw-r--r--scene/2d/physics_body_2d.cpp8
-rw-r--r--scene/2d/polygon_2d.cpp18
-rw-r--r--scene/2d/polygon_2d.h14
-rw-r--r--scene/2d/position_2d.cpp2
-rw-r--r--scene/2d/position_2d.h2
-rw-r--r--scene/2d/screen_button.cpp8
-rw-r--r--scene/2d/screen_button.h2
-rw-r--r--scene/2d/sprite.cpp231
-rw-r--r--scene/2d/sprite.h53
-rw-r--r--scene/2d/tile_map.cpp33
-rw-r--r--scene/2d/tile_map.h6
-rw-r--r--scene/2d/visibility_notifier_2d.cpp2
-rw-r--r--scene/2d/visibility_notifier_2d.h4
-rw-r--r--scene/3d/collision_polygon.cpp4
-rw-r--r--scene/3d/collision_polygon.h4
-rw-r--r--scene/3d/gi_probe.cpp65
-rw-r--r--scene/3d/gi_probe.h14
-rw-r--r--scene/3d/immediate_geometry.cpp2
-rw-r--r--scene/3d/immediate_geometry.h4
-rw-r--r--scene/3d/light.cpp21
-rw-r--r--scene/3d/light.h3
-rw-r--r--scene/3d/mesh_instance.cpp4
-rw-r--r--scene/3d/mesh_instance.h2
-rw-r--r--scene/3d/multimesh_instance.cpp4
-rw-r--r--scene/3d/multimesh_instance.h2
-rw-r--r--scene/3d/particles.cpp22
-rw-r--r--scene/3d/particles.h10
-rw-r--r--scene/3d/physics_body.cpp16
-rw-r--r--scene/3d/portal.cpp2
-rw-r--r--scene/3d/portal.h4
-rw-r--r--scene/3d/reflection_probe.cpp4
-rw-r--r--scene/3d/reflection_probe.h2
-rw-r--r--scene/3d/room_instance.cpp6
-rw-r--r--scene/3d/room_instance.h2
-rw-r--r--scene/3d/spatial.cpp32
-rw-r--r--scene/3d/spatial.h8
-rw-r--r--scene/3d/sprite_3d.cpp6
-rw-r--r--scene/3d/sprite_3d.h6
-rw-r--r--scene/3d/visibility_notifier.cpp8
-rw-r--r--scene/3d/visibility_notifier.h6
-rw-r--r--scene/3d/visual_instance.cpp2
-rw-r--r--scene/3d/visual_instance.h4
-rw-r--r--scene/animation/animation_player.cpp9
-rw-r--r--scene/animation/tween.cpp16
-rw-r--r--scene/audio/audio_player.cpp50
-rw-r--r--scene/audio/audio_player.h1
-rw-r--r--scene/gui/check_button.cpp23
-rw-r--r--scene/gui/check_button.h1
-rw-r--r--scene/gui/control.cpp198
-rw-r--r--scene/gui/control.h39
-rw-r--r--scene/gui/item_list.cpp4
-rw-r--r--scene/gui/line_edit.cpp17
-rw-r--r--scene/gui/line_edit.h3
-rw-r--r--scene/gui/rich_text_label.cpp26
-rw-r--r--scene/gui/rich_text_label.h3
-rw-r--r--scene/gui/scroll_container.cpp5
-rw-r--r--scene/gui/tabs.cpp161
-rw-r--r--scene/gui/tabs.h7
-rw-r--r--scene/gui/text_edit.cpp617
-rw-r--r--scene/gui/text_edit.h43
-rw-r--r--scene/gui/tree.cpp32
-rw-r--r--scene/gui/video_player.cpp144
-rw-r--r--scene/gui/video_player.h22
-rw-r--r--scene/main/canvas_layer.cpp28
-rw-r--r--scene/main/canvas_layer.h8
-rwxr-xr-xscene/main/node.cpp58
-rw-r--r--scene/main/node.h10
-rw-r--r--scene/register_scene_types.cpp2
-rw-r--r--scene/resources/animation.cpp12
-rw-r--r--scene/resources/audio_stream_sample.cpp32
-rw-r--r--scene/resources/box_shape.cpp2
-rw-r--r--scene/resources/capsule_shape_2d.cpp2
-rw-r--r--scene/resources/circle_shape_2d.cpp2
-rw-r--r--scene/resources/concave_polygon_shape_2d.cpp2
-rw-r--r--scene/resources/convex_polygon_shape_2d.cpp2
-rw-r--r--scene/resources/default_theme/default_theme.cpp33
-rw-r--r--scene/resources/dynamic_font.cpp2
-rw-r--r--scene/resources/dynamic_font_stb.cpp5
-rw-r--r--scene/resources/environment.cpp3
-rw-r--r--scene/resources/material.cpp27
-rw-r--r--scene/resources/material.h12
-rw-r--r--scene/resources/mesh.cpp46
-rw-r--r--scene/resources/mesh.h23
-rw-r--r--scene/resources/multimesh.cpp2
-rw-r--r--scene/resources/multimesh.h2
-rw-r--r--scene/resources/primitive_meshes.cpp42
-rw-r--r--scene/resources/primitive_meshes.h9
-rw-r--r--scene/resources/rectangle_shape_2d.cpp2
-rw-r--r--scene/resources/scene_format_text.cpp2
-rw-r--r--scene/resources/segment_shape_2d.cpp4
-rw-r--r--scene/resources/shape_line_2d.cpp2
-rw-r--r--scene/resources/tile_set.cpp20
-rw-r--r--scene/resources/tile_set.h3
-rw-r--r--scene/resources/video_stream.h4
-rw-r--r--scene/resources/world.cpp10
-rw-r--r--scene/resources/world.h4
-rw-r--r--scene/scene_string_names.cpp2
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");