More exact picking for canvas editor
This commit is contained in:
parent
32d8b99bc3
commit
8505871a87
31 changed files with 345 additions and 46 deletions
|
@ -30,6 +30,17 @@
|
|||
#include "geometry.h"
|
||||
#include "print_string.h"
|
||||
|
||||
bool Geometry::is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon) {
|
||||
|
||||
Vector<int> indices = Geometry::triangulate_polygon(p_polygon);
|
||||
for (int j = 0; j + 3 <= indices.size(); j += 3) {
|
||||
int i1 = indices[j], i2 = indices[j + 1], i3 = indices[j + 2];
|
||||
if (Geometry::is_point_in_triangle(p_point, p_polygon[i1], p_polygon[i2], p_polygon[i3]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Geometry::MeshData::optimize_vertices() {
|
||||
|
||||
Map<int, int> vtx_remap;
|
||||
|
|
|
@ -512,6 +512,9 @@ public:
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon);
|
||||
|
||||
static Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 *p_segment) {
|
||||
|
||||
Vector2 p = p_point - p_segment[0];
|
||||
|
|
|
@ -612,6 +612,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no
|
|||
if (Object::cast_to<Viewport>(p_node))
|
||||
return;
|
||||
|
||||
const real_t grab_distance = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
|
||||
CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
|
||||
|
||||
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
|
||||
|
@ -630,9 +631,12 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no
|
|||
if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !Object::cast_to<CanvasLayer>(c)) {
|
||||
|
||||
Rect2 rect = c->_edit_get_rect();
|
||||
Point2 local_pos = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse().xform(p_pos);
|
||||
Transform2D to_local = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse();
|
||||
Point2 local_pos = to_local.xform(p_pos);
|
||||
const real_t local_grab_distance = (to_local.xform(p_pos + Vector2(grab_distance, 0)) - local_pos).length();
|
||||
Rect2 local_pos_rect = Rect2(local_pos, Vector2(0, 0)).grow(local_grab_distance);
|
||||
|
||||
if (rect.has_point(local_pos)) {
|
||||
if (rect.intersects(local_pos_rect) && c->_edit_is_selected_on_click(local_pos, local_grab_distance)) {
|
||||
Node2D *node = Object::cast_to<Node2D>(c);
|
||||
|
||||
_SelectResult res;
|
||||
|
|
|
@ -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; };
|
||||
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -32,6 +32,25 @@
|
|||
#include "servers/physics_2d_server.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
Vector<Vector2> CapsuleShape2D::_get_points() const {
|
||||
|
||||
Vector<Vector2> points;
|
||||
for (int i = 0; i < 24; i++) {
|
||||
Vector2 ofs = Vector2(0, (i > 6 && i <= 18) ? -get_height() * 0.5 : get_height() * 0.5);
|
||||
|
||||
points.push_back(Vector2(Math::sin(i * Math_PI * 2 / 24.0), Math::cos(i * Math_PI * 2 / 24.0)) * get_radius() + ofs);
|
||||
if (i == 6 || i == 18)
|
||||
points.push_back(Vector2(Math::sin(i * Math_PI * 2 / 24.0), Math::cos(i * Math_PI * 2 / 24.0)) * get_radius() - ofs);
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
bool CapsuleShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
|
||||
|
||||
return Geometry::is_point_in_polygon(p_point, _get_points());
|
||||
}
|
||||
|
||||
void CapsuleShape2D::_update_shape() {
|
||||
|
||||
Physics2DServer::get_singleton()->shape_set_data(get_rid(), Vector2(radius, height));
|
||||
|
@ -62,15 +81,7 @@ real_t CapsuleShape2D::get_height() const {
|
|||
|
||||
void CapsuleShape2D::draw(const RID &p_to_rid, const Color &p_color) {
|
||||
|
||||
Vector<Vector2> points;
|
||||
for (int i = 0; i < 24; i++) {
|
||||
Vector2 ofs = Vector2(0, (i > 6 && i <= 18) ? -get_height() * 0.5 : get_height() * 0.5);
|
||||
|
||||
points.push_back(Vector2(Math::sin(i * Math_PI * 2 / 24.0), Math::cos(i * Math_PI * 2 / 24.0)) * get_radius() + ofs);
|
||||
if (i == 6 || i == 18)
|
||||
points.push_back(Vector2(Math::sin(i * Math_PI * 2 / 24.0), Math::cos(i * Math_PI * 2 / 24.0)) * get_radius() - ofs);
|
||||
}
|
||||
|
||||
Vector<Vector2> points = _get_points();
|
||||
Vector<Color> col;
|
||||
col.push_back(p_color);
|
||||
VisualServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col);
|
||||
|
|
|
@ -39,11 +39,14 @@ class CapsuleShape2D : public Shape2D {
|
|||
real_t radius;
|
||||
|
||||
void _update_shape();
|
||||
Vector<Vector2> _get_points() const;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
|
||||
|
||||
void set_height(real_t p_height);
|
||||
real_t get_height() const;
|
||||
|
||||
|
|
|
@ -31,6 +31,12 @@
|
|||
|
||||
#include "servers/physics_2d_server.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
bool CircleShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
|
||||
|
||||
return p_point.length() < get_radius() + p_tolerance;
|
||||
}
|
||||
|
||||
void CircleShape2D::_update_shape() {
|
||||
|
||||
Physics2DServer::get_singleton()->shape_set_data(get_rid(), radius);
|
||||
|
|
|
@ -42,6 +42,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
|
||||
|
||||
void set_radius(real_t p_radius);
|
||||
real_t get_radius() const;
|
||||
|
||||
|
|
|
@ -32,6 +32,23 @@
|
|||
#include "servers/physics_2d_server.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
bool ConcavePolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
|
||||
|
||||
PoolVector<Vector2> s = get_segments();
|
||||
int len = s.size();
|
||||
if (len == 0 || (len % 2) == 1)
|
||||
return false;
|
||||
|
||||
PoolVector<Vector2>::Read r = s.read();
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, &r[i]);
|
||||
if (p_point.distance_to(closest) < p_tolerance)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConcavePolygonShape2D::set_segments(const PoolVector<Vector2> &p_segments) {
|
||||
|
||||
Physics2DServer::get_singleton()->shape_set_data(get_rid(), p_segments);
|
||||
|
|
|
@ -39,6 +39,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
|
||||
|
||||
void set_segments(const PoolVector<Vector2> &p_segments);
|
||||
PoolVector<Vector2> get_segments() const;
|
||||
|
||||
|
|
|
@ -33,6 +33,11 @@
|
|||
#include "servers/physics_2d_server.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
bool ConvexPolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
|
||||
|
||||
return Geometry::is_point_in_polygon(p_point, points);
|
||||
}
|
||||
|
||||
void ConvexPolygonShape2D::_update_shape() {
|
||||
|
||||
Physics2DServer::get_singleton()->shape_set_data(get_rid(), points);
|
||||
|
|
|
@ -42,6 +42,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
|
||||
|
||||
void set_point_cloud(const Vector<Vector2> &p_points);
|
||||
void set_points(const Vector<Vector2> &p_points);
|
||||
Vector<Vector2> get_points() const;
|
||||
|
|
|
@ -32,6 +32,13 @@
|
|||
#include "servers/physics_2d_server.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
bool SegmentShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
|
||||
|
||||
Vector2 l[2] = { a, b };
|
||||
Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, l);
|
||||
return p_point.distance_to(closest) < p_tolerance;
|
||||
}
|
||||
|
||||
void SegmentShape2D::_update_shape() {
|
||||
|
||||
Rect2 r;
|
||||
|
|
|
@ -44,6 +44,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
|
||||
|
||||
void set_a(const Vector2 &p_a);
|
||||
void set_b(const Vector2 &p_b);
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ protected:
|
|||
Shape2D(const RID &p_rid);
|
||||
|
||||
public:
|
||||
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return true; }
|
||||
|
||||
void set_custom_solver_bias(real_t p_bias);
|
||||
real_t get_custom_solver_bias() const;
|
||||
|
||||
|
|
|
@ -30,6 +30,21 @@
|
|||
#include "shape_line_2d.h"
|
||||
#include "servers/physics_2d_server.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
bool LineShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
|
||||
|
||||
Vector2 point = get_d() * get_normal();
|
||||
Vector2 l[2][2] = { { point - get_normal().tangent() * 100, point + get_normal().tangent() * 100 }, { point, point + get_normal() * 30 } };
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, l[i]);
|
||||
if (p_point.distance_to(closest) < p_tolerance)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LineShape2D::_update_shape() {
|
||||
|
||||
Array arr;
|
||||
|
|
|
@ -44,6 +44,8 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const;
|
||||
|
||||
void set_normal(const Vector2 &p_normal);
|
||||
void set_d(real_t p_d);
|
||||
|
||||
|
|
Loading…
Reference in a new issue