aboutsummaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/animated_sprite.cpp4
-rw-r--r--scene/2d/animated_sprite.h1
-rw-r--r--scene/2d/back_buffer_copy.cpp4
-rw-r--r--scene/2d/back_buffer_copy.h1
-rw-r--r--scene/2d/canvas_item.cpp14
-rw-r--r--scene/2d/canvas_item.h46
-rw-r--r--scene/2d/collision_polygon_2d.cpp4
-rw-r--r--scene/2d/collision_polygon_2d.h1
-rw-r--r--scene/2d/collision_shape_2d.cpp5
-rw-r--r--scene/2d/collision_shape_2d.h1
-rw-r--r--scene/2d/light_2d.cpp4
-rw-r--r--scene/2d/light_2d.h1
-rw-r--r--scene/2d/light_occluder_2d.cpp6
-rw-r--r--scene/2d/light_occluder_2d.h2
-rw-r--r--scene/2d/line_2d.cpp7
-rw-r--r--scene/2d/line_2d.h1
-rw-r--r--scene/2d/node_2d.cpp54
-rw-r--r--scene/2d/node_2d.h8
-rw-r--r--scene/2d/path_2d.cpp7
-rw-r--r--scene/2d/path_2d.h1
-rw-r--r--scene/2d/polygon_2d.cpp174
-rw-r--r--scene/2d/polygon_2d.h25
-rw-r--r--scene/2d/position_2d.cpp4
-rw-r--r--scene/2d/position_2d.h1
-rw-r--r--scene/2d/screen_button.cpp4
-rw-r--r--scene/2d/screen_button.h1
-rw-r--r--scene/2d/skeleton_2d.cpp86
-rw-r--r--scene/2d/skeleton_2d.h11
-rw-r--r--scene/2d/sprite.cpp32
-rw-r--r--scene/2d/sprite.h4
-rw-r--r--scene/2d/tile_map.cpp10
-rw-r--r--scene/2d/tile_map.h1
-rw-r--r--scene/2d/visibility_notifier_2d.cpp4
-rw-r--r--scene/2d/visibility_notifier_2d.h1
-rw-r--r--scene/3d/camera.h4
-rw-r--r--scene/3d/collision_polygon.cpp5
-rw-r--r--scene/3d/collision_polygon.h2
-rw-r--r--scene/3d/particles.cpp31
-rw-r--r--scene/3d/path.cpp5
-rw-r--r--scene/3d/spatial.cpp13
-rw-r--r--scene/3d/spatial.h2
-rw-r--r--scene/3d/voxel_light_baker.cpp4
-rw-r--r--scene/animation/animation_player.cpp4
-rw-r--r--scene/animation/animation_tree_player.cpp7
-rw-r--r--scene/animation/animation_tree_player.h2
-rw-r--r--scene/gui/color_picker.cpp9
-rw-r--r--scene/gui/color_picker.h2
-rw-r--r--scene/gui/control.cpp8
-rw-r--r--scene/gui/control.h3
-rw-r--r--scene/gui/grid_container.cpp40
-rw-r--r--scene/gui/grid_container.h1
-rw-r--r--scene/gui/item_list.cpp2
-rw-r--r--scene/gui/line_edit.cpp62
-rw-r--r--scene/gui/line_edit.h6
-rw-r--r--scene/gui/rich_text_label.cpp4
-rw-r--r--scene/gui/text_edit.cpp33
-rw-r--r--scene/gui/text_edit.h1
-rw-r--r--scene/main/node.cpp28
-rw-r--r--scene/main/node.h8
-rw-r--r--scene/main/scene_tree.cpp20
-rw-r--r--scene/main/scene_tree.h2
-rw-r--r--scene/register_scene_types.cpp3
-rw-r--r--scene/resources/curve.cpp166
-rw-r--r--scene/resources/curve.h4
-rw-r--r--scene/resources/mesh.cpp5
-rw-r--r--scene/resources/primitive_meshes.cpp18
-rw-r--r--scene/resources/primitive_meshes.h4
-rw-r--r--scene/resources/style_box.cpp6
-rw-r--r--scene/resources/tile_set.cpp20
-rw-r--r--scene/resources/tile_set.h7
70 files changed, 889 insertions, 182 deletions
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index 824f50495..447bd9a09 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -80,6 +80,10 @@ Rect2 AnimatedSprite::_edit_get_rect() const {
return Rect2(ofs, s);
}
+bool AnimatedSprite::_edit_use_rect() const {
+ return true;
+}
+
void SpriteFrames::add_frame(const StringName &p_anim, const Ref<Texture> &p_frame, int p_at_pos) {
Map<StringName, Anim>::Element *E = animations.find(p_anim);
diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h
index a38adf792..c7606d88a 100644
--- a/scene/2d/animated_sprite.h
+++ b/scene/2d/animated_sprite.h
@@ -157,6 +157,7 @@ public:
virtual Point2 _edit_get_pivot() const;
virtual bool _edit_use_pivot() const;
virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
void set_sprite_frames(const Ref<SpriteFrames> &p_frames);
Ref<SpriteFrames> get_sprite_frames() const;
diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp
index 446b367be..caa1adebd 100644
--- a/scene/2d/back_buffer_copy.cpp
+++ b/scene/2d/back_buffer_copy.cpp
@@ -55,6 +55,10 @@ Rect2 BackBufferCopy::_edit_get_rect() const {
return rect;
}
+bool BackBufferCopy::_edit_use_rect() const {
+ return true;
+}
+
void BackBufferCopy::set_rect(const Rect2 &p_rect) {
rect = p_rect;
diff --git a/scene/2d/back_buffer_copy.h b/scene/2d/back_buffer_copy.h
index b786c2b82..752d56de2 100644
--- a/scene/2d/back_buffer_copy.h
+++ b/scene/2d/back_buffer_copy.h
@@ -54,6 +54,7 @@ protected:
public:
Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
void set_rect(const Rect2 &p_rect);
Rect2 get_rect() const;
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 2b8906218..a2637f816 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -245,6 +245,14 @@ CanvasItemMaterial::~CanvasItemMaterial() {
///////////////////////////////////////////////////////////////////
+bool CanvasItem::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+ if (_edit_use_rect()) {
+ return _edit_get_rect().has_point(p_point);
+ } else {
+ return p_point.length() < p_tolerance;
+ }
+}
+
bool CanvasItem::is_visible_in_tree() const {
if (!is_inside_tree())
@@ -263,7 +271,8 @@ bool CanvasItem::is_visible_in_tree() const {
void CanvasItem::_propagate_visibility_changed(bool p_visible) {
- notification(NOTIFICATION_VISIBILITY_CHANGED);
+ if (!first_draw)
+ notification(NOTIFICATION_VISIBILITY_CHANGED);
if (p_visible)
update(); //todo optimize
@@ -980,7 +989,8 @@ void CanvasItem::_bind_methods() {
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_scale", "scale"), &CanvasItem::_edit_set_scale);
+ ClassDB::bind_method(D_METHOD("_edit_get_scale"), &CanvasItem::_edit_get_scale);
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);
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 980fcb410..85de0d279 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -220,30 +220,46 @@ public:
/* EDITOR */
+ // Save and restore a CanvasItem state
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 move the node
+ virtual void _edit_set_position(const Point2 &p_position) = 0;
+ virtual Point2 _edit_get_position() const = 0;
- // Used to resize/move/select the node
+ // Used to scale the node
+ virtual void _edit_set_scale(const Size2 &p_scale) = 0;
+ virtual Size2 _edit_get_scale() const = 0;
+
+ // Used to resize/move the node
virtual void _edit_set_rect(const Rect2 &p_rect){};
- virtual Rect2 _edit_get_rect() const { return Rect2(-32, -32, 64, 64); };
- virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return _edit_get_rect().has_point(p_point); }
- Rect2 _edit_get_item_and_children_rect() const;
+ virtual Rect2 _edit_get_rect() const { return Rect2(0, 0, 0, 0); };
virtual bool _edit_use_rect() const { return false; };
+ Rect2 _edit_get_item_and_children_rect() const;
+
+ // used to select the node
+ virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+
// 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; };
+ 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 Point2 _edit_get_pivot() const {
+ return Point2();
+ };
+ virtual bool _edit_use_pivot() const {
+ return false;
+ };
virtual Size2 _edit_get_minimum_size() const;
@@ -308,7 +324,9 @@ public:
virtual Transform2D get_global_transform_with_canvas() const;
CanvasItem *get_toplevel() const;
- _FORCE_INLINE_ RID get_canvas_item() const { return canvas_item; }
+ _FORCE_INLINE_ RID get_canvas_item() const {
+ return canvas_item;
+ }
void set_block_transform_notify(bool p_enable);
bool is_block_transform_notify_enabled() const;
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 7e2026d22..9d2a83fda 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -264,6 +264,10 @@ Rect2 CollisionPolygon2D::_edit_get_rect() const {
return aabb;
}
+bool CollisionPolygon2D::_edit_use_rect() const {
+ return true;
+}
+
bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
return Geometry::is_point_in_polygon(p_point, Variant(polygon));
diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h
index 4dafe7d1d..412a92329 100644
--- a/scene/2d/collision_polygon_2d.h
+++ b/scene/2d/collision_polygon_2d.h
@@ -73,6 +73,7 @@ public:
Vector<Point2> get_polygon() const;
virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
virtual String get_configuration_warning() const;
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index 0eeb6dafe..83ef4df8f 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -173,11 +173,6 @@ Ref<Shape2D> CollisionShape2D::get_shape() const {
return shape;
}
-Rect2 CollisionShape2D::_edit_get_rect() const {
-
- return rect;
-}
-
bool CollisionShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
if (!shape.is_valid())
diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h
index cdff59582..ed2c09d53 100644
--- a/scene/2d/collision_shape_2d.h
+++ b/scene/2d/collision_shape_2d.h
@@ -54,7 +54,6 @@ protected:
static void _bind_methods();
public:
- virtual Rect2 _edit_get_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
void set_shape(const Ref<Shape2D> &p_shape);
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 1220ff299..9a44eb31b 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -65,6 +65,10 @@ Rect2 Light2D::_edit_get_rect() const {
return Rect2(texture_offset - s / 2.0, s);
}
+bool Light2D::_edit_use_rect() const {
+ return true;
+}
+
void Light2D::_update_light_visibility() {
if (!is_inside_tree())
diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h
index 16d8c485d..543805e32 100644
--- a/scene/2d/light_2d.h
+++ b/scene/2d/light_2d.h
@@ -92,6 +92,7 @@ public:
virtual Point2 _edit_get_pivot() const;
virtual bool _edit_use_pivot() const;
virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
void set_enabled(bool p_enabled);
bool is_enabled() const;
diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp
index d4481583f..c9e5d0f1b 100644
--- a/scene/2d/light_occluder_2d.cpp
+++ b/scene/2d/light_occluder_2d.cpp
@@ -107,12 +107,12 @@ OccluderPolygon2D::~OccluderPolygon2D() {
VS::get_singleton()->free(occ_polygon);
}
-#ifdef DEBUG_ENABLED
void LightOccluder2D::_poly_changed() {
+#ifdef DEBUG_ENABLED
update();
-}
#endif
+}
void LightOccluder2D::_notification(int p_what) {
@@ -221,9 +221,7 @@ void LightOccluder2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_occluder_light_mask", "mask"), &LightOccluder2D::set_occluder_light_mask);
ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &LightOccluder2D::get_occluder_light_mask);
-#ifdef DEBUG_ENABLED
ClassDB::bind_method("_poly_changed", &LightOccluder2D::_poly_changed);
-#endif
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D"), "set_occluder_polygon", "get_occluder_polygon");
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_occluder_light_mask", "get_occluder_light_mask");
diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h
index 5e16351a6..d59c9100b 100644
--- a/scene/2d/light_occluder_2d.h
+++ b/scene/2d/light_occluder_2d.h
@@ -78,9 +78,7 @@ class LightOccluder2D : public Node2D {
int mask;
Ref<OccluderPolygon2D> occluder_polygon;
-#ifdef DEBUG_ENABLED
void _poly_changed();
-#endif
protected:
void _notification(int p_what);
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index ba4a5c557..3e61dd05f 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -62,6 +62,10 @@ Rect2 Line2D::_edit_get_rect() const {
return aabb;
}
+bool Line2D::_edit_use_rect() const {
+ return true;
+}
+
bool Line2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
const real_t d = _width / 2 + p_tolerance;
@@ -266,7 +270,8 @@ void Line2D::_draw() {
lb.indices,
lb.vertices,
lb.colors,
- lb.uvs,
+ lb.uvs, Vector<int>(), Vector<float>(),
+
texture_rid);
// DEBUG
diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h
index 0eba02455..24c48982c 100644
--- a/scene/2d/line_2d.h
+++ b/scene/2d/line_2d.h
@@ -59,6 +59,7 @@ public:
Line2D();
virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
void set_points(const PoolVector<Vector2> &p_points);
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 95e24505b..3813bd96f 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -58,16 +58,39 @@ void Node2D::_edit_set_state(const Dictionary &p_state) {
}
void Node2D::_edit_set_position(const Point2 &p_position) {
- pos = p_position;
- _update_transform();
- _change_notify("position");
+ set_position(p_position);
}
Point2 Node2D::_edit_get_position() const {
return pos;
}
+void Node2D::_edit_set_scale(const Size2 &p_scale) {
+ set_scale(p_scale);
+}
+
+Size2 Node2D::_edit_get_scale() const {
+ return _scale;
+}
+
+void Node2D::_edit_set_rotation(float p_rotation) {
+ angle = p_rotation;
+ _update_transform();
+ _change_notify("rotation");
+ _change_notify("rotation_degrees");
+}
+
+float Node2D::_edit_get_rotation() const {
+ return angle;
+}
+
+bool Node2D::_edit_use_rotation() const {
+ return true;
+}
+
void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) {
+ ERR_FAIL_COND(!_edit_use_rect());
+
Rect2 r = _edit_get_rect();
Vector2 zero_offset;
@@ -83,7 +106,7 @@ void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) {
if (r.size.y != 0)
new_scale.y = p_edit_rect.size.y / r.size.y;
- Point2 new_pos = p_edit_rect.position + p_edit_rect.size * zero_offset; //p_edit_rect.pos - r.pos;
+ Point2 new_pos = p_edit_rect.position + p_edit_rect.size * zero_offset;
Transform2D postxf;
postxf.set_rotation_and_scale(angle, _scale);
@@ -97,25 +120,6 @@ void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) {
_change_notify("position");
}
-bool Node2D::_edit_use_rect() const {
- return true;
-}
-
-void Node2D::_edit_set_rotation(float p_rotation) {
- angle = p_rotation;
- _update_transform();
- _change_notify("rotation");
- _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() {
pos = _mat.elements[2];
@@ -444,10 +448,10 @@ void Node2D::_bind_methods() {
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::VECTOR2, "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_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::VECTOR2, "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");
ADD_GROUP("Z Index", "");
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index f817b214f..725686cdf 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -62,12 +62,16 @@ public:
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_scale(const Size2 &p_scale);
+ virtual Size2 _edit_get_scale() 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_rect(const Rect2 &p_edit_rect);
+
void set_position(const Point2 &p_pos);
void set_rotation(float p_radians);
void set_rotation_degrees(float p_degrees);
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index 052a0ac02..7377591f7 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -57,6 +57,10 @@ Rect2 Path2D::_edit_get_rect() const {
return aabb;
}
+bool Path2D::_edit_use_rect() const {
+ return true;
+}
+
bool Path2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
for (int i = 0; i < curve->get_point_count(); i++) {
@@ -92,7 +96,7 @@ void Path2D::_notification(int p_what) {
#else
const float line_width = 2;
#endif
- const Color color = Color(0.5, 0.6, 1.0, 0.7);
+ const Color color = Color(1.0, 1.0, 1.0, 1.0);
for (int i = 0; i < curve->get_point_count(); i++) {
@@ -147,6 +151,7 @@ void Path2D::_bind_methods() {
Path2D::Path2D() {
set_curve(Ref<Curve2D>(memnew(Curve2D))); //create one by default
+ set_self_modulate(Color(0.5, 0.6, 1.0, 0.7));
}
/////////////////////////////////////////////////////////////////////////////////
diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h
index 735d289d7..64696442c 100644
--- a/scene/2d/path_2d.h
+++ b/scene/2d/path_2d.h
@@ -48,6 +48,7 @@ protected:
public:
virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
void set_curve(const Ref<Curve2D> &p_curve);
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 2cb1e86f5..4d6ebc81c 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -30,7 +30,7 @@
#include "polygon_2d.h"
#include "core/math/geometry.h"
-
+#include "skeleton_2d.h"
Dictionary Polygon2D::_edit_get_state() const {
Dictionary state = Node2D::_edit_get_state();
state["offset"] = offset;
@@ -73,6 +73,10 @@ Rect2 Polygon2D::_edit_get_rect() const {
return item_rect;
}
+bool Polygon2D::_edit_use_rect() const {
+ return true;
+}
+
bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
return Geometry::is_point_in_polygon(p_point - get_offset(), Variant(polygon));
@@ -87,8 +91,20 @@ void Polygon2D::_notification(int p_what) {
if (polygon.size() < 3)
return;
+ Skeleton2D *skeleton_node = NULL;
+ if (has_node(skeleton)) {
+ skeleton_node = Object::cast_to<Skeleton2D>(get_node(skeleton));
+ }
+
+ if (skeleton_node)
+ VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), skeleton_node->get_skeleton());
+ else
+ VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), RID());
+
Vector<Vector2> points;
Vector<Vector2> uvs;
+ Vector<int> bones;
+ Vector<float> weights;
points.resize(polygon.size());
@@ -176,6 +192,70 @@ void Polygon2D::_notification(int p_what) {
}
}
+ if (!invert && bone_weights.size()) {
+ //a skeleton is set! fill indices and weights
+ int vc = points.size();
+ bones.resize(vc * 4);
+ weights.resize(vc * 4);
+
+ int *bonesw = bones.ptrw();
+ float *weightsw = weights.ptrw();
+
+ for (int i = 0; i < vc * 4; i++) {
+ bonesw[i] = 0;
+ weightsw[i] = 0;
+ }
+
+ for (int i = 0; i < bone_weights.size(); i++) {
+ if (bone_weights[i].weights.size() != points.size()) {
+ continue; //different number of vertices, sorry not using.
+ }
+ if (!skeleton_node->has_node(bone_weights[i].path)) {
+ continue; //node does not exist
+ }
+ Bone2D *bone = Object::cast_to<Bone2D>(skeleton_node->get_node(bone_weights[i].path));
+ if (!bone) {
+ continue;
+ }
+
+ int bone_index = bone->get_index_in_skeleton();
+ PoolVector<float>::Read r = bone_weights[i].weights.read();
+ for (int j = 0; j < vc; j++) {
+ if (r[j] == 0.0)
+ continue; //weight is unpainted, skip
+ //find an index with a weight
+ for (int k = 0; k < 4; k++) {
+ if (weightsw[j * 4 + k] < r[j]) {
+ //this is less than this weight, insert weight!
+ for (int l = 3; l > k; l--) {
+ weightsw[j * 4 + l] = weightsw[j * 4 + l - 1];
+ bonesw[j * 4 + l] = bonesw[j * 4 + l - 1];
+ }
+ weightsw[j * 4 + k] = r[j];
+ bonesw[j * 4 + k] = bone_index;
+ break;
+ }
+ }
+ }
+ }
+
+ //normalize the weights
+ for (int i = 0; i < vc; i++) {
+ float tw = 0;
+ for (int j = 0; j < 4; j++) {
+ tw += weightsw[i * 4 + j];
+ }
+ if (tw == 0)
+ continue; //unpainted, do nothing
+
+ //normalize
+ for (int j = 0; j < 4; j++) {
+ weightsw[i * 4 + j] /= tw;
+ // print_line("point " + itos(i) + " idx " + itos(j) + " index: " + itos(bonesw[i * 4 + j]) + " weight: " + rtos(weightsw[i * 4 + j]));
+ }
+ }
+ }
+
Vector<Color> colors;
int color_len = vertex_colors.size();
colors.resize(len);
@@ -193,7 +273,8 @@ void Polygon2D::_notification(int p_what) {
// VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID());
if (invert || splits.size() == 0) {
- VS::get_singleton()->canvas_item_add_polygon(get_canvas_item(), points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID(), RID(), antialiased);
+ Vector<int> indices = Geometry::triangulate_polygon(points);
+ VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
} else {
//use splits
Vector<int> loop;
@@ -264,7 +345,7 @@ void Polygon2D::_notification(int p_what) {
//print_line("loops: " + itos(loops.size()) + " indices: " + itos(indices.size()));
- VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID());
+ VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
}
} break;
@@ -426,6 +507,74 @@ Vector2 Polygon2D::get_offset() const {
return offset;
}
+void Polygon2D::add_bone(const NodePath &p_path, const PoolVector<float> &p_weights) {
+
+ Bone bone;
+ bone.path = p_path;
+ bone.weights = p_weights;
+ bone_weights.push_back(bone);
+}
+int Polygon2D::get_bone_count() const {
+ return bone_weights.size();
+}
+NodePath Polygon2D::get_bone_path(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, bone_weights.size(), NodePath());
+ return bone_weights[p_index].path;
+}
+PoolVector<float> Polygon2D::get_bone_weights(int p_index) const {
+
+ ERR_FAIL_INDEX_V(p_index, bone_weights.size(), PoolVector<float>());
+ return bone_weights[p_index].weights;
+}
+void Polygon2D::erase_bone(int p_idx) {
+
+ ERR_FAIL_INDEX(p_idx, bone_weights.size());
+ bone_weights.remove(p_idx);
+}
+
+void Polygon2D::clear_bones() {
+ bone_weights.clear();
+}
+
+void Polygon2D::set_bone_weights(int p_index, const PoolVector<float> &p_weights) {
+ ERR_FAIL_INDEX(p_index, bone_weights.size());
+ bone_weights[p_index].weights = p_weights;
+ update();
+}
+void Polygon2D::set_bone_path(int p_index, const NodePath &p_path) {
+ ERR_FAIL_INDEX(p_index, bone_weights.size());
+ bone_weights[p_index].path = p_path;
+ update();
+}
+
+Array Polygon2D::_get_bones() const {
+ Array bones;
+ for (int i = 0; i < get_bone_count(); i++) {
+ bones.push_back(get_bone_path(i));
+ bones.push_back(get_bone_weights(i));
+ }
+ return bones;
+}
+void Polygon2D::_set_bones(const Array &p_bones) {
+
+ ERR_FAIL_COND(p_bones.size() & 1);
+ clear_bones();
+ for (int i = 0; i < p_bones.size(); i += 2) {
+ add_bone(p_bones[i], p_bones[i + 1]);
+ }
+}
+
+void Polygon2D::set_skeleton(const NodePath &p_skeleton) {
+ if (skeleton == p_skeleton)
+ return;
+ skeleton = p_skeleton;
+ update();
+}
+
+NodePath Polygon2D::get_skeleton() const {
+ return skeleton;
+}
+
void Polygon2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &Polygon2D::set_polygon);
@@ -470,6 +619,21 @@ void Polygon2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_offset", "offset"), &Polygon2D::set_offset);
ClassDB::bind_method(D_METHOD("get_offset"), &Polygon2D::get_offset);
+ ClassDB::bind_method(D_METHOD("add_bone", "path", "weights"), &Polygon2D::add_bone);
+ ClassDB::bind_method(D_METHOD("get_bone_count"), &Polygon2D::get_bone_count);
+ ClassDB::bind_method(D_METHOD("get_bone_path", "index"), &Polygon2D::get_bone_path);
+ ClassDB::bind_method(D_METHOD("get_bone_weights", "index"), &Polygon2D::get_bone_weights);
+ ClassDB::bind_method(D_METHOD("erase_bone", "index"), &Polygon2D::erase_bone);
+ ClassDB::bind_method(D_METHOD("clear_bones"), &Polygon2D::clear_bones);
+ ClassDB::bind_method(D_METHOD("set_bone_path", "index", "path"), &Polygon2D::set_bone_path);
+ ClassDB::bind_method(D_METHOD("set_bone_weights", "index", "weights"), &Polygon2D::set_bone_weights);
+
+ ClassDB::bind_method(D_METHOD("set_skeleton", "skeleton"), &Polygon2D::set_skeleton);
+ ClassDB::bind_method(D_METHOD("get_skeleton"), &Polygon2D::get_skeleton);
+
+ ClassDB::bind_method(D_METHOD("_set_bones", "bones"), &Polygon2D::_set_bones);
+ ClassDB::bind_method(D_METHOD("_get_bones"), &Polygon2D::_get_bones);
+
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "uv"), "set_uv", "get_uv");
ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "splits"), "set_splits", "get_splits");
@@ -484,10 +648,14 @@ void Polygon2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_scale"), "set_texture_scale", "get_texture_scale");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_rotation_degrees", PROPERTY_HINT_RANGE, "-1440,1440,0.1"), "set_texture_rotation_degrees", "get_texture_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_rotation", PROPERTY_HINT_NONE, "", 0), "set_texture_rotation", "get_texture_rotation");
+ ADD_GROUP("Skeleton", "");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton"), "set_skeleton", "get_skeleton");
ADD_GROUP("Invert", "invert_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_enable"), "set_invert", "get_invert");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "invert_border", PROPERTY_HINT_RANGE, "0.1,16384,0.1"), "set_invert_border", "get_invert_border");
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_bones", "_get_bones");
}
Polygon2D::Polygon2D() {
diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h
index 3a2417754..575f71d74 100644
--- a/scene/2d/polygon_2d.h
+++ b/scene/2d/polygon_2d.h
@@ -42,6 +42,13 @@ class Polygon2D : public Node2D {
PoolVector<Color> vertex_colors;
PoolVector<int> splits;
+ struct Bone {
+ NodePath path;
+ PoolVector<float> weights;
+ };
+
+ Vector<Bone> bone_weights;
+
Color color;
Ref<Texture> texture;
Size2 tex_scale;
@@ -56,6 +63,11 @@ class Polygon2D : public Node2D {
mutable bool rect_cache_dirty;
mutable Rect2 item_rect;
+ NodePath skeleton;
+
+ Array _get_bones() const;
+ void _set_bones(const Array &p_bones);
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -68,6 +80,7 @@ public:
virtual Point2 _edit_get_pivot() const;
virtual bool _edit_use_pivot() const;
virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
@@ -113,6 +126,18 @@ public:
void set_offset(const Vector2 &p_offset);
Vector2 get_offset() const;
+ void add_bone(const NodePath &p_path = NodePath(), const PoolVector<float> &p_weights = PoolVector<float>());
+ int get_bone_count() const;
+ NodePath get_bone_path(int p_index) const;
+ PoolVector<float> get_bone_weights(int p_index) const;
+ void erase_bone(int p_idx);
+ void clear_bones();
+ void set_bone_weights(int p_index, const PoolVector<float> &p_weights);
+ void set_bone_path(int p_index, const NodePath &p_path);
+
+ void set_skeleton(const NodePath &p_skeleton);
+ NodePath get_skeleton() const;
+
Polygon2D();
};
diff --git a/scene/2d/position_2d.cpp b/scene/2d/position_2d.cpp
index 37f6aaa2d..64d23719e 100644
--- a/scene/2d/position_2d.cpp
+++ b/scene/2d/position_2d.cpp
@@ -44,6 +44,10 @@ Rect2 Position2D::_edit_get_rect() const {
return Rect2(Point2(-10, -10), Size2(20, 20));
}
+bool Position2D::_edit_use_rect() const {
+ return false;
+}
+
void Position2D::_notification(int p_what) {
switch (p_what) {
diff --git a/scene/2d/position_2d.h b/scene/2d/position_2d.h
index 6f6a34c45..bff474ccc 100644
--- a/scene/2d/position_2d.h
+++ b/scene/2d/position_2d.h
@@ -44,6 +44,7 @@ protected:
public:
virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
Position2D();
};
diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp
index b6cb734ce..9480f1817 100644
--- a/scene/2d/screen_button.cpp
+++ b/scene/2d/screen_button.cpp
@@ -335,6 +335,10 @@ Rect2 TouchScreenButton::_edit_get_rect() const {
return Rect2(Size2(), texture->get_size());
}
+bool TouchScreenButton::_edit_use_rect() const {
+ return true;
+}
+
void TouchScreenButton::set_visibility_mode(VisibilityMode p_mode) {
visibility = p_mode;
update();
diff --git a/scene/2d/screen_button.h b/scene/2d/screen_button.h
index e6f2a2f3c..b2fafcc93 100644
--- a/scene/2d/screen_button.h
+++ b/scene/2d/screen_button.h
@@ -104,6 +104,7 @@ public:
bool is_pressed() const;
Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
TouchScreenButton();
};
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index 705e82bcb..2363c791f 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -12,6 +12,8 @@ void Bone2D::_notification(int p_what) {
break;
if (!Object::cast_to<Bone2D>(parent))
break; //skeletons must be chained to Bone2Ds.
+
+ parent = parent->get_parent();
}
if (skeleton) {
@@ -26,6 +28,11 @@ void Bone2D::_notification(int p_what) {
skeleton->_make_transform_dirty();
}
}
+ if (p_what == NOTIFICATION_MOVED_IN_PARENT) {
+ if (skeleton) {
+ skeleton->_make_bone_setup_dirty();
+ }
+ }
if (p_what == NOTIFICATION_EXIT_TREE) {
if (skeleton) {
@@ -46,12 +53,22 @@ void Bone2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_rest", "rest"), &Bone2D::set_rest);
ClassDB::bind_method(D_METHOD("get_rest"), &Bone2D::get_rest);
ClassDB::bind_method(D_METHOD("apply_rest"), &Bone2D::apply_rest);
+ ClassDB::bind_method(D_METHOD("get_skeleton_rest"), &Bone2D::get_skeleton_rest);
+ ClassDB::bind_method(D_METHOD("get_index_in_skeleton"), &Bone2D::get_index_in_skeleton);
+
+ ClassDB::bind_method(D_METHOD("set_default_length", "default_length"), &Bone2D::set_default_length);
+ ClassDB::bind_method(D_METHOD("get_default_length"), &Bone2D::get_default_length);
+
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D,"rest"),"set_rest","get_rest");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"default_length",PROPERTY_HINT_RANGE,"1,1024,1"),"set_default_length","get_default_length");
}
void Bone2D::set_rest(const Transform2D &p_rest) {
rest = p_rest;
if (skeleton)
skeleton->_make_bone_setup_dirty();
+
+ update_configuration_warning();
}
Transform2D Bone2D::get_rest() const {
@@ -71,22 +88,56 @@ void Bone2D::apply_rest() {
set_transform(rest);
}
+void Bone2D::set_default_length(float p_length) {
+
+ default_length=p_length;
+
+}
+
+float Bone2D::get_default_length() const {
+ return default_length;
+}
+
+int Bone2D::get_index_in_skeleton() const {
+ ERR_FAIL_COND_V(!skeleton,-1);
+ skeleton->_update_bone_setup();
+ return skeleton_index;
+}
String Bone2D::get_configuration_warning() const {
+
+ String warning = Node2D::get_configuration_warning();
if (!skeleton) {
+ if (warning!=String()) {
+ warning+="\n";
+ }
if (parent_bone) {
- return TTR("This Bone2D chain should end at a Skeleton2D node.");
+ warning+=TTR("This Bone2D chain should end at a Skeleton2D node.");
} else {
- return TTR("A Bone2D only works with a Skeleton2D or another Bone2D as parent node.");
+ warning+=TTR("A Bone2D only works with a Skeleton2D or another Bone2D as parent node.");
+ }
+ }
+
+ if (rest==Transform2D(0,0,0,0,0,0)) {
+ if (warning!=String()) {
+ warning+="\n";
}
+ warning+=TTR("This bone lacks a proper REST pose. Go to the Skeleton2D node and set one.");
+
}
- return Node2D::get_configuration_warning();
+ return warning;
}
Bone2D::Bone2D() {
skeleton = NULL;
parent_bone = NULL;
+ skeleton_index=-1;
+ default_length=16;
set_notify_local_transform(true);
+ //this is a clever hack so the bone knows no rest has been set yet, allowing to show an error.
+ for(int i=0;i<3;i++) {
+ rest[i]=Vector2(0,0);
+ }
}
//////////////////////////////////////
@@ -112,7 +163,14 @@ void Skeleton2D::_update_bone_setup() {
bones.sort(); //sorty so they are always in the same order/index
for (int i = 0; i < bones.size(); i++) {
- bones[i].rest_inverse = bones[i].bone->get_skeleton_rest(); //bind pose
+ bones[i].rest_inverse = bones[i].bone->get_skeleton_rest().affine_inverse(); //bind pose
+ bones[i].bone->skeleton_index=i;
+ Bone2D *parent_bone = Object::cast_to<Bone2D>(bones[i].bone->get_parent());
+ if (parent_bone) {
+ bones[i].parent_index=parent_bone->skeleton_index;
+ } else {
+ bones[i].parent_index=-1;
+ }
}
transform_dirty = true;
@@ -140,13 +198,20 @@ void Skeleton2D::_update_transform() {
transform_dirty = false;
- Transform2D global_xform = get_global_transform();
- Transform2D global_xform_inverse = global_xform.affine_inverse();
+ for (int i = 0; i < bones.size(); i++) {
+
+ ERR_CONTINUE(bones[i].parent_index>=i);
+ if (bones[i].parent_index>=0) {
+ bones[i].accum_transform = bones[bones[i].parent_index].accum_transform * bones[i].bone->get_transform();
+ } else {
+ bones[i].accum_transform = bones[i].bone->get_transform();
+ }
+ }
for (int i = 0; i < bones.size(); i++) {
- Transform2D final_xform = bones[i].rest_inverse * bones[i].bone->get_relative_transform_to_parent(this);
- VS::get_singleton()->skeleton_bone_set_transform_2d(skeleton, i, global_xform * (final_xform * global_xform_inverse));
+ Transform2D final_xform = bones[i].accum_transform * bones[i].rest_inverse;
+ VS::get_singleton()->skeleton_bone_set_transform_2d(skeleton, i, final_xform);
}
}
@@ -177,10 +242,12 @@ void Skeleton2D::_notification(int p_what) {
_update_bone_setup();
if (transform_dirty)
_update_transform();
+
+ request_ready();
}
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
- _make_transform_dirty();
+ VS::get_singleton()->skeleton_set_base_transform_2d(skeleton,get_global_transform());
}
}
@@ -201,6 +268,7 @@ void Skeleton2D::_bind_methods() {
Skeleton2D::Skeleton2D() {
bone_setup_dirty = true;
transform_dirty = true;
+
skeleton = VS::get_singleton()->skeleton_create();
}
diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h
index 49199f684..cd270dac8 100644
--- a/scene/2d/skeleton_2d.h
+++ b/scene/2d/skeleton_2d.h
@@ -11,6 +11,10 @@ class Bone2D : public Node2D {
Bone2D *parent_bone;
Skeleton2D *skeleton;
Transform2D rest;
+ float default_length;
+
+friend class Skeleton2D;
+ int skeleton_index;
protected:
void _notification(int p_what);
@@ -24,6 +28,11 @@ public:
String get_configuration_warning() const;
+ void set_default_length(float p_length);
+ float get_default_length() const;
+
+ int get_index_in_skeleton() const;
+
Bone2D();
};
@@ -37,6 +46,8 @@ class Skeleton2D : public Node2D {
return p_bone.bone->is_greater_than(bone);
}
Bone2D *bone;
+ int parent_index;
+ Transform2D accum_transform;
Transform2D rest_inverse;
};
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index 67f016ae7..bc39368c8 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -58,6 +58,14 @@ bool Sprite::_edit_use_pivot() const {
return true;
}
+Rect2 Sprite::_edit_get_rect() const {
+ return get_rect();
+}
+
+bool Sprite::_edit_use_rect() const {
+ return true;
+}
+
void Sprite::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const {
Size2 s;
@@ -323,7 +331,31 @@ bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc
}
ERR_FAIL_COND_V(image.is_null(), false);
+ if (image->is_compressed()) {
+ return dst_rect.has_point(p_point);
+ }
+ bool is_repeat = texture->get_flags() & Texture::FLAG_REPEAT;
+ bool is_mirrored_repeat = texture->get_flags() & Texture::FLAG_MIRRORED_REPEAT;
+ if (is_repeat) {
+ int mirror_x = 0;
+ int mirror_y = 0;
+ if (is_mirrored_repeat) {
+ mirror_x = (int)(q.x / texture->get_size().width);
+ mirror_y = (int)(q.y / texture->get_size().height);
+ }
+ q.x = Math::fmod(q.x, texture->get_size().width);
+ q.y = Math::fmod(q.y, texture->get_size().height);
+ if (mirror_x % 2 == 1) {
+ q.x = texture->get_size().width - q.x - 1;
+ }
+ if (mirror_y % 2 == 1) {
+ q.y = texture->get_size().height - q.y - 1;
+ }
+ } else {
+ q.x = MIN(q.x, texture->get_size().width - 1);
+ q.y = MIN(q.y, texture->get_size().height - 1);
+ }
image->lock();
const Color c = image->get_pixel((int)q.x, (int)q.y);
image->unlock();
diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h
index abd04515e..609ad8bb3 100644
--- a/scene/2d/sprite.h
+++ b/scene/2d/sprite.h
@@ -74,7 +74,9 @@ public:
virtual Point2 _edit_get_pivot() const;
virtual bool _edit_use_pivot() const;
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
- virtual Rect2 _edit_get_rect() const { return get_rect(); }
+
+ virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
void set_texture(const Ref<Texture> &p_texture);
Ref<Texture> get_texture() const;
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index c126dd8f6..3d3f43d5c 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -304,6 +304,7 @@ void TileMap::_update_dirty_quadrants() {
}
q.occluder_instances.clear();
Ref<ShaderMaterial> prev_material;
+ int prev_z_index;
RID prev_canvas_item;
RID prev_debug_canvas_item;
@@ -324,11 +325,12 @@ void TileMap::_update_dirty_quadrants() {
continue;
Ref<ShaderMaterial> mat = tile_set->tile_get_material(c.id);
+ int z_index = tile_set->tile_get_z_index(c.id);
RID canvas_item;
RID debug_canvas_item;
- if (prev_canvas_item == RID() || prev_material != mat) {
+ if (prev_canvas_item == RID() || prev_material != mat || prev_z_index != z_index) {
canvas_item = vs->canvas_item_create();
if (mat.is_valid())
@@ -339,6 +341,7 @@ void TileMap::_update_dirty_quadrants() {
xform.set_origin(q.pos);
vs->canvas_item_set_transform(canvas_item, xform);
vs->canvas_item_set_light_mask(canvas_item, get_light_mask());
+ vs->canvas_item_set_z_index(canvas_item, z_index);
q.canvas_items.push_back(canvas_item);
@@ -354,6 +357,7 @@ void TileMap::_update_dirty_quadrants() {
prev_canvas_item = canvas_item;
prev_material = mat;
+ prev_z_index = z_index;
} else {
canvas_item = prev_canvas_item;
@@ -1119,6 +1123,10 @@ Rect2 TileMap::_edit_get_rect() const {
return rect_cache;
}
+bool TileMap::_edit_use_rect() const {
+ return true;
+}
+
void TileMap::set_collision_layer(uint32_t p_layer) {
collision_layer = p_layer;
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 587bd3b68..07947004b 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -245,6 +245,7 @@ public:
int get_cellv(const Vector2 &p_pos) const;
Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
void make_bitmask_area_dirty(const Vector2 &p_pos);
void update_bitmask_area(const Vector2 &p_pos);
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index 4b38534d9..ddca97e60 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -89,6 +89,10 @@ Rect2 VisibilityNotifier2D::_edit_get_rect() const {
return rect;
}
+bool VisibilityNotifier2D::_edit_use_rect() const {
+ return true;
+}
+
Rect2 VisibilityNotifier2D::get_rect() const {
return rect;
diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h
index 93a35a709..c4e12dfa2 100644
--- a/scene/2d/visibility_notifier_2d.h
+++ b/scene/2d/visibility_notifier_2d.h
@@ -56,6 +56,7 @@ protected:
public:
virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_use_rect() const;
void set_rect(const Rect2 &p_rect);
Rect2 get_rect() const;
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index 109bf3adc..1b506e0c4 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -132,9 +132,9 @@ public:
virtual Transform get_camera_transform() const;
- Vector3 project_ray_normal(const Point2 &p_pos) const;
+ virtual Vector3 project_ray_normal(const Point2 &p_pos) const;
virtual Vector3 project_ray_origin(const Point2 &p_pos) const;
- Vector3 project_local_ray_normal(const Point2 &p_pos) const;
+ virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const;
virtual Point2 unproject_position(const Vector3 &p_pos) const;
bool is_position_behind(const Vector3 &p_pos) const;
virtual Vector3 project_position(const Point2 &p_point) const;
diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp
index 3a77360bc..379dd21c3 100644
--- a/scene/3d/collision_polygon.cpp
+++ b/scene/3d/collision_polygon.cpp
@@ -173,6 +173,9 @@ String CollisionPolygon::get_configuration_warning() const {
return String();
}
+bool CollisionPolygon::_is_editable_3d_polygon() const {
+ return true;
+}
void CollisionPolygon::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_depth", "depth"), &CollisionPolygon::set_depth);
@@ -184,6 +187,8 @@ void CollisionPolygon::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionPolygon::set_disabled);
ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionPolygon::is_disabled);
+ ClassDB::bind_method(D_METHOD("_is_editable_3d_polygon"), &CollisionPolygon::_is_editable_3d_polygon);
+
ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth"), "set_depth", "get_depth");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h
index 971c67f1a..f1f137c9c 100644
--- a/scene/3d/collision_polygon.h
+++ b/scene/3d/collision_polygon.h
@@ -53,6 +53,8 @@ protected:
void _update_in_shape_owner(bool p_xform_only = false);
+ bool _is_editable_3d_polygon() const;
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp
index 693b416f6..a39ac5a8f 100644
--- a/scene/3d/particles.cpp
+++ b/scene/3d/particles.cpp
@@ -1028,8 +1028,6 @@ void ParticlesMaterial::set_param(Parameter p_param, float p_value) {
case PARAM_ANIM_OFFSET: {
VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset, p_value);
} break;
- case PARAM_MAX: {
- };
}
}
float ParticlesMaterial::get_param(Parameter p_param) const {
@@ -1082,8 +1080,6 @@ void ParticlesMaterial::set_param_randomness(Parameter p_param, float p_value) {
case PARAM_ANIM_OFFSET: {
VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_random, p_value);
} break;
- case PARAM_MAX: {
- };
}
}
float ParticlesMaterial::get_param_randomness(Parameter p_param) const {
@@ -1160,8 +1156,6 @@ void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture>
case PARAM_ANIM_OFFSET: {
VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, p_texture);
} break;
- case PARAM_MAX: {
- };
}
_queue_shader_change();
@@ -1233,28 +1227,19 @@ void ParticlesMaterial::set_emission_box_extents(Vector3 p_extents) {
void ParticlesMaterial::set_emission_point_texture(const Ref<Texture> &p_points) {
emission_point_texture = p_points;
- RID texture;
- if (p_points.is_valid())
- texture = p_points->get_rid();
- VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, texture);
+ VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, p_points);
}
void ParticlesMaterial::set_emission_normal_texture(const Ref<Texture> &p_normals) {
emission_normal_texture = p_normals;
- RID texture;
- if (p_normals.is_valid())
- texture = p_normals->get_rid();
- VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, texture);
+ VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, p_normals);
}
void ParticlesMaterial::set_emission_color_texture(const Ref<Texture> &p_colors) {
emission_color_texture = p_colors;
- RID texture;
- if (p_colors.is_valid())
- texture = p_colors->get_rid();
- VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, texture);
+ VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, p_colors);
_queue_shader_change();
}
@@ -1316,10 +1301,7 @@ void ParticlesMaterial::set_trail_size_modifier(const Ref<CurveTexture> &p_trail
curve->ensure_default_setup();
}
- RID texture;
- if (p_trail_size_modifier.is_valid())
- texture = p_trail_size_modifier->get_rid();
- VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_size_modifier, texture);
+ VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_size_modifier, curve);
_queue_shader_change();
}
@@ -1331,10 +1313,7 @@ Ref<CurveTexture> ParticlesMaterial::get_trail_size_modifier() const {
void ParticlesMaterial::set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier) {
trail_color_modifier = p_trail_color_modifier;
- RID texture;
- if (p_trail_color_modifier.is_valid())
- texture = p_trail_color_modifier->get_rid();
- VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_color_modifier, texture);
+ VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_color_modifier, p_trail_color_modifier);
_queue_shader_change();
}
diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp
index 7ac7f74bb..57d79c960 100644
--- a/scene/3d/path.cpp
+++ b/scene/3d/path.cpp
@@ -40,6 +40,9 @@ void Path::_curve_changed() {
if (is_inside_tree() && Engine::get_singleton()->is_editor_hint())
update_gizmo();
+ if (is_inside_tree()) {
+ emit_signal("curve_changed");
+ }
}
void Path::set_curve(const Ref<Curve3D> &p_curve) {
@@ -68,6 +71,8 @@ void Path::_bind_methods() {
ClassDB::bind_method(D_METHOD("_curve_changed"), &Path::_curve_changed);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve3D"), "set_curve", "get_curve");
+
+ ADD_SIGNAL(MethodInfo("curve_changed"));
}
Path::Path() {
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index f8a5c7f40..5deeb75c6 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -85,9 +85,7 @@ void Spatial::_notify_dirty() {
}
void Spatial::_update_local_transform() const {
- data.local_transform.basis = Basis();
- data.local_transform.basis.scale(data.scale);
- data.local_transform.basis.rotate(data.rotation);
+ data.local_transform.basis.set_euler_scale(data.rotation, data.scale);
data.dirty &= ~DIRTY_LOCAL;
}
@@ -432,10 +430,9 @@ Ref<SpatialGizmo> Spatial::get_gizmo() const {
#endif
}
-#ifdef TOOLS_ENABLED
-
void Spatial::_update_gizmo() {
+#ifdef TOOLS_ENABLED
if (!is_inside_world())
return;
data.gizmo_dirty = false;
@@ -447,8 +444,10 @@ void Spatial::_update_gizmo() {
data.gizmo->clear();
}
}
+#endif
}
+#ifdef TOOLS_ENABLED
void Spatial::set_disable_gizmo(bool p_enabled) {
data.gizmo_disabled = p_enabled;
@@ -728,9 +727,7 @@ 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);
-#ifdef TOOLS_ENABLED
ClassDB::bind_method(D_METHOD("_update_gizmo"), &Spatial::_update_gizmo);
-#endif
ClassDB::bind_method(D_METHOD("update_gizmo"), &Spatial::update_gizmo);
ClassDB::bind_method(D_METHOD("set_gizmo", "gizmo"), &Spatial::set_gizmo);
@@ -792,9 +789,7 @@ void Spatial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale");
ADD_GROUP("Visibility", "");
ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
-#ifdef TOOLS_ENABLED
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "SpatialGizmo", 0), "set_gizmo", "get_gizmo");
-#endif
ADD_SIGNAL(MethodInfo("visibility_changed"));
}
diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h
index 518bba9a5..ca35d8534 100644
--- a/scene/3d/spatial.h
+++ b/scene/3d/spatial.h
@@ -100,10 +100,8 @@ class Spatial : public Node {
#endif
} data;
-#ifdef TOOLS_ENABLED
void _update_gizmo();
-#endif
void _notify_dirty();
void _propagate_transform_changed(Spatial *p_origin);
diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp
index d389b69ef..13700e0bd 100644
--- a/scene/3d/voxel_light_baker.cpp
+++ b/scene/3d/voxel_light_baker.cpp
@@ -2338,9 +2338,9 @@ Ref<MultiMesh> VoxelLightBaker::create_debug_multimesh(DebugMode p_mode) {
for (int k = 0; k < 3; k++) {
if (i < 3)
- face_points[j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
+ face_points[j][(i + k) % 3] = v[k];
else
- face_points[3 - j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
+ face_points[3 - j][(i + k) % 3] = -v[k];
}
}
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 63580bcae..eca7caeaf 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -590,9 +590,7 @@ void AnimationPlayer::_animation_update_transforms() {
Transform t;
t.origin = nc->loc_accum;
- t.basis.scale(nc->scale_accum);
- t.basis.rotate(nc->rot_accum.get_euler());
-
+ t.basis.set_quat_scale(nc->rot_accum, nc->scale_accum);
if (nc->skeleton && nc->bone_idx >= 0) {
nc->skeleton->set_bone_pose(nc->bone_idx, t);
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index e811b7a7b..afdb8b6f7 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -812,8 +812,6 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
t.value = t.object->get_indexed(t.subpath);
t.value.zero();
-
- t.skip = false;
}
/* STEP 2 PROCESS ANIMATIONS */
@@ -886,7 +884,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
Track &t = E->get();
- if (t.skip || !t.object)
+ if (!t.object)
continue;
if (t.subpath.size()) { // value track
@@ -900,8 +898,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
t.scale.x += 1.0;
t.scale.y += 1.0;
t.scale.z += 1.0;
- xform.basis.scale(t.scale);
- xform.basis.rotate(t.rot.get_euler());
+ xform.basis.set_quat_scale(t.rot, t.scale);
if (t.bone_idx >= 0) {
if (t.skeleton)
diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h
index 09d6f6fcb..873ff8a9d 100644
--- a/scene/animation/animation_tree_player.h
+++ b/scene/animation/animation_tree_player.h
@@ -107,8 +107,6 @@ private:
Vector3 scale;
Variant value;
-
- bool skip;
};
typedef Map<TrackKey, Track> TrackMap;
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 31be18612..6f34f3e49 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -660,6 +660,11 @@ void ColorPickerButton::_color_changed(const Color &p_color) {
emit_signal("color_changed", p_color);
}
+void ColorPickerButton::_modal_closed() {
+
+ emit_signal("popup_closed");
+}
+
void ColorPickerButton::pressed() {
popup->set_position(get_global_position() - picker->get_combined_minimum_size());
@@ -722,8 +727,10 @@ void ColorPickerButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPickerButton::set_edit_alpha);
ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPickerButton::is_editing_alpha);
ClassDB::bind_method(D_METHOD("_color_changed"), &ColorPickerButton::_color_changed);
+ ClassDB::bind_method(D_METHOD("_modal_closed"), &ColorPickerButton::_modal_closed);
ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color")));
+ ADD_SIGNAL(MethodInfo("popup_closed"));
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_pick_color", "get_pick_color");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha");
}
@@ -735,5 +742,7 @@ ColorPickerButton::ColorPickerButton() {
popup->add_child(picker);
picker->connect("color_changed", this, "_color_changed");
+ popup->connect("modal_closed", this, "_modal_closed");
+
add_child(popup);
}
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 40ded4fff..7d1a554ad 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -120,6 +120,8 @@ class ColorPickerButton : public Button {
ColorPicker *picker;
void _color_changed(const Color &p_color);
+ void _modal_closed();
+
virtual void pressed();
protected:
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 6ca6d8280..b7c1d35fd 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -94,6 +94,14 @@ Point2 Control::_edit_get_position() const {
return get_position();
};
+void Control::_edit_set_scale(const Size2 &p_scale) {
+ set_scale(p_scale);
+}
+
+Size2 Control::_edit_get_scale() const {
+ return data.scale;
+}
+
void Control::_edit_set_rect(const Rect2 &p_edit_rect) {
set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1)));
set_size(p_edit_rect.size.snapped(Vector2(1, 1)));
diff --git a/scene/gui/control.h b/scene/gui/control.h
index a21549029..b5453e60f 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -283,6 +283,9 @@ public:
virtual void _edit_set_position(const Point2 &p_position);
virtual Point2 _edit_get_position() const;
+ virtual void _edit_set_scale(const Size2 &p_scale);
+ virtual Size2 _edit_get_scale() const;
+
virtual void _edit_set_rect(const Rect2 &p_edit_rect);
virtual Rect2 _edit_get_rect() const;
virtual bool _edit_use_rect() const;
diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp
index b401abd43..278e4123d 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -36,6 +36,8 @@ void GridContainer::_notification(int p_what) {
case NOTIFICATION_SORT_CHILDREN: {
+ int valid_controls_index;
+
Map<int, int> col_minw; // max of min_width of all controls in each col (indexed by col)
Map<int, int> row_minh; // max of min_height of all controls in each row (indexed by row)
Set<int> col_expanded; // columns which have the SIZE_EXPAND flag set
@@ -47,13 +49,15 @@ void GridContainer::_notification(int p_what) {
int max_row = get_child_count() / columns;
// Compute the per-column/per-row data
+ valid_controls_index = 0;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
if (!c || !c->is_visible_in_tree())
continue;
- int row = i / columns;
- int col = i % columns;
+ int row = valid_controls_index / columns;
+ int col = valid_controls_index % columns;
+ valid_controls_index++;
Size2i ms = c->get_combined_minimum_size();
if (col_minw.has(col))
@@ -136,12 +140,14 @@ void GridContainer::_notification(int p_what) {
int col_ofs = 0;
int row_ofs = 0;
+ valid_controls_index = 0;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
if (!c || !c->is_visible_in_tree())
continue;
- int row = i / columns;
- int col = i % columns;
+ int row = valid_controls_index / columns;
+ int col = valid_controls_index % columns;
+ valid_controls_index++;
if (col == 0) {
col_ofs = 0;
@@ -178,6 +184,8 @@ void GridContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_columns", "columns"), &GridContainer::set_columns);
ClassDB::bind_method(D_METHOD("get_columns"), &GridContainer::get_columns);
+ ClassDB::bind_method(D_METHOD("get_child_control_at_cell", "row", "column"),
+ &GridContainer::get_child_control_at_cell);
ADD_PROPERTY(PropertyInfo(Variant::INT, "columns", PROPERTY_HINT_RANGE, "1,1024,1"), "set_columns", "get_columns");
}
@@ -190,17 +198,19 @@ Size2 GridContainer::get_minimum_size() const {
int hsep = get_constant("hseparation");
int vsep = get_constant("vseparation");
- int idx = 0;
int max_row = 0;
int max_col = 0;
+ int valid_controls_index = 0;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
if (!c || !c->is_visible_in_tree())
continue;
- int row = idx / columns;
- int col = idx % columns;
+ int row = valid_controls_index / columns;
+ int col = valid_controls_index % columns;
+ valid_controls_index++;
+
Size2i ms = c->get_combined_minimum_size();
if (col_minw.has(col))
col_minw[col] = MAX(col_minw[col], ms.width);
@@ -213,7 +223,6 @@ Size2 GridContainer::get_minimum_size() const {
row_minh[row] = ms.height;
max_col = MAX(col, max_col);
max_row = MAX(row, max_row);
- idx++;
}
Size2 ms;
@@ -232,6 +241,21 @@ Size2 GridContainer::get_minimum_size() const {
return ms;
}
+Control *GridContainer::get_child_control_at_cell(int row, int column) {
+ Control *c;
+ int grid_index = row * columns + column;
+ for (int i = 0; i < get_child_count(); i++) {
+ c = Object::cast_to<Control>(get_child(i));
+ if (!c || !c->is_visible_in_tree())
+ continue;
+
+ if (grid_index == i) {
+ break;
+ }
+ }
+ return c;
+}
+
GridContainer::GridContainer() {
set_mouse_filter(MOUSE_FILTER_PASS);
diff --git a/scene/gui/grid_container.h b/scene/gui/grid_container.h
index 243d06f03..7e3470dc8 100644
--- a/scene/gui/grid_container.h
+++ b/scene/gui/grid_container.h
@@ -47,6 +47,7 @@ public:
void set_columns(int p_columns);
int get_columns() const;
virtual Size2 get_minimum_size() const;
+ Control *get_child_control_at_cell(int row, int column);
GridContainer();
};
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index ecd98f054..511dc248a 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -678,7 +678,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
search_string = ""; //any mousepress cancels
- if (current % current_columns != (current_columns - 1)) {
+ if (current % current_columns != (current_columns - 1) && current + 1 < items.size()) {
set_current(current + 1);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 09c6a3b32..1ceb3f0a8 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -215,6 +215,12 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
case (KEY_A): { //Select All
select();
} break;
+ case (KEY_LEFT): { // Go to start of text - like HOME key
+ set_cursor_position(0);
+ } break;
+ case (KEY_RIGHT): { // Go to end of text - like END key
+ set_cursor_position(text.length());
+ } break;
default: { handled = false; }
}
@@ -663,8 +669,8 @@ void LineEdit::_notification(int p_what) {
if (ofs >= ime_text.length())
break;
- CharType cchar = (pass && !text.empty()) ? '*' : ime_text[ofs];
- CharType next = (pass && !text.empty()) ? '*' : ime_text[ofs + 1];
+ CharType cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs];
+ CharType next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1];
int im_char_width = font->get_char_size(cchar, next).width;
if ((x_ofs + im_char_width) > ofs_max)
@@ -685,8 +691,8 @@ void LineEdit::_notification(int p_what) {
}
}
- CharType cchar = (pass && !text.empty()) ? '*' : t[char_ofs];
- CharType next = (pass && !text.empty()) ? '*' : t[char_ofs + 1];
+ CharType cchar = (pass && !text.empty()) ? secret_character[0] : t[char_ofs];
+ CharType next = (pass && !text.empty()) ? secret_character[0] : t[char_ofs + 1];
int char_width = font->get_char_size(cchar, next).width;
// end of widget, break!
@@ -717,8 +723,8 @@ void LineEdit::_notification(int p_what) {
if (ofs >= ime_text.length())
break;
- CharType cchar = (pass && !text.empty()) ? '*' : ime_text[ofs];
- CharType next = (pass && !text.empty()) ? '*' : ime_text[ofs + 1];
+ CharType cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs];
+ CharType next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1];
int im_char_width = font->get_char_size(cchar, next).width;
if ((x_ofs + im_char_width) > ofs_max)
@@ -1137,7 +1143,6 @@ void LineEdit::clear_internal() {
_clear_undo_stack();
cached_width = 0;
- cached_placeholder_width = 0;
cursor_pos = 0;
window_pos = 0;
undo_text = "";
@@ -1225,6 +1230,7 @@ void LineEdit::select_all() {
selection.enabled = true;
update();
}
+
void LineEdit::set_editable(bool p_editable) {
editable = p_editable;
@@ -1241,11 +1247,27 @@ void LineEdit::set_secret(bool p_secret) {
pass = p_secret;
update();
}
+
bool LineEdit::is_secret() const {
return pass;
}
+void LineEdit::set_secret_character(const String &p_string) {
+
+ // An empty string as the secret character would crash the engine
+ // It also wouldn't make sense to use multiple characters as the secret character
+ ERR_EXPLAIN("Secret character must be exactly one character long (" + itos(p_string.length()) + " characters given)");
+ ERR_FAIL_COND(p_string.length() != 1);
+
+ secret_character = p_string;
+ update();
+}
+
+String LineEdit::get_secret_character() const {
+ return secret_character;
+}
+
void LineEdit::select(int p_from, int p_to) {
if (p_from == 0 && p_to == 0) {
@@ -1327,12 +1349,12 @@ PopupMenu *LineEdit::get_menu() const {
return menu;
}
-#ifdef TOOLS_ENABLED
void LineEdit::_editor_settings_changed() {
+#ifdef TOOLS_ENABLED
cursor_set_blink_enabled(EDITOR_DEF("text_editor/cursor/caret_blink", false));
cursor_set_blink_speed(EDITOR_DEF("text_editor/cursor/caret_blink_speed", 0.65));
-}
#endif
+}
void LineEdit::set_expand_to_text_length(bool p_enabled) {
@@ -1401,9 +1423,7 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("_text_changed"), &LineEdit::_text_changed);
ClassDB::bind_method(D_METHOD("_toggle_draw_caret"), &LineEdit::_toggle_draw_caret);
-#ifdef TOOLS_ENABLED
ClassDB::bind_method("_editor_settings_changed", &LineEdit::_editor_settings_changed);
-#endif
ClassDB::bind_method(D_METHOD("set_align", "align"), &LineEdit::set_align);
ClassDB::bind_method(D_METHOD("get_align"), &LineEdit::get_align);
@@ -1434,6 +1454,8 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_editable"), &LineEdit::is_editable);
ClassDB::bind_method(D_METHOD("set_secret", "enabled"), &LineEdit::set_secret);
ClassDB::bind_method(D_METHOD("is_secret"), &LineEdit::is_secret);
+ ClassDB::bind_method(D_METHOD("set_secret_character", "character"), &LineEdit::set_secret_character);
+ ClassDB::bind_method(D_METHOD("get_secret_character"), &LineEdit::get_secret_character);
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);
@@ -1461,6 +1483,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_PROPERTYNZ(PropertyInfo(Variant::STRING, "secret_character"), "set_secret_character", "get_secret_character");
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_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
@@ -1469,7 +1492,7 @@ void LineEdit::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "placeholder_alpha", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_placeholder_alpha", "get_placeholder_alpha");
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_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "cursor_set_blink_speed", "cursor_get_blink_speed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "caret_position"), "set_cursor_position", "get_cursor_position");
}
@@ -1485,6 +1508,7 @@ LineEdit::LineEdit() {
window_has_focus = true;
max_length = 0;
pass = false;
+ secret_character = "*";
text_changed_dirty = false;
placeholder_alpha = 0.6;
@@ -1505,15 +1529,15 @@ LineEdit::LineEdit() {
context_menu_enabled = true;
menu = memnew(PopupMenu);
add_child(menu);
- menu->add_item(TTR("Cut"), MENU_CUT, KEY_MASK_CMD | KEY_X);
- menu->add_item(TTR("Copy"), MENU_COPY, KEY_MASK_CMD | KEY_C);
- menu->add_item(TTR("Paste"), MENU_PASTE, KEY_MASK_CMD | KEY_V);
+ menu->add_item(RTR("Cut"), MENU_CUT, KEY_MASK_CMD | KEY_X);
+ menu->add_item(RTR("Copy"), MENU_COPY, KEY_MASK_CMD | KEY_C);
+ menu->add_item(RTR("Paste"), MENU_PASTE, KEY_MASK_CMD | KEY_V);
menu->add_separator();
- menu->add_item(TTR("Select All"), MENU_SELECT_ALL, KEY_MASK_CMD | KEY_A);
- menu->add_item(TTR("Clear"), MENU_CLEAR);
+ menu->add_item(RTR("Select All"), MENU_SELECT_ALL, KEY_MASK_CMD | KEY_A);
+ menu->add_item(RTR("Clear"), MENU_CLEAR);
menu->add_separator();
- menu->add_item(TTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z);
- menu->add_item(TTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z);
+ menu->add_item(RTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z);
+ menu->add_item(RTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z);
menu->connect("id_pressed", this, "menu_option");
expand_to_text_length = false;
}
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index c60ea36cc..304faed9b 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -72,6 +72,7 @@ private:
String undo_text;
String text;
String placeholder;
+ String secret_character;
float placeholder_alpha;
String ime_text;
Point2 ime_selection;
@@ -134,9 +135,7 @@ private:
void clear_internal();
void changed_internal();
-#ifdef TOOLS_ENABLED
void _editor_settings_changed();
-#endif
void _gui_input(Ref<InputEvent> p_event);
void _notification(int p_what);
@@ -194,6 +193,9 @@ public:
void set_secret(bool p_secret);
bool is_secret() const;
+ void set_secret_character(const String &p_string);
+ String get_secret_character() const;
+
virtual Size2 get_minimum_size() const;
void set_expand_to_text_length(bool p_enabled);
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 615fef91d..ffc8a7216 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -892,9 +892,9 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
// Erase previous selection.
if (selection.active) {
selection.from = NULL;
- selection.from_char = NULL;
+ selection.from_char = '\0';
selection.to = NULL;
- selection.to_char = NULL;
+ selection.to_char = '\0';
selection.active = false;
update();
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 068ea9d4f..d451a6536 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -2410,6 +2410,12 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
cursor_set_line(line);
cursor_set_column(column);
+#ifdef APPLE_STYLE_KEYS
+ } else if (k->get_command()) {
+ int cursor_current_column = cursor.column;
+ cursor.column = 0;
+ _remove_text(cursor.line, 0, cursor.line, cursor_current_column);
+#endif
} else {
if (cursor.line > 0 && is_line_hidden(cursor.line - 1))
unfold_line(cursor.line - 1);
@@ -2684,7 +2690,11 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
next_line = line;
next_column = column;
-
+#ifdef APPLE_STYLE_KEYS
+ } else if (k->get_command()) {
+ next_column = curline_len;
+ next_line = cursor.line;
+#endif
} else {
next_column = cursor.column < curline_len ? (cursor.column + 1) : 0;
}
@@ -4978,6 +4988,11 @@ void TextEdit::set_indent_size(const int p_size) {
update();
}
+int TextEdit::get_indent_size() {
+
+ return indent_size;
+}
+
void TextEdit::set_draw_tabs(bool p_draw) {
draw_tabs = p_draw;
@@ -5644,7 +5659,7 @@ void TextEdit::_bind_methods() {
ADD_GROUP("Caret", "caret_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_block_mode"), "cursor_set_block_mode", "cursor_is_block_mode");
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_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.01"), "cursor_set_blink_speed", "cursor_get_blink_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_moving_by_right_click"), "set_right_click_moves_caret", "is_right_click_moving_caret");
ADD_SIGNAL(MethodInfo("cursor_changed"));
@@ -5689,7 +5704,7 @@ TextEdit::TextEdit() {
indent_size = 4;
text.set_indent_size(indent_size);
text.clear();
- //text.insert(1,"Mongolia..");
+ //text.insert(1,"Mongolia...");
//text.insert(2,"PAIS GENEROSO!!");
text.set_color_regions(&color_regions);
@@ -5779,14 +5794,14 @@ TextEdit::TextEdit() {
context_menu_enabled = true;
menu = memnew(PopupMenu);
add_child(menu);
- menu->add_item(TTR("Cut"), MENU_CUT, KEY_MASK_CMD | KEY_X);
- menu->add_item(TTR("Copy"), MENU_COPY, KEY_MASK_CMD | KEY_C);
- menu->add_item(TTR("Paste"), MENU_PASTE, KEY_MASK_CMD | KEY_V);
+ menu->add_item(RTR("Cut"), MENU_CUT, KEY_MASK_CMD | KEY_X);
+ menu->add_item(RTR("Copy"), MENU_COPY, KEY_MASK_CMD | KEY_C);
+ menu->add_item(RTR("Paste"), MENU_PASTE, KEY_MASK_CMD | KEY_V);
menu->add_separator();
- menu->add_item(TTR("Select All"), MENU_SELECT_ALL, KEY_MASK_CMD | KEY_A);
- menu->add_item(TTR("Clear"), MENU_CLEAR);
+ menu->add_item(RTR("Select All"), MENU_SELECT_ALL, KEY_MASK_CMD | KEY_A);
+ menu->add_item(RTR("Clear"), MENU_CLEAR);
menu->add_separator();
- menu->add_item(TTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z);
+ menu->add_item(RTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z);
menu->connect("id_pressed", this, "menu_option");
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 30e70bfd0..60c6ab492 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -557,6 +557,7 @@ public:
void set_indent_using_spaces(const bool p_use_spaces);
bool is_indent_using_spaces() const;
void set_indent_size(const int p_size);
+ int get_indent_size();
void set_draw_tabs(bool p_draw);
bool is_drawing_tabs() const;
void set_override_selected_font_color(bool p_override_selected_font_color);
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index fcf876809..a1d79e735 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -979,9 +979,23 @@ void Node::_set_name_nocheck(const StringName &p_name) {
data.name = p_name;
}
+String Node::invalid_character = ". : @ / \"";
+
+bool Node::_validate_node_name(String &p_name) {
+ String name = p_name;
+ Vector<String> chars = Node::invalid_character.split(" ");
+ for (int i = 0; i < chars.size(); i++) {
+ name = name.replace(chars[i], "");
+ }
+ bool is_valid = name == p_name;
+ p_name = name;
+ return is_valid;
+}
+
void Node::set_name(const String &p_name) {
- String name = p_name.replace(":", "").replace("/", "").replace("@", "");
+ String name = p_name;
+ _validate_node_name(name);
ERR_FAIL_COND(name == "");
data.name = name;
@@ -2567,18 +2581,21 @@ Array Node::_get_children() const {
return arr;
}
-#ifdef TOOLS_ENABLED
void Node::set_import_path(const NodePath &p_import_path) {
+#ifdef TOOLS_ENABLED
data.import_path = p_import_path;
+#endif
}
NodePath Node::get_import_path() const {
+#ifdef TOOLS_ENABLED
return data.import_path;
-}
-
+#else
+ return NodePath();
#endif
+}
static void _add_nodes_to_options(const Node *p_base, const Node *p_node, List<String> *r_options) {
@@ -2737,13 +2754,10 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("rpc_config", "method", "mode"), &Node::rpc_config);
ClassDB::bind_method(D_METHOD("rset_config", "property", "mode"), &Node::rset_config);
-#ifdef TOOLS_ENABLED
ClassDB::bind_method(D_METHOD("_set_import_path", "import_path"), &Node::set_import_path);
ClassDB::bind_method(D_METHOD("_get_import_path"), &Node::get_import_path);
ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "_import_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_import_path", "_get_import_path");
-#endif
-
{
MethodInfo mi;
diff --git a/scene/main/node.h b/scene/main/node.h
index b9bafb1ed..b5a956116 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -190,6 +190,12 @@ private:
void _set_tree(SceneTree *p_tree);
+#ifdef TOOLS_ENABLED
+ friend class SceneTreeEditor;
+#endif
+ static String invalid_character;
+ static bool _validate_node_name(String &p_name);
+
protected:
void _block() { data.blocked++; }
void _unblock() { data.blocked--; }
@@ -374,10 +380,8 @@ public:
void force_parent_owned() { data.parent_owned = true; } //hack to avoid duplicate nodes
-#ifdef TOOLS_ENABLED
void set_import_path(const NodePath &p_import_path); //path used when imported, used by scene editors to keep tracking
NodePath get_import_path() const;
-#endif
bool is_owned_by_parent() const;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 4419dfe70..011087b48 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -33,6 +33,7 @@
#include "editor/editor_node.h"
#include "io/marshalls.h"
#include "io/resource_loader.h"
+#include "main/input_default.h"
#include "message_queue.h"
#include "node.h"
#include "os/keyboard.h"
@@ -620,6 +621,13 @@ void SceneTree::_notification(int p_notification) {
case NOTIFICATION_WM_FOCUS_IN:
case NOTIFICATION_WM_FOCUS_OUT: {
+ if (p_notification == NOTIFICATION_WM_FOCUS_IN) {
+ InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
+ if (id) {
+ id->ensure_touch_mouse_raised();
+ }
+ }
+
get_root()->propagate_notification(p_notification);
} break;
case NOTIFICATION_TRANSLATION_CHANGED: {
@@ -1197,16 +1205,20 @@ void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, c
_update_root_rect();
}
-#ifdef TOOLS_ENABLED
void SceneTree::set_edited_scene_root(Node *p_node) {
+#ifdef TOOLS_ENABLED
edited_scene_root = p_node;
+#endif
}
Node *SceneTree::get_edited_scene_root() const {
+#ifdef TOOLS_ENABLED
return edited_scene_root;
-}
+#else
+ return NULL;
#endif
+}
void SceneTree::set_current_scene(Node *p_scene) {
@@ -1737,10 +1749,8 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_debug_navigation_hint", "enable"), &SceneTree::set_debug_navigation_hint);
ClassDB::bind_method(D_METHOD("is_debugging_navigation_hint"), &SceneTree::is_debugging_navigation_hint);
-#ifdef TOOLS_ENABLED
ClassDB::bind_method(D_METHOD("set_edited_scene_root", "scene"), &SceneTree::set_edited_scene_root);
ClassDB::bind_method(D_METHOD("get_edited_scene_root"), &SceneTree::get_edited_scene_root);
-#endif
ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause);
ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused);
@@ -1815,9 +1825,7 @@ void SceneTree::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_font_oversampling"), "set_use_font_oversampling", "is_using_font_oversampling");
-#ifdef TOOLS_ENABLED
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_edited_scene_root", "get_edited_scene_root");
-#endif
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_current_scene", "get_current_scene");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "", "get_root");
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 203c1d9c9..9c06e4ded 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -390,10 +390,8 @@ public:
//void change_scene(const String& p_path);
//Node *get_loaded_scene();
-#ifdef TOOLS_ENABLED
void set_edited_scene_root(Node *p_node);
Node *get_edited_scene_root() const;
-#endif
void set_current_scene(Node *p_scene);
Node *get_current_scene() const;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 19d8f09eb..d94b32afd 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -58,6 +58,7 @@
#include "scene/2d/ray_cast_2d.h"
#include "scene/2d/remote_transform_2d.h"
#include "scene/2d/screen_button.h"
+#include "scene/2d/skeleton_2d.h"
#include "scene/2d/sprite.h"
#include "scene/2d/tile_map.h"
#include "scene/2d/visibility_notifier_2d.h"
@@ -449,6 +450,8 @@ void register_scene_types() {
ClassDB::register_class<VisibilityNotifier2D>();
ClassDB::register_class<VisibilityEnabler2D>();
ClassDB::register_class<Polygon2D>();
+ ClassDB::register_class<Skeleton2D>();
+ ClassDB::register_class<Bone2D>();
ClassDB::register_class<Light2D>();
ClassDB::register_class<LightOccluder2D>();
ClassDB::register_class<OccluderPolygon2D>();
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index 5fd6f6c74..4ec1e8973 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -806,6 +806,87 @@ float Curve2D::get_bake_interval() const {
return bake_interval;
}
+Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const {
+ // Brute force method
+
+ if (baked_cache_dirty)
+ _bake();
+
+ //validate//
+ int pc = baked_point_cache.size();
+ if (pc == 0) {
+ ERR_EXPLAIN("No points in Curve2D");
+ ERR_FAIL_COND_V(pc == 0, Vector2());
+ }
+
+ if (pc == 1)
+ return baked_point_cache.get(0);
+
+ PoolVector2Array::Read r = baked_point_cache.read();
+
+ Vector2 nearest;
+ float nearest_dist = -1.0f;
+
+ for (int i = 0; i < pc - 1; i++) {
+ Vector2 origin = r[i];
+ Vector2 direction = (r[i + 1] - origin) / bake_interval;
+
+ float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ Vector2 proj = origin + direction * d;
+
+ float dist = proj.distance_squared_to(p_to_point);
+
+ if (nearest_dist < 0.0f || dist < nearest_dist) {
+ nearest = proj;
+ nearest_dist = dist;
+ }
+ }
+
+ return nearest;
+}
+
+float Curve2D::get_closest_offset(const Vector2 &p_to_point) const {
+ // Brute force method
+
+ if (baked_cache_dirty)
+ _bake();
+
+ //validate//
+ int pc = baked_point_cache.size();
+ if (pc == 0) {
+ ERR_EXPLAIN("No points in Curve2D");
+ ERR_FAIL_COND_V(pc == 0, 0.0f);
+ }
+
+ if (pc == 1)
+ return 0.0f;
+
+ PoolVector2Array::Read r = baked_point_cache.read();
+
+ float nearest = 0.0f;
+ float nearest_dist = -1.0f;
+ float offset = 0.0f;
+
+ for (int i = 0; i < pc - 1; i++) {
+ Vector2 origin = r[i];
+ Vector2 direction = (r[i + 1] - origin) / bake_interval;
+
+ float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ Vector2 proj = origin + direction * d;
+
+ float dist = proj.distance_squared_to(p_to_point);
+
+ if (nearest_dist < 0.0f || dist < nearest_dist) {
+ nearest = offset + d;
+ nearest_dist = dist;
+ }
+
+ offset += bake_interval;
+ }
+
+ return nearest;
+}
+
Dictionary Curve2D::_get_data() const {
Dictionary dc;
@@ -909,6 +990,8 @@ void Curve2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve2D::get_baked_length);
ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve2D::interpolate_baked, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve2D::get_baked_points);
+ ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve2D::get_closest_point);
+ ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve2D::get_closest_offset);
ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve2D::tessellate, DEFVAL(5), DEFVAL(4));
ClassDB::bind_method(D_METHOD("_get_data"), &Curve2D::_get_data);
@@ -1276,6 +1359,87 @@ PoolRealArray Curve3D::get_baked_tilts() const {
return baked_tilt_cache;
}
+Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const {
+ // Brute force method
+
+ if (baked_cache_dirty)
+ _bake();
+
+ //validate//
+ int pc = baked_point_cache.size();
+ if (pc == 0) {
+ ERR_EXPLAIN("No points in Curve3D");
+ ERR_FAIL_COND_V(pc == 0, Vector3());
+ }
+
+ if (pc == 1)
+ return baked_point_cache.get(0);
+
+ PoolVector3Array::Read r = baked_point_cache.read();
+
+ Vector3 nearest;
+ float nearest_dist = -1.0f;
+
+ for (int i = 0; i < pc - 1; i++) {
+ Vector3 origin = r[i];
+ Vector3 direction = (r[i + 1] - origin) / bake_interval;
+
+ float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ Vector3 proj = origin + direction * d;
+
+ float dist = proj.distance_squared_to(p_to_point);
+
+ if (nearest_dist < 0.0f || dist < nearest_dist) {
+ nearest = proj;
+ nearest_dist = dist;
+ }
+ }
+
+ return nearest;
+}
+
+float Curve3D::get_closest_offset(const Vector3 &p_to_point) const {
+ // Brute force method
+
+ if (baked_cache_dirty)
+ _bake();
+
+ //validate//
+ int pc = baked_point_cache.size();
+ if (pc == 0) {
+ ERR_EXPLAIN("No points in Curve3D");
+ ERR_FAIL_COND_V(pc == 0, 0.0f);
+ }
+
+ if (pc == 1)
+ return 0.0f;
+
+ PoolVector3Array::Read r = baked_point_cache.read();
+
+ float nearest = 0.0f;
+ float nearest_dist = -1.0f;
+ float offset = 0.0f;
+
+ for (int i = 0; i < pc - 1; i++) {
+ Vector3 origin = r[i];
+ Vector3 direction = (r[i + 1] - origin) / bake_interval;
+
+ float d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+ Vector3 proj = origin + direction * d;
+
+ float dist = proj.distance_squared_to(p_to_point);
+
+ if (nearest_dist < 0.0f || dist < nearest_dist) {
+ nearest = offset + d;
+ nearest_dist = dist;
+ }
+
+ offset += bake_interval;
+ }
+
+ return nearest;
+}
+
void Curve3D::set_bake_interval(float p_tolerance) {
bake_interval = p_tolerance;
@@ -1404,6 +1568,8 @@ void Curve3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve3D::interpolate_baked, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve3D::get_baked_points);
ClassDB::bind_method(D_METHOD("get_baked_tilts"), &Curve3D::get_baked_tilts);
+ ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve3D::get_closest_point);
+ ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve3D::get_closest_offset);
ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve3D::tessellate, DEFVAL(5), DEFVAL(4));
ClassDB::bind_method(D_METHOD("_get_data"), &Curve3D::_get_data);
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index 4f55e4055..492eb05d1 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -199,6 +199,8 @@ public:
float get_baked_length() const;
Vector2 interpolate_baked(float p_offset, bool p_cubic = false) const;
PoolVector2Array get_baked_points() const; //useful for going through
+ Vector2 get_closest_point(const Vector2 &p_to_point) const;
+ float get_closest_offset(const Vector2 &p_to_point) const;
PoolVector2Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display
@@ -268,6 +270,8 @@ public:
float interpolate_baked_tilt(float p_offset) const;
PoolVector3Array get_baked_points() const; //useful for going through
PoolRealArray get_baked_tilts() const; //useful for going through
+ Vector3 get_closest_point(const Vector3 &p_to_point) const;
+ float get_closest_offset(const Vector3 &p_to_point) const;
PoolVector3Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index b832ea123..d87644381 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -912,6 +912,7 @@ void ArrayMesh::surface_set_material(int p_idx, const Ref<Material> &p_material)
VisualServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid());
_change_notify("material");
+ emit_changed();
}
void ArrayMesh::surface_set_name(int p_idx, const String &p_name) {
@@ -919,6 +920,7 @@ void ArrayMesh::surface_set_name(int p_idx, const String &p_name) {
ERR_FAIL_INDEX(p_idx, surfaces.size());
surfaces[p_idx].name = p_name;
+ emit_changed();
}
String ArrayMesh::surface_get_name(int p_idx) const {
@@ -931,6 +933,7 @@ void ArrayMesh::surface_update_region(int p_surface, int p_offset, const PoolVec
ERR_FAIL_INDEX(p_surface, surfaces.size());
VS::get_singleton()->mesh_surface_update_region(mesh, p_surface, p_offset, p_data);
+ emit_changed();
}
void ArrayMesh::surface_set_custom_aabb(int p_idx, const AABB &p_aabb) {
@@ -938,6 +941,7 @@ 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;
// set custom aabb too?
+ emit_changed();
}
Ref<Material> ArrayMesh::surface_get_material(int p_idx) const {
@@ -986,6 +990,7 @@ void ArrayMesh::set_custom_aabb(const AABB &p_custom) {
custom_aabb = p_custom;
VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb);
+ emit_changed();
}
AABB ArrayMesh::get_custom_aabb() const {
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 94c54c91d..ad63422aa 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -65,6 +65,8 @@ void PrimitiveMesh::_update() const {
pending_request = false;
_clear_triangle_mesh();
+
+ const_cast<PrimitiveMesh *>(this)->emit_changed();
}
void PrimitiveMesh::_request_update() {
@@ -164,7 +166,11 @@ void PrimitiveMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_mesh_arrays"), &PrimitiveMesh::get_mesh_arrays);
+ ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &PrimitiveMesh::set_custom_aabb);
+ ClassDB::bind_method(D_METHOD("get_custom_aabb"), &PrimitiveMesh::get_custom_aabb);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "SpatialMaterial,ShaderMaterial"), "set_material", "get_material");
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
}
void PrimitiveMesh::set_material(const Ref<Material> &p_material) {
@@ -185,6 +191,18 @@ Array PrimitiveMesh::get_mesh_arrays() const {
return surface_get_arrays(0);
}
+void PrimitiveMesh::set_custom_aabb(const AABB &p_custom) {
+
+ custom_aabb = p_custom;
+ VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb);
+ emit_changed();
+}
+
+AABB PrimitiveMesh::get_custom_aabb() const {
+
+ return custom_aabb;
+}
+
PrimitiveMesh::PrimitiveMesh() {
// defaults
mesh = VisualServer::get_singleton()->mesh_create();
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index 94a7a055a..23d1671d5 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -48,6 +48,7 @@ class PrimitiveMesh : public Mesh {
private:
RID mesh;
mutable AABB aabb;
+ AABB custom_aabb;
Ref<Material> material;
@@ -81,6 +82,9 @@ public:
Array get_mesh_arrays() const;
+ void set_custom_aabb(const AABB &p_custom);
+ AABB get_custom_aabb() const;
+
PrimitiveMesh();
~PrimitiveMesh();
};
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index 626fda50d..ad5a0fd9a 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -106,7 +106,11 @@ void StyleBoxTexture::set_texture(Ref<Texture> p_texture) {
if (texture == p_texture)
return;
texture = p_texture;
- region_rect = Rect2(Point2(), texture->get_size());
+ if (p_texture.is_null()) {
+ region_rect = Rect2(0, 0, 0, 0);
+ } else {
+ region_rect = Rect2(Point2(), texture->get_size());
+ }
emit_signal("texture_changed");
emit_changed();
_change_notify("texture");
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index bebbf6e23..42d64376f 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -142,6 +142,8 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
tile_set_navigation_polygon(id, p_value);
else if (what == "navigation_offset")
tile_set_navigation_polygon_offset(id, p_value);
+ else if (what == "z_index")
+ tile_set_z_index(id, p_value);
else
return false;
@@ -239,6 +241,8 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = tile_get_navigation_polygon(id);
else if (what == "navigation_offset")
r_ret = tile_get_navigation_polygon_offset(id);
+ else if (what == "z_index")
+ r_ret = tile_get_z_index(id);
else
return false;
@@ -278,6 +282,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_EDITOR));
p_list->push_back(PropertyInfo(Variant::BOOL, pre + "shape_one_way", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "shapes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::INT, pre + "z_index", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1"));
}
}
@@ -748,6 +753,19 @@ Vector<TileSet::ShapeData> TileSet::tile_get_shapes(int p_id) const {
return tile_map[p_id].shapes_data;
}
+int TileSet::tile_get_z_index(int p_id) const {
+
+ ERR_FAIL_COND_V(!tile_map.has(p_id), 0);
+ return tile_map[p_id].z_index;
+}
+
+void TileSet::tile_set_z_index(int p_id, int p_z_index) {
+
+ ERR_FAIL_COND(!tile_map.has(p_id));
+ tile_map[p_id].z_index = p_z_index;
+ emit_changed();
+}
+
void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) {
ERR_FAIL_COND(!tile_map.has(p_id));
@@ -929,6 +947,8 @@ void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("tile_get_light_occluder", "id"), &TileSet::tile_get_light_occluder);
ClassDB::bind_method(D_METHOD("tile_set_occluder_offset", "id", "occluder_offset"), &TileSet::tile_set_occluder_offset);
ClassDB::bind_method(D_METHOD("tile_get_occluder_offset", "id"), &TileSet::tile_get_occluder_offset);
+ ClassDB::bind_method(D_METHOD("tile_set_z_index", "id", "z_index"), &TileSet::tile_set_z_index);
+ ClassDB::bind_method(D_METHOD("tile_get_z_index", "id"), &TileSet::tile_get_z_index);
ClassDB::bind_method(D_METHOD("remove_tile", "id"), &TileSet::remove_tile);
ClassDB::bind_method(D_METHOD("clear"), &TileSet::clear);
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index 706d04998..d5704ac9a 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -113,11 +113,13 @@ private:
Color modulate;
TileMode tile_mode;
AutotileData autotile_data;
+ int z_index;
// Default modulate for back-compat
explicit TileData() :
tile_mode(SINGLE_TILE),
- modulate(1, 1, 1) {}
+ modulate(1, 1, 1),
+ z_index(0) {}
};
Map<int, TileData> tile_map;
@@ -220,6 +222,9 @@ public:
Ref<NavigationPolygon> autotile_get_navigation_polygon(int p_id, const Vector2 &p_coord) const;
const Map<Vector2, Ref<NavigationPolygon> > &autotile_get_navigation_map(int p_id) const;
+ void tile_set_z_index(int p_id, int p_z_index);
+ int tile_get_z_index(int p_id) const;
+
void remove_tile(int p_id);
bool has_tile(int p_id) const;