瀏覽代碼

Huge Amount of BugFix
-=-=-=-=-=-=-=-=-=-=-

-Fixes to Collada Exporter (avoid crash situtions)
-Fixed to Collada Importer (Fixed Animation Optimizer Bugs)
-Fixes to RigidBody/RigidBody2D body_enter/body_exit, was buggy
-Fixed ability for RigidBody/RigidBody2D to get contacts reported and bodyin/out in Kinematic mode.
-Added proper trigger support for 3D Physics shapes
-Changed proper value for Z-Offset in OmniLight
-Fixed spot attenuation bug in SpotLight
-Fixed some 3D and 2D spatial soudn bugs related to distance attenuation.
-Fixed bugs in EventPlayer (channels were muted by default)
-Fix in ButtonGroup (get nodes in group are now returned in order)
-Fixed Linear->SRGB Conversion, previous algo sucked, new algo works OK
-Changed SRGB->Linear conversion to use hardware if supported, improves texture quality a lot
-Fixed options for Y-Fov and X-Fov in camera, should be more intuitive.
-Fixed bugs related to viewports and transparency

Huge Amount of New Stuff:
-=-=-=-=-=-=-=-==-=-=-=-

-Ability to manually advance an AnimationPlayer that is inactive (with advance() function)
-More work in WinRT platform
-Added XY normalmap support, imports on this format by default. Reduces normlmap size and enables much nice compression using LATC
-Added Anisotropic filter support to textures, can be specified on import
-Added support for Non-Square, Isometric and Hexagonal tilemaps in TileMap.
-Added Isometric Dungeon demo.
-Added simple hexagonal map demo.
-Added Truck-Town demo. Shows how most types of joints and vehicles are used. Please somebody make a nicer town, this one is too hardcore.
-Added an Object-Picking API to both RigidBody and Area! (and relevant demo)

Juan Linietsky 11 年之前
父節點
當前提交
b24fe3dd20
共有 84 個文件被更改,包括 1657 次插入341 次删除
  1. 31 0
      core/bind/core_bind.cpp
  2. 2 0
      core/bind/core_bind.h
  3. 8 0
      core/image.h
  4. 131 0
      core/math/geometry.cpp
  5. 3 1
      core/math/geometry.h
  6. 24 1
      core/variant_call.cpp
  7. 二進制
      demos/3d/truck_town/car_base.scn
  8. 二進制
      demos/3d/truck_town/cement.tex
  9. 二進制
      demos/3d/truck_town/crane.scn
  10. 7 0
      demos/3d/truck_town/engine.cfg
  11. 69 0
      demos/3d/truck_town/follow_camera.gd
  12. 二進制
      demos/3d/truck_town/grass.tex
  13. 二進制
      demos/3d/truck_town/trailer_truck.scn
  14. 二進制
      demos/3d/truck_town/truck_scene.scn
  15. 二進制
      demos/3d/truck_town/trucktown.scn
  16. 54 0
      demos/3d/truck_town/vehicle.gd
  17. 13 2
      drivers/theoraplayer/video_stream_theoraplayer.cpp
  18. 4 1
      platform/winrt/SCsub
  19. 162 0
      platform/winrt/app.cpp
  20. 51 0
      platform/winrt/app.h
  21. 3 3
      platform/winrt/detect.py
  22. 151 0
      platform/winrt/gl_context_egl.cpp
  23. 44 0
      platform/winrt/gl_context_egl.h
  24. 44 153
      platform/winrt/os_winrt.cpp
  25. 5 2
      platform/winrt/os_winrt.h
  26. 194 12
      scene/2d/tile_map.cpp
  27. 45 3
      scene/2d/tile_map.h
  28. 29 0
      scene/2d/y_sort.cpp
  29. 17 0
      scene/2d/y_sort.h
  30. 1 14
      scene/3d/area.cpp
  31. 1 4
      scene/3d/area.h
  32. 3 3
      scene/3d/camera.cpp
  33. 45 11
      scene/3d/collision_object.cpp
  34. 7 2
      scene/3d/collision_object.h
  35. 1 1
      scene/3d/light.cpp
  36. 12 2
      scene/3d/navigation.cpp
  37. 6 1
      scene/3d/navigation.h
  38. 3 3
      scene/3d/navigation_mesh.cpp
  39. 22 3
      scene/3d/physics_joint.cpp
  40. 5 0
      scene/3d/physics_joint.h
  41. 7 6
      scene/3d/vehicle_body.cpp
  42. 6 0
      scene/animation/animation_player.cpp
  43. 2 0
      scene/animation/animation_player.h
  44. 2 2
      scene/audio/event_player.cpp
  45. 3 0
      scene/gui/button_group.cpp
  46. 3 2
      scene/gui/label.cpp
  47. 11 5
      scene/main/viewport.cpp
  48. 2 0
      scene/register_scene_types.cpp
  49. 7 3
      scene/resources/animation.cpp
  50. 2 2
      scene/resources/animation.h
  51. 16 4
      scene/resources/packed_scene.cpp
  52. 2 1
      servers/physics/area_pair_sw.cpp
  53. 2 4
      servers/physics/area_sw.cpp
  54. 0 3
      servers/physics/area_sw.h
  55. 1 0
      servers/physics/collision_object_sw.cpp
  56. 6 0
      servers/physics/collision_object_sw.h
  57. 5 1
      servers/physics/constraint_sw.h
  58. 31 0
      servers/physics/physics_server_sw.cpp
  59. 6 0
      servers/physics/physics_server_sw.h
  60. 4 1
      servers/physics/space_sw.cpp
  61. 33 6
      servers/physics/step_sw.cpp
  62. 1 0
      servers/physics_2d/area_2d_sw.cpp
  63. 2 0
      servers/physics_2d/area_pair_2d_sw.cpp
  64. 6 0
      servers/physics_server.cpp
  65. 6 0
      servers/physics_server.h
  66. 1 0
      servers/register_server_types.cpp
  67. 9 4
      servers/spatial_sound/spatial_sound_server_sw.cpp
  68. 1 1
      servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
  69. 28 22
      servers/visual/visual_server_raster.cpp
  70. 12 3
      servers/visual/visual_server_raster.h
  71. 2 0
      servers/visual/visual_server_wrap_mt.h
  72. 1 0
      servers/visual_server.h
  73. 4 0
      tools/collada/collada.cpp
  74. 15 1
      tools/editor/io_plugins/editor_font_import_plugin.cpp
  75. 3 3
      tools/editor/io_plugins/editor_import_collada.cpp
  76. 55 2
      tools/editor/io_plugins/editor_scene_import_plugin.cpp
  77. 1 0
      tools/editor/io_plugins/editor_scene_import_plugin.h
  78. 5 0
      tools/editor/plugins/sample_player_editor_plugin.cpp
  79. 31 0
      tools/editor/plugins/spatial_editor_plugin.cpp
  80. 3 2
      tools/editor/plugins/spatial_editor_plugin.h
  81. 106 38
      tools/editor/plugins/tile_map_editor_plugin.cpp
  82. 3 2
      tools/editor/plugins/tile_set_editor_plugin.cpp
  83. 5 0
      tools/export/blender25/io_scene_dae/__init__.py
  84. 9 1
      tools/export/blender25/io_scene_dae/export_dae.py

+ 31 - 0
core/bind/core_bind.cpp

@@ -856,6 +856,36 @@ Vector<int> _Geometry::triangulate_polygon(const Vector<Vector2>& p_polygon) {
 	return Geometry::triangulate_polygon(p_polygon);
 }
 
+Dictionary _Geometry::make_atlas(const Vector<Size2>& p_rects) {
+
+	Dictionary ret;
+
+	Vector<Size2i> rects;
+	for (int i=0; i<p_rects.size(); i++) {
+
+		rects.push_back(p_rects[i]);
+	};
+
+	Vector<Point2i> result;
+	Size2i size;
+
+	Geometry::make_atlas(rects, result, size);
+
+	Size2 r_size = size;
+	Vector<Point2> r_result;
+	for (int i=0; i<result.size(); i++) {
+
+		r_result.push_back(result[i]);
+	};
+
+
+	ret["points"] = r_result;
+	ret["size"] = r_size;
+
+	return ret;
+};
+
+
 void _Geometry::_bind_methods() {
 
 
@@ -878,6 +908,7 @@ void _Geometry::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("triangulate_polygon","polygon"),&_Geometry::triangulate_polygon);
 
+	ObjectTypeDB::bind_method(_MD("make_atlas","sizes"),&_Geometry::make_atlas);
 }
 
 

+ 2 - 0
core/bind/core_bind.h

@@ -236,6 +236,8 @@ public:
 
 	Vector<int> triangulate_polygon(const Vector<Vector2>& p_polygon);
 
+	Dictionary make_atlas(const Vector<Size2>& p_rects);
+
 	_Geometry();
 };
 

+ 8 - 0
core/image.h

@@ -216,6 +216,14 @@ public:
 	 * Convert the image to another format, as close as it can be done.
 	 */
 	void convert( Format p_new_format );
