Browse Source

Ability to visually debug geometry visually:
-Visible 2D and 3D Shapes, Polygons, Tile collisions, etc.
-Visible Navmesh and Navpoly
-Visible collision contacts for 2D and 3D as a red point
-Customizable colors in project settings

Juan Linietsky 10 years ago
parent
commit
83d9a692be
100 changed files with 1949 additions and 410 deletions
  1. 21 0
      demos/2d/dynamic_collision_shapes/ball.gd
  2. BIN
      demos/2d/dynamic_collision_shapes/ball.png
  3. BIN
      demos/2d/dynamic_collision_shapes/ball.scn
  4. BIN
      demos/2d/dynamic_collision_shapes/box.png
  5. BIN
      demos/2d/dynamic_collision_shapes/circle.png
  6. 23 0
      demos/2d/dynamic_collision_shapes/dynamic_colobjs.gd
  7. BIN
      demos/2d/dynamic_collision_shapes/dynamic_colobjs.scn
  8. 4 0
      demos/2d/dynamic_collision_shapes/engine.cfg
  9. BIN
      demos/2d/dynamic_collision_shapes/poly.png
  10. BIN
      demos/2d/isometric/dungeon.scn
  11. BIN
      demos/2d/lights_shadows/light_shadows.scn
  12. 174 169
      demos/2d/platformer/enemy.xml
  13. 4 20
      demos/2d/platformer/stage.xml
  14. 3 3
      demos/3d/platformer/player.gd
  15. 4 0
      drivers/gles2/rasterizer_gles2.cpp
  16. 6 0
      main/main.cpp
  17. 68 3
      modules/gridmap/grid_map.cpp
  18. 2 0
      modules/gridmap/grid_map.h
  19. 8 8
      platform/android/export/export.cpp
  20. 5 5
      platform/bb10/export/export.cpp
  21. 5 5
      platform/javascript/export/export.cpp
  22. 4 4
      platform/osx/export/export.cpp
  23. 9 0
      scene/2d/canvas_item.cpp
  24. 6 1
      scene/2d/canvas_item.h
  25. 82 18
      scene/2d/collision_polygon_2d.cpp
  26. 12 0
      scene/2d/collision_polygon_2d.h
  27. 62 101
      scene/2d/collision_shape_2d.cpp
  28. 8 0
      scene/2d/collision_shape_2d.h
  29. 5 5
      scene/2d/navigation_polygon.cpp
  30. 4 4
      scene/2d/ray_cast_2d.cpp
  31. 19 1
      scene/2d/tile_map.cpp
  32. 97 11
      scene/3d/body_shape.cpp
  33. 16 2
      scene/3d/body_shape.h
  34. 85 21
      scene/3d/collision_polygon.cpp
  35. 12 0
      scene/3d/collision_polygon.h
  36. 123 1
      scene/3d/navigation_mesh.cpp
  37. 17 0
      scene/3d/navigation_mesh.h
  38. 25 0
      scene/3d/spatial.cpp
  39. 5 0
      scene/3d/spatial.h
  40. 177 2
      scene/main/scene_main_loop.cpp
  41. 38 0
      scene/main/scene_main_loop.h
  42. 78 1
      scene/main/viewport.cpp
  43. 5 0
      scene/main/viewport.h
  44. 6 4
      scene/register_scene_types.cpp
  45. 19 0
      scene/resources/box_shape.cpp
  46. 1 0
      scene/resources/box_shape.h
  47. 40 1
      scene/resources/capsule_shape.cpp
  48. 2 0
      scene/resources/capsule_shape.h
  49. 27 0
      scene/resources/capsule_shape_2d.cpp
  50. 3 0
      scene/resources/capsule_shape_2d.h
  51. 22 1
      scene/resources/circle_shape_2d.cpp
  52. 4 0
      scene/resources/circle_shape_2d.h
  53. 34 0
      scene/resources/concave_polygon_shape.cpp
  54. 21 1
      scene/resources/concave_polygon_shape.h
  55. 38 1
      scene/resources/concave_polygon_shape_2d.cpp
  56. 3 0
      scene/resources/concave_polygon_shape_2d.h
  57. 27 0
      scene/resources/convex_polygon_shape.cpp
  58. 1 0
      scene/resources/convex_polygon_shape.h
  59. 24 1
      scene/resources/convex_polygon_shape_2d.cpp
  60. 3 0
      scene/resources/convex_polygon_shape_2d.h
  61. 28 1
      scene/resources/plane_shape.cpp
  62. 1 1
      scene/resources/plane_shape.h
  63. 7 0
      scene/resources/ray_shape.cpp
  64. 1 1
      scene/resources/ray_shape.h
  65. 14 1
      scene/resources/rectangle_shape_2d.cpp
  66. 3 0
      scene/resources/rectangle_shape_2d.h
  67. 49 0
      scene/resources/segment_shape_2d.cpp
  68. 5 0
      scene/resources/segment_shape_2d.h
  69. 59 0
      scene/resources/shape.cpp
  70. 10 0
      scene/resources/shape.h
  71. 2 0
      scene/resources/shape_2d.h
  72. 27 1
      scene/resources/shape_line_2d.cpp
  73. 3 0
      scene/resources/shape_line_2d.h
  74. 24 0
      scene/resources/sphere_shape.cpp
  75. 1 1
      scene/resources/sphere_shape.h
  76. 10 0
      servers/physics/body_pair_sw.cpp
  77. 24 0
      servers/physics/physics_server_sw.cpp
  78. 3 0
      servers/physics/physics_server_sw.h
  79. 3 1
      servers/physics/space_sw.cpp
  80. 8 0
      servers/physics/space_sw.h
  81. 6 1
      servers/physics_2d/body_pair_2d_sw.cpp
  82. 24 0
      servers/physics_2d/physics_2d_server_sw.cpp
  83. 5 0
      servers/physics_2d/physics_2d_server_sw.h
  84. 16 0
      servers/physics_2d/physics_2d_server_wrap_mt.h
  85. 7 0
      servers/physics_2d/space_2d_sw.cpp
  86. 11 0
      servers/physics_2d/space_2d_sw.h
  87. 3 0
      servers/physics_2d_server.h
  88. 3 0
      servers/physics_server.h
  89. 3 0
      servers/visual/rasterizer_dummy.cpp
  90. 1 0
      servers/visual/rasterizer_dummy.h
  91. 8 0
      servers/visual/visual_server_raster.cpp
  92. 1 0
      servers/visual/visual_server_raster.h
  93. 1 0
      servers/visual/visual_server_wrap_mt.h
  94. 2 0
      servers/visual_server.h
  95. 15 4
      tools/editor/editor_import_export.cpp
  96. 11 4
      tools/editor/editor_import_export.h
  97. 17 0
      tools/editor/editor_node.cpp
  98. 2 0
      tools/editor/editor_node.h
  99. 31 0
      tools/editor/editor_run.cpp
  100. 9 0
      tools/editor/editor_run.h

+ 21 - 0
demos/2d/dynamic_collision_shapes/ball.gd

@@ -0,0 +1,21 @@
+
+extends RigidBody2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+var timeout=5
+
+func _process(delta):
+	timeout-=delta
+	if (timeout<1):
+		set_opacity(timeout)
+	if (timeout<0):
+		queue_free()
+func _ready():
+	set_process(true)
+	# Initialization here
+	pass
+
+

BIN
demos/2d/dynamic_collision_shapes/ball.png


BIN
demos/2d/dynamic_collision_shapes/ball.scn


BIN
demos/2d/dynamic_collision_shapes/box.png


BIN
demos/2d/dynamic_collision_shapes/circle.png


+ 23 - 0
demos/2d/dynamic_collision_shapes/dynamic_colobjs.gd

@@ -0,0 +1,23 @@
+
+extends Node2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+const EMIT_INTERVAL=0.1
+var timeout=EMIT_INTERVAL
+
+func _process(delta):
+	timeout-=delta
+	if (timeout<0):
+		timeout=EMIT_INTERVAL
+		var ball = preload("res://ball.scn").instance()
+		ball.set_pos( Vector2(randf() * get_viewport_rect().size.x, 0) )
+		add_child(ball)
+			
+func _ready():
+	set_process(true)
+	# Initialization here
+	pass
+
+

BIN
demos/2d/dynamic_collision_shapes/dynamic_colobjs.scn


+ 4 - 0
demos/2d/dynamic_collision_shapes/engine.cfg

@@ -0,0 +1,4 @@
+[application]
+
+name="Run-Time CollisionShape"
+main_scene="res://dynamic_colobjs.scn"

BIN
demos/2d/dynamic_collision_shapes/poly.png


BIN
demos/2d/isometric/dungeon.scn


BIN
demos/2d/lights_shadows/light_shadows.scn


+ 174 - 169
demos/2d/platformer/enemy.xml

@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <?xml version="1.0" encoding="UTF-8" ?>
-<resource_file type="PackedScene" subresource_count="11" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
-	<ext_resource path="res://sound_explode.*" type="Sample"></ext_resource>
-	<ext_resource path="res://enemy.*" type="Texture"></ext_resource>
-	<ext_resource path="res://enemy.*" type="Script"></ext_resource>
-	<ext_resource path="res://sound_hit.*" type="Sample"></ext_resource>
-	<ext_resource path="res://bullet.*" type="Texture"></ext_resource>
+<resource_file type="PackedScene" subresource_count="12" version="2.0" version_name="Godot Engine v2.0.alpha.custom_build">
+	<ext_resource path="res://bullet.png" type="Texture" index="2"></ext_resource>
+	<ext_resource path="res://enemy.gd" type="Script" index="0"></ext_resource>
+	<ext_resource path="res://enemy.png" type="Texture" index="1"></ext_resource>
+	<ext_resource path="res://sound_hit.wav" type="Sample" index="4"></ext_resource>
+	<ext_resource path="res://sound_explode.wav" type="Sample" index="3"></ext_resource>
 	<resource type="CircleShape2D" path="local://1">
 	<resource type="CircleShape2D" path="local://1">
 		<real name="custom_solver_bias"> 0 </real>
 		<real name="custom_solver_bias"> 0 </real>
 		<real name="radius"> 14 </real>
 		<real name="radius"> 14 </real>
@@ -21,6 +21,8 @@
 		<dictionary name="tracks/0/keys" shared="false">
 		<dictionary name="tracks/0/keys" shared="false">
 			<string> "cont" </string>
 			<string> "cont" </string>
 			<bool> False </bool>
 			<bool> False </bool>
+			<string> "times" </string>
+			<real_array  len="10"> 				0, 0.75, 1.5, 2.25, 3, 3.75, 4.5, 5.25, 6, 6.75 </real_array>
 			<string> "transitions" </string>
 			<string> "transitions" </string>
 			<real_array  len="10"> 				1, 1, 1, 1, 1, 1, 1, 1, 1, 1 </real_array>
 			<real_array  len="10"> 				1, 1, 1, 1, 1, 1, 1, 1, 1, 1 </real_array>
 			<string> "values" </string>
 			<string> "values" </string>
@@ -36,8 +38,33 @@
 				<int> 7 </int>
 				<int> 7 </int>
 				<int> 5 </int>
 				<int> 5 </int>
 			</array>
 			</array>
+		</dictionary>
+
+	</resource>
+	<resource type="Animation" path="local://4">
+		<string name="resource/name"> "walk" </string>
+		<real name="length"> 1.25 </real>
+		<bool name="loop"> True </bool>
+		<real name="step"> 0.25 </real>
+		<string name="tracks/0/type"> "value" </string>
+		<node_path name="tracks/0/path"> "sprite:frame" </node_path>
+		<int name="tracks/0/interp"> 1 </int>
+		<dictionary name="tracks/0/keys" shared="false">
+			<string> "cont" </string>
+			<bool> False </bool>
 			<string> "times" </string>
 			<string> "times" </string>
-			<real_array  len="10"> 				0, 0.75, 1.5, 2.25, 3, 3.75, 4.5, 5.25, 6, 6.75 </real_array>
+			<real_array  len="6"> 				0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
+			<string> "transitions" </string>
+			<real_array  len="6"> 				1, 1, 1, 1, 1, 1 </real_array>
+			<string> "values" </string>
+			<array  len="6" shared="false">
+				<int> 0 </int>
+				<int> 1 </int>
+				<int> 2 </int>
+				<int> 3 </int>
+				<int> 4 </int>
+				<int> 0 </int>
+			</array>
 		</dictionary>
 		</dictionary>
 
 
 	</resource>
 	</resource>
@@ -52,6 +79,8 @@
 		<dictionary name="tracks/0/keys" shared="false">
 		<dictionary name="tracks/0/keys" shared="false">
 			<string> "cont" </string>
 			<string> "cont" </string>
 			<bool> True </bool>
 			<bool> True </bool>
+			<string> "times" </string>
+			<real_array  len="2"> 				3.58422, 4.33851 </real_array>
 			<string> "transitions" </string>
 			<string> "transitions" </string>
 			<real_array  len="2"> 				1, 1 </real_array>
 			<real_array  len="2"> 				1, 1 </real_array>
 			<string> "values" </string>
 			<string> "values" </string>
@@ -59,8 +88,6 @@
 				<real> 1 </real>
 				<real> 1 </real>
 				<real> 0 </real>
 				<real> 0 </real>
 			</array>
 			</array>
-			<string> "times" </string>
-			<real_array  len="2"> 				3.58422, 4.33851 </real_array>
 		</dictionary>
 		</dictionary>
 		<string name="tracks/1/type"> "value" </string>
 		<string name="tracks/1/type"> "value" </string>
 		<node_path name="tracks/1/path"> "sprite:frame" </node_path>
 		<node_path name="tracks/1/path"> "sprite:frame" </node_path>
@@ -68,14 +95,14 @@
 		<dictionary name="tracks/1/keys" shared="false">
 		<dictionary name="tracks/1/keys" shared="false">
 			<string> "cont" </string>
 			<string> "cont" </string>
 			<bool> True </bool>
 			<bool> True </bool>
+			<string> "times" </string>
+			<real_array  len="1"> 				0 </real_array>
 			<string> "transitions" </string>
 			<string> "transitions" </string>
 			<real_array  len="1"> 				1 </real_array>
 			<real_array  len="1"> 				1 </real_array>
 			<string> "values" </string>
 			<string> "values" </string>
 			<array  len="1" shared="false">
 			<array  len="1" shared="false">
 				<int> 4 </int>
 				<int> 4 </int>
 			</array>
 			</array>
-			<string> "times" </string>
-			<real_array  len="1"> 				0 </real_array>
 		</dictionary>
 		</dictionary>
 		<string name="tracks/2/type"> "value" </string>
 		<string name="tracks/2/type"> "value" </string>
 		<node_path name="tracks/2/path"> "Particles2D:config/emitting" </node_path>
 		<node_path name="tracks/2/path"> "Particles2D:config/emitting" </node_path>
@@ -83,19 +110,21 @@
 		<dictionary name="tracks/2/keys" shared="false">
 		<dictionary name="tracks/2/keys" shared="false">
 			<string> "cont" </string>
 			<string> "cont" </string>
 			<bool> False </bool>
 			<bool> False </bool>
+			<string> "times" </string>
+			<real_array  len="1"> 				3.47394 </real_array>
 			<string> "transitions" </string>
 			<string> "transitions" </string>
 			<real_array  len="1"> 				1 </real_array>
 			<real_array  len="1"> 				1 </real_array>
 			<string> "values" </string>
 			<string> "values" </string>
 			<array  len="1" shared="false">
 			<array  len="1" shared="false">
 				<bool> True </bool>
 				<bool> True </bool>
 			</array>
 			</array>
-			<string> "times" </string>
-			<real_array  len="1"> 				3.47394 </real_array>
 		</dictionary>
 		</dictionary>
 		<string name="tracks/3/type"> "method" </string>
 		<string name="tracks/3/type"> "method" </string>
 		<node_path name="tracks/3/path"> "." </node_path>
 		<node_path name="tracks/3/path"> "." </node_path>
 		<int name="tracks/3/interp"> 1 </int>
 		<int name="tracks/3/interp"> 1 </int>
 		<dictionary name="tracks/3/keys" shared="false">
 		<dictionary name="tracks/3/keys" shared="false">
+			<string> "times" </string>
+			<real_array  len="2"> 				3.20357, 5.07305 </real_array>
 			<string> "transitions" </string>
 			<string> "transitions" </string>
 			<real_array  len="2"> 				1, 1 </real_array>
 			<real_array  len="2"> 				1, 1 </real_array>
 			<string> "values" </string>
 			<string> "values" </string>
@@ -115,36 +144,12 @@
 					<string> "_die" </string>
 					<string> "_die" </string>
 				</dictionary>
 				</dictionary>
 			</array>
 			</array>
-			<string> "times" </string>
-			<real_array  len="2"> 				3.20357, 5.07305 </real_array>
 		</dictionary>
 		</dictionary>
 
 
 	</resource>
 	</resource>
-	<resource type="Animation" path="local://4">
-		<string name="resource/name"> "walk" </string>
-		<real name="length"> 1.25 </real>
-		<bool name="loop"> True </bool>
-		<real name="step"> 0.25 </real>
-		<string name="tracks/0/type"> "value" </string>
-		<node_path name="tracks/0/path"> "sprite:frame" </node_path>
-		<int name="tracks/0/interp"> 1 </int>
-		<dictionary name="tracks/0/keys" shared="false">
-			<string> "cont" </string>
-			<bool> False </bool>
-			<string> "transitions" </string>
-			<real_array  len="6"> 				1, 1, 1, 1, 1, 1 </real_array>
-			<string> "values" </string>
-			<array  len="6" shared="false">
-				<int> 0 </int>
-				<int> 1 </int>
-				<int> 2 </int>
-				<int> 3 </int>
-				<int> 4 </int>
-				<int> 0 </int>
-			</array>
-			<string> "times" </string>
-			<real_array  len="6"> 				0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
-		</dictionary>
+	<resource type="ColorRamp" path="local://6">
+		<real_array name="offsets" len="2"> 			0, 1 </real_array>
+		<color_array name="colors" len="2"> 			1, 0.884956, 0.823009, 1, 0.768627, 0.389381, 0, 0 </color_array>
 
 
 	</resource>
 	</resource>
 	<resource type="SampleLibrary" path="local://5">
 	<resource type="SampleLibrary" path="local://5">
@@ -154,7 +159,7 @@
 			<string> "pitch" </string>
 			<string> "pitch" </string>
 			<real> 1 </real>
 			<real> 1 </real>
 			<string> "sample" </string>
 			<string> "sample" </string>
-			<resource  resource_type="Sample" path="res://sound_explode.*">  </resource>
+			<resource  external="3">  </resource>
 		</dictionary>
 		</dictionary>
 		<dictionary name="samples/hit" shared="false">
 		<dictionary name="samples/hit" shared="false">
 			<string> "db" </string>
 			<string> "db" </string>
