summaryrefslogtreecommitdiff
path: root/scene/2d
diff options
context:
space:
mode:
authorBernhard Liebl <Bernhard.Liebl@gmx.org>2017-12-27 09:28:02 +0100
committerBernhard Liebl <Bernhard.Liebl@gmx.org>2017-12-27 20:24:58 +0100
commit8505871a87b59b27acc0912a6dd815231c3b78b1 (patch)
tree31a4fdc7afe2cd3960380fa7695d508f54c043a2 /scene/2d
parent32d8b99bc31e3762ae0dc017a05567da2802a313 (diff)
More exact picking for canvas editor
Diffstat (limited to 'scene/2d')
-rw-r--r--scene/2d/canvas_item.h1
-rw-r--r--scene/2d/collision_polygon_2d.cpp5
-rw-r--r--scene/2d/collision_polygon_2d.h1
-rw-r--r--scene/2d/collision_shape_2d.cpp8
-rw-r--r--scene/2d/collision_shape_2d.h1
-rw-r--r--scene/2d/line_2d.cpp26
-rw-r--r--scene/2d/line_2d.h3
-rw-r--r--scene/2d/navigation_polygon.cpp60
-rw-r--r--scene/2d/navigation_polygon.h9
-rw-r--r--scene/2d/path_2d.cpp54
-rw-r--r--scene/2d/path_2d.h3
-rw-r--r--scene/2d/polygon_2d.cpp7
-rw-r--r--scene/2d/polygon_2d.h1
-rw-r--r--scene/2d/sprite.cpp93
-rw-r--r--scene/2d/sprite.h3
15 files changed, 240 insertions, 35 deletions
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 2384c0f370..db4ddb445c 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -229,6 +229,7 @@ public:
// Used to resize/move/select the node
virtual void _edit_set_rect(const Rect2 &p_rect){};
virtual Rect2 _edit_get_rect() const { return Rect2(-32, -32, 64, 64); };
+ virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return true; }
Rect2 _edit_get_item_and_children_rect() const;
virtual bool _edit_use_rect() const { return false; };
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 92855299ae..cf352f0464 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -248,6 +248,11 @@ Rect2 CollisionPolygon2D::_edit_get_rect() const {
return aabb;
}
+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));
+}
+
String CollisionPolygon2D::get_configuration_warning() const {
if (!Object::cast_to<CollisionObject2D>(get_parent())) {
diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h
index 2fb08a4599..c9e825fffb 100644
--- a/scene/2d/collision_polygon_2d.h
+++ b/scene/2d/collision_polygon_2d.h
@@ -70,6 +70,7 @@ public:
Vector<Point2> get_polygon() const;
virtual Rect2 _edit_get_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 f7cb5473e3..6dcaaea543 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -163,6 +163,14 @@ 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())
+ return false;
+
+ return shape->_edit_is_selected_on_click(p_point, p_tolerance);
+}
+
String CollisionShape2D::get_configuration_warning() const {
if (!Object::cast_to<CollisionObject2D>(get_parent())) {
diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h
index 4745c659c8..68c83c615e 100644
--- a/scene/2d/collision_shape_2d.h
+++ b/scene/2d/collision_shape_2d.h
@@ -52,6 +52,7 @@ protected:
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);
Ref<Shape2D> get_shape() const;
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index 57a0e15447..d7688acec2 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -48,6 +48,32 @@ Line2D::Line2D() :
_round_precision = 8;
}
+Rect2 Line2D::_edit_get_rect() const {
+
+ if (_points.size() == 0)
+ return Rect2(0, 0, 0, 0);
+ Vector2 d = Vector2(_width, _width);
+ Rect2 aabb = Rect2(_points[0] - d, 2 * d);
+ for (int i = 1; i < _points.size(); i++) {
+ aabb.expand_to(_points[i] - d);
+ aabb.expand_to(_points[i] + d);
+ }
+ return aabb;
+}
+
+bool Line2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+
+ const real_t d = _width / 2 + p_tolerance;
+ PoolVector<Vector2>::Read points = _points.read();
+ for (int i = 0; i < _points.size() - 1; i++) {
+ Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point, &points[i]);
+ if (p.distance_to(p_point) <= d)
+ return true;
+ }
+
+ return false;
+}
+
void Line2D::set_points(const PoolVector<Vector2> &p_points) {
_points = p_points;
update();
diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h
index 6426484f02..d38f125813 100644
--- a/scene/2d/line_2d.h
+++ b/scene/2d/line_2d.h
@@ -57,6 +57,9 @@ public:
Line2D();
+ virtual Rect2 _edit_get_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);
PoolVector<Vector2> get_points() const;
diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp
index 5a6a5128e6..dc77a74119 100644
--- a/scene/2d/navigation_polygon.cpp
+++ b/scene/2d/navigation_polygon.cpp
@@ -35,9 +35,50 @@
#include "thirdparty/misc/triangulator.h"
+Rect2 NavigationPolygon::_edit_get_rect() const {
+
+ if (rect_cache_dirty) {
+ item_rect = Rect2();
+ bool first = true;
+
+ for (int i = 0; i < outlines.size(); i++) {
+ const PoolVector<Vector2> &outline = outlines[i];
+ const int outline_size = outline.size();
+ if (outline_size < 3)
+ continue;
+ PoolVector<Vector2>::Read p = outline.read();
+ for (int j = 0; j < outline_size; j++) {
+ if (first) {
+ item_rect = Rect2(p[j], Vector2(0, 0));
+ first = false;
+ } else {
+ item_rect.expand_to(p[j]);
+ }
+ }
+ }
+
+ rect_cache_dirty = false;
+ }
+ return item_rect;
+}
+
+bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+
+ for (int i = 0; i < outlines.size(); i++) {
+ const PoolVector<Vector2> &outline = outlines[i];
+ const int outline_size = outline.size();
+ if (outline_size < 3)
+ continue;
+ if (Geometry::is_point_in_polygon(p_point, Variant(outline)))
+ return true;
+ }
+ return false;
+}
+
void NavigationPolygon::set_vertices(const PoolVector<Vector2> &p_vertices) {
vertices = p_vertices;
+ rect_cache_dirty = true;
}
PoolVector<Vector2> NavigationPolygon::get_vertices() const {
@@ -70,6 +111,7 @@ void NavigationPolygon::_set_outlines(const Array &p_array) {
for (int i = 0; i < p_array.size(); i++) {
outlines[i] = p_array[i];
}
+ rect_cache_dirty = true;
}
Array NavigationPolygon::_get_outlines() const {
@@ -93,6 +135,7 @@ void NavigationPolygon::add_polygon(const Vector<int> &p_polygon) {
void NavigationPolygon::add_outline_at_index(const PoolVector<Vector2> &p_outline, int p_index) {
outlines.insert(p_index, p_outline);
+ rect_cache_dirty = true;
}
int NavigationPolygon::get_polygon_count() const {
@@ -112,6 +155,7 @@ void NavigationPolygon::clear_polygons() {
void NavigationPolygon::add_outline(const PoolVector<Vector2> &p_outline) {
outlines.push_back(p_outline);
+ rect_cache_dirty = true;
}
int NavigationPolygon::get_outline_count() const {
@@ -122,12 +166,14 @@ int NavigationPolygon::get_outline_count() const {
void NavigationPolygon::set_outline(int p_idx, const PoolVector<Vector2> &p_outline) {
ERR_FAIL_INDEX(p_idx, outlines.size());
outlines[p_idx] = p_outline;
+ rect_cache_dirty = true;
}
void NavigationPolygon::remove_outline(int p_idx) {
ERR_FAIL_INDEX(p_idx, outlines.size());
outlines.remove(p_idx);
+ rect_cache_dirty = true;
}
PoolVector<Vector2> NavigationPolygon::get_outline(int p_idx) const {
@@ -138,6 +184,7 @@ PoolVector<Vector2> NavigationPolygon::get_outline(int p_idx) const {
void NavigationPolygon::clear_outlines() {
outlines.clear();
+ rect_cache_dirty = true;
}
void NavigationPolygon::make_polygons_from_outlines() {
@@ -269,7 +316,8 @@ void NavigationPolygon::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_outlines", "_get_outlines");
}
-NavigationPolygon::NavigationPolygon() {
+NavigationPolygon::NavigationPolygon() :
+ rect_cache_dirty(true) {
}
void NavigationPolygonInstance::set_enabled(bool p_enabled) {
@@ -311,6 +359,16 @@ bool NavigationPolygonInstance::is_enabled() const {
/////////////////////////////
+Rect2 NavigationPolygonInstance::_edit_get_rect() const {
+
+ return navpoly.is_valid() ? navpoly->_edit_get_rect() : Rect2();
+}
+
+bool NavigationPolygonInstance::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+
+ return navpoly.is_valid() ? navpoly->_edit_is_selected_on_click(p_point, p_tolerance) : false;
+}
+
void NavigationPolygonInstance::_notification(int p_what) {
switch (p_what) {
diff --git a/scene/2d/navigation_polygon.h b/scene/2d/navigation_polygon.h
index 5576a3abd2..3a7298c301 100644
--- a/scene/2d/navigation_polygon.h
+++ b/scene/2d/navigation_polygon.h
@@ -43,6 +43,9 @@ class NavigationPolygon : public Resource {
Vector<Polygon> polygons;
Vector<PoolVector<Vector2> > outlines;
+ mutable Rect2 item_rect;
+ mutable bool rect_cache_dirty;
+
protected:
static void _bind_methods();
@@ -53,6 +56,9 @@ protected:
Array _get_outlines() const;
public:
+ Rect2 _edit_get_rect() const;
+ bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
+
void set_vertices(const PoolVector<Vector2> &p_vertices);
PoolVector<Vector2> get_vertices() const;
@@ -93,6 +99,9 @@ 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_enabled(bool p_enabled);
bool is_enabled() const;
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index 4029ef137b..9b659a1eb4 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -32,6 +32,51 @@
#include "engine.h"
#include "scene/scene_string_names.h"
+#ifdef TOOLS_ENABLED
+#include "editor/editor_scale.h"
+#endif
+
+Rect2 Path2D::_edit_get_rect() const {
+
+ if (curve->get_point_count() == 0)
+ return Rect2(0, 0, 0, 0);
+
+ Rect2 aabb = Rect2(curve->get_point_position(0), Vector2(0, 0));
+
+ for (int i = 0; i < curve->get_point_count(); i++) {
+
+ for (int j = 0; j <= 8; j++) {
+
+ real_t frac = j / 8.0;
+ Vector2 p = curve->interpolate(i, frac);
+ aabb.expand_to(p);
+ }
+ }
+
+ return aabb;
+}
+
+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++) {
+ Vector2 s[2];
+ s[0] = curve->get_point_position(i);
+
+ for (int j = 1; j <= 8; j++) {
+ real_t frac = j / 8.0;
+ s[1] = curve->interpolate(i, frac);
+
+ Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point, s);
+ if (p.distance_to(p_point) <= p_tolerance)
+ return true;
+
+ s[0] = s[1];
+ }
+ }
+
+ return false;
+}
+
void Path2D::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW && curve.is_valid()) {
@@ -41,6 +86,13 @@ void Path2D::_notification(int p_what) {
return;
}
+#if TOOLS_ENABLED
+ const float line_width = 2 * EDSCALE;
+#else
+ const float line_width = 2;
+#endif
+ const Color color = Color(0.5, 0.6, 1.0, 0.7);
+
for (int i = 0; i < curve->get_point_count(); i++) {
Vector2 prev_p = curve->get_point_position(i);
@@ -49,7 +101,7 @@ void Path2D::_notification(int p_what) {
real_t frac = j / 8.0;
Vector2 p = curve->interpolate(i, frac);
- draw_line(prev_p, p, Color(0.5, 0.6, 1.0, 0.7), 2);
+ draw_line(prev_p, p, color, line_width);
prev_p = p;
}
}
diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h
index 88a0abdea9..acc43e48be 100644
--- a/scene/2d/path_2d.h
+++ b/scene/2d/path_2d.h
@@ -46,6 +46,9 @@ 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_curve(const Ref<Curve2D> &p_curve);
Ref<Curve2D> get_curve() const;
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 3f2ad19e51..a8f2807862 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "polygon_2d.h"
+#include "core/math/geometry.h"
Rect2 Polygon2D::_edit_get_rect() const {
@@ -42,13 +43,17 @@ Rect2 Polygon2D::_edit_get_rect() const {
else
item_rect.expand_to(pos);
}
- item_rect = item_rect.grow(20);
rect_cache_dirty = false;
}
return item_rect;
}
+bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+
+ return Geometry::is_point_in_polygon(p_point, Variant(polygon));
+}
+
void Polygon2D::_edit_set_pivot(const Point2 &p_pivot) {
set_offset(p_pivot);
diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h
index d09e22f5ff..12db113191 100644
--- a/scene/2d/polygon_2d.h
+++ b/scene/2d/polygon_2d.h
@@ -104,6 +104,7 @@ public:
virtual bool _edit_use_pivot() const;
virtual Rect2 _edit_get_rect() const;
+ virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
Polygon2D();
};
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index df2265aae9..414b726759 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -47,6 +47,40 @@ bool Sprite::_edit_use_pivot() const {
return true;
}
+void Sprite::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const {
+
+ Size2 s;
+ r_filter_clip = false;
+
+ if (region) {
+
+ s = region_rect.size;
+ r_src_rect = region_rect;
+ r_filter_clip = region_filter_clip;
+ } else {
+ s = Size2(texture->get_size());
+ s = s / Size2(hframes, vframes);
+
+ r_src_rect.size = s;
+ r_src_rect.position.x += float(frame % hframes) * s.x;
+ r_src_rect.position.y += float(frame / hframes) * s.y;
+ }
+
+ Point2 ofs = offset;
+ if (centered)
+ ofs -= s / 2;
+ if (Engine::get_singleton()->get_use_pixel_snap()) {
+ ofs = ofs.floor();
+ }
+
+ r_dst_rect = Rect2(ofs, s);
+
+ if (hflip)
+ r_dst_rect.size.x = -r_dst_rect.size.x;
+ if (vflip)
+ r_dst_rect.size.y = -r_dst_rect.size.y;
+}
+
void Sprite::_notification(int p_what) {
switch (p_what) {
@@ -63,38 +97,9 @@ void Sprite::_notification(int p_what) {
break;
*/
- Size2 s;
- Rect2 src_rect;
- bool filter_clip = false;
-
- if (region) {
-
- s = region_rect.size;
- src_rect = region_rect;
- filter_clip = region_filter_clip;
- } else {
- s = Size2(texture->get_size());
- s = s / Size2(hframes, vframes);
-
- src_rect.size = s;
- src_rect.position.x += float(frame % hframes) * s.x;
- src_rect.position.y += float(frame / hframes) * s.y;
- }
-
- Point2 ofs = offset;
- if (centered)
- ofs -= s / 2;
- if (Engine::get_singleton()->get_use_pixel_snap()) {
- ofs = ofs.floor();
- }
-
- Rect2 dst_rect(ofs, s);
-
- if (hflip)
- dst_rect.size.x = -dst_rect.size.x;
- if (vflip)
- dst_rect.size.y = -dst_rect.size.y;
-
+ Rect2 src_rect, dst_rect;
+ bool filter_clip;
+ _get_rects(src_rect, dst_rect, filter_clip);
texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, normal_map, filter_clip);
} break;
@@ -257,6 +262,30 @@ int Sprite::get_hframes() const {
return hframes;
}
+bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
+
+ if (texture.is_null())
+ return false;
+
+ Rect2 src_rect, dst_rect;
+ bool filter_clip;
+ _get_rects(src_rect, dst_rect, filter_clip);
+
+ if (!dst_rect.has_point(p_point))
+ return false;
+
+ Vector2 q = ((p_point - dst_rect.position) / dst_rect.size) * src_rect.size + src_rect.position;
+
+ Ref<Image> image = texture->get_data();
+ ERR_FAIL_COND_V(image.is_null(), false);
+
+ image->lock();
+ const Color c = image->get_pixel((int)q.x, (int)q.y);
+ image->unlock();
+
+ return c.a > 0.01;
+}
+
Rect2 Sprite::_edit_get_rect() const {
if (texture.is_null())
diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h
index 1bef73c0a5..0e816691a2 100644
--- a/scene/2d/sprite.h
+++ b/scene/2d/sprite.h
@@ -54,6 +54,8 @@ class Sprite : public Node2D {
int vframes;
int hframes;
+ void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const;
+
protected:
void _notification(int p_what);
@@ -65,6 +67,7 @@ public:
virtual void _edit_set_pivot(const Point2 &p_pivot);
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;
void set_texture(const Ref<Texture> &p_texture);