+
+	Image converted(int p_new_format) {
+		ERR_FAIL_INDEX_V(p_new_format, FORMAT_MAX, Image());
+
+		Image ret = *this;
+		ret.convert((Format)p_new_format);
+		return ret;
+	};
 	
 	/**
 	 * Get the current image format.

+ 131 - 0
core/math/geometry.cpp

@@ -1004,3 +1004,134 @@ DVector<Plane> Geometry::build_capsule_planes(float p_radius, float p_height, in
 
 }
 
+
+struct _AtlasWorkRect {
+
+	Size2i s;
+	Point2i p;
+	int idx;
+	_FORCE_INLINE_ bool operator<(const _AtlasWorkRect& p_r) const { return s.width > p_r.s.width; };
+};
+
+struct _AtlasWorkRectResult {
+
+	Vector<_AtlasWorkRect> result;
+	int max_w;
+	int max_h;
+};
+
+void Geometry::make_atlas(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size) {
+
+	//super simple, almost brute force scanline stacking fitter
+	//it's pretty basic for now, but it tries to make sure that the aspect ratio of the
+	//resulting atlas is somehow square. This is necesary because video cards have limits
+	//on texture size (usually 2048 or 4096), so the more square a texture, the more chances
+	//it will work in every hardware.
+	// for example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a
+	// 256x8192 atlas (won't work anywhere).
+
+	ERR_FAIL_COND(p_rects.size()==0);
+
+	Vector<_AtlasWorkRect> wrects;
+	wrects.resize(p_rects.size());
+	for(int i=0;i<p_rects.size();i++) {
+		wrects[i].s=p_rects[i];
+		wrects[i].idx=i;
+	}
+	wrects.sort();
+	int widest = wrects[0].s.width;
+
+	Vector<_AtlasWorkRectResult> results;
+
+	for(int i=0;i<=12;i++) {
+
+		int w = 1<<i;
+		int max_h=0;
+		int max_w=0;
+		if ( w < widest )
+			continue;
+
+		Vector<int> hmax;
+		hmax.resize(w);
+		for(int j=0;j<w;j++)
+			hmax[j]=0;
+
+		//place them
+		int ofs=0;
+		int limit_h=0;
+		for(int j=0;j<wrects.size();j++) {
+
+
+			if (ofs+wrects[j].s.width > w) {
+
+				ofs=0;
+			}
+
+			int from_y=0;
+			for(int k=0;k<wrects[j].s.width;k++) {
+
+				if (hmax[ofs+k] > from_y)
+					from_y=hmax[ofs+k];
+			}
+
+			wrects[j].p.x=ofs;
+			wrects[j].p.y=from_y;
+			int end_h = from_y+wrects[j].s.height;
+			int end_w = ofs+wrects[j].s.width;
+			if (ofs==0)
+				limit_h=end_h;
+
+			for(int k=0;k<wrects[j].s.width;k++) {
+
+				hmax[ofs+k]=end_h;
+			}
+
+			if (end_h > max_h)
+				max_h=end_h;
+
+			if (end_w > max_w)
+				max_w=end_w;
+
+			if (ofs==0 || end_h>limit_h ) //while h limit not reched, keep stacking
+				ofs+=wrects[j].s.width;
+
+		}
+
+		_AtlasWorkRectResult result;
+		result.result=wrects;
+		result.max_h=max_h;
+		result.max_w=max_w;
+		results.push_back(result);
+
+	}
+
+	//find the result with the best aspect ratio
+
+	int best=-1;
+	float best_aspect=1e20;
+
+	for(int i=0;i<results.size();i++) {
+
+		float h = nearest_power_of_2(results[i].max_h);
+		float w = nearest_power_of_2(results[i].max_w);
+		float aspect = h>w ? h/w : w/h;
+		if (aspect < best_aspect) {
+			best=i;
+			best_aspect=aspect;
+		}
+	}
+
+	r_result.resize(p_rects.size());
+
+	for(int i=0;i<p_rects.size();i++) {
+
+		r_result[ results[best].result[i].idx ]=results[best].result[i].p;
+	}
+
+	r_size=Size2(results[best].max_w,results[best].max_h );
+
+}
+
+
+
+

+ 3 - 1
core/math/geometry.h

@@ -826,7 +826,9 @@ public:
 	static DVector<Plane> build_box_planes(const Vector3& p_extents);
 	static DVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis=Vector3::AXIS_Z);
 	static DVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis=Vector3::AXIS_Z);
-	
+
+	static void make_atlas(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size);
+
 	
 };
 

+ 24 - 1
core/variant_call.cpp

@@ -515,7 +515,7 @@ static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Varian
 #define VCALL_PTR0R(m_type,m_method)\
 static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(); }
 #define VCALL_PTR1(m_type,m_method)\
-static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0]); }
+static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0]); }
 #define VCALL_PTR1R(m_type,m_method)\
 static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0]); }
 #define VCALL_PTR2(m_type,m_method)\
@@ -551,6 +551,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
 	VCALL_PTR3R(Image, resized);
 	VCALL_PTR0R(Image, get_data);
 	VCALL_PTR3(Image, blit_rect);
+	VCALL_PTR1R(Image, converted);
 
 	VCALL_PTR0R( AABB, get_area );
 	VCALL_PTR0R( AABB, has_no_area );
@@ -605,6 +606,25 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
 		}
 	}
 
+	static void _call_Matrix32_basis_xform(Variant& r_ret,Variant& p_self,const Variant** p_args) {
+
+		switch(p_args[0]->type) {
+
+			case Variant::VECTOR2: r_ret=reinterpret_cast<Matrix32*>(p_self._data._ptr)->basis_xform( p_args[0]->operator Vector2()); return;
+			default: r_ret=Variant();
+		}
+
+	}
+
+	static void _call_Matrix32_basis_xform_inv(Variant& r_ret,Variant& p_self,const Variant** p_args) {
+
+		switch(p_args[0]->type) {
+
+			case Variant::VECTOR2: r_ret=reinterpret_cast<Matrix32*>(p_self._data._ptr)->basis_xform_inv( p_args[0]->operator Vector2()); return;
+			default: r_ret=Variant();
+		}
+	}
+
 
 	VCALL_PTR0R( Matrix3, inverse );
 	VCALL_PTR0R( Matrix3, transposed );
@@ -1313,6 +1333,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
 	ADDFUNC3(IMAGE, IMAGE, Image, resized, INT, "x", INT, "y", INT, "interpolation", varray(((int)Image::INTERPOLATE_BILINEAR)));
 	ADDFUNC0(IMAGE, RAW_ARRAY, Image, get_data, varray());
 	ADDFUNC3(IMAGE, NIL, Image, blit_rect, IMAGE, "src", RECT2, "src_rect", VECTOR2, "dest", varray(0));
+	ADDFUNC1(IMAGE, IMAGE, Image, converted, INT, "format", varray(0));
 
 	ADDFUNC0(_RID,INT,RID,get_id,varray());
 
@@ -1430,6 +1451,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
 	ADDFUNC1(MATRIX32,MATRIX32,Matrix32,translated,VECTOR2,"offset",varray());
 	ADDFUNC1(MATRIX32,MATRIX32,Matrix32,xform,NIL,"v",varray());
 	ADDFUNC1(MATRIX32,MATRIX32,Matrix32,xform_inv,NIL,"v",varray());
+	ADDFUNC1(MATRIX32,MATRIX32,Matrix32,basis_xform,NIL,"v",varray());
+	ADDFUNC1(MATRIX32,MATRIX32,Matrix32,basis_xform_inv,NIL,"v",varray());
 	ADDFUNC2(MATRIX32,MATRIX32,Matrix32,interpolate_with,MATRIX32,"m",REAL,"c",varray());
 
 	ADDFUNC0(MATRIX3,MATRIX3,Matrix3,inverse,varray());

二進制
demos/3d/truck_town/car_base.scn


二進制
demos/3d/truck_town/cement.tex


二進制
demos/3d/truck_town/crane.scn


+ 7 - 0
demos/3d/truck_town/engine.cfg

@@ -0,0 +1,7 @@
+[application]
+
+main_scene="res://truck_scene.scn"
+
+[rasterizer]
+
+shadow_filter=3

+ 69 - 0
demos/3d/truck_town/follow_camera.gd

@@ -0,0 +1,69 @@
+
+extends Camera
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+var collision_exception=[]
+export var min_distance=0.5
+export var max_distance=4.0
+export var angle_v_adjust=0.0
+export var autoturn_ray_aperture=25
+export var autoturn_speed=50
+var max_height = 2.0
+var min_height = 0
+
+func _fixed_process(dt):
+	var target  = get_parent().get_global_transform().origin
+	var pos = get_global_transform().origin
+	var up = Vector3(0,1,0)
+	
+	var delta = pos - target
+	
+	#regular delta follow
+	
+	#check ranges
+
+	if (delta.length() < min_distance):
+		delta = delta.normalized() * min_distance
+	elif (delta.length() > max_distance):
+		delta = delta.normalized() * max_distance
+	
+	#check upper and lower height
+	if ( delta.y > max_height):
+		delta.y = max_height
+	if ( delta.y < min_height):
+		delta.y = min_height
+		
+	pos = target + delta
+	
+	look_at_from_pos(pos,target,up)
+	
+	#turn a little up or down
+	var t = get_transform()
+	t.basis = Matrix3(t.basis[0],deg2rad(angle_v_adjust)) * t.basis
+	set_transform(t)
+	
+	
+
+func _ready():
+
+#find collision exceptions for ray
+	var node = self
+	while(node):
+		if (node extends RigidBody):
+			collision_exception.append(node.get_rid())
+			break
+		else:
+			node=node.get_parent()
+	# Initalization here
+	set_fixed_process(true)
+	#this detaches the camera transform from the parent spatial node
+	set_as_toplevel(true)
+
+	
+	
+
+
+

二進制
demos/3d/truck_town/grass.tex


二進制
demos/3d/truck_town/trailer_truck.scn


二進制
demos/3d/truck_town/truck_scene.scn


二進制
demos/3d/truck_town/trucktown.scn


+ 54 - 0
demos/3d/truck_town/vehicle.gd

@@ -0,0 +1,54 @@
+
+extends VehicleBody
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+
+const STEER_SPEED=1
+const STEER_LIMIT=0.4
+
+var steer_angle=0
+var steer_target=0
+
+
+export var engine_force=40
+
+func _fixed_process(delta):
+
+
+	if (Input.is_action_pressed("ui_left")):
+		steer_target=-STEER_LIMIT
+	elif (Input.is_action_pressed("ui_right")):
+		steer_target=STEER_LIMIT
+	else:
+		steer_target=0
+
+	if (Input.is_action_pressed("ui_up")):
+		set_engine_force(engine_force)
+	else:
+		set_engine_force(0)
+
+	if (Input.is_action_pressed("ui_down")):
+		set_brake(1)
+	else:
+		set_brake(0.0)
+								
+
+	if (steer_target < steer_angle):
+		steer_angle -= STEER_SPEED*delta
+		if (steer_target > steer_angle):
+			steer_angle=steer_target
+	elif (steer_target > steer_angle):
+		steer_angle += STEER_SPEED*delta
+		if (steer_target < steer_angle):
+			steer_angle=steer_target
+
+	set_steering(steer_angle)
+func _ready():
+	# Initalization here
+	set_fixed_process(true)
+	pass
+
+

+ 13 - 2
drivers/theoraplayer/video_stream_theoraplayer.cpp

@@ -86,12 +86,18 @@ public:
 		return fa->get_pos();
 	};
 
-	TPDataFA(String p_path) {
+	TPDataFA(const String& p_path) {
 
 		fa = FileAccess::open(p_path, FileAccess::READ);
 		data_name = "File: " + p_path;
 	};
 
+	TPDataFA(FileAccess* p_fa, const String& p_path) {
+
+		fa = p_fa;
+		data_name = "File: " + p_path;
+	};
+
 	~TPDataFA() {
 
 		if (fa)
@@ -366,6 +372,10 @@ void VideoStreamTheoraplayer::update(float p_time) {
 
 void VideoStreamTheoraplayer::set_file(const String& p_file) {
 
+	FileAccess* f = FileAccess::open(p_file, FileAccess::READ);
+	if (!f || !f->is_open())
+		return;
+
 	if (!audio_factory) {
 		audio_factory = memnew(TPAudioGodotFactory);
 	};
@@ -377,10 +387,11 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) {
 		
 		std::string file = p_file.replace("res://", "").utf8().get_data();
 		clip = mgr->createVideoClip(file);
+		memdelete(f);
 
 	} else {
 
-		TheoraDataSource* ds = memnew(TPDataFA(p_file));
+		TheoraDataSource* ds = memnew(TPDataFA(f, p_file));
 
 		try {
 			clip = mgr->createVideoClip(ds);

+ 4 - 1
platform/winrt/SCsub

@@ -3,6 +3,9 @@ Import('env')
 files = [
 	'thread_winrt.cpp',
 #	'#platform/windows/stream_peer_winsock.cpp',
+	'gl_context_egl.cpp',
+	'app.cpp',
+	'os_winrt.cpp',
 ]
 
-env.Program('#bin/godot_rt.exe', files)
+env.Program('#bin/godot_rt', files)

+ 162 - 0
platform/winrt/app.cpp

@@ -0,0 +1,162 @@
+//
+// This file demonstrates how to initialize EGL in a Windows Store app, using ICoreWindow.
+//
+
+#include "app.h"
+
+#include "main/main.h"
+
+using namespace Windows::ApplicationModel::Core;
+using namespace Windows::ApplicationModel::Activation;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::Input;
+using namespace Windows::Foundation;
+using namespace Windows::Graphics::Display;
+using namespace Microsoft::WRL;
+using namespace Platform;
+
+using namespace $ext_safeprojectname$;
+
+// Helper to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
+inline float ConvertDipsToPixels(float dips, float dpi)
+{
+    static const float dipsPerInch = 96.0f;
+    return floor(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer.
+}
+
+// Implementation of the IFrameworkViewSource interface, necessary to run our app.
+ref class HelloTriangleApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
+{
+public:
+    virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView()
+    {
+        return ref new App();
+    }
+};
+
+// The main function creates an IFrameworkViewSource for our app, and runs the app.
+[Platform::MTAThread]
+int main(Platform::Array<Platform::String^>^)
+{
+    auto helloTriangleApplicationSource = ref new HelloTriangleApplicationSource();
+    CoreApplication::Run(helloTriangleApplicationSource);
+    return 0;
+}
+
+App::App() :
+    mWindowClosed(false),
+    mWindowVisible(true),
+    mWindowWidth(0),
+    mWindowHeight(0),
+    mEglDisplay(EGL_NO_DISPLAY),
+    mEglContext(EGL_NO_CONTEXT),
+    mEglSurface(EGL_NO_SURFACE)
+{
+}
+
+// The first method called when the IFrameworkView is being created.
+void App::Initialize(CoreApplicationView^ applicationView)
+{
+    // Register event handlers for app lifecycle. This example includes Activated, so that we
+    // can make the CoreWindow active and start rendering on the window.
+    applicationView->Activated += 
+        ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
+
+    // Logic for other event handlers could go here.
+    // Information about the Suspending and Resuming event handlers can be found here:
+    // http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh994930.aspx
+
+	os = new OSWinrt;
+}
+
+// Called when the CoreWindow object is created (or re-created).
+void App::SetWindow(CoreWindow^ window)
+{
+    window->VisibilityChanged +=
+        ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
+
+    window->Closed += 
+        ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);
+
+    window->SizeChanged += 
+        ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged);
+
+#if !(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+    // Disable all pointer visual feedback for better performance when touching.
+    // This is not supported on Windows Phone applications.
+    auto pointerVisualizationSettings = PointerVisualizationSettings::GetForCurrentView();
+    pointerVisualizationSettings->IsContactFeedbackEnabled = false;
+    pointerVisualizationSettings->IsBarrelButtonFeedbackEnabled = false;
+#endif
+
+    // The CoreWindow has been created, so EGL can be initialized.
+	ContextEGL* context = memnew(ContextEGL(window));
+	os->set_gl_context(context);
+    UpdateWindowSize(Size(window->Bounds.Width, window->Bounds.Height));
+}
+
+// Initializes scene resources
+void App::Load(Platform::String^ entryPoint)
+{
+	char** args = {NULL};
+	Main::setup("winrt", 0, args);
+}
+
+// This method is called after the window becomes active.
+void App::Run()
+{
+
+	if (Main::start())
+		os->run();
+}
+
+// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView
+// class is torn down while the app is in the foreground.
+void App::Uninitialize()
+{
+	Main::cleanup();
+	delete os;
+}
+
+// Application lifecycle event handler.
+void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
+{
+    // Run() won't start until the CoreWindow is activated.
+    CoreWindow::GetForCurrentThread()->Activate();
+}
+
+// Window event handlers.
+void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
+{
+    mWindowVisible = args->Visible;
+}
+
+void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
+{
+    mWindowClosed = true;
+}
+
+void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
+{
+#if (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP)
+    // On Windows 8.1, apps are resized when they are snapped alongside other apps, or when the device is rotated.
+    // The default framebuffer will be automatically resized when either of these occur.
+    // In particular, on a 90 degree rotation, the default framebuffer's width and height will switch.
+    UpdateWindowSize(args->Size);
+#else if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+    // On Windows Phone 8.1, the window size changes when the device is rotated.
+    // The default framebuffer will not be automatically resized when this occurs.
+    // It is therefore up to the app to handle rotation-specific logic in its rendering code.
+#endif
+}
+
+void App::UpdateWindowSize(Size size)
+{
+	/*
+    DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
+    Size pixelSize(ConvertDipsToPixels(size.Width, currentDisplayInformation->LogicalDpi), ConvertDipsToPixels(size.Height, currentDisplayInformation->LogicalDpi));
+    
+    mWindowWidth = static_cast<GLsizei>(pixelSize.Width);
+    mWindowHeight = static_cast<GLsizei>(pixelSize.Height);
+	*/
+}

+ 51 - 0
platform/winrt/app.h

@@ -0,0 +1,51 @@
+#pragma once
+
+#include <string>
+
+#include <wrl.h>
+
+#include "os_winrt.h"
+#include "GLES2/gl2.h"
+
+namespace $ext_safeprojectname$
+{
+    ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
+    {
+    public:
+        App();
+
+        // IFrameworkView Methods.
+        virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
+        virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
+        virtual void Load(Platform::String^ entryPoint);
+        virtual void Run();
+        virtual void Uninitialize();
+
+    private:
+		void RecreateRenderer();
+
+        // Application lifecycle event handlers.
+        void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
+
+        // Window event handlers.
+        void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
+        void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
+        void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
+
+        void UpdateWindowSize(Windows::Foundation::Size size);
+        void InitializeEGL(Windows::UI::Core::CoreWindow^ window);
+        void CleanupEGL();
+
+        bool mWindowClosed;
+        bool mWindowVisible;
+        GLsizei mWindowWidth;
+        GLsizei mWindowHeight;
+        
+        EGLDisplay mEglDisplay;
+        EGLContext mEglContext;
+        EGLSurface mEglSurface;
+        
+		OSWinrt* os;
+    };
+
+}

+ 3 - 3
platform/winrt/detect.py

@@ -57,13 +57,13 @@ def configure(env):
 		env.Append(CCFLAGS=['-g','-pg'])
 		env.Append(LINKFLAGS=['-pg'])
 
-	env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/ZW', '/EHsc'])
-	env.Append(CXXFLAGS=['/TP'])
+	env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/EHsc'])
+	env.Append(CXXFLAGS=['/TP', '/ZW'])
 	env.Append(CPPFLAGS=['/DMSVC', '/GR', ])
 	#env.Append(CCFLAGS=['/I'+os.getenv("WindowsSdkDir")+"/Include"])
 	env.Append(CCFLAGS=['/DWINRT_ENABLED'])
 	env.Append(CCFLAGS=['/DWINDOWS_ENABLED'])
-	env.Append(CCFLAGS=['/DWINAPI_FAMILY=WINAPI_FAMILY_APP'])
+	env.Append(CCFLAGS=['/DWINAPI_FAMILY=WINAPI_FAMILY_APP', '/D_WIN32_WINNT=0x0603', '/DNTDDI_VERSION=0x06030000'])
 	env.Append(CCFLAGS=['/DRTAUDIO_ENABLED'])
 	#env.Append(CCFLAGS=['/DWIN32'])
 	env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])

+ 151 - 0
platform/winrt/gl_context_egl.cpp

@@ -0,0 +1,151 @@
+#include "gl_context_egl.h"
+
+using namespace Platform;
+
+void ContextEGL::release_current() {
+
+	eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, mEglContext);
+};
+
+void ContextEGL::make_current() {
+
+	eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
+};
+
+int ContextEGL::get_window_width() {
+
+	return width;
+};
+
+int ContextEGL::get_window_height() {
+
+	return height;
+};
+
+void ContextEGL::swap_buffers() {
+
+	if (eglSwapBuffers(mEglDisplay, mEglSurface) != EGL_TRUE)
+	{
+		cleanup();
+
+		window = CoreWindow::GetForCurrentThread();
+		initialize();
+
+		// tell rasterizer to reload textures and stuff?
+	}
+};
+
+Error ContextEGL::initialize() {
+
+	EGLint configAttribList[] = {
+		EGL_RED_SIZE, 8,
+		EGL_GREEN_SIZE, 8,
+		EGL_BLUE_SIZE, 8,
+		EGL_ALPHA_SIZE, 8,
+		EGL_DEPTH_SIZE, 8,
+		EGL_STENCIL_SIZE, 8,
+		EGL_SAMPLE_BUFFERS, 0,
+		EGL_NONE
+	};
+
+	EGLint surfaceAttribList[] = {
+		EGL_NONE, EGL_NONE
+	};
+
+	EGLint numConfigs = 0;
+	EGLint majorVersion = 1;
+	EGLint minorVersion = 0;
+	EGLDisplay display = EGL_NO_DISPLAY;
+	EGLContext context = EGL_NO_CONTEXT;
+	EGLSurface surface = EGL_NO_SURFACE;
+	EGLConfig config = nullptr;
+	EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
+
+	try {
+
+		display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+		if (display == EGL_NO_DISPLAY)
+		{
+			throw Exception::CreateException(E_FAIL, L"Failed to get default EGL display");
+		}
+
+		if (eglInitialize(display, &majorVersion, &minorVersion) == EGL_FALSE)
+		{
+			throw Exception::CreateException(E_FAIL, L"Failed to initialize EGL");
+		}
+
+		if (eglGetConfigs(display, NULL, 0, &numConfigs) == EGL_FALSE)
+		{
+			throw Exception::CreateException(E_FAIL, L"Failed to get EGLConfig count");
+		}
+
+		if (eglChooseConfig(display, configAttribList, &config, 1, &numConfigs) == EGL_FALSE)
+		{
+			throw Exception::CreateException(E_FAIL, L"Failed to choose first EGLConfig count");
+		}
+
+		surface = eglCreateWindowSurface(display, config, reinterpret_cast<IInspectable*>(window), surfaceAttribList);
+		if (surface == EGL_NO_SURFACE)
+		{
+			throw Exception::CreateException(E_FAIL, L"Failed to create EGL fullscreen surface");
+		}
+
+		context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
+		if (context == EGL_NO_CONTEXT)
+		{
+			throw Exception::CreateException(E_FAIL, L"Failed to create EGL context");
+		}
+
+		if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
+		{
+			throw Exception::CreateException(E_FAIL, L"Failed to make fullscreen EGLSurface current");
+		}
+	} catch (...) {
+		return FAILED;
+	};
+
+	mEglDisplay = display;
+	mEglSurface = surface;
+	mEglContext = context;
+
+	eglQuerySurface(display,surface,EGL_WIDTH,&width);
+	eglQuerySurface(display,surface,EGL_HEIGHT,&height);
+
+	return OK;
+};
+
+void ContextEGL::cleanup() {
+
+	if (mEglDisplay != EGL_NO_DISPLAY && mEglSurface != EGL_NO_SURFACE)
+	{
+		eglDestroySurface(mEglDisplay, mEglSurface);
+		mEglSurface = EGL_NO_SURFACE;
+	}
+
+	if (mEglDisplay != EGL_NO_DISPLAY && mEglContext != EGL_NO_CONTEXT)
+	{
+		eglDestroyContext(mEglDisplay, mEglContext);
+		mEglContext = EGL_NO_CONTEXT;
+	}
+
+	if (mEglDisplay != EGL_NO_DISPLAY)
+	{
+		eglTerminate(mEglDisplay);
+		mEglDisplay = EGL_NO_DISPLAY;
+	}
+};
+
+ContextEGL::ContextEGL(CoreWindow^ p_window) :
+	mEglDisplay(EGL_NO_DISPLAY),
+	mEglContext(EGL_NO_CONTEXT),
+	mEglSurface(EGL_NO_SURFACE)
+ {
+
+	window = p_window;
+};
+
+ContextEGL::~ContextEGL() {
+
+	cleanup();
+};
+

+ 44 - 0
platform/winrt/gl_context_egl.h

@@ -0,0 +1,44 @@
+#ifndef CONTEXT_EGL_H
+#define CONTEXT_EGL_H
+
+#include <wrl.h>
+
+#include "os/os.h"
+#include "EGL/egl.h"
+#include "error_list.h"
+#include "drivers/gl_context/context_gl.h"
+
+using namespace Windows::UI::Core;
+
+class ContextEGL : public ContextGL {
+
+	CoreWindow^ window;
+
+	EGLDisplay mEglDisplay;
+	EGLContext mEglContext;
+	EGLSurface mEglSurface;
+
+	EGLint width;
+	EGLint height;
+
+public:
+
+	virtual void release_current();
+
+	virtual void make_current();
+
+	virtual int get_window_width();
+	virtual int get_window_height();
+	virtual void swap_buffers();
+
+	virtual Error initialize();
+
+	void cleanup();
+
+	ContextEGL(CoreWindow^ p_window);
+	~ContextEGL();
+
+};
+
+#endif
+