@@ -162,24 +167,21 @@
 			<string> "pitch" </string>
 			<string> "pitch" </string>
 			<real> 1 </real>
 			<real> 1 </real>
 			<string> "sample" </string>
 			<string> "sample" </string>
-			<resource  resource_type="Sample" path="res://sound_hit.*">  </resource>
+			<resource  external="4">  </resource>
 		</dictionary>
 		</dictionary>
 
 
 	</resource>
 	</resource>
 	<main_resource>
 	<main_resource>
 		<dictionary name="_bundled" shared="false">
 		<dictionary name="_bundled" shared="false">
+			<string> "conn_count" </string>
+			<int> 0 </int>
+			<string> "conns" </string>
+			<int_array  len="0"> 				 </int_array>
 			<string> "names" </string>
 			<string> "names" </string>
-			<string_array  len="132">
+			<string_array  len="107">
 				<string> "enemy" </string>
 				<string> "enemy" </string>
 				<string> "RigidBody2D" </string>
 				<string> "RigidBody2D" </string>
-				<string> "visibility/visible" </string>
-				<string> "visibility/opacity" </string>
-				<string> "visibility/self_opacity" </string>
-				<string> "visibility/on_top" </string>
-				<string> "transform/pos" </string>
-				<string> "transform/rot" </string>
-				<string> "transform/scale" </string>
-				<string> "shape_count" </string>
+				<string> "input/pickable" </string>
 				<string> "shapes/0/shape" </string>
 				<string> "shapes/0/shape" </string>
 				<string> "shapes/0/transform" </string>
 				<string> "shapes/0/transform" </string>
 				<string> "shapes/0/trigger" </string>
 				<string> "shapes/0/trigger" </string>
@@ -189,71 +191,71 @@
 				<string> "shapes/2/shape" </string>
 				<string> "shapes/2/shape" </string>
 				<string> "shapes/2/transform" </string>
 				<string> "shapes/2/transform" </string>
 				<string> "shapes/2/trigger" </string>
 				<string> "shapes/2/trigger" </string>
+				<string> "collision/layers" </string>
+				<string> "collision/mask" </string>
 				<string> "mode" </string>
 				<string> "mode" </string>
 				<string> "mass" </string>
 				<string> "mass" </string>
 				<string> "friction" </string>
 				<string> "friction" </string>
 				<string> "bounce" </string>
 				<string> "bounce" </string>
+				<string> "gravity_scale" </string>
 				<string> "custom_integrator" </string>
 				<string> "custom_integrator" </string>
 				<string> "continuous_cd" </string>
 				<string> "continuous_cd" </string>
 				<string> "contacts_reported" </string>
 				<string> "contacts_reported" </string>
 				<string> "contact_monitor" </string>
 				<string> "contact_monitor" </string>
-				<string> "active" </string>
+				<string> "sleeping" </string>
 				<string> "can_sleep" </string>
 				<string> "can_sleep" </string>
 				<string> "velocity/linear" </string>
 				<string> "velocity/linear" </string>
 				<string> "velocity/angular" </string>
 				<string> "velocity/angular" </string>
+				<string> "damp_override/linear" </string>
+				<string> "damp_override/angular" </string>
 				<string> "script/script" </string>
 				<string> "script/script" </string>
 				<string> "__meta__" </string>
 				<string> "__meta__" </string>
 				<string> "enabler" </string>
 				<string> "enabler" </string>
 				<string> "VisibilityEnabler2D" </string>
 				<string> "VisibilityEnabler2D" </string>
+				<string> "transform/pos" </string>
+				<string> "transform/scale" </string>
 				<string> "rect" </string>
 				<string> "rect" </string>
 				<string> "enabler/pause_animations" </string>
 				<string> "enabler/pause_animations" </string>
 				<string> "enabler/freeze_bodies" </string>
 				<string> "enabler/freeze_bodies" </string>
+				<string> "enabler/pause_particles" </string>
+				<string> "enabler/process_parent" </string>
+				<string> "enabler/fixed_process_parent" </string>
 				<string> "anim" </string>
 				<string> "anim" </string>
 				<string> "AnimationPlayer" </string>
 				<string> "AnimationPlayer" </string>
 				<string> "playback/process_mode" </string>
 				<string> "playback/process_mode" </string>
 				<string> "playback/default_blend_time" </string>
 				<string> "playback/default_blend_time" </string>
 				<string> "root/root" </string>
 				<string> "root/root" </string>
 				<string> "anims/idle" </string>
 				<string> "anims/idle" </string>
-				<string> "anims/explode" </string>
 				<string> "anims/walk" </string>
 				<string> "anims/walk" </string>
+				<string> "anims/explode" </string>
 				<string> "playback/active" </string>
 				<string> "playback/active" </string>
 				<string> "playback/speed" </string>
 				<string> "playback/speed" </string>
 				<string> "blend_times" </string>
 				<string> "blend_times" </string>
 				<string> "autoplay" </string>
 				<string> "autoplay" </string>
-				<string> "CollisionShape2D" </string>
-				<string> "shape" </string>
-				<string> "trigger" </string>
-				<string> "CollisionShape2D 2" </string>
-				<string> "CollisionShape2D 3" </string>
 				<string> "sprite" </string>
 				<string> "sprite" </string>
 				<string> "Sprite" </string>
 				<string> "Sprite" </string>
 				<string> "texture" </string>
 				<string> "texture" </string>
-				<string> "centered" </string>
-				<string> "offset" </string>
-				<string> "flip_h" </string>
-				<string> "flip_v" </string>
-				<string> "vframes" </string>
 				<string> "hframes" </string>
 				<string> "hframes" </string>
 				<string> "frame" </string>
 				<string> "frame" </string>
-				<string> "modulate" </string>
-				<string> "region" </string>
-				<string> "region_rect" </string>
+				<string> "CollisionShape2D" </string>
+				<string> "shape" </string>
+				<string> "trigger" </string>
+				<string> "_update_shape_index" </string>
+				<string> "CollisionShape2D 2" </string>
+				<string> "CollisionShape2D 3" </string>
 				<string> "raycast_left" </string>
 				<string> "raycast_left" </string>
 				<string> "RayCast2D" </string>
 				<string> "RayCast2D" </string>
 				<string> "enabled" </string>
 				<string> "enabled" </string>
 				<string> "cast_to" </string>
 				<string> "cast_to" </string>
+				<string> "layer_mask" </string>
 				<string> "raycast_right" </string>
 				<string> "raycast_right" </string>
 				<string> "Particles2D" </string>
 				<string> "Particles2D" </string>
+				<string> "visibility/self_opacity" </string>
 				<string> "visibility/blend_mode" </string>
 				<string> "visibility/blend_mode" </string>
 				<string> "config/amount" </string>
 				<string> "config/amount" </string>
 				<string> "config/lifetime" </string>
 				<string> "config/lifetime" </string>
-				<string> "config/time_scale" </string>
-				<string> "config/preprocess" </string>
 				<string> "config/emit_timeout" </string>
 				<string> "config/emit_timeout" </string>
 				<string> "config/emitting" </string>
 				<string> "config/emitting" </string>
-				<string> "config/offset" </string>
-				<string> "config/half_extents" </string>
-				<string> "config/local_space" </string>
 				<string> "config/explosiveness" </string>
 				<string> "config/explosiveness" </string>
 				<string> "config/texture" </string>
 				<string> "config/texture" </string>
 				<string> "params/direction" </string>
 				<string> "params/direction" </string>
@@ -266,32 +268,14 @@
 				<string> "params/radial_accel" </string>
 				<string> "params/radial_accel" </string>
 				<string> "params/tangential_accel" </string>
 				<string> "params/tangential_accel" </string>
 				<string> "params/damping" </string>
 				<string> "params/damping" </string>
+				<string> "params/initial_angle" </string>
 				<string> "params/initial_size" </string>
 				<string> "params/initial_size" </string>
 				<string> "params/final_size" </string>
 				<string> "params/final_size" </string>
 				<string> "params/hue_variation" </string>
 				<string> "params/hue_variation" </string>
-				<string> "randomness/direction" </string>
-				<string> "randomness/spread" </string>
-				<string> "randomness/linear_velocity" </string>
+				<string> "params/anim_speed_scale" </string>
+				<string> "params/anim_initial_pos" </string>
 				<string> "randomness/spin_velocity" </string>
 				<string> "randomness/spin_velocity" </string>
-				<string> "randomness/orbit_velocity" </string>
-				<string> "randomness/gravity_direction" </string>
-				<string> "randomness/gravity_strength" </string>
-				<string> "randomness/radial_accel" </string>
-				<string> "randomness/tangential_accel" </string>
-				<string> "randomness/damping" </string>
-				<string> "randomness/initial_size" </string>
-				<string> "randomness/final_size" </string>
-				<string> "randomness/hue_variation" </string>
-				<string> "color_phases/count" </string>
-				<string> "phase_0/pos" </string>
-				<string> "phase_0/color" </string>
-				<string> "phase_1/pos" </string>
-				<string> "phase_1/color" </string>
-				<string> "phase_2/pos" </string>
-				<string> "phase_2/color" </string>
-				<string> "phase_3/pos" </string>
-				<string> "phase_3/color" </string>
-				<string> "emission_points" </string>
+				<string> "color/color_ramp" </string>
 				<string> "sound" </string>
 				<string> "sound" </string>
 				<string> "SamplePlayer2D" </string>
 				<string> "SamplePlayer2D" </string>
 				<string> "params/volume_db" </string>
 				<string> "params/volume_db" </string>
@@ -303,125 +287,154 @@
 				<string> "config/samples" </string>
 				<string> "config/samples" </string>
 				<string> "config/pitch_random" </string>
 				<string> "config/pitch_random" </string>
 			</string_array>
 			</string_array>
-			<string> "version" </string>
-			<int> 1 </int>
-			<string> "conn_count" </string>
-			<int> 0 </int>
 			<string> "node_count" </string>
 			<string> "node_count" </string>
 			<int> 11 </int>
 			<int> 11 </int>
+			<string> "nodes" </string>
+			<int_array  len="285"> 				-1, -1, 1, 0, -1, 29, 2, 0, 3, 1, 4, 2, 5, 0, 6, 1, 7, 3, 8, 0, 9, 1, 10, 4, 11, 0, 12, 5, 13, 5, 14, 6, 15, 7, 16, 8, 17, 8, 18, 7, 19, 0, 20, 9, 21, 10, 22, 0, 23, 0, 24, 11, 25, 12, 26, 8, 27, 13, 28, 13, 29, 14, 30, 15, 0, 0, 0, 32, 31, -1, 8, 33, 16, 34, 17, 35, 18, 36, 11, 37, 11, 38, 11, 39, 0, 40, 0, 0, 0, 0, 42, 41, -1, 10, 43, 5, 44, 8, 45, 19, 46, 20, 47, 21, 48, 22, 49, 11, 50, 23, 51, 24, 52, 25, 0, 0, 0, 54, 53, -1, 3, 55, 26, 56, 27, 57, 10, 0, 0, 0, 58, 58, -1, 4, 33, 28, 59, 1, 60, 0, 61, 29, 0, 0, 0, 58, 62, -1, 4, 33, 30, 59, 1, 60, 0, 61, 29, 0, 0, 0, 58, 63, -1, 4, 33, 31, 59, 1, 60, 0, 61, 29, 0, 0, 0, 65, 64, -1, 4, 33, 32, 66, 11, 67, 33, 68, 5, 0, 0, 0, 65, 69, -1, 4, 33, 34, 66, 11, 67, 33, 68, 5, 0, 0, 0, 70, 70, -1, 26, 71, 35, 72, 5, 73, 36, 74, 37, 75, 37, 76, 0, 77, 38, 78, 39, 79, 8, 80, 40, 81, 41, 82, 42, 83, 8, 84, 8, 85, 43, 86, 8, 87, 8, 88, 8, 89, 8, 90, 42, 91, 23, 92, 8, 93, 7, 94, 8, 95, 7, 96, 44, 0, 0, 0, 98, 97, -1, 8, 99, 8, 100, 7, 101, 7, 102, 45, 103, 7, 104, 46, 105, 47, 106, 8, 0 </int_array>
 			<string> "variants" </string>
 			<string> "variants" </string>
-			<array  len="51" shared="false">
-				<bool> True </bool>
-				<real> 1 </real>
-				<vector2> 0, 0 </vector2>
-				<real> 0 </real>
-				<vector2> 1, 1 </vector2>
-				<int> 3 </int>
+			<array  len="48" shared="false">
+				<bool> False </bool>
 				<resource  resource_type="Shape2D" path="local://1">  </resource>
 				<resource  resource_type="Shape2D" path="local://1">  </resource>
 				<matrix32> 1, -0, 0, 1, -1.08072, -2.16144 </matrix32>
 				<matrix32> 1, -0, 0, 1, -1.08072, -2.16144 </matrix32>
-				<bool> False </bool>
 				<matrix32> 1, -0, 0, 1, 6.48431, 3.24216 </matrix32>
 				<matrix32> 1, -0, 0, 1, 6.48431, 3.24216 </matrix32>
 				<matrix32> 1, -0, 0, 1, -12.495, 3.53415 </matrix32>
 				<matrix32> 1, -0, 0, 1, -12.495, 3.53415 </matrix32>
+				<int> 1 </int>
 				<int> 2 </int>
 				<int> 2 </int>
+				<real> 1 </real>
+				<real> 0 </real>
+				<int> 0 </int>
 				<int> 4 </int>
 				<int> 4 </int>
-				<resource  resource_type="Script" path="res://enemy.*">  </resource>
+				<bool> True </bool>
+				<vector2> 0, 0 </vector2>
+				<real> -1 </real>
+				<resource  external="0">  </resource>
 				<dictionary  shared="false">
 				<dictionary  shared="false">
+					<string> "__editor_plugin_screen__" </string>
+					<string> "2D" </string>
 					<string> "__editor_plugin_states__" </string>
 					<string> "__editor_plugin_states__" </string>
 					<dictionary  shared="false">
 					<dictionary  shared="false">
-						<string> "Script" </string>
-						<dictionary  shared="false">
-							<string> "current" </string>
-							<int> 0 </int>
-							<string> "sources" </string>
-							<array  len="1" shared="false">
-								<string> "res://enemy.gd" </string>
-							</array>
-						</dictionary>
 						<string> "2D" </string>
 						<string> "2D" </string>
 						<dictionary  shared="false">
 						<dictionary  shared="false">
-							<string> "pixel_snap" </string>
+							<string> "ofs" </string>
+							<vector2> -227.625, -197.9 </vector2>
+							<string> "snap_grid" </string>
+							<bool> False </bool>
+							<string> "snap_offset" </string>
+							<vector2> 0, 0 </vector2>
+							<string> "snap_pixel" </string>
+							<bool> False </bool>
+							<string> "snap_relative" </string>
+							<bool> False </bool>
+							<string> "snap_rotation" </string>
 							<bool> False </bool>
 							<bool> False </bool>
+							<string> "snap_rotation_offset" </string>
+							<real> 0 </real>
+							<string> "snap_rotation_step" </string>
+							<real> 0.261799 </real>
+							<string> "snap_show_grid" </string>
+							<bool> False </bool>
+							<string> "snap_step" </string>
+							<vector2> 10, 10 </vector2>
 							<string> "zoom" </string>
 							<string> "zoom" </string>
 							<real> 1.108033 </real>
 							<real> 1.108033 </real>
-							<string> "ofs" </string>
-							<vector2> -227.625, -197.9 </vector2>
 						</dictionary>
 						</dictionary>
 						<string> "3D" </string>
 						<string> "3D" </string>
 						<dictionary  shared="false">
 						<dictionary  shared="false">
-							<string> "zfar" </string>
-							<real> 500 </real>
+							<string> "ambient_light_color" </string>
+							<color> 0.15, 0.15, 0.15, 1 </color>
+							<string> "default_light" </string>
+							<bool> True </bool>
+							<string> "default_srgb" </string>
+							<bool> False </bool>
+							<string> "deflight_rot_x" </string>
+							<real> 0.942478 </real>
+							<string> "deflight_rot_y" </string>
+							<real> 0.628319 </real>
 							<string> "fov" </string>
 							<string> "fov" </string>
 							<real> 45 </real>
 							<real> 45 </real>
+							<string> "show_grid" </string>
+							<bool> True </bool>
+							<string> "show_origin" </string>
+							<bool> True </bool>
+							<string> "viewport_mode" </string>
+							<int> 1 </int>
 							<string> "viewports" </string>
 							<string> "viewports" </string>
 							<array  len="4" shared="false">
 							<array  len="4" shared="false">
 								<dictionary  shared="false">
 								<dictionary  shared="false">
 									<string> "distance" </string>
 									<string> "distance" </string>
 									<real> 4 </real>
 									<real> 4 </real>
+									<string> "listener" </string>
+									<bool> True </bool>
+									<string> "pos" </string>
+									<vector3> 0, 0, 0 </vector3>
+									<string> "use_environment" </string>
+									<bool> False </bool>
+									<string> "use_orthogonal" </string>
+									<bool> False </bool>
 									<string> "x_rot" </string>
 									<string> "x_rot" </string>
 									<real> 0 </real>
 									<real> 0 </real>
 									<string> "y_rot" </string>
 									<string> "y_rot" </string>
 									<real> 0 </real>
 									<real> 0 </real>
-									<string> "use_orthogonal" </string>
-									<bool> False </bool>
-									<string> "use_environment" </string>
-									<bool> False </bool>
-									<string> "pos" </string>
-									<vector3> 0, 0, 0 </vector3>
 								</dictionary>
 								</dictionary>
 								<dictionary  shared="false">
 								<dictionary  shared="false">
 									<string> "distance" </string>
 									<string> "distance" </string>
 									<real> 4 </real>
 									<real> 4 </real>
+									<string> "listener" </string>
+									<bool> False </bool>
+									<string> "pos" </string>
+									<vector3> 0, 0, 0 </vector3>
+									<string> "use_environment" </string>
+									<bool> False </bool>
+									<string> "use_orthogonal" </string>
+									<bool> False </bool>
 									<string> "x_rot" </string>
 									<string> "x_rot" </string>
 									<real> 0 </real>
 									<real> 0 </real>
 									<string> "y_rot" </string>
 									<string> "y_rot" </string>
 									<real> 0 </real>
 									<real> 0 </real>
-									<string> "use_orthogonal" </string>
-									<bool> False </bool>
-									<string> "use_environment" </string>
-									<bool> False </bool>
-									<string> "pos" </string>
-									<vector3> 0, 0, 0 </vector3>
 								</dictionary>
 								</dictionary>
 								<dictionary  shared="false">
 								<dictionary  shared="false">
 									<string> "distance" </string>
 									<string> "distance" </string>
 									<real> 4 </real>
 									<real> 4 </real>
