diff options
Diffstat (limited to 'scene')
57 files changed, 1470 insertions, 180 deletions
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 92d5088b81..49229ba500 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -1172,6 +1172,14 @@ Matrix32 CanvasItem::get_viewport_transform() const { } +void CanvasItem::set_notify_local_transform(bool p_enable) { + notify_local_transform=p_enable; +} + +bool CanvasItem::is_local_transform_notification_enabled() const { + return notify_local_transform; +} + CanvasItem::CanvasItem() : xform_change(this) { @@ -1191,6 +1199,7 @@ CanvasItem::CanvasItem() : xform_change(this) { canvas_layer=NULL; use_parent_material=false; global_invalid=true; + notify_local_transform=false; light_mask=1; C=NULL; diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 6d8308dbe4..4885256c64 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -126,6 +126,7 @@ private: bool block_transform_notify; bool behind; bool use_parent_material; + bool notify_local_transform; Ref<CanvasItemMaterial> material; @@ -155,7 +156,7 @@ private: protected: - _FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); } + _FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify && notify_local_transform) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); } void item_rect_changed(); @@ -263,6 +264,10 @@ public: Vector2 get_global_mouse_pos() const; Vector2 get_local_mouse_pos() const; + void set_notify_local_transform(bool p_enable); + bool is_local_transform_notification_enabled() const; + + CanvasItem(); ~CanvasItem(); }; diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index ceea41d1c8..1479cb7881 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -33,7 +33,7 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { - if (unparenting) + if (unparenting || !can_update_body) return; CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>(); @@ -49,6 +49,7 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { //here comes the sun, lalalala //decompose concave into multiple convex polygons and add them Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon); + shape_from=co->get_shape_count(); for(int i=0;i<decomp.size();i++) { Ref<ConvexPolygonShape2D> convex = memnew( ConvexPolygonShape2D ); convex->set_points(decomp[i]); @@ -57,6 +58,11 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { co->set_shape_as_trigger(co->get_shape_count()-1,true); } + shape_to=co->get_shape_count()-1; + if (shape_to<shape_from) { + shape_from=-1; + shape_to=-1; + } } else { @@ -78,6 +84,9 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { if (trigger) co->set_shape_as_trigger(co->get_shape_count()-1,true); + shape_from=co->get_shape_count()-1; + shape_to=co->get_shape_count()-1; + } @@ -86,6 +95,8 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) { void CollisionPolygon2D::_update_parent() { + if (!can_update_body) + return; Node *parent = get_parent(); if (!parent) return; @@ -101,33 +112,55 @@ void CollisionPolygon2D::_notification(int p_what) { switch(p_what) { case NOTIFICATION_ENTER_TREE: { unparenting=false; + can_update_body=get_tree()->is_editor_hint(); + } break; + case NOTIFICATION_EXIT_TREE: { + can_update_body=false; } break; case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { if (!is_inside_tree()) break; - _update_parent(); + if (can_update_body) { + _update_parent(); + } else if (shape_from>=0 && shape_to>=0) { + CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); + for(int i=shape_from;i<=shape_to;i++) { + co->set_shape_transform(i,get_transform()); + } + } + } break; case NOTIFICATION_DRAW: { + + if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) { + break; + } + + for(int i=0;i<polygon.size();i++) { Vector2 p = polygon[i]; Vector2 n = polygon[(i+1)%polygon.size()]; - draw_line(p,n,Color(0,0.6,0.7,0.5),3); + draw_line(p,n,Color(0.9,0.2,0.0,0.8),3); } +//#define DEBUG_DECOMPOSE +#if defined(TOOLS_ENABLED) && defined (DEBUG_DECOMPOSE) Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon); -#define DEBUG_DECOMPOSE -#ifdef DEBUG_DECOMPOSE Color c(0.4,0.9,0.1); for(int i=0;i<decomp.size();i++) { c.set_hsv( Math::fmod(c.get_h() + 0.738,1),c.get_s(),c.get_v(),0.5); draw_colored_polygon(decomp[i],c); } +#else + draw_colored_polygon(polygon,get_tree()->get_debug_collisions_color()); #endif + + } break; case NOTIFICATION_UNPARENTED: { unparenting = true; @@ -141,20 +174,22 @@ void CollisionPolygon2D::set_polygon(const Vector<Point2>& p_polygon) { polygon=p_polygon; - for(int i=0;i<polygon.size();i++) { - if (i==0) - aabb=Rect2(polygon[i],Size2()); - else - aabb.expand_to(polygon[i]); - } - if (aabb==Rect2()) { + if (can_update_body) { + for(int i=0;i<polygon.size();i++) { + if (i==0) + aabb=Rect2(polygon[i],Size2()); + else + aabb.expand_to(polygon[i]); + } + if (aabb==Rect2()) { - aabb=Rect2(-10,-10,20,20); - } else { - aabb.pos-=aabb.size*0.3; - aabb.size+=aabb.size*0.6; + aabb=Rect2(-10,-10,20,20); + } else { + aabb.pos-=aabb.size*0.3; + aabb.size+=aabb.size*0.6; + } + _update_parent(); } - _update_parent(); update(); } @@ -184,6 +219,13 @@ void CollisionPolygon2D::set_trigger(bool p_trigger) { trigger=p_trigger; _update_parent(); + if (!can_update_body && is_inside_tree() && shape_from>=0 && shape_to>=0) { + CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); + for(int i=shape_from;i<=shape_to;i++) { + co->set_shape_as_trigger(i,p_trigger); + } + + } } bool CollisionPolygon2D::is_trigger() const{ @@ -192,6 +234,17 @@ bool CollisionPolygon2D::is_trigger() const{ } +void CollisionPolygon2D::_set_shape_range(const Vector2& p_range) { + + shape_from=p_range.x; + shape_to=p_range.y; +} + +Vector2 CollisionPolygon2D::_get_shape_range() const { + + return Vector2(shape_from,shape_to); +} + void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon2D::_add_to_collision_object); @@ -204,9 +257,17 @@ void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_trigger"),&CollisionPolygon2D::set_trigger); ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionPolygon2D::is_trigger); + ObjectTypeDB::bind_method(_MD("_set_shape_range","shape_range"),&CollisionPolygon2D::_set_shape_range); + ObjectTypeDB::bind_method(_MD("_get_shape_range"),&CollisionPolygon2D::_get_shape_range); + + ObjectTypeDB::bind_method(_MD("get_collision_object_first_shape"),&CollisionPolygon2D::get_collision_object_first_shape); + ObjectTypeDB::bind_method(_MD("get_collision_object_last_shape"),&CollisionPolygon2D::get_collision_object_last_shape); + ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Segments"),_SCS("set_build_mode"),_SCS("get_build_mode")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"shape_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_shape_range"),_SCS("_get_shape_range")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); + } CollisionPolygon2D::CollisionPolygon2D() { @@ -215,6 +276,9 @@ CollisionPolygon2D::CollisionPolygon2D() { build_mode=BUILD_SOLIDS; trigger=false; unparenting=false; - + shape_from=-1; + shape_to=-1; + can_update_body=false; + set_notify_local_transform(true); } diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index 4e78868082..4bc9713c8a 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -56,6 +56,14 @@ protected: void _add_to_collision_object(Object *p_obj); void _update_parent(); + bool can_update_body; + int shape_from; + int shape_to; + + void _set_shape_range(const Vector2& p_range); + Vector2 _get_shape_range() const; + + protected: void _notification(int p_what); @@ -72,6 +80,10 @@ public: Vector<Point2> get_polygon() const; virtual Rect2 get_item_rect() const; + + int get_collision_object_first_shape() const { return shape_from; } + int get_collision_object_last_shape() const { return shape_to; } + CollisionPolygon2D(); }; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 5012c54b17..85751fc735 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -44,10 +44,12 @@ void CollisionShape2D::_add_to_collision_object(Object *p_obj) { CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>(); ERR_FAIL_COND(!co); + update_shape_index=co->get_shape_count(); co->add_shape(shape,get_transform()); if (trigger) co->set_shape_as_trigger(co->get_shape_count()-1,true); + } void CollisionShape2D::_shape_changed() { @@ -74,12 +76,27 @@ void CollisionShape2D::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { unparenting=false; + can_update_body=get_tree()->is_editor_hint(); + } break; case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { if (!is_inside_tree()) break; - _update_parent(); + if (can_update_body) { + _update_parent(); + } else if (update_shape_index>=0){ + + CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); + if (co) { + co->set_shape_transform(update_shape_index,get_transform()); + } + + } + + } break; + case NOTIFICATION_EXIT_TREE: { + can_update_body=false; } break; /* @@ -92,106 +109,22 @@ void CollisionShape2D::_notification(int p_what) { } break;*/ case NOTIFICATION_DRAW: { - rect=Rect2(); - - Color draw_col=Color(0,0.6,0.7,0.5); - - if (shape->cast_to<LineShape2D>()) { - - LineShape2D *l = shape->cast_to<LineShape2D>(); - Vector2 point = l->get_d() * l->get_normal(); - - Vector2 l1[2]={point-l->get_normal().tangent()*100,point+l->get_normal().tangent()*100}; - draw_line(l1[0],l1[1],draw_col,3); - Vector2 l2[2]={point,point+l->get_normal()*30}; - draw_line(l2[0],l2[1],draw_col,3); - rect.pos=l1[0]; - rect.expand_to(l1[1]); - rect.expand_to(l2[0]); - rect.expand_to(l2[1]); - - } else if (shape->cast_to<SegmentShape2D>()) { - - SegmentShape2D *s = shape->cast_to<SegmentShape2D>(); - draw_line(s->get_a(),s->get_b(),draw_col,3); - rect.pos=s->get_a(); - rect.expand_to(s->get_b()); - - } else if (shape->cast_to<RayShape2D>()) { - - RayShape2D *s = shape->cast_to<RayShape2D>(); - - Vector2 tip = Vector2(0,s->get_length()); - draw_line(Vector2(),tip,draw_col,3); - Vector<Vector2> pts; - float tsize=4; - pts.push_back(tip+Vector2(0,tsize)); - pts.push_back(tip+Vector2(0.707*tsize,0)); - pts.push_back(tip+Vector2(-0.707*tsize,0)); - Vector<Color> cols; - for(int i=0;i<3;i++) - cols.push_back(draw_col); - - draw_primitive(pts,cols,Vector<Vector2>()); //small arrow - - rect.pos=Vector2(); - rect.expand_to(tip); - rect=rect.grow(0.707*tsize); - - } else if (shape->cast_to<CircleShape2D>()) { - - CircleShape2D *s = shape->cast_to<CircleShape2D>(); - Vector<Vector2> points; - for(int i=0;i<24;i++) { - - points.push_back(Vector2(Math::cos(i*Math_PI*2/24.0),Math::sin(i*Math_PI*2/24.0))*s->get_radius()); - } - - draw_colored_polygon(points,draw_col); - rect.pos=-Point2(s->get_radius(),s->get_radius()); - rect.size=Point2(s->get_radius(),s->get_radius())*2.0; - - } else if (shape->cast_to<RectangleShape2D>()) { - - RectangleShape2D *s = shape->cast_to<RectangleShape2D>(); - Vector2 he = s->get_extents(); - rect=Rect2(-he,he*2.0); - draw_rect(rect,draw_col);; - - } else if (shape->cast_to<CapsuleShape2D>()) { - - CapsuleShape2D *s = shape->cast_to<CapsuleShape2D>(); - - Vector<Vector2> points; - for(int i=0;i<24;i++) { - Vector2 ofs = Vector2(0,(i>6 && i<=18) ? -s->get_height()*0.5 : s->get_height()*0.5); - - points.push_back(Vector2(Math::sin(i*Math_PI*2/24.0),Math::cos(i*Math_PI*2/24.0))*s->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))*s->get_radius() - ofs); - } - - draw_colored_polygon(points,draw_col); - Vector2 he=Point2(s->get_radius(),s->get_radius()+s->get_height()*0.5); - rect.pos=-he; - rect.size=he*2.0; + if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) { + break; + } - } else if (shape->cast_to<ConvexPolygonShape2D>()) { + if (!shape.is_valid()) { + break; + } - ConvexPolygonShape2D *s = shape->cast_to<ConvexPolygonShape2D>(); + rect=Rect2(); - Vector<Vector2> points = s->get_points(); - for(int i=0;i<points.size();i++) { - if (i==0) - rect.pos=points[i]; - else - rect.expand_to(points[i]); - } - draw_colored_polygon(points,draw_col); + Color draw_col=get_tree()->get_debug_collisions_color(); + shape->draw(get_canvas_item(),draw_col); - } + rect=shape->get_rect(); rect=rect.grow(3); } break; @@ -209,7 +142,14 @@ void CollisionShape2D::set_shape(const Ref<Shape2D>& p_shape) { shape->disconnect("changed",this,"_shape_changed"); shape=p_shape; update(); - _update_parent(); + if (is_inside_tree() && can_update_body) + _update_parent(); + if (is_inside_tree() && !can_update_body && update_shape_index>=0) { + CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); + if (co) { + co->set_shape(update_shape_index,p_shape); + } + } if (shape.is_valid()) shape->connect("changed",this,"_shape_changed"); @@ -228,7 +168,14 @@ Rect2 CollisionShape2D::get_item_rect() const { void CollisionShape2D::set_trigger(bool p_trigger) { trigger=p_trigger; - _update_parent(); + if (can_update_body) { + _update_parent(); + } else if (is_inside_tree() && update_shape_index>=0){ + CollisionObject2D *co = get_parent()->cast_to<CollisionObject2D>(); + if (co) { + co->set_shape_as_trigger(update_shape_index,p_trigger); + } + } } bool CollisionShape2D::is_trigger() const{ @@ -236,6 +183,19 @@ bool CollisionShape2D::is_trigger() const{ return trigger; } + +void CollisionShape2D::_set_update_shape_index(int p_index) { + + + update_shape_index=p_index; +} + +int CollisionShape2D::_get_update_shape_index() const{ + + return update_shape_index; +} + + void CollisionShape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_shape","shape"),&CollisionShape2D::set_shape); @@ -245,14 +205,23 @@ void CollisionShape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_trigger","enable"),&CollisionShape2D::set_trigger); ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionShape2D::is_trigger); + ObjectTypeDB::bind_method(_MD("_set_update_shape_index","index"),&CollisionShape2D::_set_update_shape_index); + ObjectTypeDB::bind_method(_MD("_get_update_shape_index"),&CollisionShape2D::_get_update_shape_index); + + ObjectTypeDB::bind_method(_MD("get_collision_object_shape_index"),&CollisionShape2D::get_collision_object_shape_index); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D"),_SCS("set_shape"),_SCS("get_shape")); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), _SCS("_set_update_shape_index"), _SCS("_get_update_shape_index")); + } CollisionShape2D::CollisionShape2D() { rect=Rect2(-Point2(10,10),Point2(20,20)); - + set_notify_local_transform(true); trigger=false; unparenting = false; + can_update_body = false; + update_shape_index=-1; } diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h index 507912d31e..82e1137174 100644 --- a/scene/2d/collision_shape_2d.h +++ b/scene/2d/collision_shape_2d.h @@ -39,7 +39,13 @@ class CollisionShape2D : public Node2D { Rect2 rect; bool trigger; bool unparenting; + bool can_update_body; void _shape_changed(); + int update_shape_index; + + void _set_update_shape_index(int p_index); + int _get_update_shape_index() const; + protected: void _update_parent(); @@ -55,6 +61,8 @@ public: void set_trigger(bool p_trigger); bool is_trigger() const; + int get_collision_object_shape_index() const { return _get_update_shape_index(); } + CollisionShape2D(); }; diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp index fc69ea8a0d..792f079ab0 100644 --- a/scene/2d/navigation_polygon.cpp +++ b/scene/2d/navigation_polygon.cpp @@ -279,7 +279,7 @@ void NavigationPolygonInstance::set_enabled(bool p_enabled) { } - if (get_tree()->is_editor_hint()) + if (get_tree()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) update(); // update_gizmo(); @@ -338,7 +338,7 @@ void NavigationPolygonInstance::_notification(int p_what) { } break; case NOTIFICATION_DRAW: { - if (is_inside_tree() && get_tree()->is_editor_hint() && navpoly.is_valid()) { + if (is_inside_tree() && (get_tree()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) && navpoly.is_valid()) { DVector<Vector2> verts=navpoly->get_vertices(); int vsize = verts.size(); @@ -348,9 +348,9 @@ void NavigationPolygonInstance::_notification(int p_what) { Color color; if (enabled) { - color=Color(0.1,0.8,1.0,0.4); + color=get_tree()->get_debug_navigation_color(); } else { - color=Color(1.0,0.8,0.1,0.4); + color=get_tree()->get_debug_navigation_disabled_color(); } Vector<Color> colors; Vector<Vector2> vertices; @@ -423,7 +423,7 @@ Ref<NavigationPolygon> NavigationPolygonInstance::get_navigation_polygon() const void NavigationPolygonInstance::_navpoly_changed() { - if (is_inside_tree() && get_tree()->is_editor_hint()) + if (is_inside_tree() && (get_tree()->is_editor_hint() || get_tree()->is_debugging_navigation_hint())) update(); } diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 20abe42cd9..05594fd79c 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -115,17 +115,17 @@ void RayCast2D::_notification(int p_what) { set_fixed_process(false); } break; -#ifdef TOOLS_ENABLED + case NOTIFICATION_DRAW: { - if (!get_tree()->is_editor_hint()) + if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) break; Matrix32 xf; xf.rotate(cast_to.atan2()); xf.translate(Vector2(0,cast_to.length())); //Vector2 tip = Vector2(0,s->get_length()); - Color dcol(0.9,0.2,0.2,0.4); + Color dcol=get_tree()->get_debug_collisions_color();//0.9,0.2,0.2,0.4); draw_line(Vector2(),cast_to,dcol,3); Vector<Vector2> pts; float tsize=4; @@ -139,7 +139,7 @@ void RayCast2D::_notification(int p_what) { draw_primitive(pts,cols,Vector<Vector2>()); //small arrow } break; -#endif + case NOTIFICATION_FIXED_PROCESS: { diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 17f93f816f..418ee192b2 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -30,6 +30,7 @@ #include "io/marshalls.h" #include "servers/physics_2d_server.h" #include "method_bind_ext.inc" +#include "os/os.h" int TileMap::_get_quadrant_size() const { @@ -262,6 +263,14 @@ void TileMap::_update_dirty_quadrants() { Vector2 qofs; + SceneTree *st=SceneTree::get_singleton(); + Color debug_collision_color; + + bool debug_shapes = st && st->is_debugging_collisions_hint(); + if (debug_shapes) { + debug_collision_color=st->get_debug_collisions_color(); + } + while (dirty_quadrant_list.first()) { Quadrant &q = *dirty_quadrant_list.first()->self(); @@ -398,11 +407,19 @@ void TileMap::_update_dirty_quadrants() { _fix_cell_transform(xform,c,shape_ofs+center_ofs,s); - ps->body_add_shape(q.body,shape->get_rid(),xform); + if (debug_shapes) { + vs->canvas_item_add_set_transform(canvas_item,xform); + shape->draw(canvas_item,debug_collision_color); + + } + ps->body_add_shape(q.body,shape->get_rid(),xform); ps->body_set_shape_metadata(q.body,shape_idx++,Vector2(E->key().x,E->key().y)); } } + if (debug_shapes) { + vs->canvas_item_add_set_transform(canvas_item,Matrix32()); + } if (navigation) { Ref<NavigationPolygon> navpoly = tile_set->tile_get_navigation_polygon(c.id); @@ -412,6 +429,7 @@ void TileMap::_update_dirty_quadrants() { xform.set_origin(offset.floor()+q.pos); _fix_cell_transform(xform,c,npoly_ofs+center_ofs,s); + int pid = navigation->navpoly_create(navpoly,nav_rel * xform); Quadrant::NavPoly np; diff --git a/scene/3d/body_shape.cpp b/scene/3d/body_shape.cpp index c49d1b028c..b54cbfe0f9 100644 --- a/scene/3d/body_shape.cpp +++ b/scene/3d/body_shape.cpp @@ -43,7 +43,10 @@ void CollisionShape::_update_body() { - + if (!is_inside_tree() || !can_update_body) + return; + if (!get_tree()->is_editor_hint()) + return; if (get_parent() && get_parent()->cast_to<CollisionObject>()) get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children(); @@ -310,10 +313,13 @@ void CollisionShape::_add_to_collision_object(Object* p_cshape) { if (shape.is_valid()) { + update_shape_index=co->get_shape_count(); co->add_shape(shape,get_transform()); - if (trigger) - co->set_shape_as_trigger( co->get_shape_count() -1, true ); - } + if (trigger) + co->set_shape_as_trigger( co->get_shape_count() -1, true ); + } else { + update_shape_index=-1; + } } void CollisionShape::_notification(int p_what) { @@ -322,12 +328,18 @@ void CollisionShape::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { unparenting=false; + can_update_body=get_tree()->is_editor_hint(); + set_notify_local_transform(!can_update_body); + + if (get_tree()->is_debugging_collisions_hint()) { + _create_debug_shape(); + } //indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario()); } break; case NOTIFICATION_TRANSFORM_CHANGED: { // VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform()); - if (updating_body) { + if (can_update_body && updating_body) { _update_body(); } } break; @@ -336,16 +348,34 @@ void CollisionShape::_notification(int p_what) { VisualServer::get_singleton()->free(indicator_instance); indicator_instance=RID(); }*/ + can_update_body=false; + set_notify_local_transform(false); + if (debug_shape) { + debug_shape->queue_delete(); + debug_shape=NULL; + } } break; case NOTIFICATION_UNPARENTED: { unparenting=true; - if (updating_body) + if (can_update_body && updating_body) _update_body(); } break; case NOTIFICATION_PARENTED: { - if (updating_body) + if (can_update_body && updating_body) _update_body(); } break; + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + + if (!can_update_body && update_shape_index>=0) { + + CollisionObject *co = get_parent()->cast_to<CollisionObject>(); + if (co) { + co->set_shape_transform(update_shape_index,get_transform()); + } + } + + } break; + } } @@ -357,6 +387,18 @@ void CollisionShape::resource_changed(RES res) { } +void CollisionShape::_set_update_shape_index(int p_index) { + + + update_shape_index=p_index; +} + +int CollisionShape::_get_update_shape_index() const{ + + return update_shape_index; +} + + void CollisionShape::_bind_methods() { //not sure if this should do anything @@ -368,10 +410,14 @@ void CollisionShape::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionShape::is_trigger); ObjectTypeDB::bind_method(_MD("make_convex_from_brothers"),&CollisionShape::make_convex_from_brothers); ObjectTypeDB::set_method_flags("CollisionShape","make_convex_from_brothers",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + ObjectTypeDB::bind_method(_MD("_set_update_shape_index","index"),&CollisionShape::_set_update_shape_index); + ObjectTypeDB::bind_method(_MD("_get_update_shape_index"),&CollisionShape::_get_update_shape_index); + ObjectTypeDB::bind_method(_MD("get_collision_object_shape_index"),&CollisionShape::get_collision_object_shape_index); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), _SCS("set_shape"), _SCS("get_shape")); - ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), _SCS("_set_update_shape_index"), _SCS("_get_update_shape_index")); } @@ -383,8 +429,15 @@ void CollisionShape::set_shape(const Ref<Shape> &p_shape) { if (!shape.is_null()) shape->register_owner(this); update_gizmo(); - if (updating_body) + if (updating_body) { _update_body(); + } else if (can_update_body && update_shape_index>=0 && is_inside_tree()){ + CollisionObject *co = get_parent()->cast_to<CollisionObject>(); + if (co) { + co->set_shape(update_shape_index,p_shape); + } + + } } Ref<Shape> CollisionShape::get_shape() const { @@ -405,8 +458,14 @@ bool CollisionShape::is_updating_body() const { void CollisionShape::set_trigger(bool p_trigger) { trigger=p_trigger; - if (updating_body) + if (updating_body) { _update_body(); + } else if (can_update_body && update_shape_index>=0 && is_inside_tree()){ + CollisionObject *co = get_parent()->cast_to<CollisionObject>(); + if (co) { + co->set_shape_as_trigger(update_shape_index,p_trigger); + } + } } bool CollisionShape::is_trigger() const{ @@ -419,7 +478,10 @@ CollisionShape::CollisionShape() { //indicator = VisualServer::get_singleton()->mesh_create(); updating_body=true; unparenting=false; - trigger=false; + update_shape_index=-1; + trigger=false; + can_update_body=false; + debug_shape=NULL; } CollisionShape::~CollisionShape() { @@ -428,6 +490,30 @@ CollisionShape::~CollisionShape() { //VisualServer::get_singleton()->free(indicator); } +void CollisionShape::_create_debug_shape() { + + + if (debug_shape) { + debug_shape->queue_delete();; + debug_shape=NULL; + } + + Ref<Shape> s = get_shape(); + + if (s.is_null()) + return; + + + Ref<Mesh> mesh = s->get_debug_mesh(); + + MeshInstance *mi = memnew( MeshInstance ); + mi->set_mesh(mesh); + + add_child(mi); + debug_shape=mi; + +} + #if 0 #include "body_volume.h" diff --git a/scene/3d/body_shape.h b/scene/3d/body_shape.h index b3c0006d79..6c0b89da56 100644 --- a/scene/3d/body_shape.h +++ b/scene/3d/body_shape.h @@ -50,14 +50,26 @@ class CollisionShape : public Spatial { RID indicator_instance; */ + Node* debug_shape; + void resource_changed(RES res); bool updating_body; bool unparenting; bool trigger; + bool can_update_body; + + int update_shape_index; + void _update_body(); void _add_to_collision_object(Object* p_cshape); + + void _set_update_shape_index(int p_index); + int _get_update_shape_index() const; + + void _create_debug_shape(); + protected: void _notification(int p_what); @@ -73,8 +85,10 @@ public: void set_updating_body(bool p_update); bool is_updating_body() const; - void set_trigger(bool p_trigger); - bool is_trigger() const; + void set_trigger(bool p_trigger); + bool is_trigger() const; + + int get_collision_object_shape_index() const { return _get_update_shape_index(); } CollisionShape(); ~CollisionShape(); diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp index 4ab1a1a1ab..c857b4851a 100644 --- a/scene/3d/collision_polygon.cpp +++ b/scene/3d/collision_polygon.cpp @@ -6,6 +6,8 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) { + if (!can_update_body) + return; CollisionObject *co = p_obj->cast_to<CollisionObject>(); ERR_FAIL_COND(!co); @@ -23,6 +25,7 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) { //here comes the sun, lalalala //decompose concave into multiple convex polygons and add them + shape_from=co->get_shape_count(); for(int i=0;i<decomp.size();i++) { Ref<ConvexPolygonShape> convex = memnew( ConvexPolygonShape ); DVector<Vector3> cp; @@ -43,6 +46,11 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) { co->add_shape(convex,get_transform()); } + shape_to=co->get_shape_count()-1; + if (shape_to<shape_from) { + shape_from=-1; + shape_to=-1; + } } else { #if 0 @@ -71,6 +79,9 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) { void CollisionPolygon::_update_parent() { + if (!can_update_body) + return; + Node *parent = get_parent(); if (!parent) return; @@ -80,15 +91,50 @@ void CollisionPolygon::_update_parent() { co->_update_shapes_from_children(); } +void CollisionPolygon::_set_shape_range(const Vector2& p_range) { + + shape_from=p_range.x; + shape_to=p_range.y; +} + +Vector2 CollisionPolygon::_get_shape_range() const { + + return Vector2(shape_from,shape_to); +} + void CollisionPolygon::_notification(int p_what) { switch(p_what) { + case NOTIFICATION_ENTER_TREE: { + can_update_body=get_tree()->is_editor_hint(); + set_notify_local_transform(!can_update_body); + + //indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario()); + } break; + case NOTIFICATION_EXIT_TREE: { + can_update_body=false; + set_notify_local_transform(false); + } break; case NOTIFICATION_TRANSFORM_CHANGED: { if (!is_inside_tree()) break; - _update_parent(); + if (can_update_body) { + _update_parent(); + } + + } break; + case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { + if (!can_update_body && shape_from>=0 && shape_from>=0) { + + CollisionObject *co = get_parent()->cast_to<CollisionObject>(); + if (co) { + for(int i=shape_from;i<=shape_to;i++) { + co->set_shape_transform(i,get_transform()); + } + } + } } break; #if 0 @@ -119,29 +165,31 @@ void CollisionPolygon::_notification(int p_what) { void CollisionPolygon::set_polygon(const Vector<Point2>& p_polygon) { polygon=p_polygon; + if (can_update_body) { - for(int i=0;i<polygon.size();i++) { + for(int i=0;i<polygon.size();i++) { - Vector3 p1(polygon[i].x,polygon[i].y,depth*0.5); + Vector3 p1(polygon[i].x,polygon[i].y,depth*0.5); - if (i==0) - aabb=AABB(p1,Vector3()); - else - aabb.expand_to(p1); + if (i==0) + aabb=AABB(p1,Vector3()); + else + aabb.expand_to(p1); - Vector3 p2(polygon[i].x,polygon[i].y,-depth*0.5); - aabb.expand_to(p2); + Vector3 p2(polygon[i].x,polygon[i].y,-depth*0.5); + aabb.expand_to(p2); - } - if (aabb==AABB()) { + } + if (aabb==AABB()) { - aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); - } else { - aabb.pos-=aabb.size*0.3; - aabb.size+=aabb.size*0.6; + aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); + } else { + aabb.pos-=aabb.size*0.3; + aabb.size+=aabb.size*0.6; + } + _update_parent(); } - _update_parent(); update_gizmo(); } @@ -154,6 +202,8 @@ void CollisionPolygon::set_build_mode(BuildMode p_mode) { ERR_FAIL_INDEX(p_mode,2); build_mode=p_mode; + if (!can_update_body) + return; _update_parent(); } @@ -170,6 +220,8 @@ AABB CollisionPolygon::get_item_rect() const { void CollisionPolygon::set_depth(float p_depth) { depth=p_depth; + if (!can_update_body) + return; _update_parent(); update_gizmo(); } @@ -183,22 +235,34 @@ float CollisionPolygon::get_depth() const { void CollisionPolygon::_bind_methods() { ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon::_add_to_collision_object); - ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon::set_polygon); - ObjectTypeDB::bind_method(_MD("get_polygon"),&CollisionPolygon::get_polygon); + + ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon::set_build_mode); + ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon::get_build_mode); ObjectTypeDB::bind_method(_MD("set_depth","depth"),&CollisionPolygon::set_depth); ObjectTypeDB::bind_method(_MD("get_depth"),&CollisionPolygon::get_depth); - ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon::set_build_mode); - ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon::get_build_mode); + ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon::set_polygon); + ObjectTypeDB::bind_method(_MD("get_polygon"),&CollisionPolygon::get_polygon); + + ObjectTypeDB::bind_method(_MD("_set_shape_range","shape_range"),&CollisionPolygon::_set_shape_range); + ObjectTypeDB::bind_method(_MD("_get_shape_range"),&CollisionPolygon::_get_shape_range); + + ObjectTypeDB::bind_method(_MD("get_collision_object_first_shape"),&CollisionPolygon::get_collision_object_first_shape); + ObjectTypeDB::bind_method(_MD("get_collision_object_last_shape"),&CollisionPolygon::get_collision_object_last_shape); ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Triangles"),_SCS("set_build_mode"),_SCS("get_build_mode")); - ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"depth"),_SCS("set_depth"),_SCS("get_depth")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"shape_range",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_shape_range"),_SCS("_get_shape_range")); } CollisionPolygon::CollisionPolygon() { + shape_from=-1; + shape_to=-1; + can_update_body=false; + aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); build_mode=BUILD_SOLIDS; depth=1.0; diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h index efb3666778..9b9afea34f 100644 --- a/scene/3d/collision_polygon.h +++ b/scene/3d/collision_polygon.h @@ -24,9 +24,17 @@ protected: BuildMode build_mode; Vector<Point2> polygon; + void _add_to_collision_object(Object *p_obj); void _update_parent(); + bool can_update_body; + int shape_from; + int shape_to; + + void _set_shape_range(const Vector2& p_range); + Vector2 _get_shape_range() const; + protected: void _notification(int p_what); @@ -43,6 +51,10 @@ public: Vector<Point2> get_polygon() const; virtual AABB get_item_rect() const; + + int get_collision_object_first_shape() const { return shape_from; } + int get_collision_object_last_shape() const { return shape_to; } + CollisionPolygon(); }; diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp index 8c52d4c35c..a238a8ff22 100644 --- a/scene/3d/navigation_mesh.cpp +++ b/scene/3d/navigation_mesh.cpp @@ -1,6 +1,6 @@ #include "navigation_mesh.h" #include "navigation.h" - +#include "mesh_instance.h" void NavigationMesh::create_from_mesh(const Ref<Mesh>& p_mesh) { @@ -87,6 +87,97 @@ void NavigationMesh::clear_polygons(){ polygons.clear(); } +Ref<Mesh> NavigationMesh::get_debug_mesh() { + + if (debug_mesh.is_valid()) + return debug_mesh; + + + + DVector<Vector3> vertices = get_vertices(); + DVector<Vector3>::Read vr=vertices.read(); + List<Face3> faces; + for(int i=0;i<get_polygon_count();i++) { + Vector<int> p = get_polygon(i); + + for(int j=2;j<p.size();j++) { + Face3 f; + f.vertex[0]=vr[p[0]]; + f.vertex[1]=vr[p[j-1]]; + f.vertex[2]=vr[p[j]]; + + faces.push_back(f); + } + } + + + Map<_EdgeKey,bool> edge_map; + DVector<Vector3> tmeshfaces; + tmeshfaces.resize(faces.size()*3); + + { + DVector<Vector3>::Write tw=tmeshfaces.write(); + int tidx=0; + + + for(List<Face3>::Element *E=faces.front();E;E=E->next()) { + + const Face3 &f = E->get(); + + for(int j=0;j<3;j++) { + + tw[tidx++]=f.vertex[j]; + _EdgeKey ek; + ek.from=f.vertex[j].snapped(CMP_EPSILON); + ek.to=f.vertex[(j+1)%3].snapped(CMP_EPSILON); + if (ek.from<ek.to) + SWAP(ek.from,ek.to); + + Map<_EdgeKey,bool>::Element *E=edge_map.find(ek); + + if (E) { + + E->get()=false; + + } else { + + edge_map[ek]=true; + } + + } + } + } + List<Vector3> lines; + + for(Map<_EdgeKey,bool>::Element *E=edge_map.front();E;E=E->next()) { + + if (E->get()) { + lines.push_back(E->key().from); + lines.push_back(E->key().to); + } + } + + DVector<Vector3> varr; + varr.resize(lines.size()); + { + DVector<Vector3>::Write w = varr.write(); + int idx=0; + for(List<Vector3>::Element *E=lines.front();E;E=E->next()) { + w[idx++]=E->get(); + } + } + + debug_mesh = Ref<Mesh>( memnew( Mesh ) ); + + Array arr; + arr.resize(Mesh::ARRAY_MAX); + arr[Mesh::ARRAY_VERTEX]=varr; + + debug_mesh->add_surface(Mesh::PRIMITIVE_LINES,arr); + + return debug_mesh; +} + void NavigationMesh::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_vertices","vertices"),&NavigationMesh::set_vertices); @@ -135,6 +226,16 @@ void NavigationMeshInstance::set_enabled(bool p_enabled) { } + if (debug_view) { + MeshInstance *dm=debug_view->cast_to<MeshInstance>(); + if (is_enabled()) { + dm->set_material_override( get_tree()->get_debug_navigation_material() ); + } else { + dm->set_material_override( get_tree()->get_debug_navigation_disabled_material() ); + } + + } + update_gizmo(); } @@ -170,6 +271,19 @@ void NavigationMeshInstance::_notification(int p_what) { c=c->get_parent_spatial(); } + if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) { + + MeshInstance *dm = memnew( MeshInstance ); + dm->set_mesh( navmesh->get_debug_mesh() ); + if (is_enabled()) { + dm->set_material_override( get_tree()->get_debug_navigation_material() ); + } else { + dm->set_material_override( get_tree()->get_debug_navigation_disabled_material() ); + } + add_child(dm); + debug_view=dm; + } + } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -177,6 +291,8 @@ void NavigationMeshInstance::_notification(int p_what) { navigation->navmesh_set_transform(nav_id,get_relative_transform(navigation)); } + + } break; case NOTIFICATION_EXIT_TREE: { @@ -187,6 +303,11 @@ void NavigationMeshInstance::_notification(int p_what) { nav_id=-1; } } + + if (debug_view) { + debug_view->queue_delete(); + debug_view=NULL; + } navigation=NULL; } break; } @@ -230,6 +351,7 @@ void NavigationMeshInstance::_bind_methods() { NavigationMeshInstance::NavigationMeshInstance() { + debug_view=NULL; navigation=NULL; nav_id=-1; enabled=true; diff --git a/scene/3d/navigation_mesh.h b/scene/3d/navigation_mesh.h index fccf405f9d..1e53b2127a 100644 --- a/scene/3d/navigation_mesh.h +++ b/scene/3d/navigation_mesh.h @@ -4,6 +4,7 @@ #include "scene/3d/spatial.h" #include "scene/resources/mesh.h" +class Mesh; class NavigationMesh : public Resource { @@ -14,6 +15,16 @@ class NavigationMesh : public Resource { Vector<int> indices; }; Vector<Polygon> polygons; + Ref<Mesh> debug_mesh; + + struct _EdgeKey { + + Vector3 from; + Vector3 to; + + bool operator<(const _EdgeKey& p_with) const { return from==p_with.from ? to < p_with.to : from < p_with.from; } + }; + protected: @@ -21,6 +32,7 @@ protected: void _set_polygons(const Array& p_array); Array _get_polygons() const; + public: void create_from_mesh(const Ref<Mesh>& p_mesh); @@ -33,6 +45,8 @@ public: Vector<int> get_polygon(int p_idx); void clear_polygons(); + Ref<Mesh> get_debug_mesh(); + NavigationMesh(); }; @@ -47,6 +61,9 @@ class NavigationMeshInstance : public Spatial { int nav_id; Navigation *navigation; Ref<NavigationMesh> navmesh; + + Node *debug_view; + protected: void _notification(int p_what); diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 7117c59176..a65f68ed2c 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -231,6 +231,11 @@ void Spatial::set_transform(const Transform& p_transform) { _change_notify("transform/rotation"); _change_notify("transform/scale"); _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } + + } @@ -335,6 +340,9 @@ void Spatial::set_translation(const Vector3& p_translation) { data.local_transform.origin=p_translation; _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } } @@ -348,6 +356,9 @@ void Spatial::set_rotation(const Vector3& p_euler){ data.rotation=p_euler; data.dirty|=DIRTY_LOCAL; _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } } void Spatial::set_scale(const Vector3& p_scale){ @@ -360,6 +371,9 @@ void Spatial::set_scale(const Vector3& p_scale){ data.scale=p_scale; data.dirty|=DIRTY_LOCAL; _propagate_transform_changed(this); + if (data.notify_local_transform) { + notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); + } } @@ -685,6 +699,13 @@ void Spatial::look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, con } +void Spatial::set_notify_local_transform(bool p_enable) { + data.notify_local_transform=p_enable; +} + +bool Spatial::is_local_transform_notification_enabled() const { + return data.notify_local_transform; +} void Spatial::_bind_methods() { @@ -725,6 +746,9 @@ void Spatial::_bind_methods() { ObjectTypeDB::bind_method(_MD("_set_visible_"), &Spatial::_set_visible_); ObjectTypeDB::bind_method(_MD("_is_visible_"), &Spatial::_is_visible_); + ObjectTypeDB::bind_method(_MD("set_notify_local_transform","enable"), &Spatial::set_notify_local_transform); + ObjectTypeDB::bind_method(_MD("is_local_transform_notification_enabled"), &Spatial::is_local_transform_notification_enabled); + void rotate(const Vector3& p_normal,float p_radians); void rotate_x(float p_radians); void rotate_y(float p_radians); @@ -783,6 +807,7 @@ Spatial::Spatial() : xform_change(this) data.gizmo_disabled=false; data.gizmo_dirty=false; #endif + data.notify_local_transform=false; data.parent=NULL; data.C=NULL; diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index 8b40786fb8..7fa6099d7a 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -91,6 +91,7 @@ class Spatial : public Node { List<Spatial*>::Element *C; bool ignore_notification; + bool notify_local_transform; bool visible; @@ -134,6 +135,7 @@ public: NOTIFICATION_ENTER_WORLD=41, NOTIFICATION_EXIT_WORLD=42, NOTIFICATION_VISIBILITY_CHANGED=43, + NOTIFICATION_LOCAL_TRANSFORM_CHANGED=44, }; Spatial *get_parent_spatial() const; @@ -179,6 +181,9 @@ public: void look_at(const Vector3& p_target, const Vector3& p_up_normal); void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal); + void set_notify_local_transform(bool p_enable); + bool is_local_transform_notification_enabled() const; + void orthonormalize(); void set_identity(); diff --git a/scene/3d/spatial_stream_player.cpp b/scene/3d/spatial_stream_player.cpp index b81d98e8bf..346e354df2 100644 --- a/scene/3d/spatial_stream_player.cpp +++ b/scene/3d/spatial_stream_player.cpp @@ -331,7 +331,7 @@ void SpatialStreamPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&SpatialStreamPlayer::set_stream); ObjectTypeDB::bind_method(_MD("get_stream:Stream"),&SpatialStreamPlayer::get_stream); - ObjectTypeDB::bind_method(_MD("play"),&SpatialStreamPlayer::play); + ObjectTypeDB::bind_method(_MD("play"),&SpatialStreamPlayer::play,DEFVAL(0)); ObjectTypeDB::bind_method(_MD("stop"),&SpatialStreamPlayer::stop); ObjectTypeDB::bind_method(_MD("is_playing"),&SpatialStreamPlayer::is_playing); diff --git a/scene/audio/stream_player.cpp b/scene/audio/stream_player.cpp index 699d068287..c4e1ccc9b6 100644 --- a/scene/audio/stream_player.cpp +++ b/scene/audio/stream_player.cpp @@ -325,7 +325,7 @@ void StreamPlayer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&StreamPlayer::set_stream); ObjectTypeDB::bind_method(_MD("get_stream:Stream"),&StreamPlayer::get_stream); - ObjectTypeDB::bind_method(_MD("play"),&StreamPlayer::play); + ObjectTypeDB::bind_method(_MD("play"),&StreamPlayer::play,DEFVAL(0)); ObjectTypeDB::bind_method(_MD("stop"),&StreamPlayer::stop); ObjectTypeDB::bind_method(_MD("is_playing"),&StreamPlayer::is_playing); diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index 6489cbccd5..b63b3de530 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -99,8 +99,10 @@ void BoxContainer::_resort() { elements exist */ + bool has_stretched = false; while(stretch_ratio_total>0) { // first of all, dont even be here if no stretchable objects exist + has_stretched = true; bool refit_successful=true; //assume refit-test will go well for(int i=0;i<get_child_count();i++) { @@ -143,6 +145,18 @@ void BoxContainer::_resort() { int ofs=0; + if (!has_stretched) { + switch (align) { + case ALIGN_BEGIN: + break; + case ALIGN_CENTER: + ofs = stretch_diff / 2; + break; + case ALIGN_END: + ofs = stretch_diff; + break; + } + } first=true; int idx=0; @@ -254,6 +268,15 @@ void BoxContainer::_notification(int p_what) { } } +void BoxContainer::set_alignment(AlignMode p_align) { + align = p_align; + _resort(); +} + +BoxContainer::AlignMode BoxContainer::get_alignment() const { + return align; +} + void BoxContainer::add_spacer(bool p_begin) { Control *c = memnew( Control ); @@ -270,10 +293,23 @@ void BoxContainer::add_spacer(bool p_begin) { BoxContainer::BoxContainer(bool p_vertical) { vertical=p_vertical; + align = ALIGN_BEGIN; // set_ignore_mouse(true); set_stop_mouse(false); } +void BoxContainer::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("get_alignment"),&BoxContainer::get_alignment); + ObjectTypeDB::bind_method(_MD("set_alignment","alignment"),&BoxContainer::set_alignment); + + BIND_CONSTANT( ALIGN_BEGIN ); + BIND_CONSTANT( ALIGN_CENTER ); + BIND_CONSTANT( ALIGN_END ); + + ADD_PROPERTY( PropertyInfo(Variant::INT,"alignment", PROPERTY_HINT_ENUM, "Begin,Center,End"), _SCS("set_alignment"),_SCS("get_alignment") ); + +} MarginContainer* VBoxContainer::add_margin_child(const String& p_label,Control *p_control,bool p_expand) { diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h index d461b4aebe..c357814baf 100644 --- a/scene/gui/box_container.h +++ b/scene/gui/box_container.h @@ -35,16 +35,31 @@ class BoxContainer : public Container { OBJ_TYPE(BoxContainer,Container); +public: + + enum AlignMode { + ALIGN_BEGIN, + ALIGN_CENTER, + ALIGN_END + }; + +private: bool vertical; + AlignMode align; void _resort(); protected: void _notification(int p_what); + + static void _bind_methods(); public: void add_spacer(bool p_begin=false); + void set_alignment(AlignMode p_align); + AlignMode get_alignment() const; + virtual Size2 get_minimum_size() const; BoxContainer(bool p_vertical=false); @@ -73,4 +88,6 @@ public: VBoxContainer() : BoxContainer(true) {} }; +VARIANT_ENUM_CAST(BoxContainer::AlignMode); + #endif // BOX_CONTAINER_H diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index 45e3d92ece..adf053f5c9 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -42,6 +42,8 @@ #include "io/resource_loader.h" #include "viewport.h" #include "scene/resources/packed_scene.h" +#include "scene/resources/material.h" +#include "scene/resources/mesh.h" void SceneTree::tree_changed() { @@ -470,7 +472,6 @@ void SceneTree::init() { input_handled=false; - editor_hint=false; pause=false; root->_set_tree(this); @@ -624,6 +625,175 @@ bool SceneTree::is_editor_hint() const { return editor_hint; } +void SceneTree::set_debug_collisions_hint(bool p_enabled) { + + debug_collisions_hint=p_enabled; +} + +bool SceneTree::is_debugging_collisions_hint() const { + + return debug_collisions_hint; +} + +void SceneTree::set_debug_navigation_hint(bool p_enabled) { + + debug_navigation_hint=p_enabled; +} + +bool SceneTree::is_debugging_navigation_hint() const { + + return debug_navigation_hint; +} + +void SceneTree::set_debug_collisions_color(const Color& p_color) { + + debug_collisions_color=p_color; +} + +Color SceneTree::get_debug_collisions_color() const { + + return debug_collisions_color; +} + +void SceneTree::set_debug_collision_contact_color(const Color& p_color) { + + debug_collision_contact_color=p_color; +} + +Color SceneTree::get_debug_collision_contact_color() const { + + return debug_collision_contact_color; +} + +void SceneTree::set_debug_navigation_color(const Color& p_color) { + + debug_navigation_color=p_color; +} + +Color SceneTree::get_debug_navigation_color() const { + + return debug_navigation_color; +} + +void SceneTree::set_debug_navigation_disabled_color(const Color& p_color) { + + debug_navigation_disabled_color=p_color; +} + +Color SceneTree::get_debug_navigation_disabled_color() const { + + return debug_navigation_disabled_color; +} + +Ref<Material> SceneTree::get_debug_navigation_material() { + + if (navigation_material.is_valid()) + return navigation_material; + + Ref<FixedMaterial> line_material = Ref<FixedMaterial>( memnew( FixedMaterial )); + line_material->set_flag(Material::FLAG_UNSHADED, true); + line_material->set_line_width(3.0); + line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + line_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true); + line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,get_debug_navigation_color()); + + navigation_material=line_material; + + return navigation_material; + +} + +Ref<Material> SceneTree::get_debug_navigation_disabled_material(){ + + if (navigation_disabled_material.is_valid()) + return navigation_disabled_material; + + Ref<FixedMaterial> line_material = Ref<FixedMaterial>( memnew( FixedMaterial )); + line_material->set_flag(Material::FLAG_UNSHADED, true); + line_material->set_line_width(3.0); + line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + line_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true); + line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,get_debug_navigation_disabled_color()); + + navigation_disabled_material=line_material; + + return navigation_disabled_material; + +} +Ref<Material> SceneTree::get_debug_collision_material() { + + if (collision_material.is_valid()) + return collision_material; + + + Ref<FixedMaterial> line_material = Ref<FixedMaterial>( memnew( FixedMaterial )); + line_material->set_flag(Material::FLAG_UNSHADED, true); + line_material->set_line_width(3.0); + line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + line_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true); + line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,get_debug_collisions_color()); + + collision_material=line_material; + + return collision_material; +} + +Ref<Mesh> SceneTree::get_debug_contact_mesh() { + + if (debug_contact_mesh.is_valid()) + return debug_contact_mesh; + + debug_contact_mesh = Ref<Mesh>( memnew( Mesh ) ); + + Ref<FixedMaterial> mat = memnew( FixedMaterial ); + mat->set_flag(Material::FLAG_UNSHADED,true); + mat->set_flag(Material::FLAG_DOUBLE_SIDED,true); + mat->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); + mat->set_parameter(FixedMaterial::PARAM_DIFFUSE,get_debug_collision_contact_color()); + + Vector3 diamond[6]={ + Vector3(-1, 0, 0), + Vector3( 1, 0, 0), + Vector3( 0, -1, 0), + Vector3( 0, 1, 0), + Vector3( 0, 0, -1), + Vector3( 0, 0, 1) + }; + + int diamond_faces[8*3]={ + 0,2,4, + 0,3,4, + 1,2,4, + 1,3,4, + 0,2,5, + 0,3,5, + 1,2,5, + 1,3,5, + }; + + DVector<int> indices; + for(int i=0;i<8*3;i++) + indices.push_back(diamond_faces[i]); + + DVector<Vector3> vertices; + for(int i=0;i<6;i++) + vertices.push_back(diamond[i]*0.1); + + Array arr; + arr.resize(Mesh::ARRAY_MAX); + arr[Mesh::ARRAY_VERTEX]=vertices; + arr[Mesh::ARRAY_INDEX]=indices; + + + debug_contact_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,arr); + debug_contact_mesh->surface_set_material(0,mat); + + return debug_contact_mesh; + +} + + + void SceneTree::set_pause(bool p_enabled) { if (p_enabled==pause) @@ -1424,6 +1594,11 @@ void SceneTree::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_editor_hint","enable"),&SceneTree::set_editor_hint); ObjectTypeDB::bind_method(_MD("is_editor_hint"),&SceneTree::is_editor_hint); + ObjectTypeDB::bind_method(_MD("set_debug_collisions_hint","enable"),&SceneTree::set_debug_collisions_hint); + ObjectTypeDB::bind_method(_MD("is_debugging_collisions_hint"),&SceneTree::is_debugging_collisions_hint); + ObjectTypeDB::bind_method(_MD("set_debug_navigation_hint","enable"),&SceneTree::set_debug_navigation_hint); + ObjectTypeDB::bind_method(_MD("is_debugging_navigation_hint"),&SceneTree::is_debugging_navigation_hint); + #ifdef TOOLS_ENABLED ObjectTypeDB::bind_method(_MD("set_edited_scene_root","scene"),&SceneTree::set_edited_scene_root); ObjectTypeDB::bind_method(_MD("get_edited_scene_root"),&SceneTree::get_edited_scene_root); @@ -1490,10 +1665,23 @@ void SceneTree::_bind_methods() { } +SceneTree *SceneTree::singleton=NULL; + SceneTree::SceneTree() { + singleton=this; _quit=false; initialized=false; + editor_hint=false; + debug_collisions_hint=false; + debug_navigation_hint=false; + debug_collisions_color=GLOBAL_DEF("debug/collision_shape_color",Color(0.0,0.6,0.7,0.5)); + debug_collision_contact_color=GLOBAL_DEF("debug/collision_contact_color",Color(1.0,0.2,0.1,0.8)); + debug_navigation_color=GLOBAL_DEF("debug/navigation_geometry_color",Color(0.1,1.0,0.7,0.4)); + debug_navigation_disabled_color=GLOBAL_DEF("debug/navigation_disabled_geometry_color",Color(1.0,0.7,0.1,0.4)); + collision_debug_contacts=GLOBAL_DEF("debug/collision_max_contacts_displayed",10000); + + tree_version=1; fixed_process_time=1; idle_process_time=1; diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h index 1f09d9c546..8d9021d24e 100644 --- a/scene/main/scene_main_loop.h +++ b/scene/main/scene_main_loop.h @@ -45,6 +45,8 @@ class SceneTree; class PackedScene; class Node; class Viewport; +class Material; +class Mesh; class SceneTree : public MainLoop { @@ -87,6 +89,8 @@ private: uint32_t last_id; bool editor_hint; + bool debug_collisions_hint; + bool debug_navigation_hint; bool pause; int root_lock; @@ -138,9 +142,20 @@ private: Node *current_scene; + Color debug_collisions_color; + Color debug_collision_contact_color; + Color debug_navigation_color; + Color debug_navigation_disabled_color; + Ref<Mesh> debug_contact_mesh; + Ref<Material> navigation_material; + Ref<Material> navigation_disabled_material; + Ref<Material> collision_material; + int collision_debug_contacts; + void _change_scene(Node* p_to); //void _call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,const Variant& p_arg1,const Variant& p_arg2); + static SceneTree *singleton; friend class Node; void tree_changed(); @@ -270,6 +285,32 @@ public: void set_camera(const RID& p_camera); RID get_camera() const; + void set_debug_collisions_hint(bool p_enabled); + bool is_debugging_collisions_hint() const; + + void set_debug_navigation_hint(bool p_enabled); + bool is_debugging_navigation_hint() const; + + void set_debug_collisions_color(const Color& p_color); + Color get_debug_collisions_color() const; + + void set_debug_collision_contact_color(const Color& p_color); + Color get_debug_collision_contact_color() const; + + void set_debug_navigation_color(const Color& p_color); + Color get_debug_navigation_color() const; + + void set_debug_navigation_disabled_color(const Color& p_color); + Color get_debug_navigation_disabled_color() const; + + + Ref<Material> get_debug_navigation_material(); + Ref<Material> get_debug_navigation_disabled_material(); + Ref<Material> get_debug_collision_material(); + Ref<Mesh> get_debug_contact_mesh(); + + int get_collision_debug_contact_count() { return collision_debug_contacts; } + int64_t get_frame() const; int get_node_count() const; @@ -297,6 +338,7 @@ public: //used by Main::start, don't use otherwise void add_current_scene(Node * p_current); + static SceneTree* get_singleton() { return singleton; } SceneTree(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 3bb64e54c6..d19b5767c2 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -37,6 +37,7 @@ #include "servers/spatial_sound_2d_server.h" #include "scene/gui/control.h" #include "scene/3d/camera.h" +#include "scene/resources/mesh.h" #include "scene/3d/spatial_indexer.h" #include "scene/3d/collision_object.h" @@ -319,6 +320,23 @@ void Viewport::_notification(int p_what) { } add_to_group("_viewports"); + if (get_tree()->is_debugging_collisions_hint()) { + //2D + Physics2DServer::get_singleton()->space_set_debug_contacts(find_world_2d()->get_space(),get_tree()->get_collision_debug_contact_count()); + contact_2d_debug=VisualServer::get_singleton()->canvas_item_create(); + VisualServer::get_singleton()->canvas_item_set_parent(contact_2d_debug,find_world_2d()->get_canvas()); + //3D + PhysicsServer::get_singleton()->space_set_debug_contacts(find_world()->get_space(),get_tree()->get_collision_debug_contact_count()); + contact_3d_debug_multimesh=VisualServer::get_singleton()->multimesh_create(); + VisualServer::get_singleton()->multimesh_set_instance_count(contact_3d_debug_multimesh,get_tree()->get_collision_debug_contact_count()); + VisualServer::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh,0); + VisualServer::get_singleton()->multimesh_set_mesh(contact_3d_debug_multimesh,get_tree()->get_debug_contact_mesh()->get_rid()); + contact_3d_debug_instance=VisualServer::get_singleton()->instance_create(); + VisualServer::get_singleton()->instance_set_base(contact_3d_debug_instance,contact_3d_debug_multimesh); + VisualServer::get_singleton()->instance_set_scenario(contact_3d_debug_instance,find_world()->get_scenario()); + VisualServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance,VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS,true); + + } } break; case NOTIFICATION_READY: { @@ -351,11 +369,69 @@ void Viewport::_notification(int p_what) { VisualServer::get_singleton()->viewport_set_scenario(viewport,RID()); SpatialSoundServer::get_singleton()->listener_set_space(listener,RID()); VisualServer::get_singleton()->viewport_remove_canvas(viewport,current_canvas); + if (contact_2d_debug.is_valid()) { + VisualServer::get_singleton()->free(contact_2d_debug); + contact_2d_debug=RID(); + } + + if (contact_3d_debug_multimesh.is_valid()) { + VisualServer::get_singleton()->free(contact_3d_debug_multimesh); + VisualServer::get_singleton()->free(contact_3d_debug_instance); + contact_3d_debug_instance=RID(); + contact_3d_debug_multimesh=RID(); + } + remove_from_group("_viewports"); } break; case NOTIFICATION_FIXED_PROCESS: { + + if (get_tree()->is_debugging_collisions_hint() && contact_2d_debug.is_valid()) { + + VisualServer::get_singleton()->canvas_item_clear(contact_2d_debug); + VisualServer::get_singleton()->canvas_item_raise(contact_2d_debug); + + Vector<Vector2> points = Physics2DServer::get_singleton()->space_get_contacts(find_world_2d()->get_space()); + int point_count = Physics2DServer::get_singleton()->space_get_contact_count(find_world_2d()->get_space()); + Color ccol = get_tree()->get_debug_collision_contact_color(); + + + for(int i=0;i<point_count;i++) { + + VisualServer::get_singleton()->canvas_item_add_rect(contact_2d_debug,Rect2(points[i]-Vector2(2,2),Vector2(5,5)),ccol); + } + } + + if (get_tree()->is_debugging_collisions_hint() && contact_3d_debug_multimesh.is_valid()) { + + + Vector<Vector3> points = PhysicsServer::get_singleton()->space_get_contacts(find_world()->get_space()); + int point_count = PhysicsServer::get_singleton()->space_get_contact_count(find_world()->get_space()); + + + VS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh,point_count); + + if (point_count>0) { + AABB aabb; + + Transform t; + for(int i=0;i<point_count;i++) { + + if (i==0) + aabb.pos=points[i]; + else + aabb.expand_to(points[i]); + t.origin=points[i]; + VisualServer::get_singleton()->multimesh_instance_set_transform(contact_3d_debug_multimesh,i,t); + } + aabb.grow(aabb.get_longest_axis_size()*0.01); + VisualServer::get_singleton()->multimesh_set_aabb(contact_3d_debug_multimesh,aabb); + } + } + + + if (physics_object_picking) { Vector2 last_pos(1e20,1e20); @@ -1449,6 +1525,8 @@ Viewport::Viewport() { unhandled_key_input_group = "_vp_unhandled_key_input"+id; + + } diff --git a/scene/main/viewport.h b/scene/main/viewport.h index c3c339ac5d..843a1fd9b7 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -104,6 +104,11 @@ friend class RenderTargetTexture; Rect2 rect; Rect2 to_screen_rect; + RID contact_2d_debug; + RID contact_3d_debug_multimesh; + RID contact_3d_debug_instance; + + bool size_override; bool size_override_stretch; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 3727c2e8ec..851de4a89f 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -458,7 +458,6 @@ void register_scene_types() { /* disable types by default, only editors should enable them */ - ObjectTypeDB::set_type_enabled("CollisionShape",false); //ObjectTypeDB::set_type_enabled("BodyVolumeSphere",false); //ObjectTypeDB::set_type_enabled("BodyVolumeBox",false); //ObjectTypeDB::set_type_enabled("BodyVolumeCapsule",false); @@ -492,9 +491,12 @@ void register_scene_types() { ObjectTypeDB::register_type<OccluderPolygon2D>(); ObjectTypeDB::register_type<YSort>(); ObjectTypeDB::register_type<BackBufferCopy>(); - - ObjectTypeDB::set_type_enabled("CollisionShape2D",false); - ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false); + if (bool(GLOBAL_DEF("physics/remove_collision_helpers_at_runtime",false))) { + ObjectTypeDB::set_type_enabled("CollisionShape2D",false); + ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false); + ObjectTypeDB::set_type_enabled("CollisionShape",false); + ObjectTypeDB::set_type_enabled("CollisionPolygon",false); + } OS::get_singleton()->yield(); //may take time to init diff --git a/scene/resources/box_shape.cpp b/scene/resources/box_shape.cpp index 22ee9f8c09..ba29a1b601 100644 --- a/scene/resources/box_shape.cpp +++ b/scene/resources/box_shape.cpp @@ -30,6 +30,25 @@ #include "servers/physics_server.h" +Vector<Vector3> BoxShape::_gen_debug_mesh_lines() { + + + Vector<Vector3> lines; + AABB aabb; + aabb.pos=-get_extents(); + aabb.size=aabb.pos*-2; + + for(int i=0;i<12;i++) { + Vector3 a,b; + aabb.get_edge(i,a,b); + lines.push_back(a); + lines.push_back(b); + } + + + return lines; +} + void BoxShape::_update_shape() { PhysicsServer::get_singleton()->shape_set_data(get_shape(),extents); diff --git a/scene/resources/box_shape.h b/scene/resources/box_shape.h index 18c5f5e5fb..9667515657 100644 --- a/scene/resources/box_shape.h +++ b/scene/resources/box_shape.h @@ -41,6 +41,7 @@ protected: static void _bind_methods(); virtual void _update_shape(); + virtual Vector<Vector3> _gen_debug_mesh_lines(); public: diff --git a/scene/resources/capsule_shape.cpp b/scene/resources/capsule_shape.cpp index 2633b132cf..67ceed6be0 100644 --- a/scene/resources/capsule_shape.cpp +++ b/scene/resources/capsule_shape.cpp @@ -30,6 +30,46 @@ #include "servers/physics_server.h" +Vector<Vector3> CapsuleShape::_gen_debug_mesh_lines() { + + + float radius = get_radius(); + float height = get_height(); + + + Vector<Vector3> points; + + Vector3 d(0,0,height*0.5); + for(int i=0;i<360;i++) { + + float ra=Math::deg2rad(i); + float rb=Math::deg2rad(i+1); + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*radius; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*radius; + + points.push_back(Vector3(a.x,a.y,0)+d); + points.push_back(Vector3(b.x,b.y,0)+d); + + points.push_back(Vector3(a.x,a.y,0)-d); + points.push_back(Vector3(b.x,b.y,0)-d); + + if (i%90==0) { + + points.push_back(Vector3(a.x,a.y,0)+d); + points.push_back(Vector3(a.x,a.y,0)-d); + } + + Vector3 dud = i<180?d:-d; + + points.push_back(Vector3(0,a.y,a.x)+dud); + points.push_back(Vector3(0,b.y,b.x)+dud); + points.push_back(Vector3(a.y,0,a.x)+dud); + points.push_back(Vector3(b.y,0,b.x)+dud); + + } + + return points; +} void CapsuleShape::_update_shape() { @@ -65,7 +105,6 @@ float CapsuleShape::get_height() const { return height; } - void CapsuleShape::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_radius","radius"),&CapsuleShape::set_radius); diff --git a/scene/resources/capsule_shape.h b/scene/resources/capsule_shape.h index 43b8331949..e516d0e3c7 100644 --- a/scene/resources/capsule_shape.h +++ b/scene/resources/capsule_shape.h @@ -43,6 +43,7 @@ protected: virtual void _update_shape(); + virtual Vector<Vector3> _gen_debug_mesh_lines(); public: void set_radius(float p_radius); @@ -50,6 +51,7 @@ public: void set_height(float p_height); float get_height() const; + CapsuleShape(); }; diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp index 135eb41d8f..923a509ad5 100644 --- a/scene/resources/capsule_shape_2d.cpp +++ b/scene/resources/capsule_shape_2d.cpp @@ -29,6 +29,7 @@ #include "capsule_shape_2d.h" #include "servers/physics_2d_server.h" +#include "servers/visual_server.h" void CapsuleShape2D::_update_shape() { @@ -60,6 +61,32 @@ 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<Color> col; + col.push_back(p_color); + VisualServer::get_singleton()->canvas_item_add_polygon(p_to_rid,points,col); + +} + +Rect2 CapsuleShape2D::get_rect() const { + + Vector2 he=Point2(get_radius(),get_radius()+get_height()*0.5); + Rect2 rect; + rect.pos=-he; + rect.size=he*2.0; + return rect; +} + void CapsuleShape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_radius","radius"),&CapsuleShape2D::set_radius); diff --git a/scene/resources/capsule_shape_2d.h b/scene/resources/capsule_shape_2d.h index 4dd6348282..dc679966f9 100644 --- a/scene/resources/capsule_shape_2d.h +++ b/scene/resources/capsule_shape_2d.h @@ -49,6 +49,9 @@ public: void set_radius(real_t p_radius); real_t get_radius() const; + virtual void draw(const RID& p_to_rid,const Color& p_color); + virtual Rect2 get_rect() const ; + CapsuleShape2D(); }; diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp index 4135bc7c3b..c77395612c 100644 --- a/scene/resources/circle_shape_2d.cpp +++ b/scene/resources/circle_shape_2d.cpp @@ -29,7 +29,7 @@ #include "circle_shape_2d.h" #include "servers/physics_2d_server.h" - +#include "servers/visual_server.h" void CircleShape2D::_update_shape() { Physics2DServer::get_singleton()->shape_set_data(get_rid(),radius); @@ -58,6 +58,27 @@ void CircleShape2D::_bind_methods() { } +Rect2 CircleShape2D::get_rect() const { + Rect2 rect; + rect.pos=-Point2(get_radius(),get_radius()); + rect.size=Point2(get_radius(),get_radius())*2.0; + return rect; +} + +void CircleShape2D::draw(const RID& p_to_rid,const Color& p_color) { + + Vector<Vector2> points; + for(int i=0;i<24;i++) { + + points.push_back(Vector2(Math::cos(i*Math_PI*2/24.0),Math::sin(i*Math_PI*2/24.0))*get_radius()); + } + + Vector<Color> col; + col.push_back(p_color); + VisualServer::get_singleton()->canvas_item_add_polygon(p_to_rid,points,col); + +} + CircleShape2D::CircleShape2D() : Shape2D( Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CIRCLE)) { radius=10; diff --git a/scene/resources/circle_shape_2d.h b/scene/resources/circle_shape_2d.h index d937af2979..a5902b189c 100644 --- a/scene/resources/circle_shape_2d.h +++ b/scene/resources/circle_shape_2d.h @@ -44,6 +44,10 @@ public: void set_radius(real_t p_radius); real_t get_radius() const; + virtual void draw(const RID& p_to_rid,const Color& p_color); + virtual Rect2 get_rect() const; + + CircleShape2D(); }; diff --git a/scene/resources/concave_polygon_shape.cpp b/scene/resources/concave_polygon_shape.cpp index 55bd5de690..7aeac04a22 100644 --- a/scene/resources/concave_polygon_shape.cpp +++ b/scene/resources/concave_polygon_shape.cpp @@ -30,6 +30,40 @@ #include "servers/physics_server.h" +Vector<Vector3> ConcavePolygonShape::_gen_debug_mesh_lines() { + + Set<DrawEdge> edges; + + DVector<Vector3> data=get_faces(); + int datalen=data.size(); + ERR_FAIL_COND_V( (datalen%3)!=0,Vector<Vector3>() ); + + DVector<Vector3>::Read r=data.read(); + + for(int i=0;i<datalen;i+=3) { + + for(int j=0;j<3;j++) { + + DrawEdge de(r[i+j],r[i+((j+1)%3)]); + edges.insert(de); + } + + } + + Vector<Vector3> points; + points.resize(edges.size()*2); + int idx=0; + for (Set<DrawEdge>::Element*E=edges.front();E;E=E->next()) { + + points[idx+0]=E->get().a; + points[idx+1]=E->get().b; + idx+=2; + } + + return points; + +} + bool ConcavePolygonShape::_set(const StringName& p_name, const Variant& p_value) { if (p_name=="data") diff --git a/scene/resources/concave_polygon_shape.h b/scene/resources/concave_polygon_shape.h index 7bd80eb9c0..fae98ee046 100644 --- a/scene/resources/concave_polygon_shape.h +++ b/scene/resources/concave_polygon_shape.h @@ -35,16 +35,36 @@ class ConcavePolygonShape : public Shape { OBJ_TYPE(ConcavePolygonShape,Shape); + struct DrawEdge { + + Vector3 a; + Vector3 b; + bool operator<(const DrawEdge& p_edge) const { + if (a==p_edge.a) + return b<p_edge.b; + else + return a<p_edge.a; + } + + DrawEdge(const Vector3& p_a=Vector3(),const Vector3& p_b=Vector3()) { + a=p_a; + b=p_b; + if (a<b) { + SWAP(a,b); + } + } + }; protected: + bool _set(const StringName& p_name, const Variant& p_value); bool _get(const StringName& p_name,Variant &r_ret) const; void _get_property_list( List<PropertyInfo> *p_list) const; static void _bind_methods(); virtual void _update_shape(); - + virtual Vector<Vector3> _gen_debug_mesh_lines(); public: void set_faces(const DVector<Vector3>& p_faces); diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp index 0287d79dc6..923e2817ef 100644 --- a/scene/resources/concave_polygon_shape_2d.cpp +++ b/scene/resources/concave_polygon_shape_2d.cpp @@ -29,7 +29,7 @@ #include "concave_polygon_shape_2d.h" #include "servers/physics_2d_server.h" - +#include "servers/visual_server.h" void ConcavePolygonShape2D::set_segments(const DVector<Vector2>& p_segments) { @@ -41,6 +41,43 @@ DVector<Vector2> ConcavePolygonShape2D::get_segments() const { return Physics2DServer::get_singleton()->shape_get_data(get_rid()); } +void ConcavePolygonShape2D::draw(const RID& p_to_rid,const Color& p_color) { + + + DVector<Vector2> s = get_segments(); + int len=s.size(); + if (len==0 || (len%2)==1) + return; + + DVector<Vector2>::Read r = s.read(); + for(int i=0;i<len;i+=2) { + VisualServer::get_singleton()->canvas_item_add_line(p_to_rid,r[i],r[i+1],p_color,2); + } + +} + +Rect2 ConcavePolygonShape2D::get_rect() const { + + + DVector<Vector2> s = get_segments(); + int len=s.size(); + if (len==0) + return Rect2(); + + Rect2 rect; + + DVector<Vector2>::Read r = s.read(); + for(int i=0;i<len;i++) { + if (i==0) + rect.pos=r[i]; + else + rect.expand_to(r[i]); + } + + return rect; + +} + void ConcavePolygonShape2D::_bind_methods() { diff --git a/scene/resources/concave_polygon_shape_2d.h b/scene/resources/concave_polygon_shape_2d.h index b835096b2a..29666c88c1 100644 --- a/scene/resources/concave_polygon_shape_2d.h +++ b/scene/resources/concave_polygon_shape_2d.h @@ -41,6 +41,9 @@ public: void set_segments(const DVector<Vector2>& p_segments); DVector<Vector2> get_segments() const; + virtual void draw(const RID& p_to_rid,const Color& p_color); + virtual Rect2 get_rect() const ; + ConcavePolygonShape2D(); }; diff --git a/scene/resources/convex_polygon_shape.cpp b/scene/resources/convex_polygon_shape.cpp index 326a0e5180..6a405c9c94 100644 --- a/scene/resources/convex_polygon_shape.cpp +++ b/scene/resources/convex_polygon_shape.cpp @@ -28,7 +28,34 @@ /*************************************************************************/ #include "convex_polygon_shape.h" #include "servers/physics_server.h" +#include "quick_hull.h" +Vector<Vector3> ConvexPolygonShape::_gen_debug_mesh_lines() { + + DVector<Vector3> points = get_points(); + + if (points.size()>3) { + + QuickHull qh; + Vector<Vector3> varr = Variant(points); + Geometry::MeshData md; + Error err = qh.build(varr,md); + if (err==OK) { + Vector<Vector3> lines; + lines.resize(md.edges.size()*2); + for(int i=0;i<md.edges.size();i++) { + lines[i*2+0]=md.vertices[md.edges[i].a]; + lines[i*2+1]=md.vertices[md.edges[i].b]; + } + return lines; + + + } + + } + + return Vector<Vector3>(); +} void ConvexPolygonShape::_update_shape() { diff --git a/scene/resources/convex_polygon_shape.h b/scene/resources/convex_polygon_shape.h index e0a590e09d..48454deb2b 100644 --- a/scene/resources/convex_polygon_shape.h +++ b/scene/resources/convex_polygon_shape.h @@ -42,6 +42,7 @@ protected: virtual void _update_shape(); + virtual Vector<Vector3> _gen_debug_mesh_lines(); public: void set_points(const DVector<Vector3>& p_points); diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp index 74506f8600..dac39fc846 100644 --- a/scene/resources/convex_polygon_shape_2d.cpp +++ b/scene/resources/convex_polygon_shape_2d.cpp @@ -29,7 +29,7 @@ #include "convex_polygon_shape_2d.h" #include "servers/physics_2d_server.h" - +#include "servers/visual_server.h" void ConvexPolygonShape2D::_update_shape() { Physics2DServer::get_singleton()->shape_set_data(get_rid(),points); @@ -66,6 +66,29 @@ void ConvexPolygonShape2D::_bind_methods() { } +void ConvexPolygonShape2D::draw(const RID& p_to_rid,const Color& p_color) { + + + Vector<Color> col; + col.push_back(p_color); + VisualServer::get_singleton()->canvas_item_add_polygon(p_to_rid,points,col); +} + +Rect2 ConvexPolygonShape2D::get_rect() const { + + + Rect2 rect; + for(int i=0;i<points.size();i++) { + if (i==0) + rect.pos=points[i]; + else + rect.expand_to(points[i]); + } + + return rect; + +} + ConvexPolygonShape2D::ConvexPolygonShape2D() : Shape2D( Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CONVEX_POLYGON)) { diff --git a/scene/resources/convex_polygon_shape_2d.h b/scene/resources/convex_polygon_shape_2d.h index efcaa19be6..1af7787f67 100644 --- a/scene/resources/convex_polygon_shape_2d.h +++ b/scene/resources/convex_polygon_shape_2d.h @@ -45,6 +45,9 @@ public: void set_points(const Vector<Vector2>& p_points); Vector<Vector2> get_points() const; + virtual void draw(const RID& p_to_rid,const Color& p_color); + virtual Rect2 get_rect() const ; + ConvexPolygonShape2D(); }; diff --git a/scene/resources/plane_shape.cpp b/scene/resources/plane_shape.cpp index 150406ceff..760a36a91e 100644 --- a/scene/resources/plane_shape.cpp +++ b/scene/resources/plane_shape.cpp @@ -30,7 +30,34 @@ #include "servers/physics_server.h" - +Vector<Vector3> PlaneShape::_gen_debug_mesh_lines() { + + Plane p = get_plane(); + Vector<Vector3> points; + + Vector3 n1 = p.get_any_perpendicular_normal(); + Vector3 n2 = p.normal.cross(n1).normalized(); + + Vector3 pface[4]={ + p.normal*p.d+n1*10.0+n2*10.0, + p.normal*p.d+n1*10.0+n2*-10.0, + p.normal*p.d+n1*-10.0+n2*-10.0, + p.normal*p.d+n1*-10.0+n2*10.0, + }; + + points.push_back(pface[0]); + points.push_back(pface[1]); + points.push_back(pface[1]); + points.push_back(pface[2]); + points.push_back(pface[2]); + points.push_back(pface[3]); + points.push_back(pface[3]); + points.push_back(pface[0]); + points.push_back(p.normal*p.d); + points.push_back(p.normal*p.d+p.normal*3); + + return points; +} void PlaneShape::_update_shape() { diff --git a/scene/resources/plane_shape.h b/scene/resources/plane_shape.h index 3bdf8f2bef..dd285171c4 100644 --- a/scene/resources/plane_shape.h +++ b/scene/resources/plane_shape.h @@ -39,9 +39,9 @@ class PlaneShape : public Shape { protected: static void _bind_methods(); - virtual void _update_shape(); + virtual Vector<Vector3> _gen_debug_mesh_lines(); public: void set_plane(Plane p_plane); diff --git a/scene/resources/ray_shape.cpp b/scene/resources/ray_shape.cpp index e12ecf107b..ee55cc6e37 100644 --- a/scene/resources/ray_shape.cpp +++ b/scene/resources/ray_shape.cpp @@ -30,7 +30,14 @@ #include "servers/physics_server.h" +Vector<Vector3> RayShape::_gen_debug_mesh_lines() { + Vector<Vector3> points; + points.push_back(Vector3()); + points.push_back(Vector3(0,0,get_length())); + + return points; +} void RayShape::_update_shape() { diff --git a/scene/resources/ray_shape.h b/scene/resources/ray_shape.h index 0b6156d343..edb29b83b5 100644 --- a/scene/resources/ray_shape.h +++ b/scene/resources/ray_shape.h @@ -39,7 +39,7 @@ protected: static void _bind_methods(); virtual void _update_shape(); - + virtual Vector<Vector3> _gen_debug_mesh_lines(); public: void set_length(float p_length); diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp index d3332f45a5..7903d88736 100644 --- a/scene/resources/rectangle_shape_2d.cpp +++ b/scene/resources/rectangle_shape_2d.cpp @@ -29,7 +29,7 @@ #include "rectangle_shape_2d.h" #include "servers/physics_2d_server.h" - +#include "servers/visual_server.h" void RectangleShape2D::_update_shape() { Physics2DServer::get_singleton()->shape_set_data(get_rid(),extents); @@ -48,6 +48,19 @@ Vector2 RectangleShape2D::get_extents() const { return extents; } +void RectangleShape2D::draw(const RID& p_to_rid,const Color& p_color) { + + + VisualServer::get_singleton()->canvas_item_add_rect(p_to_rid,Rect2(-extents,extents*2.0),p_color); + +} + +Rect2 RectangleShape2D::get_rect() const { + + return Rect2(-extents,extents*2.0); + +} + void RectangleShape2D::_bind_methods() { diff --git a/scene/resources/rectangle_shape_2d.h b/scene/resources/rectangle_shape_2d.h index 0b89441d04..96de02fb70 100644 --- a/scene/resources/rectangle_shape_2d.h +++ b/scene/resources/rectangle_shape_2d.h @@ -44,6 +44,9 @@ public: void set_extents(const Vector2& p_extents); Vector2 get_extents() const; + virtual void draw(const RID& p_to_rid,const Color& p_color); + virtual Rect2 get_rect() const ; + RectangleShape2D(); }; diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp index b8bd3de552..88f7adcd9b 100644 --- a/scene/resources/segment_shape_2d.cpp +++ b/scene/resources/segment_shape_2d.cpp @@ -29,6 +29,7 @@ #include "segment_shape_2d.h" #include "servers/physics_2d_server.h" +#include "servers/visual_server.h" void SegmentShape2D::_update_shape() { @@ -62,6 +63,23 @@ Vector2 SegmentShape2D::get_b() const { return b; } +void SegmentShape2D::draw(const RID& p_to_rid,const Color& p_color) { + + VisualServer::get_singleton()->canvas_item_add_line(p_to_rid,a,b,p_color,3); +} + +Rect2 SegmentShape2D::get_rect() const{ + + Rect2 rect; + rect.pos=a; + rect.expand_to(b); + return rect; + +} + + + + void SegmentShape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_a","a"),&SegmentShape2D::set_a); @@ -94,6 +112,37 @@ void RayShape2D::_update_shape() { } + +void RayShape2D::draw(const RID& p_to_rid,const Color& p_color) { + + + Vector2 tip = Vector2(0,get_length()); + VS::get_singleton()->canvas_item_add_line(p_to_rid,Vector2(),tip,p_color,3); + Vector<Vector2> pts; + float tsize=4; + pts.push_back(tip+Vector2(0,tsize)); + pts.push_back(tip+Vector2(0.707*tsize,0)); + pts.push_back(tip+Vector2(-0.707*tsize,0)); + Vector<Color> cols; + for(int i=0;i<3;i++) + cols.push_back(p_color); + + VS::get_singleton()->canvas_item_add_primitive(p_to_rid,pts,cols,Vector<Point2>(),RID()); + + + +} + +Rect2 RayShape2D::get_rect() const { + + Rect2 rect; + rect.pos=Vector2(); + rect.expand_to(Vector2(0,length)); + rect=rect.grow(0.707*4); + return rect; +} + + void RayShape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_length","length"),&RayShape2D::set_length); diff --git a/scene/resources/segment_shape_2d.h b/scene/resources/segment_shape_2d.h index ec771cd2ed..37c68b6c92 100644 --- a/scene/resources/segment_shape_2d.h +++ b/scene/resources/segment_shape_2d.h @@ -49,6 +49,9 @@ public: Vector2 get_a() const; Vector2 get_b() const; + virtual void draw(const RID& p_to_rid,const Color& p_color); + virtual Rect2 get_rect() const; + SegmentShape2D(); }; @@ -67,6 +70,8 @@ public: void set_length(real_t p_length); real_t get_length() const; + virtual void draw(const RID& p_to_rid,const Color& p_color); + virtual Rect2 get_rect() const; RayShape2D(); }; diff --git a/scene/resources/shape.cpp b/scene/resources/shape.cpp index 1120a8d672..143ef82d51 100644 --- a/scene/resources/shape.cpp +++ b/scene/resources/shape.cpp @@ -29,9 +29,67 @@ #include "shape.h" #include "servers/physics_server.h" +#include "scene/resources/mesh.h" +#include "os/os.h" +#include "scene/main/scene_main_loop.h" +void Shape::add_vertices_to_array(DVector<Vector3> &array, const Transform& p_xform) { + Vector<Vector3> toadd = _gen_debug_mesh_lines(); + + if (toadd.size()) { + + int base=array.size(); + array.resize(base+toadd.size()); + DVector<Vector3>::Write w = array.write(); + for(int i=0;i<toadd.size();i++) { + w[i+base]=p_xform.xform(toadd[i]); + } + + } +} + +Ref<Mesh> Shape::get_debug_mesh() { + + if (debug_mesh_cache.is_valid()) + return debug_mesh_cache; + + Vector<Vector3> lines = _gen_debug_mesh_lines(); + + debug_mesh_cache = Ref<Mesh>(memnew(Mesh)); + + if (!lines.empty()) { + //make mesh + DVector<Vector3> array; + array.resize(lines.size()); + { + + DVector<Vector3>::Write w=array.write(); + for(int i=0;i<lines.size();i++) { + w[i]=lines[i]; + } + } + + Array arr; + arr.resize(Mesh::ARRAY_MAX); + arr[Mesh::ARRAY_VERTEX]=array; + + SceneTree *st=OS::get_singleton()->get_main_loop()->cast_to<SceneTree>(); + + debug_mesh_cache->add_surface(Mesh::PRIMITIVE_LINES,arr); + + if (st) { + debug_mesh_cache->surface_set_material(0,st->get_debug_collision_material()); + } + + } + + + + return debug_mesh_cache; + +} Shape::Shape() { @@ -49,3 +107,4 @@ Shape::~Shape() { PhysicsServer::get_singleton()->free(shape); } + diff --git a/scene/resources/shape.h b/scene/resources/shape.h index 3cc806c7a3..1992ce51c3 100644 --- a/scene/resources/shape.h +++ b/scene/resources/shape.h @@ -30,6 +30,7 @@ #define SHAPE_H #include "resource.h" +class Mesh; class Shape : public Resource { @@ -38,13 +39,22 @@ class Shape : public Resource { RES_BASE_EXTENSION("shp"); RID shape; + Ref<Mesh> debug_mesh_cache; + protected: _FORCE_INLINE_ RID get_shape() const { return shape; } Shape(RID p_shape); + + virtual Vector<Vector3> _gen_debug_mesh_lines()=0;// { return Vector<Vector3>(); } public: virtual RID get_rid() const { return shape; } + + Ref<Mesh> get_debug_mesh(); + + void add_vertices_to_array(DVector<Vector3> &array, const Transform& p_xform); + Shape(); ~Shape(); }; diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h index 55f3173db4..1737301d9d 100644 --- a/scene/resources/shape_2d.h +++ b/scene/resources/shape_2d.h @@ -53,6 +53,8 @@ public: Variant collide_with_motion_and_get_contacts(const Matrix32& p_local_xform, const Vector2& p_local_motion, const Ref<Shape2D>& p_shape, const Matrix32& p_shape_xform, const Vector2 &p_p_shape_motion); Variant collide_and_get_contacts(const Matrix32& p_local_xform, const Ref<Shape2D>& p_shape, const Matrix32& p_shape_xform); + virtual void draw(const RID& p_to_rid,const Color& p_color) {} + virtual Rect2 get_rect() const { return Rect2(); } virtual RID get_rid() const; Shape2D(); ~Shape2D(); diff --git a/scene/resources/shape_line_2d.cpp b/scene/resources/shape_line_2d.cpp index d4dc46d64f..c660b604f3 100644 --- a/scene/resources/shape_line_2d.cpp +++ b/scene/resources/shape_line_2d.cpp @@ -28,7 +28,7 @@ /*************************************************************************/ #include "shape_line_2d.h" #include "servers/physics_2d_server.h" - +#include "servers/visual_server.h" void LineShape2D::_update_shape() { Array arr; @@ -61,6 +61,32 @@ real_t LineShape2D::get_d() const { return d; } + +void LineShape2D::draw(const RID& p_to_rid,const Color& p_color) { + + Vector2 point = get_d() * get_normal(); + + Vector2 l1[2]={point-get_normal().tangent()*100,point+get_normal().tangent()*100}; + VS::get_singleton()->canvas_item_add_line(p_to_rid,l1[0],l1[1],p_color,3); + Vector2 l2[2]={point,point+get_normal()*30}; + VS::get_singleton()->canvas_item_add_line(p_to_rid,l2[0],l2[1],p_color,3); + +} +Rect2 LineShape2D::get_rect() const{ + + Vector2 point = get_d() * get_normal(); + + Vector2 l1[2]={point-get_normal().tangent()*100,point+get_normal().tangent()*100}; + Vector2 l2[2]={point,point+get_normal()*30}; + Rect2 rect; + rect.pos=l1[0]; + rect.expand_to(l1[1]); + rect.expand_to(l2[0]); + rect.expand_to(l2[1]); + return rect; + +} + void LineShape2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_normal","normal"),&LineShape2D::set_normal); diff --git a/scene/resources/shape_line_2d.h b/scene/resources/shape_line_2d.h index 3ba8f57add..f32ad7fb7c 100644 --- a/scene/resources/shape_line_2d.h +++ b/scene/resources/shape_line_2d.h @@ -49,6 +49,9 @@ public: Vector2 get_normal() const; real_t get_d() const; + virtual void draw(const RID& p_to_rid,const Color& p_color); + virtual Rect2 get_rect() const; + LineShape2D(); }; diff --git a/scene/resources/sphere_shape.cpp b/scene/resources/sphere_shape.cpp index e93d718efa..a7e28eb727 100644 --- a/scene/resources/sphere_shape.cpp +++ b/scene/resources/sphere_shape.cpp @@ -29,6 +29,30 @@ #include "sphere_shape.h" #include "servers/physics_server.h" +Vector<Vector3> SphereShape::_gen_debug_mesh_lines() { + + float r=get_radius(); + + Vector<Vector3> points; + + for(int i=0;i<=360;i++) { + + float ra=Math::deg2rad(i); + float rb=Math::deg2rad(i+1); + Point2 a = Vector2(Math::sin(ra),Math::cos(ra))*r; + Point2 b = Vector2(Math::sin(rb),Math::cos(rb))*r; + + points.push_back(Vector3(a.x,0,a.y)); + points.push_back(Vector3(b.x,0,b.y)); + points.push_back(Vector3(0,a.x,a.y)); + points.push_back(Vector3(0,b.x,b.y)); + points.push_back(Vector3(a.x,a.y,0)); + points.push_back(Vector3(b.x,b.y,0)); + + } + + return points; +} void SphereShape::_update_shape() { diff --git a/scene/resources/sphere_shape.h b/scene/resources/sphere_shape.h index 1bbddb9fd9..2543d94439 100644 --- a/scene/resources/sphere_shape.h +++ b/scene/resources/sphere_shape.h @@ -42,7 +42,7 @@ protected: static void _bind_methods(); virtual void _update_shape(); - + virtual Vector<Vector3> _gen_debug_mesh_lines(); public: void set_radius(float p_radius); |