+ 44 - 153
platform/winrt/os_winrt.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  os_windows.cpp                                                       */
+/*  os_winrt.cpp                                                       */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,12 +28,12 @@
 /*************************************************************************/
 #include "drivers/gles2/rasterizer_gles2.h"
 #include "drivers/gles1/rasterizer_gles1.h"
-#include "os_windows.h"
+#include "os_winrt.h"
 #include "drivers/nedmalloc/memory_pool_static_nedmalloc.h"
 #include "drivers/unix/memory_pool_static_malloc.h"
 #include "os/memory_pool_dynamic_static.h"
-#include "drivers/windows/thread_windows.h"
-#include "drivers/windows/semaphore_windows.h"
+#include "thread_winrt.h"
+//#include "drivers/windows/semaphore_windows.h"
 #include "drivers/windows/mutex_windows.h"
 #include "main/main.h"
 #include "drivers/windows/file_access_windows.h"
@@ -44,14 +44,22 @@
 #include "servers/audio/audio_server_sw.h"
 #include "servers/visual/visual_server_wrap_mt.h"
 
-#include "tcp_server_winsock.h"
-#include "stream_peer_winsock.h"
 #include "os/pc_joystick_map.h"
-#include "lang_table.h"
 #include "os/memory_pool_dynamic_prealloc.h"
 #include "globals.h"
 #include "io/marshalls.h"
 
+#include <wrl.h>
+
+using namespace Windows::ApplicationModel::Core;
+using namespace Windows::ApplicationModel::Activation;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::Input;
+using namespace Windows::Foundation;
+using namespace Windows::Graphics::Display;
+using namespace Microsoft::WRL;
+
+
 int OSWinrt::get_video_driver_count() const {
 
 	return 2;
@@ -129,59 +137,18 @@ bool OSWinrt::can_draw() const {
 };
 
 
-void OSWinrt::_touch_event(int idx, UINT uMsg, WPARAM	wParam,	LPARAM	lParam) {
-
-	InputEvent event;
-	event.type = InputEvent::SCREEN_TOUCH;
-	event.ID=++last_id;
-	event.screen_touch.index = idx;
+void OSWinrt::set_gl_context(ContextEGL* p_context) {
 
-	switch (uMsg) {
-		case WM_LBUTTONDOWN:
-		case WM_MBUTTONDOWN:
-		case WM_RBUTTONDOWN: {
-
-			event.screen_touch.pressed = true;
-		} break;
-
-		case WM_LBUTTONUP:
-		case WM_MBUTTONUP:
-		case WM_RBUTTONUP: {
-			event.screen_touch.pressed = false;
-		} break;
-	};
-
-	event.screen_touch.x=GET_X_LPARAM(lParam);
-	event.screen_touch.y=GET_Y_LPARAM(lParam);
-
-	if (main_loop) {
-		input->parse_input_event(event);
-	}
+	gl_context = p_context;
 };
 
-void OSWinrt::_drag_event(int idx,UINT uMsg, WPARAM	wParam,	LPARAM	lParam) {
-
-	InputEvent event;
-	event.type = InputEvent::SCREEN_DRAG;
-	event.ID=++last_id;
-	event.screen_drag.index = idx;
-
-	event.screen_drag.x=GET_X_LPARAM(lParam);
-	event.screen_drag.y=GET_Y_LPARAM(lParam);
-
-	if (main_loop)
-		input->parse_input_event(event);
-};
-
-
 void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
 
-
-
     main_loop=NULL;
     outside=true;
 
-	
+	gl_context->initialize();
+
 	visual_server = memnew( VisualServerRaster(rasterizer) );
 	if (get_render_thread_mode()!=RENDER_THREAD_UNSAFE) {
 
@@ -222,6 +189,7 @@ void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_aud
 
 void OSWinrt::set_clipboard(const String& p_text) {
 
+	/*
 	if (!OpenClipboard(hWnd)) {
 		ERR_EXPLAIN("Unable to open clipboard.");
 		ERR_FAIL();
@@ -255,10 +223,12 @@ void OSWinrt::set_clipboard(const String& p_text) {
 	SetClipboardData(CF_TEXT, mem);
 
 	CloseClipboard();
+	*/
 };
 
 String OSWinrt::get_clipboard() const {
 
+	/*
 	String ret;
 	if (!OpenClipboard(hWnd)) {
 		ERR_EXPLAIN("Unable to open clipboard.");
@@ -295,6 +265,8 @@ String OSWinrt::get_clipboard() const {
 	CloseClipboard();
 
 	return ret;
+	*/
+	return "";
 };
 
 
@@ -327,10 +299,6 @@ void OSWinrt::finalize() {
 	if (rasterizer)
 		memdelete(rasterizer);
 
-	if (user_proc) {
-		SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
-	};
-
 	spatial_sound_server->finish();
 	memdelete(spatial_sound_server);
 	spatial_sound_2d_server->finish();
@@ -355,16 +323,11 @@ void OSWinrt::finalize() {
 }
 void OSWinrt::finalize_core() {
 
-	memdelete(process_map);
-
 	if (mempool_dynamic)
 		memdelete( mempool_dynamic );
 	if (mempool_static)
 		delete mempool_static;
 
-
-	TCPServerWinsock::cleanup();
-	StreamPeerWinsock::cleanup();
 }
 
 void OSWinrt::vprint(const char* p_format, va_list p_list, bool p_stderr) {
@@ -399,10 +362,7 @@ void OSWinrt::vprint(const char* p_format, va_list p_list, bool p_stderr) {
 
 void OSWinrt::alert(const String& p_alert,const String& p_title) {
 
-	if (!is_no_window_mode_enabled())
-		MessageBoxW(NULL,p_alert.c_str(),p_title.c_str(),MB_OK|MB_ICONEXCLAMATION);
-	else
-		print_line("ALERT: "+p_alert);
+	print_line("ALERT: "+p_alert);
 }
 
 void OSWinrt::set_mouse_mode(MouseMode p_mode) {
@@ -445,71 +405,16 @@ void OSWinrt::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) con
 
 void OSWinrt::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) {
 
-	HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE);
-	if (!hCon || hCon==INVALID_HANDLE_VALUE) {
-		if (p_rationale && p_rationale[0]) {
-
-			print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
-			print("\E[0;31;40m   At: %s:%i.\E[0;0;37m\n",p_file,p_line);
+	if (p_rationale && p_rationale[0]) {
 
-		} else {
-			print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
-			print("\E[0;31;40m   At: %s:%i.\E[0;0;37m\n",p_file,p_line);
+		print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
+		print("\E[0;31;40m   At: %s:%i.\E[0;0;37m\n",p_file,p_line);
 
-		}
 	} else {
+		print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
+		print("\E[0;31;40m   At: %s:%i.\E[0;0;37m\n",p_file,p_line);
 
-		CONSOLE_SCREEN_BUFFER_INFO sbi; //original
-		GetConsoleScreenBufferInfo(hCon,&sbi);
-
-		SetConsoleTextAttribute(hCon,sbi.wAttributes);
-
-
-
-		uint32_t basecol=0;
-		switch(p_type) {
-			case ERR_ERROR: basecol = FOREGROUND_RED; break;
-			case ERR_WARNING: basecol = FOREGROUND_RED|FOREGROUND_GREEN; break;
-			case ERR_SCRIPT: basecol = FOREGROUND_GREEN; break;
-		}
-
-		if (p_rationale && p_rationale[0]) {
-
-			SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
-
-
-			switch(p_type) {
-				case ERR_ERROR: print("ERROR: "); break;
-				case ERR_WARNING: print("WARNING: "); break;
-				case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
-			}
-
-			SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
-			print(" %s\n",p_rationale);
-			SetConsoleTextAttribute(hCon,basecol);
-			print("At: ");
-			SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
-			print(" %s:%i\n",p_file,p_line);
-
-
-		} else {
-			SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
-			switch(p_type) {
-				case ERR_ERROR: print("ERROR: %s: ",p_function); break;
-				case ERR_WARNING: print("WARNING: %s: ",p_function); break;
-				case ERR_SCRIPT: print("SCRIPT ERROR: %s: ",p_function); break;
-			}
-			SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
-			print(" %s\n",p_code);
-			SetConsoleTextAttribute(hCon,basecol);
-			print("At: ");
-			SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
-			print(" %s:%i\n",p_file,p_line);
-		}
-
-		SetConsoleTextAttribute(hCon,sbi.wAttributes);
 	}
-
 }
 
 
@@ -566,10 +471,10 @@ uint64_t OSWinrt::get_unix_time() const {
 
 void OSWinrt::delay_usec(uint32_t p_usec) const {
 
-        if (p_usec < 1000)
-                Sleep(1);
-        else
-                Sleep(p_usec / 1000);
+	int msec = p_usec < 1000 ? 1 : p_usec / 1000;
+
+	// no Sleep()
+	WaitForSingleObjectEx(GetCurrentThread(), msec, false);
 	
 }
 uint64_t OSWinrt::get_ticks_usec() const {
@@ -607,19 +512,12 @@ Error OSWinrt::kill(const ProcessID& p_pid) {
 
 Error OSWinrt::set_cwd(const String& p_cwd) {
 
-	if (_wchdir(p_cwd.c_str())!=0)
-		return ERR_CANT_OPEN;
-
 	return OK;
 }
 
 String OSWinrt::get_executable_path() const {
 
-	wchar_t bufname[4096];
-	GetModuleFileNameW(NULL,bufname,4096);
-	String s= bufname;
-	print_line("EXEC PATHPó: "+s);
-	return s;
+	return "";
 }
 
 void OSWinrt::set_icon(const Image& p_icon) {
@@ -629,25 +527,16 @@ void OSWinrt::set_icon(const Image& p_icon) {
 
 bool OSWinrt::has_environment(const String& p_var) const {
 
-	return getenv(p_var.utf8().get_data()) != NULL;
+	return false;
 };
 
 String OSWinrt::get_environment(const String& p_var) const {
 
-	char* val = getenv(p_var.utf8().get_data());
-	if (val)
-		return val;
-
 	return "";
 };
 
 String OSWinrt::get_stdin_string(bool p_block) {
 
-	if (p_block) {
-		char buff[1024];
-		return fgets(buff,1024,stdin);
-	};
-
 	return String();
 }
 
@@ -665,23 +554,22 @@ Error OSWinrt::shell_open(String p_uri) {
 String OSWinrt::get_locale() const {
 
 	Platform::String ^language = Windows::Globalization::Language::CurrentInputMethodLanguageTag;
-	return language.Data();
+	return language->Data();
 }
 
 void OSWinrt::release_rendering_thread() {
 
-	//gl_context->release_current();
-
+	gl_context->release_current();
 }
 
 void OSWinrt::make_rendering_thread() {
 
-	//gl_context->make_current();
+	gl_context->make_current();
 }
 
 void OSWinrt::swap_buffers() {
 
-	//gl_context->swap_buffers();
+	gl_context->swap_buffers();
 }
 
 
@@ -699,6 +587,7 @@ void OSWinrt::run() {
 	
 	while (!force_quit) {
 	
+		CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
 		process_events(); // get rid of pending events
 		if (Main::iteration()==true)
 			break;
@@ -724,7 +613,7 @@ String OSWinrt::get_data_dir() const {
 }
 
 
-OSWinrt::OSWinrt(HINSTANCE _hInstance) {
+OSWinrt::OSWinrt() {
 
 	key_event_pos=0;
 	force_quit=false;
@@ -743,6 +632,8 @@ OSWinrt::OSWinrt(HINSTANCE _hInstance) {
 	stdo=fopen("stdout.txt","wb");
 #endif
 
+	gl_context = NULL;
+
 }
 
 

+ 5 - 2
platform/winrt/os_winrt.h

@@ -41,11 +41,10 @@
 #include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h"
 #include "servers/physics_2d/physics_2d_server_sw.h"
 
+#include "gl_context_egl.h"
 
 #include <windows.h>
 
-#include "key_mapping_win.h"
-#include <windowsx.h>
 #include <io.h>
 
 #include <fcntl.h>
@@ -93,6 +92,8 @@ class OSWinrt : public OS {
 	Physics2DServer *physics_2d_server;
 	int pressrc;
 
+	ContextEGL* gl_context;
+
 	struct Joystick {
 
 		int id;
@@ -224,6 +225,8 @@ public:
 	virtual void move_window_to_foreground();
 	virtual String get_data_dir() const;
 
+	void set_gl_context(ContextEGL* p_context);
+
 	virtual void release_rendering_thread();
 	virtual void make_rendering_thread();
 	virtual void swap_buffers();

+ 194 - 12
scene/2d/tile_map.cpp

@@ -106,9 +106,9 @@ Ref<TileSet> TileMap::get_tileset() const {
 	return tile_set;
 }
 
-void TileMap::set_cell_size(int p_size) {
+void TileMap::set_cell_size(Size2 p_size) {
 
-	ERR_FAIL_COND(p_size<1);
+	ERR_FAIL_COND(p_size.x<1 || p_size.y<1);
 
 	_clear_quadrants();
 	cell_size=p_size;
@@ -117,7 +117,7 @@ void TileMap::set_cell_size(int p_size) {
 
 
 }
-int TileMap::get_cell_size() const {
+Size2 TileMap::get_cell_size() const {
 
 	return cell_size;
 }
@@ -171,6 +171,7 @@ void TileMap::_update_dirty_quadrants() {
 
 	VisualServer *vs = VisualServer::get_singleton();
 	Physics2DServer *ps = Physics2DServer::get_singleton();
+	Vector2 tofs = get_cell_draw_offset();
 
 	while (dirty_quadrant_list.first()) {
 
@@ -189,7 +190,7 @@ void TileMap::_update_dirty_quadrants() {
 			Ref<Texture> tex = tile_set->tile_get_texture(c.id);
 			Vector2 tile_ofs = tile_set->tile_get_texture_offset(c.id);
 
-			Vector2 offset = Point2( E->key().x, E->key().y )*cell_size - q.pos;
+			Vector2 offset = _map_to_world(E->key().x, E->key().y) - q.pos + tofs;
 
 			if (!tex.is_valid())
 				continue;
@@ -299,7 +300,11 @@ void TileMap::_recompute_rect_cache() {
 	for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
 
 
-		Rect2 r( Point2(E->key().x, E->key().y)*cell_size*quadrant_size, Size2(1,1)*cell_size*quadrant_size );
+		Rect2 r;
+		r.pos=_map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size);
+		r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size) );
+		r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size+quadrant_size) );
+		r.expand_to( _map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size+quadrant_size) );
 		if (E==quadrant_map.front())
 			r_total=r;
 		else
@@ -323,8 +328,10 @@ void TileMap::_recompute_rect_cache() {
 Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const PosKey& p_qk) {
 
 	Matrix32 xform;
-	xform.set_origin(Point2(p_qk.x,p_qk.y)*quadrant_size*cell_size);
+	//xform.set_origin(Point2(p_qk.x,p_qk.y)*cell_size*quadrant_size);
 	Quadrant q;
+	q.pos = _map_to_world(p_qk.x*quadrant_size,p_qk.y*quadrant_size);
+	xform.set_origin( q.pos );
 	q.canvas_item = VisualServer::get_singleton()->canvas_item_create();
 	VisualServer::get_singleton()->canvas_item_set_parent( q.canvas_item, get_canvas_item() );
 	VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform );
@@ -341,7 +348,6 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const
 	}
 
 	Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
-	q.pos=Vector2(p_qk.x,p_qk.y)*quadrant_size*cell_size;
 
 	rect_cache_dirty=true;
 	quadrant_order_dirty=true;
@@ -478,8 +484,11 @@ void TileMap::_recreate_quadrants() {
 		}
 
 		Q->get().cells.insert(E->key());
-
+		_make_quadrant_dirty(Q);
 	}
+
+
+
 }
 
 void TileMap::_clear_quadrants() {
@@ -614,6 +623,152 @@ uint32_t TileMap::get_collision_layer_mask() const {
 	return collision_layer;
 }
 
+void TileMap::set_mode(Mode p_mode) {
+
+	_clear_quadrants();
+	mode=p_mode;
+	_recreate_quadrants();
+	emit_signal("settings_changed");
+}
+
+TileMap::Mode TileMap::get_mode() const {
+	return mode;
+}
+
+void TileMap::set_half_offset(HalfOffset p_half_offset) {
+
+	_clear_quadrants();
+	half_offset=p_half_offset;
+	_recreate_quadrants();
+	emit_signal("settings_changed");
+}
+
+Vector2 TileMap::get_cell_draw_offset() const {
+
+	switch(mode) {
+
+		case MODE_SQUARE: {
+
+			return Vector2();
+		} break;
+		case MODE_ISOMETRIC: {
+
+			return Vector2(-cell_size.x*0.5,0);
+
+		} break;
+		case MODE_CUSTOM: {
+
+			Vector2 min;
+			min.x = MIN(custom_transform[0].x,min.x);
+			min.y = MIN(custom_transform[0].y,min.y);
+			min.x = MIN(custom_transform[1].x,min.x);
+			min.y = MIN(custom_transform[1].y,min.y);
+			return min;
+		} break;
+	}
+
+	return Vector2();
+
+}
+
+TileMap::HalfOffset TileMap::get_half_offset() const {
+	return half_offset;
+}
+
+Matrix32 TileMap::get_cell_transform() const {
+
+	switch(mode) {
+
+		case MODE_SQUARE: {
+
+			Matrix32 m;
+			m[0]*=cell_size.x;
+			m[1]*=cell_size.y;
+			return m;
+		} break;
+		case MODE_ISOMETRIC: {
+
+			//isometric only makes sense when y is positive in both x and y vectors, otherwise
+			//the drawing of tiles will overlap
+			Matrix32 m;
+			m[0]=Vector2(cell_size.x*0.5,cell_size.y*0.5);
+			m[1]=Vector2(-cell_size.x*0.5,cell_size.y*0.5);
+			return m;
+
+		} break;
+		case MODE_CUSTOM: {
+
+			return custom_transform;
+		} break;
+	}
+
+	return Matrix32();
+}
+
+void TileMap::set_custom_transform(const Matrix32& p_xform) {
+
+	_clear_quadrants();
+	custom_transform=p_xform;
+	_recreate_quadrants();
+	emit_signal("settings_changed");
+
+}
+
+Matrix32 TileMap::get_custom_transform() const{
+
+	return custom_transform;
+}
+
+Vector2 TileMap::_map_to_world(int x,int y,bool p_ignore_ofs) const {
+
+	Vector2 ret = get_cell_transform().xform(Vector2(x,y));
+	if (!p_ignore_ofs) {
+		switch(half_offset) {
+
+			case HALF_OFFSET_X: {
+				if (ABS(y)&1) {
+
+					ret+=get_cell_transform()[0]*0.5;
+				}
+			} break;
+			case HALF_OFFSET_Y: {
+				if (ABS(x)&1) {
+					ret+=get_cell_transform()[1]*0.5;
+				}
+			} break;
+			default: {}
+		}
+	}
+	return ret;
+}
+Vector2 TileMap::map_to_world(const Vector2& p_pos,bool p_ignore_ofs) const {
+
+	return _map_to_world(p_pos.x,p_pos.y,p_ignore_ofs);
+}
+Vector2 TileMap::world_to_map(const Vector2& p_pos) const{
+
+	Vector2 ret = get_cell_transform().affine_inverse().xform(p_pos);
+
+
+	switch(half_offset) {
+
+		case HALF_OFFSET_X: {
+			if (int(ret.y)&1) {
+
+				ret.x-=0.5;
+			}
+		} break;
+		case HALF_OFFSET_Y: {
+			if (int(ret.x)&1) {
+				ret.y-=0.5;
+			}
+		} break;
+		default: {}
+	}
+
+	return ret.floor();
+}
+
 
 void TileMap::_bind_methods() {
 
@@ -621,10 +776,21 @@ void TileMap::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_tileset","tileset:TileSet"),&TileMap::set_tileset);
 	ObjectTypeDB::bind_method(_MD("get_tileset:TileSet"),&TileMap::get_tileset);
 
+	ObjectTypeDB::bind_method(_MD("set_mode","mode"),&TileMap::set_mode);
+	ObjectTypeDB::bind_method(_MD("get_mode"),&TileMap::get_mode);
+
+	ObjectTypeDB::bind_method(_MD("set_half_offset","half_offset"),&TileMap::set_half_offset);
+	ObjectTypeDB::bind_method(_MD("get_half_offset"),&TileMap::get_half_offset);
+
+	ObjectTypeDB::bind_method(_MD("set_custom_transform","custom_transform"),&TileMap::set_custom_transform);
+	ObjectTypeDB::bind_method(_MD("get_custom_transform"),&TileMap::get_custom_transform);
 
 	ObjectTypeDB::bind_method(_MD("set_cell_size","size"),&TileMap::set_cell_size);
 	ObjectTypeDB::bind_method(_MD("get_cell_size"),&TileMap::get_cell_size);
 
+	ObjectTypeDB::bind_method(_MD("_set_old_cell_size","size"),&TileMap::_set_old_cell_size);
+	ObjectTypeDB::bind_method(_MD("_get_old_cell_size"),&TileMap::_get_old_cell_size);
+
 	ObjectTypeDB::bind_method(_MD("set_quadrant_size","size"),&TileMap::set_quadrant_size);
 	ObjectTypeDB::bind_method(_MD("get_quadrant_size"),&TileMap::get_quadrant_size);
 
@@ -650,6 +816,9 @@ void TileMap::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("clear"),&TileMap::clear);
 
+	ObjectTypeDB::bind_method(_MD("map_to_world","mappos","ignore_half_ofs"),&TileMap::map_to_world,DEFVAL(false));
+	ObjectTypeDB::bind_method(_MD("world_to_map","worldpos"),&TileMap::world_to_map);
+
 	ObjectTypeDB::bind_method(_MD("_clear_quadrants"),&TileMap::_clear_quadrants);
 	ObjectTypeDB::bind_method(_MD("_recreate_quadrants"),&TileMap::_recreate_quadrants);
 	ObjectTypeDB::bind_method(_MD("_update_dirty_quadrants"),&TileMap::_update_dirty_quadrants);
@@ -657,17 +826,28 @@ void TileMap::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("_set_tile_data"),&TileMap::_set_tile_data);
 	ObjectTypeDB::bind_method(_MD("_get_tile_data"),&TileMap::_get_tile_data);
 
-	ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1"),_SCS("set_cell_size"),_SCS("get_cell_size"));
-	ADD_PROPERTY( PropertyInfo(Variant::INT,"quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size"));
+	ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Square,Isometric,Custom"),_SCS("set_mode"),_SCS("get_mode"));
 	ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_set",PROPERTY_HINT_RESOURCE_TYPE,"TileSet"),_SCS("set_tileset"),_SCS("get_tileset"));
-	ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data"));
+	ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1",0),_SCS("_set_old_cell_size"),_SCS("_get_old_cell_size"));
+	ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"cell/size",PROPERTY_HINT_RANGE,"1,8192,1"),_SCS("set_cell_size"),_SCS("get_cell_size"));
+	ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size"));
+	ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"cell/custom_transform"),_SCS("set_custom_transform"),_SCS("get_custom_transform"));
+	ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),_SCS("set_half_offset"),_SCS("get_half_offset"));
 	ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction"));
 	ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce"));
 	ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer_mask"),_SCS("get_collision_layer_mask"));
+	ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data"));
 
 	ADD_SIGNAL(MethodInfo("settings_changed"));
 
 	BIND_CONSTANT( INVALID_CELL );
+	BIND_CONSTANT( MODE_SQUARE );
+	BIND_CONSTANT( MODE_ISOMETRIC );
+	BIND_CONSTANT( MODE_CUSTOM );
+	BIND_CONSTANT( HALF_OFFSET_X );
+	BIND_CONSTANT( HALF_OFFSET_Y );
+	BIND_CONSTANT( HALF_OFFSET_DISABLED );
+
 }
 
 TileMap::TileMap() {
@@ -678,12 +858,14 @@ TileMap::TileMap() {
 	pending_update=false;
 	quadrant_order_dirty=false;
 	quadrant_size=16;
-	cell_size=64;
+	cell_size=Size2(64,64);
 	center_x=false;
 	center_y=false;
 	collision_layer=1;
 	friction=1;
 	bounce=0;
+	mode=MODE_SQUARE;
+	half_offset=HALF_OFFSET_DISABLED;
 
 	fp_adjust=0.01;
 	fp_adjust=0.01;

+ 45 - 3
scene/2d/tile_map.h

@@ -37,12 +37,30 @@
 class TileMap : public Node2D {
 
 	OBJ_TYPE( TileMap, Node2D );
+public:
+
+	enum Mode {
+		MODE_SQUARE,
+		MODE_ISOMETRIC,
+		MODE_CUSTOM
+	};
+
+	enum HalfOffset {
+		HALF_OFFSET_X,
+		HALF_OFFSET_Y,
+		HALF_OFFSET_DISABLED,
+	};
 
+private:
 
 	Ref<TileSet> tile_set;
-	int cell_size;
+	Size2i cell_size;
 	int quadrant_size;
 	bool center_x,center_y;
+	Mode mode;
+	Matrix32 custom_transform;
+	HalfOffset half_offset;
+
 
 	union PosKey {
 
@@ -117,6 +135,12 @@ class TileMap : public Node2D {
 
 	void _set_tile_data(const DVector<int>& p_data);
 	DVector<int> _get_tile_data() const;
+
+	void _set_old_cell_size(int p_size) { set_cell_size(Size2(p_size,p_size)); }
+	int _get_old_cell_size() const { return cell_size.x; }
+
+	_FORCE_INLINE_ Vector2 _map_to_world(int p_x,int p_y,bool p_ignore_ofs=false) const;
+
 protected:
 
 
@@ -132,8 +156,8 @@ public:
 	void set_tileset(const Ref<TileSet>& p_tileset);
 	Ref<TileSet> get_tileset() const;
 
-	void set_cell_size(int p_size);
-	int get_cell_size() const;
+	void set_cell_size(Size2 p_size);
+	Size2 get_cell_size() const;
 
 	void set_quadrant_size(int p_size);
 	int get_quadrant_size() const;
@@ -159,10 +183,28 @@ public:
 	void set_collision_bounce(float p_bounce);
 	float get_collision_bounce() const;
 
+	void set_mode(Mode p_mode);
+	Mode get_mode() const;
+
+	void set_half_offset(HalfOffset p_half_offset);
+	HalfOffset get_half_offset() const;
+
+	void set_custom_transform(const Matrix32& p_xform);
+	Matrix32 get_custom_transform() const;
+
+	Matrix32 get_cell_transform() const;
+	Vector2 get_cell_draw_offset() const;
+
+	Vector2 map_to_world(const Vector2& p_pos, bool p_ignore_ofs=false) const;
+	Vector2 world_to_map(const Vector2& p_pos) const;
+
 	void clear();
 
 	TileMap();
 	~TileMap();
 };
 
+VARIANT_ENUM_CAST(TileMap::Mode);
+VARIANT_ENUM_CAST(TileMap::HalfOffset);
+
 #endif // TILE_MAP_H

+ 29 - 0
scene/2d/y_sort.cpp

@@ -0,0 +1,29 @@
+#include "y_sort.h"
+
+
+
+void YSort::set_sort_enabled(bool p_enabled) {
+
+	sort_enabled=p_enabled;
+	VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(),sort_enabled);
+}
+
+bool YSort::is_sort_enabled() const {
+
+	return sort_enabled;
+}
+
+void YSort::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("set_sort_enabled","enabled"),&YSort::set_sort_enabled);
+	ObjectTypeDB::bind_method(_MD("is_sort_enabled"),&YSort::is_sort_enabled);
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"sort/enabled"),_SCS("set_sort_enabled"),_SCS("is_sort_enabled"));
+}
+
+
+YSort::YSort() {
+
+	sort_enabled=true;
+	VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(),true);
+}

+ 17 - 0
scene/2d/y_sort.h

@@ -0,0 +1,17 @@
+#ifndef Y_SORT_H
+#define Y_SORT_H
+
+#include "scene/2d/node_2d.h"
+
+class YSort : public Node2D {
+	OBJ_TYPE(YSort,Node2D);
+	bool sort_enabled;
+	static void _bind_methods();
+public:
+
+	void set_sort_enabled(bool p_enabled);
+	bool is_sort_enabled() const;
+	YSort();
+};
+
+#endif // Y_SORT_H

+ 1 - 14
scene/3d/area.cpp

@@ -255,16 +255,6 @@ bool Area::is_monitoring_enabled() const {
 }
 
 
-void Area::set_ray_pickable(bool p_ray_pickable) {
-
-	ray_pickable=p_ray_pickable;
-	PhysicsServer::get_singleton()->area_set_ray_pickable(get_rid(),p_ray_pickable);
-}
-
-bool Area::is_ray_pickable() const {
-
-	return ray_pickable;
-}
 
 void Area::_bind_methods() {
 
@@ -289,8 +279,6 @@ void Area::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area::set_priority);
 	ObjectTypeDB::bind_method(_MD("get_priority"),&Area::get_priority);
 
-	ObjectTypeDB::bind_method(_MD("set_ray_pickable","ray_pickable"),&Area::set_ray_pickable);
-	ObjectTypeDB::bind_method(_MD("is_ray_pickable"),&Area::is_ray_pickable);
 
 	ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area::set_enable_monitoring);
 	ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area::is_monitoring_enabled);
@@ -310,7 +298,6 @@ void Area::_bind_methods() {
 	ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density"));
 	ADD_PROPERTY( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
 	ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled"));
-	ADD_PROPERTY( PropertyInfo(Variant::BOOL,"ray_pickable"),_SCS("set_ray_pickable"),_SCS("is_ray_pickable"));
 
 }
 
@@ -323,7 +310,7 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru
 	density=0.1;
 	priority=0;
 	monitoring=false;
-	ray_pickable=false;
+	set_ray_pickable(false);
 	set_enable_monitoring(true);
 
 }

+ 1 - 4
scene/3d/area.h

@@ -52,7 +52,7 @@ private:
 	real_t density;
 	int priority;
 	bool monitoring;
-	bool ray_pickable;
+
 
 	void _body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape);
 
@@ -109,9 +109,6 @@ public:
 	void set_priority(real_t p_priority);
 	real_t get_priority() const;
 
-	void set_ray_pickable(bool p_ray_pickable);
-	bool is_ray_pickable() const;
-
 	void set_enable_monitoring(bool p_enable);
 	bool is_monitoring_enabled() const;
 

+ 3 - 3
scene/3d/camera.cpp

@@ -262,7 +262,7 @@ void Camera::_notification(int p_what) {
 
 Transform Camera::get_camera_transform() const {
 
-	return get_global_transform();
+	return get_global_transform().orthonormalized();
 }
 
 void Camera::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
@@ -695,7 +695,7 @@ Vector<Plane> Camera::get_frustum() const {
 	else
 		cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH);
 
-	return cm.get_projection_planes(get_global_transform());
+	return cm.get_projection_planes(get_camera_transform());
 
 }
 
@@ -704,7 +704,7 @@ Vector<Plane> Camera::get_frustum() const {
 void Camera::look_at(const Vector3& p_target, const Vector3& p_up_normal) {
 
 	Transform lookat;
-	lookat.origin=get_global_transform().origin;
+	lookat.origin=get_camera_transform().origin;
 	lookat=lookat.looking_at(p_target,p_up_normal);
 	set_global_transform(lookat);
 }

+ 45 - 11
scene/3d/collision_object.cpp

@@ -53,8 +53,9 @@ void CollisionObject::_notification(int p_what) {
 			} else
 				PhysicsServer::get_singleton()->body_set_space(rid,space);
 
+			_update_pickable();
 		//get space
-		}
+		};
 
 		case NOTIFICATION_TRANSFORM_CHANGED: {
 
@@ -63,6 +64,11 @@ void CollisionObject::_notification(int p_what) {
 			else
 				PhysicsServer::get_singleton()->body_set_state(rid,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform());
 
+		} break;
+		case NOTIFICATION_VISIBILITY_CHANGED: {
+
+			_update_pickable();
+
 		} break;
 		case NOTIFICATION_EXIT_WORLD: {
 
@@ -91,11 +97,11 @@ void CollisionObject::_update_shapes() {
 			continue;
 		if (area)
 			PhysicsServer::get_singleton()->area_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform);
-        else {
+		else {
 			PhysicsServer::get_singleton()->body_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform);
-            if (shapes[i].trigger)
-                PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid,i,shapes[i].trigger);
-        }
+			if (shapes[i].trigger)
+				PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid,i,shapes[i].trigger);
+		}
 	}
 }
 
