summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/canvas_item.cpp9
-rw-r--r--scene/2d/canvas_item.h7
-rw-r--r--scene/2d/collision_polygon_2d.cpp100
-rw-r--r--scene/2d/collision_polygon_2d.h12
-rw-r--r--scene/2d/collision_shape_2d.cpp165
-rw-r--r--scene/2d/collision_shape_2d.h8
-rw-r--r--scene/2d/navigation_polygon.cpp10
-rw-r--r--scene/2d/ray_cast_2d.cpp8
-rw-r--r--scene/2d/tile_map.cpp20
-rw-r--r--scene/3d/body_shape.cpp108
-rw-r--r--scene/3d/body_shape.h18
-rw-r--r--scene/3d/collision_polygon.cpp106
-rw-r--r--scene/3d/collision_polygon.h12
-rw-r--r--scene/3d/navigation_mesh.cpp124
-rw-r--r--scene/3d/navigation_mesh.h17
-rw-r--r--scene/3d/spatial.cpp25
-rw-r--r--scene/3d/spatial.h5
-rw-r--r--scene/3d/spatial_stream_player.cpp2
-rw-r--r--scene/audio/stream_player.cpp2
-rw-r--r--scene/gui/box_container.cpp36
-rw-r--r--scene/gui/box_container.h17
-rw-r--r--scene/main/scene_main_loop.cpp190
-rw-r--r--scene/main/scene_main_loop.h42
-rw-r--r--scene/main/viewport.cpp78
-rw-r--r--scene/main/viewport.h5
-rw-r--r--scene/register_scene_types.cpp10
-rw-r--r--scene/resources/box_shape.cpp19
-rw-r--r--scene/resources/box_shape.h1
-rw-r--r--scene/resources/capsule_shape.cpp41
-rw-r--r--scene/resources/capsule_shape.h2
-rw-r--r--scene/resources/capsule_shape_2d.cpp27
-rw-r--r--scene/resources/capsule_shape_2d.h3
-rw-r--r--scene/resources/circle_shape_2d.cpp23
-rw-r--r--scene/resources/circle_shape_2d.h4
-rw-r--r--scene/resources/concave_polygon_shape.cpp34
-rw-r--r--scene/resources/concave_polygon_shape.h22
-rw-r--r--scene/resources/concave_polygon_shape_2d.cpp39
-rw-r--r--scene/resources/concave_polygon_shape_2d.h3
-rw-r--r--scene/resources/convex_polygon_shape.cpp27
-rw-r--r--scene/resources/convex_polygon_shape.h1
-rw-r--r--scene/resources/convex_polygon_shape_2d.cpp25
-rw-r--r--scene/resources/convex_polygon_shape_2d.h3
-rw-r--r--scene/resources/plane_shape.cpp29
-rw-r--r--scene/resources/plane_shape.h2
-rw-r--r--scene/resources/ray_shape.cpp7
-rw-r--r--scene/resources/ray_shape.h2
-rw-r--r--scene/resources/rectangle_shape_2d.cpp15
-rw-r--r--scene/resources/rectangle_shape_2d.h3
-rw-r--r--scene/resources/segment_shape_2d.cpp49
-rw-r--r--scene/resources/segment_shape_2d.h5
-rw-r--r--scene/resources/shape.cpp59
-rw-r--r--scene/resources/shape.h10
-rw-r--r--scene/resources/shape_2d.h2
-rw-r--r--scene/resources/shape_line_2d.cpp28
-rw-r--r--scene/resources/shape_line_2d.h3
-rw-r--r--scene/resources/sphere_shape.cpp24
-rw-r--r--scene/resources/sphere_shape.h2
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);