Browse Source

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 năm trước cách đây
mục cha
commit
b24fe3dd20
84 tập tin đã thay đổi với 1657 bổ sung341 xóa
  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. BIN
      demos/3d/truck_town/car_base.scn
  8. BIN
      demos/3d/truck_town/cement.tex
  9. BIN
      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. BIN
      demos/3d/truck_town/grass.tex
  13. BIN
      demos/3d/truck_town/trailer_truck.scn
  14. BIN
      demos/3d/truck_town/truck_scene.scn
  15. BIN
      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());

BIN
demos/3d/truck_town/car_base.scn


BIN
demos/3d/truck_town/cement.tex


BIN
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)
+
+	
+	
+
+
+

BIN
demos/3d/truck_town/grass.tex


BIN
demos/3d/truck_town/trailer_truck.scn


BIN
demos/3d/truck_town/truck_scene.scn


BIN
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