@@ -160,18 +166,18 @@ void CollisionObject::_get_property_list( List<PropertyInfo> *p_list) const {
 		String path="shapes/"+itos(i)+"/";
 		p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape",PROPERTY_USAGE_NOEDITOR) );
 		p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
-        p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
+		p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
 
 	}
 }
 
 
-void CollisionObject::_input_event(const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape) {
+void CollisionObject::_input_event(Node *p_camera, const InputEvent& p_input_event, const Vector3& p_pos, const Vector3& p_normal, int p_shape) {
 
 	if (get_script_instance()) {
-		get_script_instance()->call(SceneStringNames::get_singleton()->_input_event,p_input_event,p_pos,p_normal,p_shape);
+		get_script_instance()->call(SceneStringNames::get_singleton()->_input_event,p_camera,p_input_event,p_pos,p_normal,p_shape);
 	}
-	emit_signal(SceneStringNames::get_singleton()->input_event,p_input_event,p_pos,p_normal,p_shape);
+	emit_signal(SceneStringNames::get_singleton()->input_event,p_camera,p_input_event,p_pos,p_normal,p_shape);
 }
 
 void CollisionObject::_mouse_enter() {
@@ -192,6 +198,28 @@ void CollisionObject::_mouse_exit() {
 
 }
 
+void CollisionObject::_update_pickable() {
+	if (!is_inside_scene())
+		return;
+	bool pickable = ray_pickable && is_inside_scene() && is_visible();
+	if (area)
+		PhysicsServer::get_singleton()->area_set_ray_pickable(rid,pickable);
+	else
+		PhysicsServer::get_singleton()->body_set_ray_pickable(rid,pickable);
+}
+
+void CollisionObject::set_ray_pickable(bool p_ray_pickable) {
+
+	ray_pickable=p_ray_pickable;
+	_update_pickable();
+
+}
+
+bool CollisionObject::is_ray_pickable() const {
+
+	return ray_pickable;
+}
+
 
 void CollisionObject::_bind_methods() {
 
@@ -206,15 +234,18 @@ void CollisionObject::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_shape_transform","shape_idx"),&CollisionObject::get_shape_transform);
 	ObjectTypeDB::bind_method(_MD("remove_shape","shape_idx"),&CollisionObject::remove_shape);
 	ObjectTypeDB::bind_method(_MD("clear_shapes"),&CollisionObject::clear_shapes);
+	ObjectTypeDB::bind_method(_MD("set_ray_pickable","ray_pickable"),&CollisionObject::set_ray_pickable);
+	ObjectTypeDB::bind_method(_MD("is_ray_pickable"),&CollisionObject::is_ray_pickable);
 	ObjectTypeDB::bind_method(_MD("set_capture_input_on_drag","enable"),&CollisionObject::set_capture_input_on_drag);
 	ObjectTypeDB::bind_method(_MD("get_capture_input_on_drag"),&CollisionObject::get_capture_input_on_drag);
 	ObjectTypeDB::bind_method(_MD("get_rid"),&CollisionObject::get_rid);
-	BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
+	BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::OBJECT,"camera"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
 
-	ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
+	ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::OBJECT,"camera"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
 	ADD_SIGNAL( MethodInfo("mouse_enter"));
 	ADD_SIGNAL( MethodInfo("mouse_exit"));
 
+	ADD_PROPERTY( PropertyInfo(Variant::BOOL,"input/ray_pickable"),_SCS("set_ray_pickable"),_SCS("is_ray_pickable"));
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"input/capture_on_drag"),_SCS("set_capture_input_on_drag"),_SCS("get_capture_input_on_drag"));
 }
 