+									<string> "listener" </string>
+									<bool> False </bool>
+									<string> "pos" </string>
+									<vector3> 0, 0, 0 </vector3>
+									<string> "use_environment" </string>
+									<bool> False </bool>
+									<string> "use_orthogonal" </string>
+									<bool> False </bool>
 									<string> "x_rot" </string>
 									<string> "x_rot" </string>
 									<real> 0 </real>
 									<real> 0 </real>
 									<string> "y_rot" </string>
 									<string> "y_rot" </string>
 									<real> 0 </real>
 									<real> 0 </real>
-									<string> "use_orthogonal" </string>
-									<bool> False </bool>
-									<string> "use_environment" </string>
-									<bool> False </bool>
-									<string> "pos" </string>
-									<vector3> 0, 0, 0 </vector3>
 								</dictionary>
 								</dictionary>
 								<dictionary  shared="false">
 								<dictionary  shared="false">
 									<string> "distance" </string>
 									<string> "distance" </string>
 									<real> 4 </real>
 									<real> 4 </real>
+									<string> "listener" </string>
+									<bool> False </bool>
+									<string> "pos" </string>
+									<vector3> 0, 0, 0 </vector3>
+									<string> "use_environment" </string>
+									<bool> False </bool>
+									<string> "use_orthogonal" </string>
+									<bool> False </bool>
 									<string> "x_rot" </string>
 									<string> "x_rot" </string>
 									<real> 0 </real>
 									<real> 0 </real>
 									<string> "y_rot" </string>
 									<string> "y_rot" </string>
 									<real> 0 </real>
 									<real> 0 </real>
-									<string> "use_orthogonal" </string>
-									<bool> False </bool>
-									<string> "use_environment" </string>
-									<bool> False </bool>
-									<string> "pos" </string>
-									<vector3> 0, 0, 0 </vector3>
 								</dictionary>
 								</dictionary>
 							</array>
 							</array>
-							<string> "viewport_mode" </string>
-							<int> 1 </int>
-							<string> "default_light" </string>
-							<bool> True </bool>
-							<string> "show_grid" </string>
-							<bool> True </bool>
-							<string> "show_origin" </string>
-							<bool> True </bool>
+							<string> "zfar" </string>
+							<real> 500 </real>
 							<string> "znear" </string>
 							<string> "znear" </string>
 							<real> 0.1 </real>
 							<real> 0.1 </real>
 						</dictionary>
 						</dictionary>
+						<string> "Anim" </string>
+						<dictionary  shared="false">
+							<string> "visible" </string>
+							<bool> False </bool>
+						</dictionary>
 					</dictionary>
 					</dictionary>
 					<string> "__editor_run_settings__" </string>
 					<string> "__editor_run_settings__" </string>
 					<dictionary  shared="false">
 					<dictionary  shared="false">
@@ -430,28 +443,24 @@
 						<string> "run_mode" </string>
 						<string> "run_mode" </string>
 						<int> 0 </int>
 						<int> 0 </int>
 					</dictionary>
 					</dictionary>
-					<string> "__editor_plugin_screen__" </string>
-					<string> "2D" </string>
 				</dictionary>
 				</dictionary>
 				<vector2> 16.2569, 11.0034 </vector2>
 				<vector2> 16.2569, 11.0034 </vector2>
 				<vector2> 23.5056, 10.8629 </vector2>
 				<vector2> 23.5056, 10.8629 </vector2>
 				<rect2> -10, -10, 20, 20 </rect2>
 				<rect2> -10, -10, 20, 20 </rect2>
-				<int> 1 </int>
 				<node_path> ".." </node_path>
 				<node_path> ".." </node_path>
 				<resource  resource_type="Animation" path="local://2">  </resource>
 				<resource  resource_type="Animation" path="local://2">  </resource>
-				<resource  resource_type="Animation" path="local://3">  </resource>
 				<resource  resource_type="Animation" path="local://4">  </resource>
 				<resource  resource_type="Animation" path="local://4">  </resource>
+				<resource  resource_type="Animation" path="local://3">  </resource>
 				<real> 3 </real>
 				<real> 3 </real>
 				<array  len="0" shared="false">
 				<array  len="0" shared="false">
 				</array>
 				</array>
 				<string> "" </string>
 				<string> "" </string>
+				<resource  external="1">  </resource>
+				<int> 8 </int>
 				<vector2> -1.08072, -2.16144 </vector2>
 				<vector2> -1.08072, -2.16144 </vector2>
+				<int> -1 </int>
 				<vector2> 6.48431, 3.24216 </vector2>
 				<vector2> 6.48431, 3.24216 </vector2>
 				<vector2> -12.495, 3.53415 </vector2>
 				<vector2> -12.495, 3.53415 </vector2>
-				<resource  resource_type="Texture" path="res://enemy.*">  </resource>
-				<int> 8 </int>
-				<color> 1, 1, 1, 1 </color>
-				<rect2> 0, 0, 0, 0 </rect2>
 				<vector2> -33.2868, -9.34363 </vector2>
 				<vector2> -33.2868, -9.34363 </vector2>
 				<vector2> 0, 45 </vector2>
 				<vector2> 0, 45 </vector2>
 				<vector2> 29.1987, -9.34363 </vector2>
 				<vector2> 29.1987, -9.34363 </vector2>
@@ -459,22 +468,18 @@
 				<int> 32 </int>
 				<int> 32 </int>
 				<real> 0.5 </real>
 				<real> 0.5 </real>
 				<real> 0.1 </real>
 				<real> 0.1 </real>
-				<resource  resource_type="Texture" path="res://bullet.*">  </resource>
+				<resource  external="2">  </resource>
 				<real> 180 </real>
 				<real> 180 </real>
 				<real> 90 </real>
 				<real> 90 </real>
 				<real> 2 </real>
 				<real> 2 </real>
 				<real> 9.8 </real>
 				<real> 9.8 </real>
-				<color> 1, 0.884956, 0.823009, 1 </color>
-				<color> 0.768627, 0.389381, 0, 0 </color>
-				<color> 0, 0, 0, 1 </color>
-				<vector2_array  len="0"> 					 </vector2_array>
+				<resource  resource_type="ColorRamp" path="local://6">  </resource>
 				<real> 2048 </real>
 				<real> 2048 </real>
+				<int> 3 </int>
 				<resource  resource_type="SampleLibrary" path="local://5">  </resource>
 				<resource  resource_type="SampleLibrary" path="local://5">  </resource>
 			</array>
 			</array>
-			<string> "nodes" </string>
-			<int_array  len="445"> 				-1, -1, 1, 0, -1, 31, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 8, 13, 6, 14, 9, 15, 8, 16, 6, 17, 10, 18, 8, 19, 11, 20, 1, 21, 3, 22, 3, 23, 8, 24, 8, 25, 12, 26, 8, 27, 0, 28, 0, 29, 2, 30, 3, 31, 13, 32, 14, 0, 0, 0, 34, 33, -1, 10, 2, 0, 3, 1, 4, 1, 5, 0, 6, 15, 7, 3, 8, 16, 35, 17, 36, 0, 37, 0, 0, 0, 0, 39, 38, -1, 10, 40, 18, 41, 3, 42, 19, 43, 20, 44, 21, 45, 22, 46, 0, 47, 23, 48, 24, 49, 25, 0, 0, 0, 50, 50, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 26, 7, 3, 8, 4, 51, 6, 52, 8, 0, 0, 0, 50, 53, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 27, 7, 3, 8, 4, 51, 6, 52, 8, 0, 0, 0, 50, 54, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 28, 7, 3, 8, 4, 51, 6, 52, 8, 0, 0, 0, 56, 55, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 57, 29, 58, 0, 59, 2, 60, 8, 61, 8, 62, 18, 63, 30, 64, 12, 65, 31, 66, 8, 67, 32, 0, 0, 0, 69, 68, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 33, 7, 3, 8, 4, 70, 0, 71, 34, 0, 0, 0, 69, 72, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 35, 7, 3, 8, 4, 70, 0, 71, 34, 0, 0, 0, 73, 73, -1, 55, 2, 0, 3, 1, 4, 36, 5, 0, 74, 18, 6, 2, 7, 3, 8, 4, 75, 37, 76, 38, 77, 1, 78, 3, 79, 38, 80, 8, 81, 2, 82, 2, 83, 0, 84, 39, 85, 40, 86, 3, 87, 41, 88, 42, 89, 43, 90, 3, 91, 3, 92, 44, 93, 3, 94, 3, 95, 3, 96, 43, 97, 23, 98, 3, 99, 3, 100, 3, 101, 3, 102, 1, 103, 3, 104, 3, 105, 3, 106, 3, 107, 3, 108, 3, 109, 3, 110, 3, 111, 3, 112, 11, 113, 3, 114, 45, 115, 1, 116, 46, 117, 1, 118, 47, 119, 1, 120, 47, 121, 48, 0, 0, 0, 123, 122, -1, 15, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 124, 3, 125, 1, 126, 1, 127, 49, 128, 1, 129, 5, 130, 50, 131, 3, 0 </int_array>
-			<string> "conns" </string>
-			<int_array  len="0"> 				 </int_array>
+			<string> "version" </string>
+			<int> 1 </int>
 		</dictionary>
 		</dictionary>
 
 
 	</main_resource>
 	</main_resource>

File diff suppressed because it is too large
+ 4 - 20
demos/2d/platformer/stage.xml


+ 3 - 3
demos/3d/platformer/player.gd

@@ -69,9 +69,9 @@ func _integrate_forces( state ):
 	var lv = state.get_linear_velocity() # linear velocity
 	var lv = state.get_linear_velocity() # linear velocity
 	var g = state.get_total_gravity()
 	var g = state.get_total_gravity()
 	var delta = state.get_step()
 	var delta = state.get_step()
-	var d = 1.0 - delta*state.get_total_density()
-	if (d<0):
-		d=0
+#	var d = 1.0 - delta*state.get_total_density()
+#	if (d<0):
+#		d=0
 	lv += g * delta #apply gravity
 	lv += g * delta #apply gravity
 
 
 	var anim = ANIM_FLOOR
 	var anim = ANIM_FLOOR

+ 4 - 0
drivers/gles2/rasterizer_gles2.cpp