@@ -296,6 +327,8 @@ CollisionObject::CollisionObject(RID p_rid, bool p_area) {
 
 	rid=p_rid;
 	area=p_area;
+	capture_input_on_drag=false;
+	ray_pickable=true;
 	if (p_area) {
 		PhysicsServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID());
 	} else {
@@ -321,6 +354,7 @@ CollisionObject::CollisionObject() {
 
 
 	capture_input_on_drag=false;
+	ray_pickable=true;
 
 	//owner=
 

+ 7 - 2
scene/3d/collision_object.h

@@ -51,9 +51,10 @@ class CollisionObject : public Spatial {
 	};
 
 	bool capture_input_on_drag;
-
+	bool ray_pickable;
 	Vector<ShapeData> shapes;
 
+	void _update_pickable();
 	void _update_shapes();
 
 friend class CollisionShape;
@@ -69,7 +70,7 @@ protected:
 	void _get_property_list( List<PropertyInfo> *p_list) const;
 	static void _bind_methods();
 friend class Viewport;
-	virtual void _input_event(const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape);
+	virtual void _input_event(Node* p_camera,const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape);
 	virtual void _mouse_enter();
 	virtual void _mouse_exit();
 
@@ -87,9 +88,13 @@ public:
 	void set_shape_as_trigger(int p_shape_idx, bool p_trigger);
 	bool is_shape_set_as_trigger(int p_shape_idx) const;
 
+	void set_ray_pickable(bool p_ray_pickable);
+	bool is_ray_pickable() const;
+
 	void set_capture_input_on_drag(bool p_capture);
 	bool get_capture_input_on_drag() const;
 
+
 	_FORCE_INLINE_ RID get_rid() const { return rid; }
 
 	CollisionObject();

+ 1 - 1
scene/3d/light.cpp

@@ -622,7 +622,7 @@ void SpotLight::_bind_methods() {
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ATTENUATION );
 
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_angle", PROPERTY_HINT_RANGE, "0.01,89.9,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ANGLE );
-	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ATTENUATION );
+	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ATTENUATION );
 
 }
 

+ 12 - 2
scene/3d/navigation.cpp

@@ -21,6 +21,7 @@ void Navigation::_navmesh_link(int p_id) {
 
 		List<Polygon>::Element *P=nm.polygons.push_back(Polygon());
 		Polygon &p=P->get();
+		p.owner=&nm;
 
 		Vector<int> poly = nm.navmesh->get_polygon(i);
 		int plen=poly.size();
@@ -145,13 +146,14 @@ void Navigation::_navmesh_unlink(int p_id) {
 }
 
 
-int Navigation::navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform) {
+int Navigation::navmesh_create(const Ref<NavigationMesh>& p_mesh, const Transform& p_xform, Object *p_owner) {
 
 	int id = last_id++;
 	NavMesh nm;
 	nm.linked=false;
 	nm.navmesh=p_mesh;
 	nm.xform=p_xform;
+	nm.owner=p_owner;
 	navmesh_map[id]=nm;
 
 	_navmesh_link(id);
@@ -453,6 +455,7 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
 	bool use_collision=false;
 	Vector3 closest_point;
 	float closest_point_d=1e20;
+	NavMesh *closest_navmesh=NULL;
 
 	for (Map<int,NavMesh>::Element*E=navmesh_map.front();E;E=E->next()) {
 
@@ -471,10 +474,12 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
 						closest_point=inters;
 						use_collision=true;
 						closest_point_d=p_from.distance_to(inters);
+						closest_navmesh=p.owner;
 					} else if (closest_point_d > inters.distance_to(p_from)){
 
 						closest_point=inters;
 						closest_point_d=p_from.distance_to(inters);
+						closest_navmesh=p.owner;
 					}
 				}
 			}
@@ -492,6 +497,7 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
 
 						closest_point_d=d;
 						closest_point=b;
+						closest_navmesh=p.owner;
 					}
 
 				}
@@ -499,6 +505,10 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
 		}
 	}
 
+	if (closest_navmesh && closest_navmesh->owner) {
+		//print_line("navmesh is: "+closest_navmesh->owner->cast_to<Node>()->get_name());
+	}
+
 	return closest_point;
 }
 
@@ -577,7 +587,7 @@ Vector3 Navigation::get_up_vector() const{
 
 void Navigation::_bind_methods() {
 
-	ObjectTypeDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform"),&Navigation::navmesh_create);
+	ObjectTypeDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform","owner"),&Navigation::navmesh_create,DEFVAL(Variant()));
 	ObjectTypeDB::bind_method(_MD("navmesh_set_transform","id","xform"),&Navigation::navmesh_set_transform);
 	ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove);
 

+ 6 - 1
scene/3d/navigation.h

@@ -41,6 +41,8 @@ class Navigation : public Spatial {
 	};
 
 
+	struct NavMesh;
+
 
 	struct Polygon {
 
@@ -57,6 +59,8 @@ class Navigation : public Spatial {
 
 		float distance;
 		int prev_edge;
+
+		NavMesh *owner;
 	};
 
 
@@ -74,6 +78,7 @@ class Navigation : public Spatial {
 
 	struct NavMesh {
 
+		Object *owner;
 		Transform xform;
 		bool linked;
 		Ref<NavigationMesh> navmesh;
@@ -124,7 +129,7 @@ public:
 	Vector3 get_up_vector() const;
 
 	//API should be as dynamic as possible
-	int navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform);
+	int navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform,Object* p_owner=NULL);
 	void navmesh_set_transform(int p_id, const Transform& p_xform);
 	void navmesh_remove(int p_id);
 

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

@@ -129,7 +129,7 @@ void NavigationMeshInstance::set_enabled(bool p_enabled) {
 
 			if (navmesh.is_valid()) {
 
-				nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
+				nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this);
 			}
 		}
 
@@ -162,7 +162,7 @@ void NavigationMeshInstance::_notification(int p_what) {
 
 					if (enabled && navmesh.is_valid()) {
 
-						nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
+						nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this);
 					}
 					break;
 				}
@@ -205,7 +205,7 @@ void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh>& p_na
 	navmesh=p_navmesh;
 
 	if (navigation && navmesh.is_valid() && enabled) {
-		nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
+		nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this);
 	}
 	update_gizmo();
 

+ 22 - 3
scene/3d/physics_joint.cpp

@@ -66,6 +66,9 @@ void Joint::_update_joint(bool p_only_free) {
 
 	joint = _configure_joint(body_a,body_b);
 
+	if (joint.is_valid())
+		PhysicsServer::get_singleton()->joint_set_solver_priority(joint,solver_priority);
+
 	if (body_b && joint.is_valid()) {
 
 		ba=body_a->get_rid();
@@ -107,6 +110,20 @@ NodePath Joint::get_node_b() const{
 }
 
 
+void Joint::set_solver_priority(int p_priority) {
+
+	solver_priority=p_priority;
+	if (joint.is_valid())
+		PhysicsServer::get_singleton()->joint_set_solver_priority(joint,solver_priority);
+
+}
+
+int Joint::get_solver_priority() const {
+
+	return solver_priority;
+}
+
+
 void Joint::_notification(int p_what) {
 
 	switch(p_what) {
@@ -117,8 +134,6 @@ void Joint::_notification(int p_what) {
 		case NOTIFICATION_EXIT_SCENE: {
 			if (joint.is_valid()) {
 				_update_joint(true);
-
-
 				PhysicsServer::get_singleton()->free(joint);
 				joint=RID();
 			}
@@ -138,9 +153,13 @@ void Joint::_bind_methods() {
 	ObjectTypeDB::bind_method( _MD("set_node_b","node"), &Joint::set_node_b );
 	ObjectTypeDB::bind_method( _MD("get_node_b"), &Joint::get_node_b );
 
+	ObjectTypeDB::bind_method( _MD("set_solver_priority","priority"), &Joint::set_solver_priority );
+	ObjectTypeDB::bind_method( _MD("get_solver_priority"), &Joint::get_solver_priority );
 
 	ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "nodes/node_a"), _SCS("set_node_a"),_SCS("get_node_a") );
 	ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "nodes/node_b"), _SCS("set_node_b"),_SCS("get_node_b") );
+	ADD_PROPERTY( PropertyInfo( Variant::INT, "solver/priority",PROPERTY_HINT_RANGE,"1,8,1"), _SCS("set_solver_priority"),_SCS("get_solver_priority") );
+
 
 }
 
@@ -148,7 +167,7 @@ void Joint::_bind_methods() {
 
 Joint::Joint() {
 
-
+	solver_priority=1;
 }
 
 

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

@@ -44,6 +44,8 @@ class Joint : public Spatial {
 	NodePath a;
 	NodePath b;
 
+	int solver_priority;
+
 
 protected:
 
@@ -62,6 +64,9 @@ public:
 	void set_node_b(const NodePath& p_node_b);
 	NodePath get_node_b() const;
 
+	void set_solver_priority(int p_priority);
+	int get_solver_priority() const;
+
 	RID get_joint() const { return joint; }
 	Joint();
 

+ 7 - 6
scene/3d/vehicle_body.cpp

@@ -179,7 +179,7 @@ void VehicleWheel::set_damping_compression(float p_value){
 }
 float VehicleWheel::get_damping_compression() const{
 
-	return m_wheelsDampingRelaxation;
+	return m_wheelsDampingCompression;
 }
 
 void VehicleWheel::set_damping_relaxation(float p_value){
@@ -745,11 +745,12 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) {
 			{
 				if (engine_force != 0.f)
 				{
-					rollingFriction = engine_force* s->get_step();
+					rollingFriction = -engine_force* s->get_step();
 				} else
 				{
 					real_t defaultRollingFrictionImpulse = 0.f;
-					real_t maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
+					float cbrake = MAX(wheelInfo.m_brake,brake);
+					real_t maxImpulse = cbrake ? cbrake : defaultRollingFrictionImpulse;
 					btVehicleWheelContactPoint contactPt(s,wheelInfo.m_raycastInfo.m_groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
 					rollingFriction = _calc_rolling_friction(contactPt);
 				}
@@ -1009,9 +1010,9 @@ void VehicleBody::_bind_methods(){
 
 	ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&VehicleBody::_direct_state_changed);
 
-	ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/engine_force",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_engine_force"),_SCS("get_engine_force"));
-	ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/brake",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_brake"),_SCS("get_brake"));
-	ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/steering",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_steering"),_SCS("get_steering"));
+	ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/engine_force",PROPERTY_HINT_RANGE,"0.00,1024.0,0.01"),_SCS("set_engine_force"),_SCS("get_engine_force"));
+	ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/brake",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_brake"),_SCS("get_brake"));
+	ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/steering",PROPERTY_HINT_RANGE,"-180,180.0,0.01"),_SCS("set_steering"),_SCS("get_steering"));
 	ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/mass",PROPERTY_HINT_RANGE,"0.01,65536,0.01"),_SCS("set_mass"),_SCS("get_mass"));
 	ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/friction",PROPERTY_HINT_RANGE,"0.01,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
 

+ 6 - 0
scene/animation/animation_player.cpp

@@ -180,6 +180,10 @@ void AnimationPlayer::_get_property_list( List<PropertyInfo> *p_list) const {
 
 }
 
+void AnimationPlayer::advance(float p_time) {
+
+	_animation_process( p_time );
+}
 
 void AnimationPlayer::_notification(int p_what) {
 
@@ -1227,6 +1231,8 @@ void AnimationPlayer::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_current_animation_pos"),&AnimationPlayer::get_current_animation_pos);
 	ObjectTypeDB::bind_method(_MD("get_current_animation_length"),&AnimationPlayer::get_current_animation_length);
 
+	ObjectTypeDB::bind_method(_MD("advance","delta"),&AnimationPlayer::advance);
+
 
 	ADD_PROPERTY( PropertyInfo( Variant::INT, "playback/process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_animation_process_mode"), _SCS("get_animation_process_mode"));
         ADD_PROPERTY( PropertyInfo( Variant::REAL, "playback/default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), _SCS("set_default_blend_time"), _SCS("get_default_blend_time"));

+ 2 - 0
scene/animation/animation_player.h

@@ -283,6 +283,8 @@ public:
 	float get_current_animation_pos() const;
 	float get_current_animation_length() const;
 
+	void advance(float p_time);
+
 	void set_root(const NodePath& p_root);
 	NodePath get_root() const;
 

+ 2 - 2
scene/audio/event_player.cpp

@@ -280,8 +280,8 @@ float EventPlayer::get_channel_last_note_time(int p_channel) const {
 
 void EventPlayer::_bind_methods() {
 
-	ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&EventPlayer::set_stream);
-	ObjectTypeDB::bind_method(_MD("get_stream:Stream"),&EventPlayer::get_stream);
+	ObjectTypeDB::bind_method(_MD("set_stream","stream:EventStream"),&EventPlayer::set_stream);
+	ObjectTypeDB::bind_method(_MD("get_stream:EventStream"),&EventPlayer::get_stream);
 
 	ObjectTypeDB::bind_method(_MD("play"),&EventPlayer::play);
 	ObjectTypeDB::bind_method(_MD("stop"),&EventPlayer::stop);

+ 3 - 0
scene/gui/button_group.cpp

@@ -67,6 +67,9 @@ Array ButtonGroup::_get_button_list() const {
 
 	List<BaseButton*> b;
 	get_button_list(&b);
+
+	b.sort_custom<Node::Comparator>();
+
 	Array arr;
 	arr.resize(b.size());
 

+ 3 - 2
scene/gui/label.cpp

@@ -397,6 +397,7 @@ void Label::regenerate_word_cache() {
 				
 			}
 			
+
 			if (current=='\n') {
 				insert_newline=true;
 			} else {
@@ -446,7 +447,7 @@ void Label::regenerate_word_cache() {
 		
 	}
 	
-	total_char_cache -= line_count + 1; // do not count new lines (including the first one)
+	//total_char_cache -= line_count + 1; // do not count new lines (including the first one)
 	
 	if (!autowrap) {
 		
@@ -535,7 +536,7 @@ void Label::set_percent_visible(float p_percent) {
 	if (p_percent<0)
 		set_visible_characters(-1);
 	else
-		set_visible_characters(get_total_character_count()*p_percent);
+		set_visible_characters(get_total_character_count()*p_percent);	
 	percent_visible=p_percent;
 }
 

+ 11 - 5
scene/main/viewport.cpp

@@ -164,6 +164,9 @@ void Viewport::_parent_visibility_changed() {
 
 		Control *c = parent->cast_to<Control>();
 		VisualServer::get_singleton()->canvas_item_set_visible(canvas_item,c->is_visible());
+
+		_update_listener();
+		_update_listener_2d();
 	}
 
 
@@ -394,7 +397,7 @@ void Viewport::_notification(int p_what) {
 						if (obj) {
 							CollisionObject *co = obj->cast_to<CollisionObject>();
 							if (co) {
-								co->_input_event(ev,Vector3(),Vector3(),0);
+								co->_input_event(camera,ev,Vector3(),Vector3(),0);
 								captured=true;
 								if (ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && !ev.mouse_button.pressed) {
 									physics_object_capture=0;
@@ -416,7 +419,7 @@ void Viewport::_notification(int p_what) {
 						if (last_id) {
 							if (ObjectDB::get_instance(last_id)) {
 								//good, exists
-								last_object->_input_event(ev,result.position,result.normal,result.shape);
+								last_object->_input_event(camera,ev,result.position,result.normal,result.shape);
 								if (last_object->get_capture_input_on_drag() && ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && ev.mouse_button.pressed) {
 									physics_object_capture=last_id;
 								}
@@ -440,10 +443,13 @@ void Viewport::_notification(int p_what) {
 								bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
 								ObjectID new_collider=0;
 								if (col) {
+
 									if (result.collider) {
+
 										CollisionObject *co = result.collider->cast_to<CollisionObject>();
 										if (co) {
-											co->_input_event(ev,result.position,result.normal,result.shape);
+
+											co->_input_event(camera,ev,result.position,result.normal,result.shape);
 											last_object=co;
 											last_id=result.collider_id;
 											new_collider=last_id;
@@ -541,7 +547,7 @@ Rect2 Viewport::get_rect() const {
 
 void Viewport::_update_listener() {
 
-	if (is_inside_scene() && audio_listener && camera) {
+	if (is_inside_scene() && audio_listener && camera && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible())))  {
 		SpatialSoundServer::get_singleton()->listener_set_space(listener,find_world()->get_sound_space());
 	} else {
 		SpatialSoundServer::get_singleton()->listener_set_space(listener,RID());
@@ -552,7 +558,7 @@ void Viewport::_update_listener() {
 
 void Viewport::_update_listener_2d() {
 
-	if (is_inside_scene() && audio_listener_2d)
+	if (is_inside_scene() && audio_listener && camera && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible())))
 		SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,find_world_2d()->get_sound_space());
 	else
 		SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,RID());

+ 2 - 0
scene/register_scene_types.cpp

@@ -100,6 +100,7 @@
 #include "scene/2d/sample_player_2d.h"
 #include "scene/2d/screen_button.h"
 #include "scene/2d/remote_transform_2d.h"
+#include "scene/2d/y_sort.h"
 
 #include "scene/2d/position_2d.h"
 #include "scene/2d/tile_map.h"
@@ -491,6 +492,7 @@ void register_scene_types() {
 	ObjectTypeDB::register_type<VisibilityNotifier2D>();
 	ObjectTypeDB::register_type<VisibilityEnabler2D>();
 	ObjectTypeDB::register_type<Polygon2D>();
+	ObjectTypeDB::register_type<YSort>();
 
 	ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
 	ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false);

+ 7 - 3
scene/resources/animation.cpp

@@ -1716,7 +1716,7 @@ void Animation::clear() {
 
 }
 
-void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err) {
+void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err,float p_max_optimizable_angle) {
 
 	ERR_FAIL_INDEX(p_idx,tracks.size());
 	ERR_FAIL_COND(tracks[p_idx]->type!=TYPE_TRANSFORM);
@@ -1779,6 +1779,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl
 
 			} else {
 
+
 				Quat r02 = (q0.inverse() * q2).normalized();
 				Quat r01 = (q0.inverse() * q1).normalized();
 
@@ -1788,6 +1789,9 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl
 				r02.get_axis_and_angle(v02,a02);
 				r01.get_axis_and_angle(v01,a01);
 
+				if (Math::abs(a02)>p_max_optimizable_angle)
+					continue;
+
 				if (v01.dot(v02)<0) {
 					//make sure both rotations go the same way to compare
 					v02=-v02;
@@ -1905,7 +1909,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl
 
 }
 
-void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err) {
+void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err,float p_angle_max) {
 
 
 	int total_tt=0;
@@ -1913,7 +1917,7 @@ void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err)
 	for(int i=0;i<tracks.size();i++) {
 
 		if (tracks[i]->type==TYPE_TRANSFORM)
-			_transform_track_optimize(i,p_allowed_linear_err,p_allowed_angular_err);
+			_transform_track_optimize(i,p_allowed_linear_err,p_allowed_angular_err,p_angle_max);
 
 	}
 

+ 2 - 2
scene/resources/animation.h

@@ -204,7 +204,7 @@ private:
 		return idxr;
 	}
 
-	void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01);
+	void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01,float p_max_optimizable_angle=Math_PI*0.125);
 
 protected:	
 
@@ -271,7 +271,7 @@ public:
 
 	void clear();
 
-	void optimize(float p_allowed_linear_err=0.05,float p_allowed_angular_err=0.01);
+	void optimize(float p_allowed_linear_err=0.05,float p_allowed_angular_err=0.01,float p_max_optimizable_angle=Math_PI*0.125);
 
 	Animation();	
 	~Animation();

+ 16 - 4
scene/resources/packed_scene.cpp

@@ -225,22 +225,34 @@ Error PackedScene::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<
 	p_node->get_property_list(&plist);
 	for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
 
-		if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
+
+		if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
 			continue;
+		}
 
 		String name = E->get().name;
 		Variant value = p_node->get( E->get().name );
 
-		if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero())
+		if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero()) {
 			continue;
+		}
 
 
 		if (nd.instance>=0) {
 			//only save changed properties in instance
-			if (!instance_state.has(name))
+			/*
+			  // this was commented because it would not save properties created from within script
+			  // done with _get_property_list, that are not in the original node.
+			  // if some property is not saved, check again
+
+			  if (!instance_state.has(name)) {
+				print_line("skip not in instance");
 				continue;
-			if (instance_state[name]==value)
+			}*/
+
+			if (instance_state[name]==value) {
 				continue;
+			}
 
 		}
 

+ 2 - 1
servers/physics/area_pair_sw.cpp

@@ -67,7 +67,6 @@ void AreaPairSW::solve(float p_step) {
 
 AreaPairSW::AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_area_shape) {
 
-
 	body=p_body;
 	area=p_area;
 	body_shape=p_body_shape;
@@ -75,6 +74,8 @@ AreaPairSW::AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_are
 	colliding=false;
 	body->add_constraint(this,0);
 	area->add_constraint(this);
+	if (p_body->get_mode()==PhysicsServer::BODY_MODE_KINEMATIC)
+		p_body->set_active(true);
 
 }
 

+ 2 - 4
servers/physics/area_sw.cpp

@@ -148,8 +148,6 @@ void AreaSW::call_queries() {
 			return;
 		}
 
-
-
 		for (Map<BodyKey,BodyState>::Element *E=monitored_bodies.front();E;E=E->next()) {
 
 			if (E->get().state==0)
@@ -182,8 +180,8 @@ AreaSW::AreaSW() : CollisionObjectSW(TYPE_AREA), monitor_query_list(this),  move
 	point_attenuation=1;
 	density=0.1;
 	priority=0;
-	ray_pickable=false;
-
+	set_ray_pickable(false);
+	monitor_callback_id=0;
 
 }
 

+ 0 - 3
servers/physics/area_sw.h

@@ -48,7 +48,6 @@ class AreaSW : public CollisionObjectSW{
 	float point_attenuation;
 	float density;
 	int priority;
-	bool ray_pickable;
 
 	ObjectID monitor_callback_id;
 	StringName monitor_callback_method;
@@ -139,8 +138,6 @@ public:
 	_FORCE_INLINE_ void remove_constraint( ConstraintSW* p_constraint) { constraints.erase(p_constraint); }
 	_FORCE_INLINE_ const Set<ConstraintSW*>& get_constraints() const { return constraints; }
 
-	_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable=p_enable; }
-	_FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
 
 
 

+ 1 - 0
servers/physics/collision_object_sw.cpp

@@ -217,4 +217,5 @@ CollisionObjectSW::CollisionObjectSW(Type p_type) {
 	space=NULL;
 	instance_id=0;
 	layer_mask=1;
+	ray_pickable=true;
 }

+ 6 - 0
servers/physics/collision_object_sw.h

@@ -94,6 +94,9 @@ protected:
 	virtual void _shapes_changed()=0;
 	void _set_space(SpaceSW *space);
 
+	bool ray_pickable;
+
+
 	CollisionObjectSW(Type p_type);
 public:
 
@@ -119,6 +122,9 @@ public:
 	_FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; }
 	_FORCE_INLINE_ SpaceSW* get_space() const { return space; }
 
+	_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable=p_enable; }
+	_FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
+
 
 	_FORCE_INLINE_ void set_layer_mask(uint32_t p_mask) { layer_mask=p_mask; }
 	_FORCE_INLINE_ uint32_t get_layer_mask() const { return layer_mask; }

+ 5 - 1
servers/physics/constraint_sw.h

@@ -38,12 +38,13 @@ class ConstraintSW {
 	uint64_t island_step;
 	ConstraintSW *island_next;
 	ConstraintSW *island_list_next;
+	int priority;
 
 
 	RID self;
 
 protected:
-	ConstraintSW(BodySW **p_body_ptr=NULL,int p_body_count=0) { _body_ptr=p_body_ptr; _body_count=p_body_count; island_step=0; }
+	ConstraintSW(BodySW **p_body_ptr=NULL,int p_body_count=0) { _body_ptr=p_body_ptr; _body_count=p_body_count; island_step=0; priority=1; }
 public:
 
 	_FORCE_INLINE_ void set_self(const RID& p_self) { self=p_self; }
@@ -62,6 +63,9 @@ public:
 	_FORCE_INLINE_ BodySW **get_body_ptr() const { return _body_ptr; }
 	_FORCE_INLINE_ int get_body_count() const { return _body_count; }
 
+	_FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; }
+	_FORCE_INLINE_ int get_priority() const { return priority; }
+
 
 	virtual bool setup(float p_step)=0;
 	virtual void solve(float p_step)=0;

+ 31 - 0
servers/physics/physics_server_sw.cpp

@@ -836,6 +836,22 @@ void PhysicsServerSW::body_set_force_integration_callback(RID p_body,Object *p_r
 
 }
 
+void PhysicsServerSW::body_set_ray_pickable(RID p_body,bool p_enable) {
+
+	BodySW *body = body_owner.get(p_body);
+	ERR_FAIL_COND(!body);
+	body->set_ray_pickable(p_enable);
+
+}
+
+bool PhysicsServerSW::body_is_ray_pickable(RID p_body) const{
+
+	BodySW *body = body_owner.get(p_body);
+	ERR_FAIL_COND_V(!body,false);
+	return body->is_ray_pickable();
+
+}
+
 
 /* JOINT API */
 
@@ -1000,6 +1016,21 @@ bool PhysicsServerSW::hinge_joint_get_flag(RID p_joint,HingeJointFlag p_flag) co
 	return hinge_joint->get_flag(p_flag);
 }
 
+void PhysicsServerSW::joint_set_solver_priority(RID p_joint,int p_priority) {
+
+	JointSW *joint = joint_owner.get(p_joint);
+	ERR_FAIL_COND(!joint);
+	joint->set_priority(p_priority);
+}
+
+int PhysicsServerSW::joint_get_solver_priority(RID p_joint) const{
+
+	JointSW *joint = joint_owner.get(p_joint);
+	ERR_FAIL_COND_V(!joint,0);
+	return joint->get_priority();
+
+}
+
 PhysicsServerSW::JointType PhysicsServerSW::joint_get_type(RID p_joint) const {
 
 	JointSW *joint = joint_owner.get(p_joint);

+ 6 - 0
servers/physics/physics_server_sw.h

@@ -201,6 +201,9 @@ public:
 
 	virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant());
 
+	virtual void body_set_ray_pickable(RID p_body,bool p_enable);
+	virtual bool body_is_ray_pickable(RID p_body) const;
+
 	/* JOINT API */
 
 	virtual RID joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID p_body_B,const Vector3& p_local_B);
@@ -244,6 +247,9 @@ public:
 
 	virtual JointType joint_get_type(RID p_joint) const;
 
+	virtual void joint_set_solver_priority(RID p_joint,int p_priority);
+	virtual int joint_get_solver_priority(RID p_joint) const;
+
 #if 0
 	virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value);
 	virtual real_t joint_get_param(RID p_joint,JointParam p_param) const;

+ 4 - 1
servers/physics/space_sw.cpp

@@ -71,12 +71,13 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto
 	real_t min_d=1e10;
 
 
+
 	for(int i=0;i<amount;i++) {
 
 		if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
 			continue;
 
-		if (space->intersection_query_results[i]->get_type()==CollisionObjectSW::TYPE_AREA && !(static_cast<AreaSW*>(space->intersection_query_results[i])->is_ray_pickable()))
+		if (!(static_cast<AreaSW*>(space->intersection_query_results[i])->is_ray_pickable()))
 			continue;
 
 		if (p_exclude.has( space->intersection_query_results[i]->get_self()))
@@ -97,6 +98,8 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto
 
 		if (shape->intersect_segment(local_from,local_to,shape_point,shape_normal)) {
 
+
+
 			Transform xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
 			shape_point=xform.xform(shape_point);
 

+ 33 - 6
servers/physics/step_sw.cpp

@@ -27,7 +27,7 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 #include "step_sw.h"
-
+#include "joints_sw.h"
 
 void StepSW::_populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_constraint_island) {
 
@@ -68,14 +68,41 @@ void StepSW::_setup_island(ConstraintSW *p_island,float p_delta) {
 
 void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta){
 
-	for(int i=0;i<p_iterations;i++) {
+	int at_priority=1;
 
-		ConstraintSW *ci=p_island;
-		while(ci) {
-			ci->solve(p_delta);
-			ci=ci->get_island_next();
+	while(p_island) {
+
+		for(int i=0;i<p_iterations;i++) {
+
+			ConstraintSW *ci=p_island;
+			while(ci) {
+				ci->solve(p_delta);
+				ci=ci->get_island_next();
+			}
+		}
+
+		at_priority++;
+
+		{
+			ConstraintSW *ci=p_island;
+			ConstraintSW *prev=NULL;
+			while(ci) {
+				if (ci->get_priority()<at_priority) {
+					if (prev) {
+						prev->set_island_next(ci->get_island_next()); //remove
+					} else {
+						p_island=ci->get_island_next();
+					}
+				} else {
+
+					prev=ci;
+				}
+
+				ci=ci->get_island_next();
+			}
 		}
 	}
+
 }
 
 void StepSW::_check_suspend(BodySW *p_island,float p_delta) {

+ 1 - 0
servers/physics_2d/area_2d_sw.cpp

@@ -180,6 +180,7 @@ Area2DSW::Area2DSW() : CollisionObject2DSW(TYPE_AREA), monitor_query_list(this),
 	gravity_vector=Vector2(0,-1);
 	gravity_is_point=false;
 	point_attenuation=1;
+
 	density=0.1;
 	priority=0;
 	monitor_callback_id=0;

+ 2 - 0
servers/physics_2d/area_pair_2d_sw.cpp

@@ -75,6 +75,8 @@ AreaPair2DSW::AreaPair2DSW(Body2DSW *p_body,int p_body_shape, Area2DSW *p_area,i
 	colliding=false;
 	body->add_constraint(this,0);
 	area->add_constraint(this);
+	if (p_body->get_mode()==Physics2DServer::BODY_MODE_KINEMATIC) //need to be active to process pair
+		p_body->set_active(true);
 
 }
 

+ 6 - 0
servers/physics_server.cpp

@@ -520,6 +520,9 @@ void PhysicsServer::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method","userdata"),&PhysicsServer::body_set_force_integration_callback,DEFVAL(Variant()));
 
+	ObjectTypeDB::bind_method(_MD("body_set_ray_pickable","body","enable"),&PhysicsServer::body_set_ray_pickable);
+	ObjectTypeDB::bind_method(_MD("body_is_ray_pickable","body"),&PhysicsServer::body_is_ray_pickable);
+
 	/* JOINT API */
 
 	BIND_CONSTANT( JOINT_PIN );
@@ -627,6 +630,9 @@ void PhysicsServer::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
 
+	ObjectTypeDB::bind_method(_MD("joint_set_solver_priority","joint","priority"),&PhysicsServer::joint_set_solver_priority);
+	ObjectTypeDB::bind_method(_MD("joint_get_solver_priority","joint"),&PhysicsServer::joint_get_solver_priority);
+
 	ObjectTypeDB::bind_method(_MD("joint_create_generic_6dof","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_generic_6dof);
 
 	ObjectTypeDB::bind_method(_MD("generic_6dof_joint_set_param","joint","axis","param","value"),&PhysicsServer::generic_6dof_joint_set_param);

+ 6 - 0
servers/physics_server.h

@@ -450,6 +450,10 @@ public:
 
 	virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant())=0;
 
+	virtual void body_set_ray_pickable(RID p_body,bool p_enable)=0;
+	virtual bool body_is_ray_pickable(RID p_body) const=0;
+
+
 	/* JOINT API */
 
 	enum JointType {
@@ -464,6 +468,8 @@ public:
 
 	virtual JointType joint_get_type(RID p_joint) const=0;
 
+	virtual void joint_set_solver_priority(RID p_joint,int p_priority)=0;
+	virtual int joint_get_solver_priority(RID p_joint) const=0;
 
 
 	virtual RID joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID p_body_B,const Vector3& p_local_B)=0;

+ 1 - 0
servers/register_server_types.cpp

@@ -57,6 +57,7 @@ void register_server_types() {
 	ObjectTypeDB::register_virtual_type<Physics2DShapeQueryResult>();
 	ObjectTypeDB::register_type<Physics2DShapeQueryParameters>();
 
+	ObjectTypeDB::register_type<PhysicsShapeQueryParameters>();
 	ObjectTypeDB::register_virtual_type<PhysicsDirectBodyState>();
 	ObjectTypeDB::register_virtual_type<PhysicsDirectSpaceState>();
 	ObjectTypeDB::register_virtual_type<PhysicsShapeQueryResult>();

+ 9 - 4
servers/spatial_sound/spatial_sound_server_sw.cpp

@@ -879,10 +879,13 @@ void SpatialSoundServerSW::update(float p_delta) {
 		float volume_attenuation = 0.0;
 		float air_absorption_hf_cutoff = 0.0;
 		float air_absorption = 0.0;
-		float pitch_scale=0.0;
+		float pitch_scale=1.0;
 		Vector3 panning;
 
 
+		//print_line("listeners: "+itos(space->listeners.size()));
+
+
 		for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) {
 
 			Listener *listener=listener_owner.get(L->get());
@@ -899,9 +902,11 @@ void SpatialSoundServerSW::update(float p_delta) {
 			float attenuation_exp=source->params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP];
 			float attenuation=1;
 
+			//print_line("DIST MIN: "+rtos(distance_min));
+			//print_line("DIST MAX: "+rtos(distance_max));
 			if (distance_max>0) {
 				distance = CLAMP(distance,distance_min,distance_max);
-				attenuation = Math::pow(1.0 - ((distance - distance_min)/distance_max),CLAMP(attenuation_exp,0.001,16));
+				attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16));
 			}
 
 			float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF];
@@ -945,7 +950,7 @@ void SpatialSoundServerSW::update(float p_delta) {
 			air_absorption+=weight*absorption;
 			air_absorption_hf_cutoff+=weight*hf_attenuation_cutoff;
 			panning+=vpanning*weight;
-			pitch_scale+=pscale*weight;
+			//pitch_scale+=pscale*weight;
 
 		}
 
@@ -991,8 +996,8 @@ void SpatialSoundServerSW::update(float p_delta) {
 			reverb_send*=volume_scale;
 			int mix_rate = v.sample_mix_rate*v.pitch_scale*pitch_scale*source->params[SOURCE_PARAM_PITCH_SCALE];
 
-			if (mix_rate<=0) {
 
+			if (mix_rate<=0) {
 				ERR_PRINT("Invalid mix rate for voice (0) check for invalid pitch_scale param.");
 				to_disable.push_back(ActiveVoice(source,voice)); // oh well..
 				continue; //invalid mix rate, disabling

+ 1 - 1
servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp

@@ -904,7 +904,7 @@ void SpatialSound2DServerSW::update(float p_delta) {
 
 			if (distance_max>0) {
 				distance = CLAMP(distance,distance_min,distance_max);
-				attenuation = Math::pow(1.0 - ((distance - distance_min)/distance_max),CLAMP(attenuation_exp,0.001,16));
+				attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16));
 			}
 
 			float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF];

+ 28 - 22
servers/visual/visual_server_raster.cpp

@@ -1202,7 +1202,7 @@ RID VisualServerRaster::camera_create() {
 }
 
 void VisualServerRaster::camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far) {
-	VS_CHANGED;
+	VS_CHANGED
 	Camera *camera = camera_owner.get( p_camera );
 	ERR_FAIL_COND(!camera);
 	camera->type=Camera::PERSPECTIVE;
@@ -1226,7 +1226,7 @@ void VisualServerRaster::camera_set_transform(RID p_camera,const Transform& p_tr
 	VS_CHANGED;
 	Camera *camera = camera_owner.get( p_camera );
 	ERR_FAIL_COND(!camera);
-	camera->transform=p_transform;
+	camera->transform=p_transform.orthonormalized();
 	
 
 }
@@ -3531,6 +3531,15 @@ void VisualServerRaster::canvas_item_add_set_blend_mode(RID p_item, MaterialBlen
 	canvas_item->commands.push_back(bm);
 };
 
+void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
+
+	VS_CHANGED;
+	CanvasItem *canvas_item = canvas_item_owner.get( p_item );
+	ERR_FAIL_COND(!canvas_item);
+	canvas_item->sort_y=p_enable;
+}
+
+
 void VisualServerRaster::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) {
 
 	VS_CHANGED;
@@ -5591,26 +5600,30 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
 
 	float opacity = ci->opacity * p_opacity;
 
-#ifndef ONTOP_DISABLED
-	CanvasItem **child_items = ci->child_items.ptr();
+
 	int child_item_count=ci->child_items.size();
-	int top_item_count=0;
-	CanvasItem **top_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*));
+	CanvasItem **child_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*));
+	copymem(child_items,ci->child_items.ptr(),child_item_count*sizeof(CanvasItem*));
 
 	if (ci->clip) {
 		rasterizer->canvas_set_clip(true,global_rect);
 		canvas_clip=global_rect;
 	}
 
+	if (ci->sort_y) {
+
+		SortArray<CanvasItem*,CanvasItemPtrSort> sorter;
+		sorter.sort(child_items,child_item_count);
+	}
+
+
 	for(int i=0;i<child_item_count;i++) {
 
 		if (child_items[i]->ontop)
-			top_items[top_item_count++]=child_items[i];
-		else {
-			_render_canvas_item(child_items[i],xform,p_clip_rect,opacity);
-		}
+			continue;
+		_render_canvas_item(child_items[i],xform,p_clip_rect,opacity);
 	}
-#endif
+
 
 	if (s!=0) {
 
@@ -5746,19 +5759,12 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
 		rasterizer->canvas_set_clip(true,canvas_clip);
 	}
 
-#ifndef ONTOP_DISABLED
-
-	for(int i=0;i<top_item_count;i++) {
-
-		_render_canvas_item(top_items[i],xform,p_clip_rect,opacity);
-	}
-
-#else
-	for(int i=0;i<p_canvas_item->child_items.size();i++) {
+	for(int i=0;i<child_item_count;i++) {
 
-		_render_canvas_item(p_canvas_item->child_items[i],xform,p_clip_rect,opacity);
+		if (!child_items[i]->ontop)
+			continue;
+		_render_canvas_item(child_items[i],xform,p_clip_rect,opacity);
 	}
-#endif
 
 
 	if (ci->clip) {

+ 12 - 3
servers/visual/visual_server_raster.h

@@ -328,7 +328,7 @@ class VisualServerRaster : public VisualServer {
 
 
 
-	
+
 
 	struct CanvasItem {
 		
@@ -446,13 +446,14 @@ class VisualServerRaster : public VisualServer {
 		bool clip;
 		bool visible;
 		bool ontop;
+		bool sort_y;
 		float opacity;
 		float self_opacity;
 		MaterialBlendMode blend_mode;
 		RID viewport;
 
 		mutable bool custom_rect;
-		mutable bool rect_dirty;
+		mutable bool rect_dirty;		
 		mutable Rect2 rect;
 		
 		Vector<Command*> commands;
@@ -460,11 +461,18 @@ class VisualServerRaster : public VisualServer {
 
 		const Rect2& get_rect() const;
 		void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true;};
-		CanvasItem() { clip=false; E=NULL; opacity=1; self_opacity=1; blend_mode=MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; }
+		CanvasItem() { clip=false; E=NULL; opacity=1; self_opacity=1; blend_mode=MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; sort_y=false;}
 		~CanvasItem() { clear(); }
 	};
 
 
+	struct CanvasItemPtrSort {
+
+		_FORCE_INLINE_ bool operator()(const CanvasItem* p_left,const CanvasItem* p_right) const {
+
+			return p_left->xform.elements[2].y < p_right->xform.elements[2].y;
+		}
+	};
 
 	struct Canvas {
 
@@ -1135,6 +1143,7 @@ public:
 	virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform);
 	virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend);
 	virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
+	virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
 
 	virtual void canvas_item_clear(RID p_item);
 	virtual void canvas_item_raise(RID p_item);

+ 2 - 0
servers/visual/visual_server_wrap_mt.h

@@ -1107,6 +1107,8 @@ public:
 	FUNC2(canvas_item_add_set_blend_mode,RID, MaterialBlendMode );
 	FUNC2(canvas_item_add_clip_ignore,RID, bool );
 
+	FUNC2(canvas_item_set_sort_children_by_y,RID,bool);
+
 	FUNC1(canvas_item_clear,RID);
 	FUNC1(canvas_item_raise,RID);
 

+ 1 - 0
servers/visual_server.h

@@ -944,6 +944,7 @@ public:
 	virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform)=0;
 	virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend)=0;
 	virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore)=0;
+	virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable)=0;
 
 	virtual void canvas_item_clear(RID p_item)=0;
 	virtual void canvas_item_raise(RID p_item)=0;

+ 4 - 0
tools/collada/collada.cpp

@@ -2144,6 +2144,7 @@ void Collada::_parse_scene(XMLParser& parser) {
 			if (name=="instance_visual_scene") {
 
 				state.root_visual_scene=_uri_to_id(parser.get_attribute_value("url"));
+				print_line("***ROOT VISUAL SCENE: "+state.root_visual_scene);
 			} if (name=="instance_physics_scene") {
 
 				state.root_physics_scene=_uri_to_id(parser.get_attribute_value("url"));
@@ -2513,6 +2514,9 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene,Node *p_node,Lis
 			ERR_FAIL_COND_V( !state.scene_map.has( nodeid ), false); //weird, it should have it...
 			NodeJoint *nj = SAFE_CAST<NodeJoint*>(state.scene_map[nodeid]);
 			ERR_FAIL_COND_V(!nj,false);
+			if (!nj->owner) {
+				print_line("Has no owner: "+nj->name);
+			}
 			ERR_FAIL_COND_V( !nj->owner,false ); //weird, node should have a skeleton owner
 
 			NodeSkeleton *sk = nj->owner;

+ 15 - 1
tools/editor/io_plugins/editor_font_import_plugin.cpp

@@ -92,6 +92,7 @@ public:
 	String gradient_image;
 
 
+	bool disable_filter;
 	bool round_advance;
 
 
@@ -153,6 +154,8 @@ public:
 			color_use_monochrome=p_value;
 		else if (n=="advanced/round_advance")
 			round_advance=p_value;
+		else if (n=="advanced/disable_filter")
+			disable_filter=p_value;
 		else
 			return false;
 
@@ -217,6 +220,8 @@ public:
 			r_ret=color_use_monochrome;
 		else if (n=="advanced/round_advance")
 			r_ret=round_advance;
+		else if (n=="advanced/disable_filter")
+			r_ret=disable_filter;
 		else
 			return false;
 
@@ -265,6 +270,7 @@ public:
 		}
 		p_list->push_back(PropertyInfo(Variant::BOOL,"color/monochrome"));
 		p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/round_advance"));
+		p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/disable_filter"));
 
 	}
 
@@ -302,6 +308,7 @@ public:
 		color_use_monochrome=false;
 
 		round_advance=true;
+		disable_filter=false;
 
 	}
 
@@ -331,6 +338,7 @@ public:
 		color_use_monochrome=false;
 
 		round_advance=true;
+		disable_filter=false;
 	}
 
 
@@ -1260,6 +1268,7 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
 	int space_space = from->get_option("extra_space/space");
 	int top_space = from->get_option("extra_space/top");
 	int bottom_space = from->get_option("extra_space/bottom");
+	bool disable_filter = from->get_option("advanced/disable_filter");
 
 	Ref<Font> font;
 
@@ -1279,7 +1288,12 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
 	//register texures
 	{
 		Ref<ImageTexture> t = memnew(ImageTexture);
-		t->create_from_image(atlas);
+		int flags;
+		if (disable_filter)
+			flags=0;
+		else
+			flags=Texture::FLAG_FILTER;
+		t->create_from_image(atlas,flags);
 		t->set_storage( ImageTexture::STORAGE_COMPRESS_LOSSLESS );
 		font->add_texture(t);
 

+ 3 - 3
tools/editor/io_plugins/editor_import_collada.cpp

@@ -1829,9 +1829,9 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
 	if (p_clip>=0 && collada.state.animation_clips[p_clip].end)
 		anim_length=collada.state.animation_clips[p_clip].end;
 
-	while(f<collada.state.animation_length) {
-		if (f>=collada.state.animation_length)
-			f=collada.state.animation_length;
+	while(f<anim_length) {
+		if (f>=anim_length)
+			f=anim_length;
 
 		base_snapshots.push_back(f);
 		f+=snapshot_interval;

+ 55 - 2
tools/editor/io_plugins/editor_scene_import_plugin.cpp

@@ -40,6 +40,7 @@
 #include "scene/3d/body_shape.h"
 #include "scene/3d/physics_body.h"
 #include "scene/3d/portal.h"
+#include "scene/3d/vehicle_body.h"
 #include "os/os.h"
 
 
@@ -649,9 +650,10 @@ const EditorSceneImportDialog::FlagInfo EditorSceneImportDialog::scene_flag_name
 	{EditorSceneImportPlugin::SCENE_FLAG_CREATE_BILLBOARDS,"Create","Create Billboards (-bb)",true},
 	{EditorSceneImportPlugin::SCENE_FLAG_CREATE_IMPOSTORS,"Create","Create Impostors (-imp:dist)",true},
 	{EditorSceneImportPlugin::SCENE_FLAG_CREATE_LODS,"Create","Create LODs (-lod:dist)",true},
-	{EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,"Create","Create Cars (-car)",true},
-	{EditorSceneImportPlugin::SCENE_FLAG_CREATE_WHEELS,"Create","Create Car Wheels (-wheel)",true},
+	{EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,"Create","Create Vehicles (-vehicle)",true},
+	{EditorSceneImportPlugin::SCENE_FLAG_CREATE_WHEELS,"Create","Create Vehicle Wheels (-wheel)",true},
 	{EditorSceneImportPlugin::SCENE_FLAG_CREATE_NAVMESH,"Create","Create Navigation Meshes (-navmesh)",true},
+	{EditorSceneImportPlugin::SCENE_FLAG_DETECT_LIGHTMAP_LAYER,"Create","Detect LightMap Layer (-lm:<int>).",true},
 	{-1,NULL,NULL,false}
 };
 
@@ -1199,6 +1201,17 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
 	    }
 	}
     }
+
+
+	if (p_flags&SCENE_FLAG_DETECT_LIGHTMAP_LAYER && _teststr(name,"lm") && p_node->cast_to<MeshInstance>()) {
+
+		MeshInstance *mi = p_node->cast_to<MeshInstance>();
+
+		String str=name;
+		int layer = str.substr(str.find("lm")+3,str.length()).to_int();
+		mi->set_baked_light_texture_id(layer);
+	}
+
 	if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly") && p_node->cast_to<MeshInstance>()) {
 
 		if (isroot)
@@ -1262,6 +1275,46 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
 		p_node->replace_by(nmi);
 		memdelete(p_node);
 		p_node=nmi;
+	} else if (p_flags&SCENE_FLAG_CREATE_CARS &&_teststr(name,"vehicle")) {
+
+		if (isroot)
+			return p_node;
+
+		Node *owner = p_node->get_owner();
+		Spatial *s = p_node->cast_to<Spatial>();
+		VehicleBody *bv = memnew( VehicleBody );
+		String n = _fixstr(p_node->get_name(),"vehicle");
+		bv->set_name(n);
+		p_node->replace_by(bv);
+		p_node->set_name(n);
+		bv->add_child(p_node);
+		bv->set_owner(owner);
+		p_node->set_owner(owner);
+		bv->set_transform(s->get_transform());
+		s->set_transform(Transform());
+
+		p_node=bv;
+
+
+	} else if (p_flags&SCENE_FLAG_CREATE_CARS &&_teststr(name,"wheel")) {
+
+		if (isroot)
+			return p_node;
+
+		Node *owner = p_node->get_owner();
+		Spatial *s = p_node->cast_to<Spatial>();
+		VehicleWheel *bv = memnew( VehicleWheel );
+		String n = _fixstr(p_node->get_name(),"wheel");
+		bv->set_name(n);
+		p_node->replace_by(bv);
+		p_node->set_name(n);
+		bv->add_child(p_node);
+		bv->set_owner(owner);
+		p_node->set_owner(owner);
+		bv->set_transform(s->get_transform());
+		s->set_transform(Transform());
+
+		p_node=bv;
 
 	} else if (p_flags&SCENE_FLAG_CREATE_ROOMS && _teststr(name,"room") && p_node->cast_to<MeshInstance>()) {
 

+ 1 - 0
tools/editor/io_plugins/editor_scene_import_plugin.h

@@ -125,6 +125,7 @@ public:
 		SCENE_FLAG_DETECT_ALPHA=1<<15,
 		SCENE_FLAG_DETECT_VCOLOR=1<<16,
 		SCENE_FLAG_CREATE_NAVMESH=1<<17,
+		SCENE_FLAG_DETECT_LIGHTMAP_LAYER=1<<18,
 
 		SCENE_FLAG_REMOVE_NOIMP=1<<24,
 		SCENE_FLAG_IMPORT_ANIMATIONS=1<<25,

+ 5 - 0
tools/editor/plugins/sample_player_editor_plugin.cpp

@@ -64,6 +64,8 @@ void SamplePlayerEditor::_play() {
 		return;
 
 	node->call("play",samples->get_item_text( samples->get_selected() ));
+	stop->set_pressed(false);
+	play->set_pressed(true);
 }
 
 void SamplePlayerEditor::_stop() {
@@ -74,6 +76,9 @@ void SamplePlayerEditor::_stop() {
 		return;
 
 	node->call("stop_all");
+	print_line("STOP ALL!!");
+	stop->set_pressed(true);
+	play->set_pressed(false);
 
 }
 

+ 31 - 0
tools/editor/plugins/spatial_editor_plugin.cpp

@@ -1925,6 +1925,15 @@ void SpatialEditorViewport::_menu_option(int p_option) {
 			call_deferred("update_transform_gizmo_view");
 
 		} break;
+		case VIEW_AUDIO_LISTENER: {
+
+			int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
+			bool current = 	view_menu->get_popup()->is_item_checked( idx );
+			current=!current;
+			viewport->set_as_audio_listener(current);
+			view_menu->get_popup()->set_item_checked( idx, current );
+
+		} break;
 
 	}
 
@@ -2055,6 +2064,13 @@ void SpatialEditorViewport::set_state(const Dictionary& p_state) {
 		_menu_option(VIEW_PERSPECTIVE);
 	if (env != camera->get_environment().is_valid())
 		_menu_option(VIEW_ENVIRONMENT);
+	if (p_state.has("listener")) {
+		bool listener = p_state["listener"];
+
+		int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
+		viewport->set_as_audio_listener(listener);
+		view_menu->get_popup()->set_item_checked( idx, listener );
+	}
 
 
 }
@@ -2068,6 +2084,7 @@ Dictionary SpatialEditorViewport::get_state() const {
 	d["distance"]=cursor.distance;
 	d["use_environment"]=camera->get_environment().is_valid();
 	d["use_orthogonal"]=camera->get_projection()==Camera::PROJECTION_ORTHOGONAL;
+	d["listener"]=viewport->is_audio_listener();
 	return d;
 }
 
@@ -2147,6 +2164,9 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
 	view_menu->get_popup()->add_separator();
 	view_menu->get_popup()->add_check_item("Environment",VIEW_ENVIRONMENT);
 	view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ENVIRONMENT),true);
+	view_menu->get_popup()->add_separator();
+	view_menu->get_popup()->add_check_item("Audio Listener",VIEW_AUDIO_LISTENER);
+
 	view_menu->get_popup()->add_separator();
 	view_menu->get_popup()->add_item("Selection (F)",VIEW_CENTER_TO_SELECTION);
 	view_menu->get_popup()->add_item("Align with view (Ctrl+Shift+F)",VIEW_ALIGN_SELECTION_WITH_VIEW);
@@ -2163,6 +2183,12 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
 	previewing=NULL;
 	preview=NULL;
 	gizmo_scale=1.0;
+
+	if (p_index==0) {
+		view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER),true);
+		viewport->set_as_audio_listener(true);
+	}
+
 	EditorSettings::get_singleton()->connect("settings_changed",this,"update_transform_gizmo_view");
 
 }