@@ -5970,6 +5970,10 @@ void RasterizerGLES2::_render(const Geometry *p_geometry,const Material *p_mater
 			if (element_count==0)
 			if (element_count==0)
 				return;
 				return;
 
 
+			if (mm->visible>=0) {
+				element_count=MIN(element_count,mm->visible);
+			}
+
 			const MultiMesh::Element *elements=&mm->elements[0];
 			const MultiMesh::Element *elements=&mm->elements[0];
 
 
 			_rinfo.vertex_count+=s->array_len*element_count;
 			_rinfo.vertex_count+=s->array_len*element_count;

+ 6 - 0
main/main.cpp

@@ -98,6 +98,7 @@ static bool init_maximized=false;
 static bool init_fullscreen=false;
 static bool init_fullscreen=false;
 static bool init_use_custom_pos=false;
 static bool init_use_custom_pos=false;
 static bool debug_collisions=false;
 static bool debug_collisions=false;
+static bool debug_navigation=false;
 static Vector2 init_custom_pos;
 static Vector2 init_custom_pos;
 static int video_driver_idx=-1;
 static int video_driver_idx=-1;
 static int audio_driver_idx=-1;
 static int audio_driver_idx=-1;
@@ -517,6 +518,8 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
 			debug_mode="local";
 			debug_mode="local";
 		} else if (I->get()=="-debugcol" || I->get()=="-dc") {
 		} else if (I->get()=="-debugcol" || I->get()=="-dc") {
 			debug_collisions=true;
 			debug_collisions=true;
+		} else if (I->get()=="-debugnav" || I->get()=="-dn") {
+			debug_navigation=true;
 		} else if (I->get()=="-editor_scene") {
 		} else if (I->get()=="-editor_scene") {
 
 
 			if (I->next()) {
 			if (I->next()) {
@@ -1160,6 +1163,9 @@ bool Main::start() {
 		if (debug_collisions) {
 		if (debug_collisions) {
 			sml->set_debug_collisions_hint(true);
 			sml->set_debug_collisions_hint(true);
 		}
 		}
+		if (debug_navigation) {
+			sml->set_debug_navigation_hint(true);
+		}
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 
 
 
 

+ 68 - 3
modules/gridmap/grid_map.cpp

@@ -34,7 +34,7 @@
 #include "scene/3d/baked_light_instance.h"
 #include "scene/3d/baked_light_instance.h"
 #include "io/marshalls.h"
 #include "io/marshalls.h"
 #include "scene/scene_string_names.h"
 #include "scene/scene_string_names.h"
-
+#include "os/os.h"
 
 
 bool GridMap::_set(const StringName& p_name, const Variant& p_value) {
 bool GridMap::_set(const StringName& p_name, const Variant& p_value) {
 
 
@@ -393,8 +393,12 @@ void GridMap::set_cell_item(int p_x,int p_y,int p_z, int p_item,int p_rot){
 		if (g.items.empty()) {
 		if (g.items.empty()) {
 
 
 			PhysicsServer::get_singleton()->free(g.static_body);
 			PhysicsServer::get_singleton()->free(g.static_body);
+			if (g.collision_debug.is_valid()) {
+				PhysicsServer::get_singleton()->free(g.collision_debug);
+				PhysicsServer::get_singleton()->free(g.collision_debug_instance);
+			}
 
 
-			memdelete(&g);
+			memdelete(&g);			
 			octant_map.erase(octantkey);
 			octant_map.erase(octantkey);
 		} else {
 		} else {
 
 
@@ -422,6 +426,20 @@ void GridMap::set_cell_item(int p_x,int p_y,int p_z, int p_item,int p_rot){
 		if (is_inside_world())
 		if (is_inside_world())
 			PhysicsServer::get_singleton()->body_set_space(g->static_body,get_world()->get_space());
 			PhysicsServer::get_singleton()->body_set_space(g->static_body,get_world()->get_space());
 
 
+		SceneTree *st=SceneTree::get_singleton();
+
+		if (st && st->is_debugging_collisions_hint()) {
+
+			g->collision_debug=VisualServer::get_singleton()->mesh_create();
+			g->collision_debug_instance=VisualServer::get_singleton()->instance_create();
+			VisualServer::get_singleton()->instance_set_base(g->collision_debug_instance,g->collision_debug);
+			if (is_inside_world()) {
+				VisualServer::get_singleton()->instance_set_scenario(g->collision_debug_instance,get_world()->get_scenario());
+				VisualServer::get_singleton()->instance_set_transform(g->collision_debug_instance,get_global_transform());
+			}
+
+		}
+
 		octant_map[octantkey]=g;
 		octant_map[octantkey]=g;
 	}
 	}
 
 
@@ -512,6 +530,13 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
 	//print_line("BODYPOS: "+get_global_transform());
 	//print_line("BODYPOS: "+get_global_transform());
 
 
 
 
+	if (g.collision_debug_instance.is_valid()) {
+		VS::get_singleton()->instance_set_scenario(g.collision_debug_instance,get_world()->get_scenario());
+		VS::get_singleton()->instance_set_transform(g.collision_debug_instance,get_global_transform());
+		if (area_map.has(p_key.area)) {
+			VS::get_singleton()->instance_set_room(g.collision_debug_instance,area_map[p_key.area]->instance);
+		}
+	}
 	if (g.baked.is_valid()) {
 	if (g.baked.is_valid()) {
 
 
 		Transform xf = get_global_transform();
 		Transform xf = get_global_transform();
@@ -545,6 +570,10 @@ void GridMap::_octant_transform(const OctantKey &p_key) {
 	Octant&g = *octant_map[p_key];
 	Octant&g = *octant_map[p_key];
 	PhysicsServer::get_singleton()->body_set_state(g.static_body,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform());
 	PhysicsServer::get_singleton()->body_set_state(g.static_body,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform());
 
 
+	if (g.collision_debug_instance.is_valid()) {
+		VS::get_singleton()->instance_set_transform(g.collision_debug_instance,get_global_transform());
+	}
+
 	if (g.baked.is_valid()) {
 	if (g.baked.is_valid()) {
 
 
 		Transform xf = get_global_transform();
 		Transform xf = get_global_transform();
@@ -572,6 +601,13 @@ void GridMap::_octant_update(const OctantKey &p_key) {
 
 
 	PhysicsServer::get_singleton()->body_clear_shapes(g.static_body);
 	PhysicsServer::get_singleton()->body_clear_shapes(g.static_body);
 
 
+	if (g.collision_debug.is_valid()) {
+
+		VS::get_singleton()->mesh_clear(g.collision_debug);
+	}
+
+	DVector<Vector3> col_debug;
+
 	for(Map<int,Octant::ItemInstances>::Element *E=g.items.front();E;E=E->next()) {
 	for(Map<int,Octant::ItemInstances>::Element *E=g.items.front();E;E=E->next()) {
 
 
 		Octant::ItemInstances &ii=E->get();
 		Octant::ItemInstances &ii=E->get();
@@ -609,6 +645,7 @@ void GridMap::_octant_update(const OctantKey &p_key) {
 			xform.basis.scale(Vector3(cell_scale,cell_scale,cell_scale));
 			xform.basis.scale(Vector3(cell_scale,cell_scale,cell_scale));
 
 
 			ii.multimesh->set_instance_transform(idx,xform);
 			ii.multimesh->set_instance_transform(idx,xform);
+			//ii.multimesh->set_instance_transform(idx,Transform()	);
 			ii.multimesh->set_instance_color(idx,Color(1,1,1,1));
 			ii.multimesh->set_instance_color(idx,Color(1,1,1,1));
 			//print_line("MMINST: "+xform);
 			//print_line("MMINST: "+xform);
 
 
@@ -624,8 +661,11 @@ void GridMap::_octant_update(const OctantKey &p_key) {
 			if (ii.shape.is_valid()) {
 			if (ii.shape.is_valid()) {
 
 
 				PhysicsServer::get_singleton()->body_add_shape(g.static_body,ii.shape->get_rid(),xform);
 				PhysicsServer::get_singleton()->body_add_shape(g.static_body,ii.shape->get_rid(),xform);
-			//	print_line("PHIS x: "+xform);
+				if (g.collision_debug.is_valid()) {
+					ii.shape->add_vertices_to_array(col_debug,xform);
+				}
 
 
+			//	print_line("PHIS x: "+xform);
 			}
 			}
 
 
 			idx++;
 			idx++;
@@ -636,6 +676,20 @@ void GridMap::_octant_update(const OctantKey &p_key) {
 
 
 	}
 	}
 
 
+	if (col_debug.size()) {
+
+
+		Array arr;
+		arr.resize(VS::ARRAY_MAX);
+		arr[VS::ARRAY_VERTEX]=col_debug;
+
+		VS::get_singleton()->mesh_add_surface(g.collision_debug,VS::PRIMITIVE_LINES,arr);
+		SceneTree *st=SceneTree::get_singleton();
+		if (st) {
+			VS::get_singleton()->mesh_surface_set_material( g.collision_debug, 0,st->get_debug_collision_material()->get_rid() );
+		}
+	}
+
 	g.dirty=false;
 	g.dirty=false;
 
 
 }
 }
@@ -656,6 +710,12 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
 
 
 	}
 	}
 
 
+	if (g.collision_debug_instance.is_valid()) {
+
+		VS::get_singleton()->instance_set_room(g.collision_debug_instance,RID());
+		VS::get_singleton()->instance_set_scenario(g.collision_debug_instance,RID());
+	}
+
 	for(Map<int,Octant::ItemInstances>::Element *E=g.items.front();E;E=E->next()) {
 	for(Map<int,Octant::ItemInstances>::Element *E=g.items.front();E;E=E->next()) {
 
 
 		VS::get_singleton()->instance_set_scenario(E->get().multimesh_instance,RID());
 		VS::get_singleton()->instance_set_scenario(E->get().multimesh_instance,RID());
@@ -959,6 +1019,11 @@ void GridMap::_clear_internal(bool p_keep_areas) {
 		if (E->get()->bake_instance.is_valid())
 		if (E->get()->bake_instance.is_valid())
 			VS::get_singleton()->free(E->get()->bake_instance);
 			VS::get_singleton()->free(E->get()->bake_instance);
 
 
+		if (E->get()->collision_debug.is_valid())
+			VS::get_singleton()->free(E->get()->collision_debug);
+		if (E->get()->collision_debug_instance.is_valid())
+			VS::get_singleton()->free(E->get()->collision_debug_instance);
+
 		PhysicsServer::get_singleton()->free(E->get()->static_body);
 		PhysicsServer::get_singleton()->free(E->get()->static_body);
 		memdelete(E->get());
 		memdelete(E->get());
 
 

+ 2 - 0
modules/gridmap/grid_map.h

@@ -93,6 +93,8 @@ class GridMap : public Spatial {
 
 
 		Ref<Mesh> baked;
 		Ref<Mesh> baked;
 		RID bake_instance;
 		RID bake_instance;
+		RID collision_debug;
+		RID collision_debug_instance;
 
 
 		bool dirty;
 		bool dirty;
 		RID static_body;
 		RID static_body;

+ 8 - 8
platform/android/export/export.cpp

@@ -249,11 +249,11 @@ public:
 	virtual int get_device_count() const;
 	virtual int get_device_count() const;
 	virtual String get_device_name(int p_device) const;
 	virtual String get_device_name(int p_device) const;
 	virtual String get_device_info(int p_device) const;
 	virtual String get_device_info(int p_device) const;
-	virtual Error run(int p_device,bool p_dumb=false,bool p_remote_debug=false);
+	virtual Error run(int p_device,int p_flags=0);
 
 
 	virtual bool requieres_password(bool p_debug) const { return !p_debug; }
 	virtual bool requieres_password(bool p_debug) const { return !p_debug; }
 	virtual String get_binary_extension() const { return "apk"; }
 	virtual String get_binary_extension() const { return "apk"; }
-	virtual Error export_project(const String& p_path, bool p_debug, bool p_dumb=false, bool p_remote_debug=false);
+	virtual Error export_project(const String& p_path, bool p_debug, int p_flags=0);
 
 
 	virtual bool can_export(String *r_error=NULL) const;
 	virtual bool can_export(String *r_error=NULL) const;
 
 
@@ -1014,7 +1014,7 @@ Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata,const String&
 
 
 
 
 
 
-Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_debug, bool p_dumb,bool p_remote_debug) {
+Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_debug, int p_flags) {
 
 
 	String src_apk;
 	String src_apk;
 
 
@@ -1078,7 +1078,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
 
 
 		if (file=="AndroidManifest.xml") {
 		if (file=="AndroidManifest.xml") {
 
 
-			_fix_manifest(data,p_dumb || p_remote_debug);
+			_fix_manifest(data,p_flags&(EXPORT_DUMB_CLIENT|EXPORT_REMOTE_DEBUG));
 		}
 		}
 
 
 		if (file=="resources.arsc") {
 		if (file=="resources.arsc") {
@@ -1156,9 +1156,9 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
 		}
 		}
 	}
 	}
 
 
-	gen_export_flags(cl,p_dumb,p_remote_debug);
+	gen_export_flags(cl,p_flags);
 
 
-	if (p_dumb) {
+	if (p_flags) {
 
 
 		/*String host = EditorSettings::get_singleton()->get("file_server/host");
 		/*String host = EditorSettings::get_singleton()->get("file_server/host");
 		int port = EditorSettings::get_singleton()->get("file_server/post");
 		int port = EditorSettings::get_singleton()->get("file_server/post");
@@ -1485,7 +1485,7 @@ void EditorExportPlatformAndroid::_device_poll_thread(void *ud) {
 
 
 }
 }
 
 
-Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb, bool p_remote_debug) {
+Error EditorExportPlatformAndroid::run(int p_device, int p_flags) {
 
 
 	ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
 	ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
 	device_lock->lock();
 	device_lock->lock();
@@ -1504,7 +1504,7 @@ Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb, bool p_remote_
 	ep.step("Exporting APK",0);
 	ep.step("Exporting APK",0);
 
 
 	String export_to=EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmpexport.apk";
 	String export_to=EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmpexport.apk";
-	Error err = export_project(export_to,true,p_dumb,p_remote_debug);
+	Error err = export_project(export_to,true,p_flags);
 	if (err) {
 	if (err) {
 		device_lock->unlock();
 		device_lock->unlock();
 		return err;
 		return err;

+ 5 - 5
platform/bb10/export/export.cpp

@@ -67,11 +67,11 @@ public:
 	virtual int get_device_count() const;
 	virtual int get_device_count() const;
 	virtual String get_device_name(int p_device) const;
 	virtual String get_device_name(int p_device) const;
 	virtual String get_device_info(int p_device) const;
 	virtual String get_device_info(int p_device) const;
-	virtual Error run(int p_device,bool p_dumb=false,bool p_remote_debug=false);
+	virtual Error run(int p_device,int p_flags=0);
 
 
 	virtual bool requieres_password(bool p_debug) const { return !p_debug; }
 	virtual bool requieres_password(bool p_debug) const { return !p_debug; }
 	virtual String get_binary_extension() const { return "bar"; }
 	virtual String get_binary_extension() const { return "bar"; }
-	virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false,bool p_remote_debug=false);
+	virtual Error export_project(const String& p_path,bool p_debug,int p_flags=0);
 
 
 	virtual bool can_export(String *r_error=NULL) const;
 	virtual bool can_export(String *r_error=NULL) const;
 
 
@@ -270,7 +270,7 @@ void EditorExportPlatformBB10::_fix_descriptor(Vector<uint8_t>& p_descriptor) {
 
 
 
 
 
 
-Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debug, bool p_dumb, bool p_remote_debug) {
+Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debug, int p_flags) {
 
 
 
 
 	EditorProgress ep("export","Exporting for BlackBerry 10",104);
 	EditorProgress ep("export","Exporting for BlackBerry 10",104);
@@ -619,7 +619,7 @@ void EditorExportPlatformBB10::_device_poll_thread(void *ud) {
 
 
 }
 }
 
 
-Error EditorExportPlatformBB10::run(int p_device, bool p_dumb, bool p_remote_debug) {
+Error EditorExportPlatformBB10::run(int p_device, int p_flags) {
 
 
 	ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
 	ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
 
 
@@ -643,7 +643,7 @@ Error EditorExportPlatformBB10::run(int p_device, bool p_dumb, bool p_remote_deb
 	ep.step("Exporting APK",0);
 	ep.step("Exporting APK",0);
 
 
 	String export_to=EditorSettings::get_singleton()->get_settings_path().plus_file("/tmp/tmpexport.bar");
 	String export_to=EditorSettings::get_singleton()->get_settings_path().plus_file("/tmp/tmpexport.bar");
-	Error err = export_project(export_to,true);
+	Error err = export_project(export_to,true,p_flags);
 	if (err) {
 	if (err) {
 		device_lock->unlock();
 		device_lock->unlock();
 		return err;
 		return err;

+ 5 - 5
platform/javascript/export/export.cpp

@@ -77,11 +77,11 @@ public:
 	virtual int get_device_count() const { return show_run?1:0; };
 	virtual int get_device_count() const { return show_run?1:0; };
 	virtual String get_device_name(int p_device) const  { return "Run in Browser"; }
 	virtual String get_device_name(int p_device) const  { return "Run in Browser"; }
 	virtual String get_device_info(int p_device) const { return "Run exported HTML in the system's default browser."; }
 	virtual String get_device_info(int p_device) const { return "Run exported HTML in the system's default browser."; }
-	virtual Error run(int p_device,bool p_dumb=false,bool p_remote_debug=false);
+	virtual Error run(int p_device,int p_flags=0);
 
 
 	virtual bool requieres_password(bool p_debug) const { return false; }
 	virtual bool requieres_password(bool p_debug) const { return false; }
 	virtual String get_binary_extension() const { return "html"; }
 	virtual String get_binary_extension() const { return "html"; }
-	virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false,bool p_remote_debug=false);
+	virtual Error export_project(const String& p_path,bool p_debug,int p_flags=0);
 
 
 	virtual bool can_export(String *r_error=NULL) const;
 	virtual bool can_export(String *r_error=NULL) const;
 
 
@@ -198,7 +198,7 @@ struct JSExportData {
 
 
 
 
 
 
-Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool p_debug, bool p_dumb, bool p_remote_debug) {
+Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool p_debug, int p_flags) {
 
 
 
 
 	String src_template;
 	String src_template;
@@ -309,10 +309,10 @@ Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool
 }
 }
 
 
 
 
-Error EditorExportPlatformJavaScript::run(int p_device, bool p_dumb, bool p_remote_debug) {
+Error EditorExportPlatformJavaScript::run(int p_device, int p_flags) {
 
 
 	String path = EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmp_export.html";
 	String path = EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmp_export.html";
-	Error err = export_project(path,true,"");
+	Error err = export_project(path,true,p_flags);
 	if (err)
 	if (err)
 		return err;
 		return err;
 
 

+ 4 - 4
platform/osx/export/export.cpp

@@ -57,11 +57,11 @@ public:
 	virtual int get_device_count() const { return 0; };
 	virtual int get_device_count() const { return 0; };
 	virtual String get_device_name(int p_device) const  { return String(); }
 	virtual String get_device_name(int p_device) const  { return String(); }
 	virtual String get_device_info(int p_device) const { return String(); }
 	virtual String get_device_info(int p_device) const { return String(); }
-	virtual Error run(int p_device,bool p_dumb=false,bool p_remote_debug=false);
+	virtual Error run(int p_device,int p_flags=0);
 
 
 	virtual bool requieres_password(bool p_debug) const { return false; }
 	virtual bool requieres_password(bool p_debug) const { return false; }
 	virtual String get_binary_extension() const { return "zip"; }
 	virtual String get_binary_extension() const { return "zip"; }
-	virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false,bool p_remote_debug=false);
+	virtual Error export_project(const String& p_path,bool p_debug,int p_flags=0);
 
 
 	virtual bool can_export(String *r_error=NULL) const;
 	virtual bool can_export(String *r_error=NULL) const;
 
 
@@ -245,7 +245,7 @@ void EditorExportPlatformOSX::_fix_plist(Vector<uint8_t>& plist,const String& p_
 	}
 	}
 }
 }
 
 
-Error EditorExportPlatformOSX::export_project(const String& p_path, bool p_debug, bool p_dumb, bool p_remote_debug) {
+Error EditorExportPlatformOSX::export_project(const String& p_path, bool p_debug, int p_flags) {
 
 
 	String src_pkg;
 	String src_pkg;
 
 
@@ -437,7 +437,7 @@ Error EditorExportPlatformOSX::export_project(const String& p_path, bool p_debug
 }
 }
 
 
 
 
-Error EditorExportPlatformOSX::run(int p_device, bool p_dumb, bool p_remote_debug) {
+Error EditorExportPlatformOSX::run(int p_device, int p_flags) {
 
 
 	return OK;
 	return OK;
 }
 }

+ 9 - 0
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) {
 CanvasItem::CanvasItem() : xform_change(this) {
 
 
 
 
@@ -1191,6 +1199,7 @@ CanvasItem::CanvasItem() : xform_change(this) {
 	canvas_layer=NULL;
 	canvas_layer=NULL;
 	use_parent_material=false;
 	use_parent_material=false;
 	global_invalid=true;
 	global_invalid=true;
+	notify_local_transform=false;
 	light_mask=1;
 	light_mask=1;
 
 
 	C=NULL;
 	C=NULL;

+ 6 - 1
scene/2d/canvas_item.h

@@ -126,6 +126,7 @@ private:
 	bool block_transform_notify;
 	bool block_transform_notify;
 	bool behind;
 	bool behind;
 	bool use_parent_material;
 	bool use_parent_material;
+	bool notify_local_transform;
 
 
 	Ref<CanvasItemMaterial> material;
 	Ref<CanvasItemMaterial> material;
 
 
@@ -155,7 +156,7 @@ private:
 
 
 protected:
 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();
 	void item_rect_changed();
 
 
@@ -263,6 +264,10 @@ public:
 	Vector2 get_global_mouse_pos() const;
 	Vector2 get_global_mouse_pos() const;
 	Vector2 get_local_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();
 	~CanvasItem();
 	~CanvasItem();
 };
 };

+ 82 - 18
scene/2d/collision_polygon_2d.cpp

@@ -33,7 +33,7 @@
 
 
 void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
 void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
 
 
-	if (unparenting)
+	if (unparenting || !can_update_body)
 		return;
 		return;
 
 
 	CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>();
 	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
 		//here comes the sun, lalalala
 		//decompose concave into multiple convex polygons and add them
 		//decompose concave into multiple convex polygons and add them
 		Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
 		Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
+		shape_from=co->get_shape_count();
 		for(int i=0;i<decomp.size();i++) {
 		for(int i=0;i<decomp.size();i++) {
 			Ref<ConvexPolygonShape2D> convex = memnew( ConvexPolygonShape2D );
 			Ref<ConvexPolygonShape2D> convex = memnew( ConvexPolygonShape2D );
 			convex->set_points(decomp[i]);
 			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);
 				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 {
 	} else {
 
 
@@ -78,6 +84,9 @@ void CollisionPolygon2D::_add_to_collision_object(Object *p_obj) {
 		if (trigger)
 		if (trigger)
 			co->set_shape_as_trigger(co->get_shape_count()-1,true);
 			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() {
 void CollisionPolygon2D::_update_parent() {
 
 
+	if (!can_update_body)
+		return;
 	Node *parent = get_parent();
 	Node *parent = get_parent();
 	if (!parent)
 	if (!parent)
 		return;
 		return;
@@ -101,33 +112,55 @@ void CollisionPolygon2D::_notification(int p_what) {
 	switch(p_what) {
 	switch(p_what) {
 		case NOTIFICATION_ENTER_TREE: {
 		case NOTIFICATION_ENTER_TREE: {
 			unparenting=false;
 			unparenting=false;
+			can_update_body=get_tree()->is_editor_hint();
+		} break;
+		case NOTIFICATION_EXIT_TREE: {
+			can_update_body=false;
 		} break;
 		} break;
 		case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
 		case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
 
 
 			if (!is_inside_tree())
 			if (!is_inside_tree())
 				break;
 				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;
 		} break;
 
 
 		case NOTIFICATION_DRAW: {
 		case NOTIFICATION_DRAW: {
+
+			if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
+				break;
+			}
+
+
 			for(int i=0;i<polygon.size();i++) {
 			for(int i=0;i<polygon.size();i++) {
 
 
 				Vector2 p = polygon[i];
 				Vector2 p = polygon[i];
 				Vector2 n = polygon[(i+1)%polygon.size()];
 				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);
 			Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
-#define DEBUG_DECOMPOSE
-#ifdef DEBUG_DECOMPOSE
 			Color c(0.4,0.9,0.1);
 			Color c(0.4,0.9,0.1);
 			for(int i=0;i<decomp.size();i++) {
 			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);
 				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);
 				draw_colored_polygon(decomp[i],c);
 			}
 			}
+#else
+			draw_colored_polygon(polygon,get_tree()->get_debug_collisions_color());
 #endif
 #endif
+
+
 		} break;
 		} break;
 		case NOTIFICATION_UNPARENTED: {
 		case NOTIFICATION_UNPARENTED: {
 			unparenting = true;
 			unparenting = true;
@@ -141,20 +174,22 @@ void CollisionPolygon2D::set_polygon(const Vector<Point2>& p_polygon) {
 
 
 	polygon=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();
 	update();
 }
 }
 
 
@@ -184,6 +219,13 @@ void CollisionPolygon2D::set_trigger(bool p_trigger) {
 
 
 	trigger=p_trigger;
 	trigger=p_trigger;
 	_update_parent();
 	_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{
 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() {
 void CollisionPolygon2D::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon2D::_add_to_collision_object);
 	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("set_trigger"),&CollisionPolygon2D::set_trigger);
 	ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionPolygon2D::is_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::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_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"));
 	ADD_PROPERTY( PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger"));
+
 }
 }
 
 
 CollisionPolygon2D::CollisionPolygon2D() {
 CollisionPolygon2D::CollisionPolygon2D() {
@@ -215,6 +276,9 @@ CollisionPolygon2D::CollisionPolygon2D() {
 	build_mode=BUILD_SOLIDS;
 	build_mode=BUILD_SOLIDS;
 	trigger=false;
 	trigger=false;
 	unparenting=false;
 	unparenting=false;
-
+	shape_from=-1;
+	shape_to=-1;
+	can_update_body=false;
+	set_notify_local_transform(true);
 
 
 }
 }

+ 12 - 0
scene/2d/collision_polygon_2d.h

@@ -56,6 +56,14 @@ protected:
 	void _add_to_collision_object(Object *p_obj);
 	void _add_to_collision_object(Object *p_obj);
 	void _update_parent();
 	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:
 protected:
 
 
 	void _notification(int p_what);
 	void _notification(int p_what);
@@ -72,6 +80,10 @@ public:
 	Vector<Point2> get_polygon() const;
 	Vector<Point2> get_polygon() const;
 
 
 	virtual Rect2 get_item_rect() 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();
 	CollisionPolygon2D();
 };
 };
 
 

+ 62 - 101
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>();
 	CollisionObject2D *co = p_obj->cast_to<CollisionObject2D>();
 	ERR_FAIL_COND(!co);
 	ERR_FAIL_COND(!co);
+	update_shape_index=co->get_shape_count();
 	co->add_shape(shape,get_transform());
 	co->add_shape(shape,get_transform());
 	if (trigger)
 	if (trigger)
 		co->set_shape_as_trigger(co->get_shape_count()-1,true);
 		co->set_shape_as_trigger(co->get_shape_count()-1,true);
 
 
+
 }
 }
 
 
 void CollisionShape2D::_shape_changed() {
 void CollisionShape2D::_shape_changed() {
@@ -74,12 +76,27 @@ void CollisionShape2D::_notification(int p_what) {
 
 
 		case NOTIFICATION_ENTER_TREE: {
 		case NOTIFICATION_ENTER_TREE: {
 			unparenting=false;
 			unparenting=false;
+			can_update_body=get_tree()->is_editor_hint();
+
 		} break;
 		} break;
 		case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
 		case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
 
 
 			if (!is_inside_tree())
 			if (!is_inside_tree())
 				break;
 				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;
 		} break;
 		/*
 		/*
@@ -92,110 +109,18 @@ void CollisionShape2D::_notification(int p_what) {
 		} break;*/
 		} break;*/
 		case NOTIFICATION_DRAW: {
 		case NOTIFICATION_DRAW: {
 
 
-			if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint())
+			if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
 				break;
 				break;
+			}
 
 
 			rect=Rect2();
 			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>()) {
+			Color draw_col=get_tree()->get_debug_collisions_color();
+			shape->draw(get_canvas_item(),draw_col);
 
 
-				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;
-
-			} else if (shape->cast_to<ConvexPolygonShape2D>()) {
-
-				ConvexPolygonShape2D *s = shape->cast_to<ConvexPolygonShape2D>();
-
-				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);
-
-			}
 
 
+			rect=shape->get_rect();
 			rect=rect.grow(3);
 			rect=rect.grow(3);
 
 
 		} break;
 		} break;
@@ -213,7 +138,14 @@ void CollisionShape2D::set_shape(const Ref<Shape2D>& p_shape) {
 		shape->disconnect("changed",this,"_shape_changed");
 		shape->disconnect("changed",this,"_shape_changed");
 	shape=p_shape;
 	shape=p_shape;
 	update();
 	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())
 	if (shape.is_valid())
 		shape->connect("changed",this,"_shape_changed");
 		shape->connect("changed",this,"_shape_changed");
 
 
@@ -232,7 +164,14 @@ Rect2 CollisionShape2D::get_item_rect() const {
 void CollisionShape2D::set_trigger(bool p_trigger) {
 void CollisionShape2D::set_trigger(bool p_trigger) {
 
 
 	trigger=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{
 bool CollisionShape2D::is_trigger() const{
@@ -240,6 +179,19 @@ bool CollisionShape2D::is_trigger() const{
 	return trigger;
 	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() {
 void CollisionShape2D::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("set_shape","shape"),&CollisionShape2D::set_shape);
 	ObjectTypeDB::bind_method(_MD("set_shape","shape"),&CollisionShape2D::set_shape);
@@ -249,14 +201,23 @@ void CollisionShape2D::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_trigger","enable"),&CollisionShape2D::set_trigger);
 	ObjectTypeDB::bind_method(_MD("set_trigger","enable"),&CollisionShape2D::set_trigger);
 	ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionShape2D::is_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_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::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() {
 CollisionShape2D::CollisionShape2D() {
 
 
 	rect=Rect2(-Point2(10,10),Point2(20,20));
 	rect=Rect2(-Point2(10,10),Point2(20,20));
-
+	set_notify_local_transform(true);
 	trigger=false;
 	trigger=false;
 	unparenting = false;
 	unparenting = false;
+	can_update_body = false;
+	update_shape_index=-1;
 }
 }

+ 8 - 0
scene/2d/collision_shape_2d.h

@@ -39,7 +39,13 @@ class CollisionShape2D : public Node2D {
 	Rect2 rect;
 	Rect2 rect;
 	bool trigger;
 	bool trigger;
 	bool unparenting;
 	bool unparenting;
+	bool can_update_body;
 	void _shape_changed();
 	void _shape_changed();
+	int update_shape_index;
+
+	void _set_update_shape_index(int p_index);
+	int _get_update_shape_index() const;
+
 protected:
 protected:
 
 
 	void _update_parent();
 	void _update_parent();
@@ -55,6 +61,8 @@ public:
 	void set_trigger(bool p_trigger);
 	void set_trigger(bool p_trigger);
 	bool is_trigger() const;
 	bool is_trigger() const;
 
 
+	int get_collision_object_shape_index() const { return _get_update_shape_index(); }
+
 	CollisionShape2D();
 	CollisionShape2D();
 };
 };
 
 

+ 5 - 5
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();
 
 
 //	update_gizmo();
 //	update_gizmo();
@@ -338,7 +338,7 @@ void NavigationPolygonInstance::_notification(int p_what) {
 		} break;
 		} break;
 		case NOTIFICATION_DRAW: {
 		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();
 				DVector<Vector2> verts=navpoly->get_vertices();
 				int vsize = verts.size();
 				int vsize = verts.size();
@@ -348,9 +348,9 @@ void NavigationPolygonInstance::_notification(int p_what) {
 
 
 				Color color;
 				Color color;
 				if (enabled) {
 				if (enabled) {
-					color=Color(0.1,0.8,1.0,0.4);
+					color=get_tree()->get_debug_navigation_color();
 				} else {
 				} else {
-					color=Color(1.0,0.8,0.1,0.4);
+					color=get_tree()->get_debug_navigation_disabled_color();
 				}
 				}
 				Vector<Color> colors;
 				Vector<Color> colors;
 				Vector<Vector2> vertices;
 				Vector<Vector2> vertices;
@@ -423,7 +423,7 @@ Ref<NavigationPolygon> NavigationPolygonInstance::get_navigation_polygon() const
 
 
 void NavigationPolygonInstance::_navpoly_changed() {
 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();
 		update();
 }
 }
 
 

+ 4 - 4
scene/2d/ray_cast_2d.cpp

@@ -115,17 +115,17 @@ void RayCast2D::_notification(int p_what) {
 				set_fixed_process(false);
 				set_fixed_process(false);
 
 
 		} break;
 		} break;
-#ifdef TOOLS_ENABLED
+
 		case NOTIFICATION_DRAW: {
 		case NOTIFICATION_DRAW: {
 
 
-			if (!get_tree()->is_editor_hint())
+			if (!get_tree()->is_editor_hint()  && !get_tree()->is_debugging_collisions_hint())
 				break;
 				break;
 			Matrix32 xf;
 			Matrix32 xf;
 			xf.rotate(cast_to.atan2());
 			xf.rotate(cast_to.atan2());
 			xf.translate(Vector2(0,cast_to.length()));
 			xf.translate(Vector2(0,cast_to.length()));
 
 
 			//Vector2 tip = Vector2(0,s->get_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);
 			draw_line(Vector2(),cast_to,dcol,3);
 			Vector<Vector2> pts;
 			Vector<Vector2> pts;
 			float tsize=4;
 			float tsize=4;
@@ -139,7 +139,7 @@ void RayCast2D::_notification(int p_what) {
 			draw_primitive(pts,cols,Vector<Vector2>()); //small arrow
 			draw_primitive(pts,cols,Vector<Vector2>()); //small arrow
 
 
 		} break;
 		} break;
-#endif
+
 
 
 		case NOTIFICATION_FIXED_PROCESS: {
 		case NOTIFICATION_FIXED_PROCESS: {
 
 

+ 19 - 1
scene/2d/tile_map.cpp

@@ -30,6 +30,7 @@
 #include "io/marshalls.h"
 #include "io/marshalls.h"
 #include "servers/physics_2d_server.h"
 #include "servers/physics_2d_server.h"
 #include "method_bind_ext.inc"
 #include "method_bind_ext.inc"
+#include "os/os.h"
 
 
 int TileMap::_get_quadrant_size() const {
 int TileMap::_get_quadrant_size() const {
 
 
@@ -262,6 +263,14 @@ void TileMap::_update_dirty_quadrants() {
 
 
 	Vector2 qofs;
 	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()) {
 	while (dirty_quadrant_list.first()) {
 
 
 		Quadrant &q = *dirty_quadrant_list.first()->self();
 		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);
 					_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));
 					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) {
 			if (navigation) {
 				Ref<NavigationPolygon> navpoly = tile_set->tile_get_navigation_polygon(c.id);
 				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);
 					xform.set_origin(offset.floor()+q.pos);
 					_fix_cell_transform(xform,c,npoly_ofs+center_ofs,s);
 					_fix_cell_transform(xform,c,npoly_ofs+center_ofs,s);
 
 
+
 					int pid = navigation->navpoly_create(navpoly,nav_rel * xform);
 					int pid = navigation->navpoly_create(navpoly,nav_rel * xform);
 
 
 					Quadrant::NavPoly np;
 					Quadrant::NavPoly np;

+ 97 - 11
scene/3d/body_shape.cpp

@@ -43,7 +43,10 @@
 
 
 void CollisionShape::_update_body() {
 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>())
 	if (get_parent() && get_parent()->cast_to<CollisionObject>())
 		get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children();
 		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()) {
 	if (shape.is_valid()) {
 
 
+		update_shape_index=co->get_shape_count();
 		co->add_shape(shape,get_transform());
 		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) {
 void CollisionShape::_notification(int p_what) {
@@ -322,12 +328,18 @@ void CollisionShape::_notification(int p_what) {
 
 
 		case NOTIFICATION_ENTER_TREE: {
 		case NOTIFICATION_ENTER_TREE: {
 			unparenting=false;
 			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());
 			//indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
 		} break;
 		} break;
 		case NOTIFICATION_TRANSFORM_CHANGED: {
 		case NOTIFICATION_TRANSFORM_CHANGED: {
 		//	VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
 		//	VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
-			if (updating_body) {
+			if (can_update_body && updating_body) {
 				_update_body();
 				_update_body();
 			}
 			}
 		} break;
 		} break;
@@ -336,16 +348,34 @@ void CollisionShape::_notification(int p_what) {
 				VisualServer::get_singleton()->free(indicator_instance);
 				VisualServer::get_singleton()->free(indicator_instance);
 				indicator_instance=RID();
 				indicator_instance=RID();
 			}*/
 			}*/
+			can_update_body=false;
+			set_notify_local_transform(false);
+			if (debug_shape) {
+				debug_shape->queue_delete();
+				debug_shape=NULL;
+			}
 		} break;
 		} break;
 		case NOTIFICATION_UNPARENTED: {
 		case NOTIFICATION_UNPARENTED: {
 			unparenting=true;
 			unparenting=true;
-			if (updating_body)
+			if (can_update_body && updating_body)
 				_update_body();
 				_update_body();
 		} break;
 		} break;
 		case NOTIFICATION_PARENTED: {
 		case NOTIFICATION_PARENTED: {
-			if (updating_body)
+			if (can_update_body && updating_body)
 				_update_body();
 				_update_body();
 		} break;
 		} 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() {
 void CollisionShape::_bind_methods() {
 
 
 	//not sure if this should do anything
 	//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("is_trigger"),&CollisionShape::is_trigger);
 	ObjectTypeDB::bind_method(_MD("make_convex_from_brothers"),&CollisionShape::make_convex_from_brothers);
 	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::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::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())
 	if (!shape.is_null())
 		shape->register_owner(this);
 		shape->register_owner(this);
 	update_gizmo();
 	update_gizmo();
-	if (updating_body)
+	if (updating_body) {
 		_update_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 {
 Ref<Shape> CollisionShape::get_shape() const {
@@ -405,8 +458,14 @@ bool CollisionShape::is_updating_body() const {
 void CollisionShape::set_trigger(bool p_trigger) {
 void CollisionShape::set_trigger(bool p_trigger) {
 
 
     trigger=p_trigger;
     trigger=p_trigger;
-    if (updating_body)
+    if (updating_body) {
         _update_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{
 bool CollisionShape::is_trigger() const{
@@ -419,7 +478,10 @@ CollisionShape::CollisionShape() {
 	//indicator = VisualServer::get_singleton()->mesh_create();
 	//indicator = VisualServer::get_singleton()->mesh_create();
 	updating_body=true;
 	updating_body=true;
 	unparenting=false;
 	unparenting=false;
-    trigger=false;
+	update_shape_index=-1;
+	trigger=false;
+	can_update_body=false;
+	debug_shape=NULL;
 }
 }
 
 
 CollisionShape::~CollisionShape() {
 CollisionShape::~CollisionShape() {
@@ -428,6 +490,30 @@ CollisionShape::~CollisionShape() {
 	//VisualServer::get_singleton()->free(indicator);
 	//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
 #if 0
 #include "body_volume.h"
 #include "body_volume.h"
 
 

+ 16 - 2
scene/3d/body_shape.h

@@ -50,14 +50,26 @@ class CollisionShape : public Spatial {
 	RID indicator_instance;
 	RID indicator_instance;
 	*/
 	*/
 
 
+	Node* debug_shape;
+
 	void resource_changed(RES res);
 	void resource_changed(RES res);
 
 
 	bool updating_body;
 	bool updating_body;
 	bool unparenting;
 	bool unparenting;
 	bool trigger;
 	bool trigger;
 
 
+	bool can_update_body;
+
+	int update_shape_index;
+
 	void _update_body();
 	void _update_body();
 	void _add_to_collision_object(Object* p_cshape);
 	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:
 protected:
 
 
 	void _notification(int p_what);
 	void _notification(int p_what);
@@ -73,8 +85,10 @@ public:
 	void set_updating_body(bool p_update);
 	void set_updating_body(bool p_update);
 	bool is_updating_body() const;
 	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();
 	~CollisionShape();
 	~CollisionShape();

+ 85 - 21
scene/3d/collision_polygon.cpp

@@ -6,6 +6,8 @@
 
 
 void CollisionPolygon::_add_to_collision_object(Object *p_obj) {
 void CollisionPolygon::_add_to_collision_object(Object *p_obj) {
 
 
+	if (!can_update_body)
+		return;
 
 
 	CollisionObject *co = p_obj->cast_to<CollisionObject>();
 	CollisionObject *co = p_obj->cast_to<CollisionObject>();
 	ERR_FAIL_COND(!co);
 	ERR_FAIL_COND(!co);
@@ -23,6 +25,7 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) {
 
 
 		//here comes the sun, lalalala
 		//here comes the sun, lalalala
 		//decompose concave into multiple convex polygons and add them
 		//decompose concave into multiple convex polygons and add them
+		shape_from=co->get_shape_count();
 		for(int i=0;i<decomp.size();i++) {
 		for(int i=0;i<decomp.size();i++) {
 			Ref<ConvexPolygonShape> convex = memnew( ConvexPolygonShape );
 			Ref<ConvexPolygonShape> convex = memnew( ConvexPolygonShape );
 			DVector<Vector3> cp;
 			DVector<Vector3> cp;
@@ -43,6 +46,11 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) {
 			co->add_shape(convex,get_transform());
 			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 {
 	} else {
 #if 0
 #if 0
@@ -71,6 +79,9 @@ void CollisionPolygon::_add_to_collision_object(Object *p_obj) {
 
 
 void CollisionPolygon::_update_parent() {
 void CollisionPolygon::_update_parent() {
 
 
+	if (!can_update_body)
+		return;
+
 	Node *parent = get_parent();
 	Node *parent = get_parent();
 	if (!parent)
 	if (!parent)
 		return;
 		return;
@@ -80,15 +91,50 @@ void CollisionPolygon::_update_parent() {
 	co->_update_shapes_from_children();
 	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) {
 void CollisionPolygon::_notification(int p_what) {
 
 
 
 
 	switch(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: {
 		case NOTIFICATION_TRANSFORM_CHANGED: {
 
 
 			if (!is_inside_tree())
 			if (!is_inside_tree())
 				break;
 				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;
 		} break;
 #if 0
 #if 0
@@ -119,29 +165,31 @@ void CollisionPolygon::_notification(int p_what) {
 void CollisionPolygon::set_polygon(const Vector<Point2>& p_polygon) {
 void CollisionPolygon::set_polygon(const Vector<Point2>& p_polygon) {
 
 
 	polygon=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();
 	update_gizmo();
 }
 }
 
 
@@ -154,6 +202,8 @@ void CollisionPolygon::set_build_mode(BuildMode p_mode) {
 
 
 	ERR_FAIL_INDEX(p_mode,2);
 	ERR_FAIL_INDEX(p_mode,2);
 	build_mode=p_mode;
 	build_mode=p_mode;
+	if (!can_update_body)
+		return;
 	_update_parent();
 	_update_parent();
 }
 }
 
 
@@ -170,6 +220,8 @@ AABB CollisionPolygon::get_item_rect() const {
 void CollisionPolygon::set_depth(float p_depth) {
 void CollisionPolygon::set_depth(float p_depth) {
 
 
 	depth=p_depth;
 	depth=p_depth;
+	if (!can_update_body)
+		return;
 	_update_parent();
 	_update_parent();
 	update_gizmo();
 	update_gizmo();
 }
 }
@@ -183,22 +235,34 @@ float CollisionPolygon::get_depth() const {
 void CollisionPolygon::_bind_methods() {
 void CollisionPolygon::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon::_add_to_collision_object);
 	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("set_depth","depth"),&CollisionPolygon::set_depth);
 	ObjectTypeDB::bind_method(_MD("get_depth"),&CollisionPolygon::get_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::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::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() {
 CollisionPolygon::CollisionPolygon() {
 
 
+	shape_from=-1;
+	shape_to=-1;
+	can_update_body=false;
+
 	aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
 	aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
 	build_mode=BUILD_SOLIDS;
 	build_mode=BUILD_SOLIDS;
 	depth=1.0;
 	depth=1.0;

+ 12 - 0
scene/3d/collision_polygon.h

@@ -24,9 +24,17 @@ protected:
 	BuildMode build_mode;
 	BuildMode build_mode;
 	Vector<Point2> polygon;
 	Vector<Point2> polygon;
 
 
+
 	void _add_to_collision_object(Object *p_obj);
 	void _add_to_collision_object(Object *p_obj);
 	void _update_parent();
 	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:
 protected:
 
 
 	void _notification(int p_what);
 	void _notification(int p_what);
@@ -43,6 +51,10 @@ public:
 	Vector<Point2> get_polygon() const;
 	Vector<Point2> get_polygon() const;
 
 
 	virtual AABB get_item_rect() 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();
 	CollisionPolygon();
 };
 };
 
 

+ 123 - 1
scene/3d/navigation_mesh.cpp

@@ -1,6 +1,6 @@
 #include "navigation_mesh.h"
 #include "navigation_mesh.h"
 #include "navigation.h"
 #include "navigation.h"
-
+#include "mesh_instance.h"
 
 
 void NavigationMesh::create_from_mesh(const Ref<Mesh>& p_mesh) {
 void NavigationMesh::create_from_mesh(const Ref<Mesh>& p_mesh) {
 
 
@@ -87,6 +87,97 @@ void NavigationMesh::clear_polygons(){
 	polygons.clear();
 	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() {
 void NavigationMesh::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("set_vertices","vertices"),&NavigationMesh::set_vertices);
 	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();
 	update_gizmo();
 }
 }
 
 
@@ -170,6 +271,19 @@ void NavigationMeshInstance::_notification(int p_what) {
 				c=c->get_parent_spatial();
 				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;
 		} break;
 		case NOTIFICATION_TRANSFORM_CHANGED: {
 		case NOTIFICATION_TRANSFORM_CHANGED: {
 
 
@@ -177,6 +291,8 @@ void NavigationMeshInstance::_notification(int p_what) {
 				navigation->navmesh_set_transform(nav_id,get_relative_transform(navigation));
 				navigation->navmesh_set_transform(nav_id,get_relative_transform(navigation));
 			}
 			}
 
 
+
+
 		} break;
 		} break;
 		case NOTIFICATION_EXIT_TREE: {
 		case NOTIFICATION_EXIT_TREE: {
 
 
@@ -187,6 +303,11 @@ void NavigationMeshInstance::_notification(int p_what) {
 					nav_id=-1;
 					nav_id=-1;
 				}
 				}
 			}
 			}
+
+			if (debug_view) {
+				debug_view->queue_delete();
+				debug_view=NULL;
+			}
 			navigation=NULL;
 			navigation=NULL;
 		} break;
 		} break;
 	}
 	}
@@ -230,6 +351,7 @@ void NavigationMeshInstance::_bind_methods() {
 
 
 NavigationMeshInstance::NavigationMeshInstance() {
 NavigationMeshInstance::NavigationMeshInstance() {
 
 
+	debug_view=NULL;
 	navigation=NULL;
 	navigation=NULL;
 	nav_id=-1;
 	nav_id=-1;
 	enabled=true;
 	enabled=true;

+ 17 - 0
scene/3d/navigation_mesh.h

@@ -4,6 +4,7 @@
 #include "scene/3d/spatial.h"
 #include "scene/3d/spatial.h"
 #include "scene/resources/mesh.h"
 #include "scene/resources/mesh.h"
 
 
+class Mesh;
 
 
 class NavigationMesh : public Resource  {
 class NavigationMesh : public Resource  {
 
 
@@ -14,6 +15,16 @@ class NavigationMesh : public Resource  {
 		Vector<int> indices;
 		Vector<int> indices;
 	};
 	};
 	Vector<Polygon> polygons;
 	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:
 protected:
 
 
@@ -21,6 +32,7 @@ protected:
 
 
 	void _set_polygons(const Array& p_array);
 	void _set_polygons(const Array& p_array);
 	Array _get_polygons() const;
 	Array _get_polygons() const;
+
 public:
 public:
 
 
 	void create_from_mesh(const Ref<Mesh>& p_mesh);
 	void create_from_mesh(const Ref<Mesh>& p_mesh);
@@ -33,6 +45,8 @@ public:
 	Vector<int> get_polygon(int p_idx);
 	Vector<int> get_polygon(int p_idx);
 	void clear_polygons();
 	void clear_polygons();
 
 
+	Ref<Mesh> get_debug_mesh();
+
 	NavigationMesh();
 	NavigationMesh();
 };
 };
 
 
@@ -47,6 +61,9 @@ class NavigationMeshInstance : public Spatial {
 	int nav_id;
 	int nav_id;
 	Navigation *navigation;
 	Navigation *navigation;
 	Ref<NavigationMesh> navmesh;
 	Ref<NavigationMesh> navmesh;
+
+	Node *debug_view;
+
 protected:
 protected:
 
 
 	void _notification(int p_what);
 	void _notification(int p_what);

+ 25 - 0
scene/3d/spatial.cpp

@@ -231,6 +231,11 @@ void Spatial::set_transform(const Transform& p_transform) {
 	_change_notify("transform/rotation");
 	_change_notify("transform/rotation");
 	_change_notify("transform/scale");
 	_change_notify("transform/scale");
 	_propagate_transform_changed(this);
 	_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;
 	data.local_transform.origin=p_translation;
 	_propagate_transform_changed(this);
 	_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.rotation=p_euler;
 	data.dirty|=DIRTY_LOCAL;
 	data.dirty|=DIRTY_LOCAL;
 	_propagate_transform_changed(this);
 	_propagate_transform_changed(this);
+	if (data.notify_local_transform) {
+		notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
+	}
 
 
 }
 }
 void Spatial::set_scale(const Vector3& p_scale){
 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.scale=p_scale;
 	data.dirty|=DIRTY_LOCAL;
 	data.dirty|=DIRTY_LOCAL;
 	_propagate_transform_changed(this);
 	_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() {
 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("_set_visible_"), &Spatial::_set_visible_);
 	ObjectTypeDB::bind_method(_MD("_is_visible_"), &Spatial::_is_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(const Vector3& p_normal,float p_radians);
 	void rotate_x(float p_radians);
 	void rotate_x(float p_radians);
 	void rotate_y(float p_radians);
 	void rotate_y(float p_radians);
@@ -783,6 +807,7 @@ Spatial::Spatial() : xform_change(this)
 	data.gizmo_disabled=false;
 	data.gizmo_disabled=false;
 	data.gizmo_dirty=false;
 	data.gizmo_dirty=false;
 #endif
 #endif
+	data.notify_local_transform=false;
 	data.parent=NULL;
 	data.parent=NULL;
 	data.C=NULL;
 	data.C=NULL;
 
 

+ 5 - 0
scene/3d/spatial.h

@@ -91,6 +91,7 @@ class Spatial : public Node {
 		List<Spatial*>::Element *C;
 		List<Spatial*>::Element *C;
 		
 		
 		bool ignore_notification;
 		bool ignore_notification;
+		bool notify_local_transform;
 
 
 		bool visible;
 		bool visible;
 
 
@@ -134,6 +135,7 @@ public:
 		NOTIFICATION_ENTER_WORLD=41,
 		NOTIFICATION_ENTER_WORLD=41,
 		NOTIFICATION_EXIT_WORLD=42,
 		NOTIFICATION_EXIT_WORLD=42,
 		NOTIFICATION_VISIBILITY_CHANGED=43,
 		NOTIFICATION_VISIBILITY_CHANGED=43,
+		NOTIFICATION_LOCAL_TRANSFORM_CHANGED=44,
 	};
 	};
 
 
 	Spatial *get_parent_spatial() const;
 	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(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 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 orthonormalize();
 	void set_identity();
 	void set_identity();
 
 

+ 177 - 2
scene/main/scene_main_loop.cpp

@@ -42,6 +42,8 @@
 #include "io/resource_loader.h"
 #include "io/resource_loader.h"
 #include "viewport.h"
 #include "viewport.h"
 #include "scene/resources/packed_scene.h"
 #include "scene/resources/packed_scene.h"
+#include "scene/resources/material.h"
+#include "scene/resources/mesh.h"
 
 
 void SceneTree::tree_changed() {
 void SceneTree::tree_changed() {
 
 
@@ -470,8 +472,6 @@ void SceneTree::init() {
 	input_handled=false;
 	input_handled=false;
 
 
 
 
-	editor_hint=false;
-	debug_collisions_hint=false;
 	pause=false;
 	pause=false;
 
 
 	root->_set_tree(this);
 	root->_set_tree(this);
@@ -635,6 +635,165 @@ bool SceneTree::is_debugging_collisions_hint() const {
 	return debug_collisions_hint;
 	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) {
 void SceneTree::set_pause(bool p_enabled) {
 
 
 	if (p_enabled==pause)
 	if (p_enabled==pause)
@@ -1437,6 +1596,9 @@ void SceneTree::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("is_editor_hint"),&SceneTree::is_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("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("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
 #ifdef TOOLS_ENABLED
 	ObjectTypeDB::bind_method(_MD("set_edited_scene_root","scene"),&SceneTree::set_edited_scene_root);
 	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);
 	ObjectTypeDB::bind_method(_MD("get_edited_scene_root"),&SceneTree::get_edited_scene_root);
@@ -1503,10 +1665,23 @@ void SceneTree::_bind_methods() {
 
 
 }
 }
 
 
+SceneTree *SceneTree::singleton=NULL;
+
 SceneTree::SceneTree() {
 SceneTree::SceneTree() {
 
 
+	singleton=this;
 	_quit=false;
 	_quit=false;
 	initialized=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;
 	tree_version=1;
 	fixed_process_time=1;
 	fixed_process_time=1;
 	idle_process_time=1;
 	idle_process_time=1;

+ 38 - 0
scene/main/scene_main_loop.h

@@ -45,6 +45,8 @@ class SceneTree;
 class PackedScene;
 class PackedScene;
 class Node;
 class Node;
 class Viewport;
 class Viewport;
+class Material;
+class Mesh;
 
 
 class SceneTree : public MainLoop {
 class SceneTree : public MainLoop {
 
 
@@ -88,6 +90,7 @@ private:
 
 
 	bool editor_hint;
 	bool editor_hint;
 	bool debug_collisions_hint;
 	bool debug_collisions_hint;
+	bool debug_navigation_hint;
 	bool pause;
 	bool pause;
 	int root_lock;
 	int root_lock;
 
 
@@ -139,9 +142,20 @@ private:
 
 
 	Node *current_scene;
 	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 _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);
 	//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;
 friend class Node;
 
 
 	void tree_changed();
 	void tree_changed();
@@ -274,6 +288,29 @@ public:
 	void set_debug_collisions_hint(bool p_enabled);
 	void set_debug_collisions_hint(bool p_enabled);
 	bool is_debugging_collisions_hint() const;
 	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;
 	int64_t get_frame() const;
 
 
 	int get_node_count() const;
 	int get_node_count() const;
@@ -301,6 +338,7 @@ public:
 	//used by Main::start, don't use otherwise
 	//used by Main::start, don't use otherwise
 	void add_current_scene(Node * p_current);
 	void add_current_scene(Node * p_current);
 
 
+	static SceneTree* get_singleton() { return singleton; }
 
 
 
 
 	SceneTree();
 	SceneTree();

+ 78 - 1
scene/main/viewport.cpp

@@ -37,6 +37,7 @@
 #include "servers/spatial_sound_2d_server.h"
 #include "servers/spatial_sound_2d_server.h"
 #include "scene/gui/control.h"
 #include "scene/gui/control.h"
 #include "scene/3d/camera.h"
 #include "scene/3d/camera.h"
+#include "scene/resources/mesh.h"
 #include "scene/3d/spatial_indexer.h"
 #include "scene/3d/spatial_indexer.h"
 #include "scene/3d/collision_object.h"
 #include "scene/3d/collision_object.h"
 
 
@@ -318,7 +319,23 @@ void Viewport::_notification(int p_what) {
 //				update_worlds();
 //				update_worlds();
 			}
 			}
 
 
-			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;
 		} break;
 		case NOTIFICATION_READY: {
 		case NOTIFICATION_READY: {
@@ -351,11 +368,69 @@ void Viewport::_notification(int p_what) {
 			VisualServer::get_singleton()->viewport_set_scenario(viewport,RID());
 			VisualServer::get_singleton()->viewport_set_scenario(viewport,RID());
 			SpatialSoundServer::get_singleton()->listener_set_space(listener,RID());
 			SpatialSoundServer::get_singleton()->listener_set_space(listener,RID());
 			VisualServer::get_singleton()->viewport_remove_canvas(viewport,current_canvas);
 			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");
 			remove_from_group("_viewports");
 
 
 		} break;
 		} break;
 		case NOTIFICATION_FIXED_PROCESS: {
 		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) {
 			if (physics_object_picking) {
 
 
 				Vector2 last_pos(1e20,1e20);
 				Vector2 last_pos(1e20,1e20);
@@ -1449,6 +1524,8 @@ Viewport::Viewport() {
 	unhandled_key_input_group = "_vp_unhandled_key_input"+id;
 	unhandled_key_input_group = "_vp_unhandled_key_input"+id;
 
 
 
 
+
+
 }
 }
 
 
 
 

+ 5 - 0
scene/main/viewport.h

@@ -104,6 +104,11 @@ friend class RenderTargetTexture;
 	Rect2 rect;
 	Rect2 rect;
 	Rect2 to_screen_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;
 	bool size_override_stretch;
 	bool size_override_stretch;

+ 6 - 4
scene/register_scene_types.cpp

@@ -458,7 +458,6 @@ void register_scene_types() {
 
 
 
 
 	/* disable types by default, only editors should enable them */
 	/* 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("BodyVolumeSphere",false);
 	//ObjectTypeDB::set_type_enabled("BodyVolumeBox",false);
 	//ObjectTypeDB::set_type_enabled("BodyVolumeBox",false);
 	//ObjectTypeDB::set_type_enabled("BodyVolumeCapsule",false);
 	//ObjectTypeDB::set_type_enabled("BodyVolumeCapsule",false);
@@ -492,9 +491,12 @@ void register_scene_types() {
 	ObjectTypeDB::register_type<OccluderPolygon2D>();
 	ObjectTypeDB::register_type<OccluderPolygon2D>();
 	ObjectTypeDB::register_type<YSort>();
 	ObjectTypeDB::register_type<YSort>();
 	ObjectTypeDB::register_type<BackBufferCopy>();
 	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
 	OS::get_singleton()->yield(); //may take time to init
 
 

+ 19 - 0
scene/resources/box_shape.cpp

@@ -30,6 +30,25 @@
 #include "servers/physics_server.h"
 #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() {
 void BoxShape::_update_shape() {
 
 
 	PhysicsServer::get_singleton()->shape_set_data(get_shape(),extents);
 	PhysicsServer::get_singleton()->shape_set_data(get_shape(),extents);

+ 1 - 0
scene/resources/box_shape.h

@@ -41,6 +41,7 @@ protected:
 	static void _bind_methods();
 	static void _bind_methods();
 
 
 	virtual void _update_shape();
 	virtual void _update_shape();
+	virtual Vector<Vector3> _gen_debug_mesh_lines();
 
 
 public:
 public:
 
 

+ 40 - 1
scene/resources/capsule_shape.cpp

@@ -30,6 +30,46 @@
 #include "servers/physics_server.h"
 #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() {
 void CapsuleShape::_update_shape() {
 
 
@@ -65,7 +105,6 @@ float CapsuleShape::get_height() const {
 	return height;
 	return height;
 }
 }
 
 
-
 void CapsuleShape::_bind_methods() {
 void CapsuleShape::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("set_radius","radius"),&CapsuleShape::set_radius);
 	ObjectTypeDB::bind_method(_MD("set_radius","radius"),&CapsuleShape::set_radius);

+ 2 - 0
scene/resources/capsule_shape.h

@@ -43,6 +43,7 @@ protected:
 
 
 	virtual void _update_shape();
 	virtual void _update_shape();
 
 
+	virtual Vector<Vector3> _gen_debug_mesh_lines();
 public:
 public:
 
 
 	void set_radius(float p_radius);
 	void set_radius(float p_radius);
@@ -50,6 +51,7 @@ public:
 	void set_height(float p_height);
 	void set_height(float p_height);
 	float get_height() const;
 	float get_height() const;
 
 
+
 	CapsuleShape();
 	CapsuleShape();
 };
 };
 
 

+ 27 - 0
scene/resources/capsule_shape_2d.cpp

@@ -29,6 +29,7 @@
 #include "capsule_shape_2d.h"
 #include "capsule_shape_2d.h"
 
 
 #include "servers/physics_2d_server.h"
 #include "servers/physics_2d_server.h"
+#include "servers/visual_server.h"
 
 
 void CapsuleShape2D::_update_shape() {
 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() {
 void CapsuleShape2D::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("set_radius","radius"),&CapsuleShape2D::set_radius);
 	ObjectTypeDB::bind_method(_MD("set_radius","radius"),&CapsuleShape2D::set_radius);

+ 3 - 0
scene/resources/capsule_shape_2d.h

@@ -49,6 +49,9 @@ public:
 	void set_radius(real_t p_radius);
 	void set_radius(real_t p_radius);
 	real_t get_radius() const;
 	real_t get_radius() const;
 
 
+	virtual void draw(const RID& p_to_rid,const Color& p_color);
+	virtual Rect2 get_rect() const ;
+
 	CapsuleShape2D();
 	CapsuleShape2D();
 };
 };
 
 

+ 22 - 1
scene/resources/circle_shape_2d.cpp

@@ -29,7 +29,7 @@
 #include "circle_shape_2d.h"
 #include "circle_shape_2d.h"
 
 
 #include "servers/physics_2d_server.h"
 #include "servers/physics_2d_server.h"
-
+#include "servers/visual_server.h"
 void CircleShape2D::_update_shape() {
 void CircleShape2D::_update_shape() {
 
 
 	Physics2DServer::get_singleton()->shape_set_data(get_rid(),radius);
 	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)) {
 CircleShape2D::CircleShape2D() : Shape2D( Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CIRCLE)) {
 
 
 	radius=10;
 	radius=10;

+ 4 - 0
scene/resources/circle_shape_2d.h

@@ -44,6 +44,10 @@ public:
 	void set_radius(real_t p_radius);
 	void set_radius(real_t p_radius);
 	real_t get_radius() const;
 	real_t get_radius() const;
 
 
+	virtual void draw(const RID& p_to_rid,const Color& p_color);
+	virtual Rect2 get_rect() const;
+
+
 	CircleShape2D();
 	CircleShape2D();
 };
 };
 
 

+ 34 - 0
scene/resources/concave_polygon_shape.cpp

@@ -30,6 +30,40 @@
 
 
 #include "servers/physics_server.h"
 #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) {
 bool ConcavePolygonShape::_set(const StringName& p_name, const Variant& p_value) {
 
 
 	if (p_name=="data")
 	if (p_name=="data")

+ 21 - 1
scene/resources/concave_polygon_shape.h

@@ -35,16 +35,36 @@ class ConcavePolygonShape : public Shape {
 
 
 	OBJ_TYPE(ConcavePolygonShape,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:
 protected:
 
 
+
 	bool _set(const StringName& p_name, const Variant& p_value);
 	bool _set(const StringName& p_name, const Variant& p_value);
 	bool _get(const StringName& p_name,Variant &r_ret) const;
 	bool _get(const StringName& p_name,Variant &r_ret) const;
 	void _get_property_list( List<PropertyInfo> *p_list) const;
 	void _get_property_list( List<PropertyInfo> *p_list) const;
 	static void _bind_methods();
 	static void _bind_methods();
 
 
 	virtual void _update_shape();
 	virtual void _update_shape();
-
+	virtual Vector<Vector3> _gen_debug_mesh_lines();
 public:
 public:
 
 
 	void set_faces(const DVector<Vector3>& p_faces);
 	void set_faces(const DVector<Vector3>& p_faces);

+ 38 - 1
scene/resources/concave_polygon_shape_2d.cpp

@@ -29,7 +29,7 @@
 #include "concave_polygon_shape_2d.h"
 #include "concave_polygon_shape_2d.h"
 
 
 #include "servers/physics_2d_server.h"
 #include "servers/physics_2d_server.h"
-
+#include "servers/visual_server.h"
 
 
 void ConcavePolygonShape2D::set_segments(const DVector<Vector2>& p_segments) {
 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());
 	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() {
 void ConcavePolygonShape2D::_bind_methods() {
 
 

+ 3 - 0
scene/resources/concave_polygon_shape_2d.h

@@ -41,6 +41,9 @@ public:
 	void set_segments(const DVector<Vector2>& p_segments);
 	void set_segments(const DVector<Vector2>& p_segments);
 	DVector<Vector2> get_segments() const;
 	DVector<Vector2> get_segments() const;
 
 
+	virtual void draw(const RID& p_to_rid,const Color& p_color);
+	virtual Rect2 get_rect() const ;
+
 	ConcavePolygonShape2D();
 	ConcavePolygonShape2D();
 };
 };
 
 

+ 27 - 0
scene/resources/convex_polygon_shape.cpp

@@ -28,7 +28,34 @@
 /*************************************************************************/
 /*************************************************************************/
 #include "convex_polygon_shape.h"
 #include "convex_polygon_shape.h"
 #include "servers/physics_server.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() {
 void ConvexPolygonShape::_update_shape() {

+ 1 - 0
scene/resources/convex_polygon_shape.h

@@ -42,6 +42,7 @@ protected:
 
 
 	virtual void _update_shape();
 	virtual void _update_shape();
 
 
+	virtual Vector<Vector3> _gen_debug_mesh_lines();
 public:
 public:
 
 
 	void set_points(const DVector<Vector3>& p_points);
 	void set_points(const DVector<Vector3>& p_points);

+ 24 - 1
scene/resources/convex_polygon_shape_2d.cpp

@@ -29,7 +29,7 @@
 #include "convex_polygon_shape_2d.h"
 #include "convex_polygon_shape_2d.h"
 
 
 #include "servers/physics_2d_server.h"
 #include "servers/physics_2d_server.h"
-
+#include "servers/visual_server.h"
 void ConvexPolygonShape2D::_update_shape() {
 void ConvexPolygonShape2D::_update_shape() {
 
 
 	Physics2DServer::get_singleton()->shape_set_data(get_rid(),points);
 	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)) {
 ConvexPolygonShape2D::ConvexPolygonShape2D() : Shape2D( Physics2DServer::get_singleton()->shape_create(Physics2DServer::SHAPE_CONVEX_POLYGON)) {
 
 
 
 

+ 3 - 0
scene/resources/convex_polygon_shape_2d.h

@@ -45,6 +45,9 @@ public:
 	void set_points(const Vector<Vector2>& p_points);
 	void set_points(const Vector<Vector2>& p_points);
 	Vector<Vector2> get_points() const;
 	Vector<Vector2> get_points() const;
 
 
+	virtual void draw(const RID& p_to_rid,const Color& p_color);
+	virtual Rect2 get_rect() const ;
+
 	ConvexPolygonShape2D();
 	ConvexPolygonShape2D();
 };
 };
 
 

+ 28 - 1
scene/resources/plane_shape.cpp

@@ -30,7 +30,34 @@
 
 
 #include "servers/physics_server.h"
 #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() {
 void PlaneShape::_update_shape() {
 
 

+ 1 - 1
scene/resources/plane_shape.h

@@ -39,9 +39,9 @@ class PlaneShape : public Shape {
 protected:
 protected:
 
 
 	static void _bind_methods();
 	static void _bind_methods();
-
 	virtual void _update_shape();
 	virtual void _update_shape();
 
 
+	virtual Vector<Vector3> _gen_debug_mesh_lines();
 public:
 public:
 
 
 	void set_plane(Plane p_plane);
 	void set_plane(Plane p_plane);

+ 7 - 0
scene/resources/ray_shape.cpp

@@ -30,7 +30,14 @@
 
 
 #include "servers/physics_server.h"
 #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() {
 void RayShape::_update_shape() {
 
 

+ 1 - 1
scene/resources/ray_shape.h

@@ -39,7 +39,7 @@ protected:
 
 
 	static void _bind_methods();
 	static void _bind_methods();
 	virtual void _update_shape();
 	virtual void _update_shape();
-
+	virtual Vector<Vector3> _gen_debug_mesh_lines();
 public:
 public:
 
 
 	void set_length(float p_length);
 	void set_length(float p_length);

+ 14 - 1
scene/resources/rectangle_shape_2d.cpp

@@ -29,7 +29,7 @@
 #include "rectangle_shape_2d.h"
 #include "rectangle_shape_2d.h"
 
 
 #include "servers/physics_2d_server.h"
 #include "servers/physics_2d_server.h"
-
+#include "servers/visual_server.h"
 void RectangleShape2D::_update_shape() {
 void RectangleShape2D::_update_shape() {
 
 
 	Physics2DServer::get_singleton()->shape_set_data(get_rid(),extents);
 	Physics2DServer::get_singleton()->shape_set_data(get_rid(),extents);
@@ -48,6 +48,19 @@ Vector2 RectangleShape2D::get_extents() const {
 	return extents;
 	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 {
+
+	Rect2(-extents,extents*2.0);
+
+}
+
 
 
 void RectangleShape2D::_bind_methods() {
 void RectangleShape2D::_bind_methods() {
 
 

+ 3 - 0
scene/resources/rectangle_shape_2d.h

@@ -44,6 +44,9 @@ public:
 	void set_extents(const Vector2& p_extents);
 	void set_extents(const Vector2& p_extents);
 	Vector2 get_extents() const;
 	Vector2 get_extents() const;
 
 
+	virtual void draw(const RID& p_to_rid,const Color& p_color);
+	virtual Rect2 get_rect() const ;
+
 	RectangleShape2D();
 	RectangleShape2D();
 };
 };
 
 

+ 49 - 0
scene/resources/segment_shape_2d.cpp

@@ -29,6 +29,7 @@
 #include "segment_shape_2d.h"
 #include "segment_shape_2d.h"
 
 
 #include "servers/physics_2d_server.h"
 #include "servers/physics_2d_server.h"
+#include "servers/visual_server.h"
 
 
 void SegmentShape2D::_update_shape() {
 void SegmentShape2D::_update_shape() {
 
 
@@ -62,6 +63,23 @@ Vector2 SegmentShape2D::get_b() const {
 	return b;
 	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() {
 void SegmentShape2D::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("set_a","a"),&SegmentShape2D::set_a);
 	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() {
 void RayShape2D::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("set_length","length"),&RayShape2D::set_length);
 	ObjectTypeDB::bind_method(_MD("set_length","length"),&RayShape2D::set_length);

+ 5 - 0
scene/resources/segment_shape_2d.h

@@ -49,6 +49,9 @@ public:
 	Vector2 get_a() const;
 	Vector2 get_a() const;
 	Vector2 get_b() const;
 	Vector2 get_b() const;
 
 
+	virtual void draw(const RID& p_to_rid,const Color& p_color);
+	virtual Rect2 get_rect() const;
+
 	SegmentShape2D();
 	SegmentShape2D();
 };
 };
 
 
@@ -67,6 +70,8 @@ public:
 
 
 	void set_length(real_t p_length);
 	void set_length(real_t p_length);
 	real_t get_length() const;
 	real_t get_length() const;
+	virtual void draw(const RID& p_to_rid,const Color& p_color);
+	virtual Rect2 get_rect() const;
 
 
 	RayShape2D();
 	RayShape2D();
 };
 };

+ 59 - 0
scene/resources/shape.cpp

@@ -29,9 +29,67 @@
 #include "shape.h"
 #include "shape.h"
 
 
 #include "servers/physics_server.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() {
 Shape::Shape() {
 
 
@@ -49,3 +107,4 @@ Shape::~Shape() {
 
 
 	PhysicsServer::get_singleton()->free(shape);
 	PhysicsServer::get_singleton()->free(shape);
 }
 }
+

+ 10 - 0
scene/resources/shape.h

@@ -30,6 +30,7 @@
 #define SHAPE_H
 #define SHAPE_H
 
 
 #include "resource.h"
 #include "resource.h"
+class Mesh;
 
 
 class Shape : public Resource {
 class Shape : public Resource {
 
 
@@ -38,13 +39,22 @@ class Shape : public Resource {
 	RES_BASE_EXTENSION("shp");
 	RES_BASE_EXTENSION("shp");
 	RID shape;
 	RID shape;
 
 
+	Ref<Mesh> debug_mesh_cache;
+
 protected:
 protected:
 
 
 	_FORCE_INLINE_ RID get_shape() const { return shape; }
 	_FORCE_INLINE_ RID get_shape() const { return shape; }
 	Shape(RID p_shape);
 	Shape(RID p_shape);
+
+	virtual Vector<Vector3> _gen_debug_mesh_lines()=0;// { return Vector<Vector3>(); }
 public:
 public:
 
 
 	virtual RID get_rid() const { return shape; }
 	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();
 	~Shape();
 	~Shape();
 };
 };

+ 2 - 0
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_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);
 	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;
 	virtual RID get_rid() const;
 	Shape2D();
 	Shape2D();
 	~Shape2D();
 	~Shape2D();

+ 27 - 1
scene/resources/shape_line_2d.cpp

@@ -28,7 +28,7 @@
 /*************************************************************************/
 /*************************************************************************/
 #include "shape_line_2d.h"
 #include "shape_line_2d.h"
 #include "servers/physics_2d_server.h"
 #include "servers/physics_2d_server.h"
-
+#include "servers/visual_server.h"
 void LineShape2D::_update_shape() {
 void LineShape2D::_update_shape() {
 
 
 	Array arr;
 	Array arr;
@@ -61,6 +61,32 @@ real_t LineShape2D::get_d() const {
 	return d;
 	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() {
 void LineShape2D::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("set_normal","normal"),&LineShape2D::set_normal);
 	ObjectTypeDB::bind_method(_MD("set_normal","normal"),&LineShape2D::set_normal);

+ 3 - 0
scene/resources/shape_line_2d.h

@@ -49,6 +49,9 @@ public:
 	Vector2 get_normal() const;
 	Vector2 get_normal() const;
 	real_t get_d() const;
 	real_t get_d() const;
 
 
+	virtual void draw(const RID& p_to_rid,const Color& p_color);
+	virtual Rect2 get_rect() const;
+
 	LineShape2D();
 	LineShape2D();
 };
 };
 
 

+ 24 - 0
scene/resources/sphere_shape.cpp

@@ -29,6 +29,30 @@
 #include "sphere_shape.h"
 #include "sphere_shape.h"
 #include "servers/physics_server.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() {
 void SphereShape::_update_shape() {
 
 

+ 1 - 1
scene/resources/sphere_shape.h

@@ -42,7 +42,7 @@ protected:
 	static void _bind_methods();
 	static void _bind_methods();
 
 
 	virtual void _update_shape();
 	virtual void _update_shape();
-
+	virtual Vector<Vector3> _gen_debug_mesh_lines();
 public:
 public:
 
 
 	void set_radius(float p_radius);
 	void set_radius(float p_radius);

+ 10 - 0
servers/physics/body_pair_sw.cpp

@@ -299,6 +299,16 @@ bool BodyPairSW::setup(float p_step) {
 
 
 		c.active=true;
 		c.active=true;
 
 
+#ifdef DEBUG_ENABLED
+
+
+		if (space->is_debugging_contacts()) {
+			space->add_debug_contact(global_A+offset_A);
+			space->add_debug_contact(global_B+offset_A);
+		}
+#endif
+
+
 		int gather_A = A->can_report_contacts();
 		int gather_A = A->can_report_contacts();
 		int gather_B = B->can_report_contacts();
 		int gather_B = B->can_report_contacts();
 
 

+ 24 - 0
servers/physics/physics_server_sw.cpp

@@ -201,6 +201,30 @@ PhysicsDirectSpaceState* PhysicsServerSW::space_get_direct_state(RID p_space) {
 	return space->get_direct_state();
 	return space->get_direct_state();
 }
 }
 
 
+void PhysicsServerSW::space_set_debug_contacts(RID p_space,int p_max_contacts) {
+
+	SpaceSW *space = space_owner.get(p_space);
+	ERR_FAIL_COND(!space);
+	space->set_debug_contacts(p_max_contacts);
+
+}
+
+Vector<Vector3> PhysicsServerSW::space_get_contacts(RID p_space) const {
+
+	SpaceSW *space = space_owner.get(p_space);
+	ERR_FAIL_COND_V(!space,Vector<Vector3>());
+	return space->get_debug_contacts();
+
+}
+
+int PhysicsServerSW::space_get_contact_count(RID p_space) const {
+
+	SpaceSW *space = space_owner.get(p_space);
+	ERR_FAIL_COND_V(!space,0);
+	return space->get_debug_contact_count();
+
+}
+
 RID PhysicsServerSW::area_create() {
 RID PhysicsServerSW::area_create() {
 
 
 	AreaSW *area = memnew( AreaSW );
 	AreaSW *area = memnew( AreaSW );

+ 3 - 0
servers/physics/physics_server_sw.h

@@ -94,6 +94,9 @@ public:
 	// this function only works on fixed process, errors and returns null otherwise
 	// this function only works on fixed process, errors and returns null otherwise
 	virtual PhysicsDirectSpaceState* space_get_direct_state(RID p_space);
 	virtual PhysicsDirectSpaceState* space_get_direct_state(RID p_space);
 
 
+	virtual void space_set_debug_contacts(RID p_space,int p_max_contacts);
+	virtual Vector<Vector3> space_get_contacts(RID p_space) const;
+	virtual int space_get_contact_count(RID p_space) const;
 
 
 	/* AREA API */
 	/* AREA API */
 
 

+ 3 - 1
servers/physics/space_sw.cpp

@@ -640,7 +640,7 @@ void SpaceSW::call_queries() {
 
 
 void SpaceSW::setup() {
 void SpaceSW::setup() {
 
 
-
+	contact_debug_count=0;
 	while(inertia_update_list.first()) {
 	while(inertia_update_list.first()) {
 		inertia_update_list.first()->self()->update_inertias();
 		inertia_update_list.first()->self()->update_inertias();
 		inertia_update_list.remove(inertia_update_list.first());
 		inertia_update_list.remove(inertia_update_list.first());
@@ -651,6 +651,7 @@ void SpaceSW::setup() {
 
 
 void SpaceSW::update() {
 void SpaceSW::update() {
 
 
+
 	broadphase->update();
 	broadphase->update();
 
 
 }
 }
@@ -712,6 +713,7 @@ SpaceSW::SpaceSW() {
 	collision_pairs=0;
 	collision_pairs=0;
 	active_objects=0;
 	active_objects=0;
 	island_count=0;
 	island_count=0;
+	contact_debug_count=0;
 
 
 	locked=false;
 	locked=false;
 	contact_recycle_radius=0.01;
 	contact_recycle_radius=0.01;

+ 8 - 0
servers/physics/space_sw.h

@@ -103,6 +103,9 @@ class SpaceSW {
 
 
 	RID static_global_body;
 	RID static_global_body;
 
 
+	Vector<Vector3> contact_debug;
+	int contact_debug_count;
+
 friend class PhysicsDirectSpaceStateSW;
 friend class PhysicsDirectSpaceStateSW;
 
 
 public:
 public:
@@ -166,6 +169,11 @@ public:
 
 
 	PhysicsDirectSpaceStateSW *get_direct_state();
 	PhysicsDirectSpaceStateSW *get_direct_state();
 
 
+	void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
+	_FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); }
+	_FORCE_INLINE_ void add_debug_contact(const Vector3& p_contact) { if (contact_debug_count<contact_debug.size()) contact_debug[contact_debug_count++]=p_contact; }
+	_FORCE_INLINE_ Vector<Vector3> get_debug_contacts() { return contact_debug; }
+	_FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; }
 
 
 	void set_static_global_body(RID p_body) { static_global_body=p_body; }
 	void set_static_global_body(RID p_body) { static_global_body=p_body; }
 	RID get_static_global_body() { return static_global_body; }
 	RID get_static_global_body() { return static_global_body; }

+ 6 - 1
servers/physics_2d/body_pair_2d_sw.cpp

@@ -379,7 +379,12 @@ bool BodyPair2DSW::setup(float p_step) {
 		}
 		}
 
 
 		c.active=true;
 		c.active=true;
-
+#ifdef DEBUG_ENABLED
+		if (space->is_debugging_contacts()) {
+			space->add_debug_contact(global_A+offset_A);
+			space->add_debug_contact(global_B+offset_A);
+		}
+#endif
 		int gather_A = A->can_report_contacts();
 		int gather_A = A->can_report_contacts();
 		int gather_B = B->can_report_contacts();
 		int gather_B = B->can_report_contacts();
 
 

+ 24 - 0
servers/physics_2d/physics_2d_server_sw.cpp

@@ -257,6 +257,30 @@ real_t Physics2DServerSW::space_get_param(RID p_space,SpaceParameter p_param) co
 	return space->get_param(p_param);
 	return space->get_param(p_param);
 }
 }
 
 
+void Physics2DServerSW::space_set_debug_contacts(RID p_space,int p_max_contacts) {
+
+	Space2DSW *space = space_owner.get(p_space);
+	ERR_FAIL_COND(!space);
+	space->set_debug_contacts(p_max_contacts);
+
+}
+
+Vector<Vector2> Physics2DServerSW::space_get_contacts(RID p_space) const {
+
+	Space2DSW *space = space_owner.get(p_space);
+	ERR_FAIL_COND_V(!space,Vector<Vector2>());
+	return space->get_debug_contacts();
+
+}
+
+int Physics2DServerSW::space_get_contact_count(RID p_space) const {
+
+	Space2DSW *space = space_owner.get(p_space);
+	ERR_FAIL_COND_V(!space,0);
+	return space->get_debug_contact_count();
+
+}
+
 Physics2DDirectSpaceState* Physics2DServerSW::space_get_direct_state(RID p_space) {
 Physics2DDirectSpaceState* Physics2DServerSW::space_get_direct_state(RID p_space) {
 
 
 	Space2DSW *space = space_owner.get(p_space);
 	Space2DSW *space = space_owner.get(p_space);

+ 5 - 0
servers/physics_2d/physics_2d_server_sw.h

@@ -102,6 +102,11 @@ public:
 	virtual void space_set_param(RID p_space,SpaceParameter p_param, real_t p_value);
 	virtual void space_set_param(RID p_space,SpaceParameter p_param, real_t p_value);
 	virtual real_t space_get_param(RID p_space,SpaceParameter p_param) const;
 	virtual real_t space_get_param(RID p_space,SpaceParameter p_param) const;
 
 
+	virtual void space_set_debug_contacts(RID p_space,int p_max_contacts);
+	virtual Vector<Vector2> space_get_contacts(RID p_space) const;
+	virtual int space_get_contact_count(RID p_space) const;
+
+
 	// this function only works on fixed process, errors and returns null otherwise
 	// this function only works on fixed process, errors and returns null otherwise
 	virtual Physics2DDirectSpaceState* space_get_direct_state(RID p_space);
 	virtual Physics2DDirectSpaceState* space_get_direct_state(RID p_space);
 
 

+ 16 - 0
servers/physics_2d/physics_2d_server_wrap_mt.h

@@ -94,6 +94,22 @@ public:
 		return physics_2d_server->space_get_direct_state(p_space);
 		return physics_2d_server->space_get_direct_state(p_space);
 	}
 	}
 
 
+	FUNC2(space_set_debug_contacts,RID,int);
+	virtual Vector<Vector2> space_get_contacts(RID p_space) const {
+
+		ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),Vector<Vector2>());
+		return physics_2d_server->space_get_contacts(p_space);
+
+	}
+
+	virtual int space_get_contact_count(RID p_space) const {
+
+		ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),0);
+		return physics_2d_server->space_get_contact_count(p_space);
+
+	}
+
+
 
 
 	/* AREA API */
 	/* AREA API */
 
 

+ 7 - 0
servers/physics_2d/space_2d_sw.cpp

@@ -1230,6 +1230,7 @@ void Space2DSW::call_queries() {
 
 
 void Space2DSW::setup() {
 void Space2DSW::setup() {
 
 
+	contact_debug_count=0;
 
 
 	while(inertia_update_list.first()) {
 	while(inertia_update_list.first()) {
 		inertia_update_list.first()->self()->update_inertias();
 		inertia_update_list.first()->self()->update_inertias();
@@ -1302,6 +1303,8 @@ Space2DSW::Space2DSW() {
 	active_objects=0;
 	active_objects=0;
 	island_count=0;
 	island_count=0;
 
 
+	contact_debug_count=0;
+
 	locked=false;
 	locked=false;
 	contact_recycle_radius=0.01;
 	contact_recycle_radius=0.01;
 	contact_max_separation=0.05;
 	contact_max_separation=0.05;
@@ -1320,6 +1323,10 @@ Space2DSW::Space2DSW() {
 
 
 	direct_access = memnew( Physics2DDirectSpaceStateSW );
 	direct_access = memnew( Physics2DDirectSpaceStateSW );
 	direct_access->space=this;
 	direct_access->space=this;
+
+
+
+
 }
 }
 
 
 Space2DSW::~Space2DSW() {
 Space2DSW::~Space2DSW() {

+ 11 - 0
servers/physics_2d/space_2d_sw.h

@@ -103,6 +103,9 @@ class Space2DSW {
 
 
 	int _cull_aabb_for_body(Body2DSW *p_body,const Rect2& p_aabb);
 	int _cull_aabb_for_body(Body2DSW *p_body,const Rect2& p_aabb);
 
 
+	Vector<Vector2> contact_debug;
+	int contact_debug_count;
+
 friend class Physics2DDirectSpaceStateSW;
 friend class Physics2DDirectSpaceStateSW;
 
 
 public:
 public:
@@ -169,6 +172,14 @@ public:
 
 
 	bool test_body_motion(Body2DSW *p_body, const Vector2&p_motion, float p_margin, Physics2DServer::MotionResult *r_result);
 	bool test_body_motion(Body2DSW *p_body, const Vector2&p_motion, float p_margin, Physics2DServer::MotionResult *r_result);
 
 
+
+	void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
+	_FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); }
+	_FORCE_INLINE_ void add_debug_contact(const Vector2& p_contact) { if (contact_debug_count<contact_debug.size()) contact_debug[contact_debug_count++]=p_contact; }
+	_FORCE_INLINE_ Vector<Vector2> get_debug_contacts() { return contact_debug; }
+	_FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; }
+
+
 	Physics2DDirectSpaceStateSW *get_direct_state();
 	Physics2DDirectSpaceStateSW *get_direct_state();
 
 
 	Space2DSW();
 	Space2DSW();

+ 3 - 0
servers/physics_2d_server.h

@@ -293,6 +293,9 @@ public:
 	// this function only works on fixed process, errors and returns null otherwise
 	// this function only works on fixed process, errors and returns null otherwise
 	virtual Physics2DDirectSpaceState* space_get_direct_state(RID p_space)=0;
 	virtual Physics2DDirectSpaceState* space_get_direct_state(RID p_space)=0;
 
 
+	virtual void space_set_debug_contacts(RID p_space,int p_max_contacts)=0;
+	virtual Vector<Vector2> space_get_contacts(RID p_space) const=0;
+	virtual int space_get_contact_count(RID p_space) const=0;
 
 
 	//missing space parameters
 	//missing space parameters
 
 

+ 3 - 0
servers/physics_server.h

@@ -286,6 +286,9 @@ public:
 	// this function only works on fixed process, errors and returns null otherwise
 	// this function only works on fixed process, errors and returns null otherwise
 	virtual PhysicsDirectSpaceState* space_get_direct_state(RID p_space)=0;
 	virtual PhysicsDirectSpaceState* space_get_direct_state(RID p_space)=0;
 
 
+	virtual void space_set_debug_contacts(RID p_space,int p_max_contacts)=0;
+	virtual Vector<Vector3> space_get_contacts(RID p_space) const=0;
+	virtual int space_get_contact_count(RID p_space) const=0;
 
 
 	//missing space parameters
 	//missing space parameters
 
 

+ 3 - 0
servers/visual/rasterizer_dummy.cpp

@@ -1948,6 +1948,9 @@ bool RasterizerDummy::has_feature(VS::Features p_feature) const {
 
 
 }
 }
 
 
+void RasterizerDummy::restore_framebuffer() {
+
+}
 
 
 RasterizerDummy::RasterizerDummy() {
 RasterizerDummy::RasterizerDummy() {
 
 

+ 1 - 0
servers/visual/rasterizer_dummy.h

@@ -779,6 +779,7 @@ public:
 
 
 	virtual bool has_feature(VS::Features p_feature) const;
 	virtual bool has_feature(VS::Features p_feature) const;
 
 
+	virtual void restore_framebuffer();
 
 
 	RasterizerDummy();
 	RasterizerDummy();
 	virtual ~RasterizerDummy();
 	virtual ~RasterizerDummy();

+ 8 - 0
servers/visual/visual_server_raster.cpp

@@ -454,6 +454,14 @@ AABB VisualServerRaster::mesh_get_custom_aabb(RID p_mesh) const {
 	return rasterizer->mesh_get_custom_aabb(p_mesh);
 	return rasterizer->mesh_get_custom_aabb(p_mesh);
 }
 }
 
 
+void VisualServerRaster::mesh_clear(RID p_mesh) {
+
+	ERR_FAIL_COND(!rasterizer->is_mesh(p_mesh));
+	while(rasterizer->mesh_get_surface_count(p_mesh)) {
+		rasterizer->mesh_remove_surface(p_mesh,0);
+	}
+}
+
 
 
 /* MULTIMESH */
 /* MULTIMESH */
 
 

+ 1 - 0
servers/visual/visual_server_raster.h

@@ -765,6 +765,7 @@ public:
 	virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb);
 	virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb);
 	virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
 	virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
 
 
+	virtual void mesh_clear(RID p_mesh);
 
 
 	/* MULTIMESH API */
 	/* MULTIMESH API */
 
 

+ 1 - 0
servers/visual/visual_server_wrap_mt.h

@@ -199,6 +199,7 @@ public:
 
 
 	FUNC2(mesh_remove_surface,RID,int);
 	FUNC2(mesh_remove_surface,RID,int);
 	FUNC1RC(int,mesh_get_surface_count,RID);
 	FUNC1RC(int,mesh_get_surface_count,RID);
+	FUNC1(mesh_clear,RID);
 
 
 
 
 	FUNC2(mesh_set_custom_aabb,RID,const AABB&);
 	FUNC2(mesh_set_custom_aabb,RID,const AABB&);

+ 2 - 0
servers/visual_server.h

@@ -353,6 +353,8 @@ public:
 	virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb)=0;
 	virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb)=0;
 	virtual AABB mesh_get_custom_aabb(RID p_mesh) const=0;
 	virtual AABB mesh_get_custom_aabb(RID p_mesh) const=0;
 
 
+	virtual void mesh_clear(RID p_mesh)=0;
+
 	/* MULTIMESH API */
 	/* MULTIMESH API */
 
 
 	virtual RID multimesh_create()=0;
 	virtual RID multimesh_create()=0;

+ 15 - 4
tools/editor/editor_import_export.cpp

@@ -942,11 +942,11 @@ static int _get_pad(int p_alignment, int p_n) {
 	return pad;
 	return pad;
 };
 };
 
 
-void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, bool p_dumb, bool p_remote_debug) {
+void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, int p_flags) {
 
 
 	String host = EditorSettings::get_singleton()->get("network/debug_host");
 	String host = EditorSettings::get_singleton()->get("network/debug_host");
 
 
-	if (p_dumb) {
+	if (p_flags&EXPORT_DUMB_CLIENT) {
 		int port = EditorSettings::get_singleton()->get("file_server/port");
 		int port = EditorSettings::get_singleton()->get("file_server/port");
 		String passwd = EditorSettings::get_singleton()->get("file_server/password");
 		String passwd = EditorSettings::get_singleton()->get("file_server/password");
 		r_flags.push_back("-rfs");
 		r_flags.push_back("-rfs");
@@ -957,7 +957,7 @@ void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, bool p_dumb
 		}
 		}
 	}
 	}
 
 
-	if (p_remote_debug) {
+	if (p_flags&EXPORT_REMOTE_DEBUG) {
 
 
 		r_flags.push_back("-rdebug");
 		r_flags.push_back("-rdebug");
 		r_flags.push_back(host+":"+String::num(GLOBAL_DEF("debug/debug_port", 6007)));
 		r_flags.push_back(host+":"+String::num(GLOBAL_DEF("debug/debug_port", 6007)));
@@ -982,6 +982,17 @@ void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, bool p_dumb
 
 
 	}
 	}
 
 
+	if (p_flags&EXPORT_VIEW_COLLISONS) {
+
+		r_flags.push_back("-debugcol");
+	}
+
+	if (p_flags&EXPORT_VIEW_NAVIGATION) {
+
+		r_flags.push_back("-debugnav");
+	}
+
+
 }
 }
 
 
 Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) {
 Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) {
@@ -1097,7 +1108,7 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles, int p
 	return OK;
 	return OK;
 }
 }
 
 
-Error EditorExportPlatformPC::export_project(const String& p_path, bool p_debug, bool p_dumb,bool p_remote_debug) {
+Error EditorExportPlatformPC::export_project(const String& p_path, bool p_debug, int p_flags) {
 
 
 
 
 
 

+ 11 - 4
tools/editor/editor_import_export.h

@@ -105,7 +105,7 @@ protected:
 
 
 	};
 	};
 
 
-	void gen_export_flags(Vector<String> &r_flags,bool p_dumb,bool p_remote_debug);
+	void gen_export_flags(Vector<String> &r_flags, int p_flags);
 	static Error save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total);
 	static Error save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total);
 
 
 public:
 public:
@@ -121,6 +121,13 @@ public:
 		IMAGE_COMPRESSION_ETC2, // ericsson new compression format (can handle alpha)
 		IMAGE_COMPRESSION_ETC2, // ericsson new compression format (can handle alpha)
 	};
 	};
 
 
+	enum ExportFlags {
+		EXPORT_DUMB_CLIENT=1,
+		EXPORT_REMOTE_DEBUG=2,
+		EXPORT_VIEW_COLLISONS=4,
+		EXPORT_VIEW_NAVIGATION=8
+	};
+
 
 
 	Error export_project_files(EditorExportSaveFunction p_func, void* p_udata,bool p_make_bundles);
 	Error export_project_files(EditorExportSaveFunction p_func, void* p_udata,bool p_make_bundles);
 
 
@@ -133,14 +140,14 @@ public:
 	virtual int get_device_count() const { return 0; }
 	virtual int get_device_count() const { return 0; }
 	virtual String get_device_name(int p_device) const { return ""; }
 	virtual String get_device_name(int p_device) const { return ""; }
 	virtual String get_device_info(int p_device) const { return ""; }
 	virtual String get_device_info(int p_device) const { return ""; }
-	virtual Error run(int p_device,bool p_dumb=false,bool p_remote_debug=false) { return OK; }
+	virtual Error run(int p_device,int p_flags) { return OK; }
 
 
 	virtual bool can_export(String *r_error=NULL) const=0;
 	virtual bool can_export(String *r_error=NULL) const=0;
 
 
 
 
 	virtual bool requieres_password(bool p_debug) const { return false; }
 	virtual bool requieres_password(bool p_debug) const { return false; }
 	virtual String get_binary_extension() const=0;
 	virtual String get_binary_extension() const=0;
-	virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false,bool p_remote_debug=false)=0;
+	virtual Error export_project(const String& p_path,bool p_debug,int p_flags=0)=0;
 
 
 	EditorExportPlatform() {};
 	EditorExportPlatform() {};
 };
 };
@@ -190,7 +197,7 @@ public:
 	virtual ImageCompression get_image_compression() const { return IMAGE_COMPRESSION_BC; }
 	virtual ImageCompression get_image_compression() const { return IMAGE_COMPRESSION_BC; }
 
 
 	virtual String get_binary_extension() const { return binary_extension; }
 	virtual String get_binary_extension() const { return binary_extension; }
-	virtual Error export_project(const String& p_path, bool p_debug, bool p_dumb=false, bool p_remote_debug=false);
+	virtual Error export_project(const String& p_path, bool p_debug, int p_flags=0);
 	virtual void set_release_binary32(const String& p_binary) { release_binary32=p_binary; }
 	virtual void set_release_binary32(const String& p_binary) { release_binary32=p_binary; }
 	virtual void set_debug_binary32(const String& p_binary) { debug_binary32=p_binary; }
 	virtual void set_debug_binary32(const String& p_binary) { debug_binary32=p_binary; }
 	virtual void set_release_binary64(const String& p_binary) { release_binary64=p_binary; }
 	virtual void set_release_binary64(const String& p_binary) { release_binary64=p_binary; }

+ 17 - 0
tools/editor/editor_node.cpp

@@ -2677,6 +2677,20 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 			run_native->set_deploy_debug_remote(!ischecked);
 			run_native->set_deploy_debug_remote(!ischecked);
 
 
 		} break;
 		} break;
+		case RUN_DEBUG_COLLISONS: {
+
+			bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_COLLISONS));
+			debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_COLLISONS),!ischecked);
+			run_native->set_debug_collisions(!ischecked);
+			editor_run.set_debug_collisions(!ischecked);
+		} break;
+		case RUN_DEBUG_NAVIGATION: {
+
+			bool ischecked = debug_button->get_popup()->is_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_NAVIGATION));
+			debug_button->get_popup()->set_item_checked( debug_button->get_popup()->get_item_index(RUN_DEBUG_NAVIGATION),!ischecked);
+			run_native->set_debug_navigation(!ischecked);
+			editor_run.set_debug_navigation(!ischecked);
+		} break;
 		case SETTINGS_UPDATE_ALWAYS: {
 		case SETTINGS_UPDATE_ALWAYS: {
 
 
 			update_menu->get_popup()->set_item_checked(0,true);
 			update_menu->get_popup()->set_item_checked(0,true);
@@ -4955,6 +4969,9 @@ EditorNode::EditorNode() {
 	p->add_separator();
 	p->add_separator();
 	p->add_check_item("Deploy Remote Debug",RUN_DEPLOY_REMOTE_DEBUG);
 	p->add_check_item("Deploy Remote Debug",RUN_DEPLOY_REMOTE_DEBUG);
 	p->add_check_item("Deploy File Server Clients",RUN_DEPLOY_DUMB_CLIENTS);
 	p->add_check_item("Deploy File Server Clients",RUN_DEPLOY_DUMB_CLIENTS);
+	p->add_separator();
+	p->add_check_item("Visible Collision Shapes",RUN_DEBUG_COLLISONS);
+	p->add_check_item("Visible Navigation",RUN_DEBUG_NAVIGATION);
 	p->connect("item_pressed",this,"_menu_option");
 	p->connect("item_pressed",this,"_menu_option");
 
 
 	/*
 	/*

+ 2 - 0
tools/editor/editor_node.h

@@ -156,6 +156,8 @@ class EditorNode : public Node {
 		RUN_FILE_SERVER,
 		RUN_FILE_SERVER,
 		RUN_DEPLOY_DUMB_CLIENTS,
 		RUN_DEPLOY_DUMB_CLIENTS,
 		RUN_LIVE_DEBUG,
 		RUN_LIVE_DEBUG,
+		RUN_DEBUG_COLLISONS,
+		RUN_DEBUG_NAVIGATION,
 		RUN_DEPLOY_REMOTE_DEBUG,
 		RUN_DEPLOY_REMOTE_DEBUG,
 		SETTINGS_UPDATE_ALWAYS,
 		SETTINGS_UPDATE_ALWAYS,
 		SETTINGS_UPDATE_CHANGES,
 		SETTINGS_UPDATE_CHANGES,

+ 31 - 0
tools/editor/editor_run.cpp

@@ -61,6 +61,13 @@ Error EditorRun::run(const String& p_scene,const String p_custom_args,const List
 		}
 		}
 	}
 	}
 
 
+	if (debug_collisions) {
+		args.push_back("-debugcol");
+	}
+
+	if (debug_navigation) {
+		args.push_back("-debugnav");
+	}
 
 
 	int screen = EditorSettings::get_singleton()->get("game_window_placement/screen");
 	int screen = EditorSettings::get_singleton()->get("game_window_placement/screen");
 
 
@@ -169,7 +176,31 @@ void EditorRun::stop() {
 	status=STATUS_STOP;
 	status=STATUS_STOP;
 }
 }
 
 
+void EditorRun::set_debug_collisions(bool p_debug) {
+
+	debug_collisions=p_debug;
+}
+
+bool EditorRun::get_debug_collisions() const{
+
+	return debug_collisions;
+}
+
+void EditorRun::set_debug_navigation(bool p_debug) {
+
+	debug_navigation=p_debug;
+}
+
+bool EditorRun::get_debug_navigation() const{
+
+	return debug_navigation;
+}
+
+
 EditorRun::EditorRun() {
 EditorRun::EditorRun() {
 
 
 	status=STATUS_STOP;
 	status=STATUS_STOP;
+	debug_collisions=false;
+	debug_navigation=false;
+
 }
 }

+ 9 - 0
tools/editor/editor_run.h

@@ -43,6 +43,8 @@ public:
 	OS::ProcessID pid;
 	OS::ProcessID pid;
 private:
 private:
 
 
+	bool debug_collisions;
+	bool debug_navigation;
 	Status status;
 	Status status;
 public:
 public:
 
 
@@ -50,6 +52,13 @@ public:
 	Error run(const String& p_scene,const String p_custom_args,const List<String>& p_breakpoints,const String& p_edited_scene);
 	Error run(const String& p_scene,const String p_custom_args,const List<String>& p_breakpoints,const String& p_edited_scene);
 	void run_native_notify() { status=STATUS_PLAY; }
 	void run_native_notify() { status=STATUS_PLAY; }
 	void stop();
 	void stop();
+
+	void set_debug_collisions(bool p_debug);
+	bool get_debug_collisions() const;
+
+	void set_debug_navigation(bool p_debug);
+	bool get_debug_navigation() const;
+
 	EditorRun();
 	EditorRun();
 };
 };
 
 

Some files were not shown because too many files changed in this diff