@@ -3307,6 +3333,11 @@ void SpatialEditor::clear() {
 		}
 	}
 
+	for(int i=0;i<4;i++) {
+
+		viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(SpatialEditorViewport::VIEW_AUDIO_LISTENER),i==0);
+		viewports[i]->viewport->set_as_audio_listener(i==0);
+	}
 	view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true );
 
 

+ 3 - 2
tools/editor/plugins/spatial_editor_plugin.h

@@ -65,7 +65,7 @@ public:
 class SpatialEditorViewport : public Control {
 
 	OBJ_TYPE( SpatialEditorViewport, Control );
-
+friend class SpatialEditor;
 	enum {
 
 		VIEW_TOP,
@@ -78,7 +78,8 @@ class SpatialEditorViewport : public Control {
 		VIEW_ALIGN_SELECTION_WITH_VIEW,
 		VIEW_PERSPECTIVE,
 		VIEW_ENVIRONMENT,
-		VIEW_ORTHOGONAL
+		VIEW_ORTHOGONAL,
+		VIEW_AUDIO_LISTENER,
 	};
 	enum {
 		GIZMO_BASE_LAYER=25

+ 106 - 38
tools/editor/plugins/tile_map_editor_plugin.cpp

@@ -166,7 +166,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 
 	Matrix32 xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
 	Matrix32 xform_inv = xform.affine_inverse();
-	Vector2 snap = Vector2(1,1)*node->get_cell_size();
+	Vector2 snap = node->get_cell_size();
 
 
 	switch(p_event.type) {
@@ -218,7 +218,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 					if (mb.mod.shift) {
 
 						tool=TOOL_SELECTING;
-						selection_begin =(xform_inv.xform(Point2(mb.x,mb.y))/snap).floor();
+						selection_begin =node->world_to_map(xform_inv.xform(Point2(mb.x,mb.y)));
 						selection.pos=selection_begin;
 						selection.size=Point2(0,0);
 						selection_active=true;
@@ -229,7 +229,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 						int id = get_selected_tile();
 						if (id!=TileMap::INVALID_CELL) {
 							tool=TOOL_PAINTING;
-							Point2i local =(xform_inv.xform(Point2(mb.x,mb.y))/snap).floor();
+							Point2i local =node->world_to_map((xform_inv.xform(Point2(mb.x,mb.y))));
 							paint_undo.clear();
 							CellOp op;
 							op.idx = node->get_cell(local.x,local.y);
@@ -278,7 +278,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 				} else if (mb.pressed && tool==TOOL_NONE) {
 
 					tool=TOOL_ERASING;
-					Point2i local =(xform_inv.xform(Point2(mb.x,mb.y))/snap).floor();
+					Point2i local =node->world_to_map(xform_inv.xform(Point2(mb.x,mb.y)));
 					paint_undo.clear();
 					CellOp op;
 					op.idx = node->get_cell(local.x,local.y);
@@ -322,7 +322,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
 
 			const InputEventMouseMotion &mm=p_event.mouse_motion;
 
-			Point2i new_over_tile = (xform_inv.xform(Point2(mm.x,mm.y))/snap).floor();
+			Point2i new_over_tile = node->world_to_map(xform_inv.xform(Point2(mm.x,mm.y)));//(xform_inv.xform(Point2(mm.x,mm.y))/snap).floor();
 			if (new_over_tile!=over_tile) {
 
 				over_tile=new_over_tile;
@@ -469,44 +469,104 @@ void TileMapEditor::_canvas_draw() {
 	if (!node)
 		return;
 
-	int cell_size=node->get_cell_size();
+	Size2 cell_size=node->get_cell_size();
+	Matrix32 cell_xf = node->get_cell_transform();
 
 	Matrix32 xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
 	Matrix32 xform_inv = xform.affine_inverse();
 
 
 	Size2 screen_size=canvas_item_editor->get_size();
-	Rect2 aabb;
-	aabb.pos=xform_inv.xform(Vector2());
-	aabb.expand_to(xform_inv.xform(Vector2(0,screen_size.height)));
-	aabb.expand_to(xform_inv.xform(Vector2(screen_size.width,0)));
-	aabb.expand_to(xform_inv.xform(screen_size));
-	Rect2i si=aabb;
+	{
+		Rect2 aabb;
+		aabb.pos=node->world_to_map(xform_inv.xform(Vector2()));
+		aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(0,screen_size.height))));
+		aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(screen_size.width,0))));
+		aabb.expand_to(node->world_to_map(xform_inv.xform(screen_size)));
+		Rect2i si=aabb.grow(1.0);
 
-	for(int i=(si.pos.x/cell_size)-1;i<=(si.pos.x+si.size.x)/cell_size;i++) {
+		if (node->get_half_offset()!=TileMap::HALF_OFFSET_X) {
 
-		int ofs = i*cell_size;
+			for(int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {
 
-		Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
-		canvas_item_editor->draw_line(xform.xform(Point2(ofs,si.pos.y)),xform.xform(Point2(ofs,si.pos.y+si.size.y)),col,1);
+				Vector2 from = xform.xform(node->map_to_world(Vector2(i,si.pos.y)));
+				Vector2 to = xform.xform(node->map_to_world(Vector2(i,si.pos.y+si.size.y+1)));
 
-	}
+				Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+				canvas_item_editor->draw_line(from,to,col,1);
+
+			}
+		} else {
 
-	for(int i=(si.pos.y/cell_size)-1;i<=(si.pos.y+si.size.y)/cell_size;i++) {
 
-		int ofs = i*cell_size;
+			for(int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {
+
+				for(int j=(si.pos.y)-1;j<=(si.pos.y+si.size.y);j++) {
+
+					Vector2 ofs;
+					if (ABS(j)&1) {
+						ofs=cell_xf[0]*0.5;
+					}
+
+					Vector2 from = xform.xform(node->map_to_world(Vector2(i,j),true)+ofs);
+					Vector2 to = xform.xform(node->map_to_world(Vector2(i,j+1),true)+ofs);
+					Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+					canvas_item_editor->draw_line(from,to,col,1);
+				}
+
+			}
+		}
+
+		if (node->get_half_offset()!=TileMap::HALF_OFFSET_Y) {
+
+			for(int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {
+
+				Vector2 from = xform.xform(node->map_to_world(Vector2(si.pos.x,i)));
+				Vector2 to = xform.xform(node->map_to_world(Vector2(si.pos.x+si.size.x+1,i)));
+
+				Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+				canvas_item_editor->draw_line(from,to,col,1);
+
+			}
+		} else {
+
+
+			for(int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {
+
+				for(int j=(si.pos.x)-1;j<=(si.pos.x+si.size.x);j++) {
+
+					Vector2 ofs;
+					if (ABS(j)&1) {
+						ofs=cell_xf[1]*0.5;
+					}
+
+					Vector2 from = xform.xform(node->map_to_world(Vector2(j,i),true)+ofs);
+					Vector2 to = xform.xform(node->map_to_world(Vector2(j+1,i),true)+ofs);
+					Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
+					canvas_item_editor->draw_line(from,to,col,1);
+				}
+
+			}
+
+
+
+		}
+/*
+	for(int i=(si.pos.y/cell_size.y)-1;i<=(si.pos.y+si.size.y)/cell_size.y;i++) {
+
+		int ofs = i*cell_size.y;
 		Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
-		canvas_item_editor->draw_line(xform.xform(Point2(si.pos.x,ofs)),xform.xform(Point2(si.pos.x+si.size.x,ofs)),col,1);
+		canvas_item_editor->draw_line(xform.xform(Point2(si.pos.x,ofs)),xform.xform(Point2(si.pos.x+si.size.x,ofs)),col,1);*/
 	}
 
 
 	if (selection_active) {
 
 		Vector<Vector2> points;
-		points.push_back( xform.xform( selection.pos * cell_size) );
-		points.push_back( xform.xform( (selection.pos+Point2(selection.size.x+1,0)) * cell_size) );
-		points.push_back( xform.xform( (selection.pos+Point2(selection.size.x+1,selection.size.y+1)) * cell_size) );
-		points.push_back( xform.xform( (selection.pos+Point2(0,selection.size.y+1)) * cell_size) );
+		points.push_back( xform.xform( node->map_to_world(( selection.pos ) )));
+		points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(selection.size.x+1,0)) ) ));
+		points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(selection.size.x+1,selection.size.y+1)) ) ));
+		points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(0,selection.size.y+1)) ) ));
 		Color col=Color(0.2,0.8,1,0.4);
 
 		canvas_item_editor->draw_colored_polygon(points,col);
@@ -515,15 +575,22 @@ void TileMapEditor::_canvas_draw() {
 
 	if (mouse_over){
 
-		const Vector2 endpoints[4]={
-
-			xform.xform( over_tile * cell_size) ,
-			xform.xform( (over_tile+Point2(1,0)) * cell_size) ,
-			xform.xform( (over_tile+Point2(1,1)) * cell_size) ,
-			xform.xform( (over_tile+Point2(0,1)) * cell_size) ,
+		Vector2 endpoints[4]={
 
+			( node->map_to_world(over_tile,true) ) ,
+			( node->map_to_world((over_tile+Point2(1,0)),true ) ),
+			( node->map_to_world((over_tile+Point2(1,1)),true ) ),
+			( node->map_to_world((over_tile+Point2(0,1)),true ) )
 
 		};
+
+		for(int i=0;i<4;i++) {
+			if (node->get_half_offset()==TileMap::HALF_OFFSET_X && ABS(over_tile.y)&1)
+				endpoints[i]+=cell_xf[0]*0.5;
+			if (node->get_half_offset()==TileMap::HALF_OFFSET_Y && ABS(over_tile.x)&1)
+				endpoints[i]+=cell_xf[1]*0.5;
+			endpoints[i]=xform.xform(endpoints[i]);
+		}
 		Color col;
 		if (node->get_cell(over_tile.x,over_tile.y)!=TileMap::INVALID_CELL)
 			col=Color(0.2,0.8,1.0,0.8);
@@ -542,10 +609,10 @@ void TileMapEditor::_canvas_draw() {
 
 
 			Vector<Vector2> points;
-			points.push_back( xform.xform( duplicate.pos * cell_size) );
-			points.push_back( xform.xform( (duplicate.pos+Point2(duplicate.size.x+1,0)) * cell_size) );
-			points.push_back( xform.xform( (duplicate.pos+Point2(duplicate.size.x+1,duplicate.size.y+1)) * cell_size) );
-			points.push_back( xform.xform( (duplicate.pos+Point2(0,duplicate.size.y+1)) * cell_size) );
+			points.push_back( xform.xform( node->map_to_world(duplicate.pos ) ));
+			points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,0)) ) ));
+			points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,duplicate.size.y+1))) ));
+			points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(0,duplicate.size.y+1))) ));
 			Color col=Color(0.2,1.0,0.8,0.4);
 
 			canvas_item_editor->draw_colored_polygon(points,col);
@@ -562,18 +629,19 @@ void TileMapEditor::_canvas_draw() {
 
 					Ref<Texture> t = ts->tile_get_texture(st);
 					if (t.is_valid()) {
-						Rect2 r = ts->tile_get_region(st);
-						Size2 sc = (endpoints[2]-endpoints[0])/cell_size;
+						Vector2 from = xform.xform(ts->tile_get_texture_offset(st)+node->map_to_world(over_tile)+node->get_cell_draw_offset());
+						Rect2 r = ts->tile_get_region(st);												
+						Size2 sc = xform.get_scale();
 						if (mirror_x->is_pressed())
 							sc.x*=-1.0;
 						if (mirror_y->is_pressed())
 							sc.y*=-1.0;
 						if (r==Rect2()) {
 
-							canvas_item_editor->draw_texture_rect(t,Rect2(endpoints[0],t->get_size()*sc),false,Color(1,1,1,0.5));
+							canvas_item_editor->draw_texture_rect(t,Rect2(from,t->get_size()*sc),false,Color(1,1,1,0.5));
 						} else {
 
-							canvas_item_editor->draw_texture_rect_region(t,Rect2(endpoints[0],r.get_size()*sc),r,Color(1,1,1,0.5));
+							canvas_item_editor->draw_texture_rect_region(t,Rect2(from,r.get_size()*sc),r,Color(1,1,1,0.5));
 						}
 					}
 				}

+ 3 - 2
tools/editor/plugins/tile_set_editor_plugin.cpp

@@ -44,6 +44,7 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me
 
 	       Node *child = scene->get_child(i);
 
+
 	       if (!child->cast_to<Sprite>()) {
 		       if (child->get_child_count()>0) {
 			       child=child->get_child(0);
@@ -72,7 +73,7 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me
 
 
 	       p_library->tile_set_texture(id,texture);
-	       Vector2 phys_offset = mi->get_offset();
+	       Vector2 phys_offset;
 
 	       if (mi->is_centered()) {
 		       Size2 s;
@@ -112,7 +113,7 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me
 
 	       }
 
-	       p_library->tile_set_texture_offset(id,Vector2());
+	       p_library->tile_set_texture_offset(id,mi->get_offset());
 	}
 }
 

+ 5 - 0
tools/export/blender25/io_scene_dae/__init__.py

@@ -108,6 +108,11 @@ class ExportDAE(bpy.types.Operator, ExportHelper):
             description=("Export all actions for the first armature found in separate DAE files"),
             default=False,
             )
+    use_anim_skip_noexp = BoolProperty(
+	    name="Skip (-noexp) Actions",
+	    description="Skip exporting of actions whose name end in (-noexp). Useful to skip control animations.",
+	    default=True,
+	    )
     use_anim_optimize = BoolProperty(
             name="Optimize Keyframes",
             description="Remove double keyframes",

+ 9 - 1
tools/export/blender25/io_scene_dae/export_dae.py

@@ -317,6 +317,7 @@ class DaeExporter:
 
 	def export_mesh(self,node,armature=None,shapename=None):
 
+		mesh = node.data
 		if (node.data in self.mesh_cache) and shapename==None:
 			return self.mesh_cache[mesh]
 
@@ -475,7 +476,12 @@ class DaeExporter:
 			self.writel(S_GEOM,3,'<source id="'+meshid+'-texcoord-'+str(uvi)+'">')
 			float_values=""
 			for v in vertices:
-				float_values+=" "+str(v.uv[uvi].x)+" "+str(v.uv[uvi].y)
+				try:
+					float_values+=" "+str(v.uv[uvi].x)+" "+str(v.uv[uvi].y)
+				except:
+					# I don't understand this weird multi-uv-layer API, but with this it seems to works
+					float_values+=" 0 0 "
+
 			self.writel(S_GEOM,4,'<float_array id="'+meshid+'-texcoord-'+str(uvi)+'-array" count="'+str(len(vertices)*2)+'">'+float_values+'</float_array>')
 			self.writel(S_GEOM,4,'<technique_common>')
 			self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-texcoord-'+str(uvi)+'-array" count="'+str(len(vertices))+'" stride="2">')
@@ -1156,6 +1162,8 @@ class DaeExporter:
 			for x in bpy.data.actions[:]:
 				if x.users==0 or x in self.action_constraints:
 					continue
+				if (self.config["use_anim_skip_noexp"] and x.name.endswith("-noexp")):
+					continue
 
 				bones=[]
 				#find bones used