浏览代码

Merge branch 'master' of git://github.com/godotengine/godot into kcc_lightoccluder2d_doc

Chris Bradfield 8 年之前
父节点
当前提交
134e24408a
共有 100 个文件被更改,包括 1999 次插入714 次删除
  1. 141 0
      DONORS.md
  2. 11 0
      core/array.cpp
  3. 2 0
      core/array.h
  4. 3 5
      core/class_db.cpp
  5. 3 0
      core/io/resource_format_binary.cpp
  6. 48 0
      core/list.h
  7. 22 64
      core/math/camera_matrix.cpp
  8. 2 0
      core/math/camera_matrix.h
  9. 15 0
      core/math/matrix3.cpp
  10. 2 0
      core/math/matrix3.h
  11. 6 6
      core/math/transform.cpp
  12. 0 12
      core/object.h
  13. 1 2
      core/resource.cpp
  14. 1 0
      core/script_language.h
  15. 102 0
      core/string_buffer.cpp
  16. 82 0
      core/string_buffer.h
  17. 94 0
      core/string_builder.cpp
  18. 36 25
      core/string_builder.h
  19. 2 0
      core/variant_call.cpp
  20. 12 10
      core/variant_parser.cpp
  21. 149 71
      doc/base/classes.xml
  22. 4 0
      drivers/gles3/rasterizer_canvas_gles3.cpp
  23. 46 37
      drivers/gles3/rasterizer_scene_gles3.cpp
  24. 4 3
      drivers/gles3/rasterizer_scene_gles3.h
  25. 19 0
      drivers/gles3/rasterizer_storage_gles3.cpp
  26. 6 0
      drivers/gles3/rasterizer_storage_gles3.h
  27. 43 10
      drivers/gles3/shader_compiler_gles3.cpp
  28. 2 2
      drivers/gles3/shaders/canvas.glsl
  29. 12 1
      drivers/gles3/shaders/effect_blur.glsl
  30. 55 29
      drivers/gles3/shaders/scene.glsl
  31. 5 1
      drivers/gles3/shaders/screen_space_reflection.glsl
  32. 19 2
      drivers/gles3/shaders/ssao.glsl
  33. 4 0
      drivers/gles3/shaders/ssao_minify.glsl
  34. 68 58
      drivers/gles3/shaders/subsurf_scattering.glsl
  35. 27 15
      drivers/unix/dir_access_unix.cpp
  36. 66 27
      drivers/unix/file_access_unix.cpp
  37. 52 8
      editor/SCsub
  38. 8 1
      editor/doc/doc_data.cpp
  39. 59 29
      editor/editor_about.cpp
  40. 1 0
      editor/editor_about.h
  41. 35 85
      editor/editor_dir_dialog.cpp
  42. 4 3
      editor/editor_dir_dialog.h
  43. 8 5
      editor/editor_fonts.cpp
  44. 13 11
      editor/editor_help.cpp
  45. 1 2
      editor/editor_log.cpp
  46. 54 15
      editor/editor_node.cpp
  47. 2 1
      editor/editor_node.h
  48. 0 1
      editor/editor_settings.cpp
  49. 20 23
      editor/editor_themes.cpp
  50. 14 2
      editor/filesystem_dock.cpp
  51. 8 1
      editor/import/resource_importer_texture.cpp
  52. 73 17
      editor/plugins/canvas_item_editor_plugin.cpp
  53. 2 2
      editor/plugins/canvas_item_editor_plugin.h
  54. 0 1
      editor/plugins/collision_polygon_2d_editor_plugin.h
  55. 0 1
      editor/plugins/collision_polygon_editor_plugin.h
  56. 4 3
      editor/plugins/cube_grid_theme_editor_plugin.cpp
  57. 0 1
      editor/plugins/light_occluder_2d_editor_plugin.h
  58. 0 1
      editor/plugins/line_2d_editor_plugin.h
  59. 0 1
      editor/plugins/navigation_polygon_editor_plugin.h
  60. 0 1
      editor/plugins/path_2d_editor_plugin.h
  61. 0 1
      editor/plugins/polygon_2d_editor_plugin.h
  62. 19 8
      editor/plugins/script_editor_plugin.cpp
  63. 2 7
      editor/plugins/script_text_editor.cpp
  64. 2 0
      editor/plugins/shader_editor_plugin.cpp
  65. 316 3
      editor/plugins/spatial_editor_plugin.cpp
  66. 34 1
      editor/plugins/spatial_editor_plugin.h
  67. 14 0
      editor/plugins/sprite_frames_editor_plugin.cpp
  68. 0 1
      editor/plugins/theme_editor_plugin.h
  69. 46 21
      editor/project_settings_editor.cpp
  70. 5 1
      editor/project_settings_editor.h
  71. 35 17
      editor/quick_open.cpp
  72. 1 0
      editor/quick_open.h
  73. 1 1
      editor/settings_config_dialog.cpp
  74. 6 0
      main/main.cpp
  75. 1 2
      modules/etc/image_etc.cpp
  76. 8 4
      modules/gdnative/SCsub
  77. 5 1
      modules/gdnative/gdnative.cpp
  78. 6 1
      modules/gdnative/gdnative.h
  79. 1 1
      modules/gdnative/gdnative/array.cpp
  80. 1 1
      modules/gdnative/gdnative/basis.cpp
  81. 1 1
      modules/gdnative/gdnative/color.cpp
  82. 1 1
      modules/gdnative/gdnative/dictionary.cpp
  83. 1 2
      modules/gdnative/gdnative/gdnative.cpp
  84. 1 1
      modules/gdnative/gdnative/node_path.cpp
  85. 1 1
      modules/gdnative/gdnative/plane.cpp
  86. 1 1
      modules/gdnative/gdnative/pool_arrays.cpp
  87. 1 1
      modules/gdnative/gdnative/quat.cpp
  88. 1 1
      modules/gdnative/gdnative/rect2.cpp
  89. 1 1
      modules/gdnative/gdnative/rect3.cpp
  90. 1 1
      modules/gdnative/gdnative/rid.cpp
  91. 1 1
      modules/gdnative/gdnative/string.cpp
  92. 1 1
      modules/gdnative/gdnative/transform.cpp
  93. 1 1
      modules/gdnative/gdnative/transform2d.cpp
  94. 1 1
      modules/gdnative/gdnative/variant.cpp
  95. 1 1
      modules/gdnative/gdnative/vector2.cpp
  96. 1 1
      modules/gdnative/gdnative/vector3.cpp
  97. 0 23
      modules/gdnative/godot/icon.png.import
  98. 3 3
      modules/gdnative/include/gdnative/array.h
  99. 3 3
      modules/gdnative/include/gdnative/basis.h
  100. 2 2
      modules/gdnative/include/gdnative/color.h

+ 141 - 0
DONORS.md

@@ -0,0 +1,141 @@
+# Donors to the Godot Engine project
+
+Godot Engine is a non-profit project developed by a community of voluntary
+contributors, as well as occasional paid contributors thanks to the financial
+support of generous donors.
+
+The ways to donate to the project, as well as details on how the funds are
+used, are described on [Godot's website](https://godotengine.org/donate).
+
+The following is a list of the current monthly donors, to be have their
+generous deed immortalized in the next stable release of Godot Engine.
+
+## Platinum sponsors
+
+None so far, but your company could be the first! :)
+
+## Gold sponsors
+
+    Gamblify <https://www.gamblify.com>
+
+## Mini sponsors
+
+    Arron Washington
+    Chrisartguy
+    Christian Uldall Pedersen
+    Hein-Pieter van Braam
+    Matthieu Huvé
+    Neal Gompa (Conan Kudo)
+    Olimpiu Metiu
+    Ruslan Mustakov
+
+## Gold donors
+
+    Alexander Otto
+    Jake Bo
+    Javier
+    Nathan Warden
+    Ranoller
+    Rémi Verschelde
+    Stephan Lanfermann
+
+    Andreas Schüle
+    Bernhard Liebl
+    Jordan M Lucas
+
+    BanjoNode2D
+    Chris Serino
+    Conrad Curry
+    Craig Smith
+    David Churchill
+    Dean Harmon
+    Guilherme Felipe de C. G. da Silva
+    Henrique Alves
+    Laurence Bannister
+    Leo
+    Przemysław Gołąb (n-pigeon)
+    Robert Willes
+    Robin Arys
+    summerblind
+    Testus Maximus
+    Thomas Bjarnelöf
+
+    Amanda Haldy
+    Andreas Haas
+    Bryanna M
+    Cody Parker
+    D
+    Ezra Theunissen
+    flesk
+    François Cantin
+    Hendrik Mans
+    Jeppe Zapp
+    Johannes Wuensch
+    Justin Arnold
+    Justo Delgado Baudí
+    Leandro Voltolino
+    Myles
+    Robert Podgorski
+    Scott Beacon
+    x1212
+
+## Silver donors
+
+    Alex Barsukov
+    Avencherus
+    Bastian Böhm
+    Ben Vercammen
+    Bryan Stevenson
+    Collin Shooltz
+    Fabian Becker
+    fengjiongmax
+    Geequlim
+    Gerrit Großkopf
+    Guldoman
+    hatniX
+    HeartBeast
+    Heribert Hirth
+    Hunter Jones
+    imekon
+    Jacob McKenney
+    Jonathon
+    Josh 'Cheeseness' Bush
+    Julian Murgia
+    Juraj Móza
+    Kevin Boyer
+    Klavdij Voncina
+    Lisandro Lorea
+    magodev
+    Martin Novák
+    Matthew Fitzpatrick
+    Matthew Valancy
+    Matthias Hölzl
+    Max R.R. Collada
+    Michael Gringauz
+    Mikael Olsson
+    Moritz Laass
+    nee
+    nvgrod
+    Pablo Seibelt
+    Pan Ip
+    Paul Mason
+    Paweł Kowal
+    Pietro Vertechi
+    rayos
+    Richman Stewart
+    Roger Smith
+    Sam Van Campenhout
+    Sam Vila
+    Sasori Olkof
+    Sootstone
+    Tavo Tell
+    Tom Larrow
+    Trent McPheron
+    Troy Bonneau
+    UltyX
+    Xananax & karroffel
+
+## Bronze donors
+
+There are even more donors that support the project with a small monthly donation.
+Every bit counts and we thank every one of them for their amazing support!

+ 11 - 0
core/array.cpp

@@ -210,6 +210,17 @@ const Variant &Array::get(int p_idx) const {
 	return operator[](p_idx);
 }
 
+Array Array::duplicate() const {
+
+	Array new_arr;
+	int element_count = size();
+	new_arr.resize(element_count);
+	for (int i = 0; i < element_count; i++) {
+		new_arr[i] = get(i);
+	}
+
+	return new_arr;
+}
 struct _ArrayVariantSort {
 
 	_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {

+ 2 - 0
core/array.h

@@ -84,6 +84,8 @@ public:
 	Variant pop_back();
 	Variant pop_front();
 
+	Array duplicate() const;
+
 	Array(const Array &p_from);
 	Array();
 	~Array();

+ 3 - 5
core/class_db.cpp

@@ -536,11 +536,9 @@ void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, b
 			minfo.return_val = method->get_return_info();
 			minfo.flags = method->get_hint_flags();
 
-			int defval_count = method->get_default_argument_count();
-			minfo.default_arguments.resize(defval_count);
-
-			for (int i = 0; i < defval_count; i++) {
-				minfo.default_arguments[i] = method->get_default_argument(defval_count - i - 1);
+			for (int i = 0; i < method->get_argument_count(); i++) {
+				if (method->has_default_argument(i))
+					minfo.default_arguments.push_back(method->get_default_argument(i));
 			}
 
 			p_methods->push_back(minfo);

+ 3 - 0
core/io/resource_format_binary.cpp

@@ -1117,6 +1117,9 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
 			memdelete(f);
 		}
 		ERR_FAIL_COND_V(!fw, ERR_CANT_CREATE);
+
+		uint8_t magic[4] = { 'R', 'S', 'R', 'C' };
+		fw->store_buffer(magic, 4);
 	}
 
 	bool big_endian = f->get_32();

+ 48 - 0
core/list.h

@@ -291,6 +291,54 @@ public:
 			erase(_data->first);
 	}
 
+	Element *insert_after(Element *p_element, const T &p_value) {
+		CRASH_COND(p_element && (!_data || p_element->data != _data));
+
+		if (!p_element) {
+			return push_back(p_value);
+		}
+
+		Element *n = memnew_allocator(Element, A);
+		n->value = (T &)p_value;
+		n->prev_ptr = p_element;
+		n->next_ptr = p_element->next_ptr;
+		n->data = _data;
+
+		if (!p_element->next_ptr) {
+			_data->last = n;
+		}
+
+		p_element->next_ptr = n;
+
+		_data->size_cache++;
+
+		return n;
+	}
+
+	Element *insert_before(Element *p_element, const T &p_value) {
+		CRASH_COND(p_element && (!_data || p_element->data != _data));
+
+		if (!p_element) {
+			return push_back(p_value);
+		}
+
+		Element *n = memnew_allocator(Element, A);
+		n->value = (T &)p_value;
+		n->prev_ptr = p_element->prev_ptr;
+		n->next_ptr = p_element;
+		n->data = _data;
+
+		if (!p_element->prev_ptr) {
+			_data->first = n;
+		}
+
+		p_element->prev_ptr = n;
+
+		_data->size_cache++;
+
+		return n;
+	}
+
 	/**
 	 * find an element in the list,
 	 */

+ 22 - 64
core/math/camera_matrix.cpp

@@ -265,76 +265,28 @@ void CameraMatrix::get_viewport_size(real_t &r_width, real_t &r_height) const {
 
 bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const {
 
-	const real_t *matrix = (const real_t *)this->matrix;
-
-	///////--- Near Plane ---///////
-	Plane near_plane = Plane(matrix[3] + matrix[2],
-			matrix[7] + matrix[6],
-			matrix[11] + matrix[10],
-			-matrix[15] - matrix[14]);
-	near_plane.normalize();
-
-	///////--- Far Plane ---///////
-	Plane far_plane = Plane(matrix[2] - matrix[3],
-			matrix[6] - matrix[7],
-			matrix[10] - matrix[11],
-			matrix[15] - matrix[14]);
-	far_plane.normalize();
-
-	///////--- Right Plane ---///////
-	Plane right_plane = Plane(matrix[0] - matrix[3],
-			matrix[4] - matrix[7],
-			matrix[8] - matrix[11],
-			-matrix[15] + matrix[12]);
-	right_plane.normalize();
-
-	///////--- Top Plane ---///////
-	Plane top_plane = Plane(matrix[1] - matrix[3],
-			matrix[5] - matrix[7],
-			matrix[9] - matrix[11],
-			-matrix[15] + matrix[13]);
-	top_plane.normalize();
-
-	Vector3 near_endpoint_left, near_endpoint_right;
-	Vector3 far_endpoint_left, far_endpoint_right;
-
-	bool res = near_plane.intersect_3(right_plane, top_plane, &near_endpoint_right);
-	ERR_FAIL_COND_V(!res, false);
-
-	res = far_plane.intersect_3(right_plane, top_plane, &far_endpoint_right);
-	ERR_FAIL_COND_V(!res, false);
-
-	if ((matrix[8] == 0) && (matrix[9] == 0)) {
-		near_endpoint_left = near_endpoint_right;
-		near_endpoint_left.x = -near_endpoint_left.x;
-
-		far_endpoint_left = far_endpoint_right;
-		far_endpoint_left.x = -far_endpoint_left.x;
-	} else {
-		///////--- Left Plane ---///////
-		Plane left_plane = Plane(matrix[0] + matrix[3],
-				matrix[4] + matrix[7],
-				matrix[8] + matrix[11],
-				-matrix[15] - matrix[12]);
-		left_plane.normalize();
+	Vector<Plane> planes = get_projection_planes(Transform());
+	const Planes intersections[8][3]={
+		{PLANE_FAR,PLANE_LEFT,PLANE_TOP},
+		{PLANE_FAR,PLANE_LEFT,PLANE_BOTTOM},
+		{PLANE_FAR,PLANE_RIGHT,PLANE_TOP},
+		{PLANE_FAR,PLANE_RIGHT,PLANE_BOTTOM},
+		{PLANE_NEAR,PLANE_LEFT,PLANE_TOP},
+		{PLANE_NEAR,PLANE_LEFT,PLANE_BOTTOM},
+		{PLANE_NEAR,PLANE_RIGHT,PLANE_TOP},
+		{PLANE_NEAR,PLANE_RIGHT,PLANE_BOTTOM},
+	};
 
-		res = near_plane.intersect_3(left_plane, top_plane, &near_endpoint_left);
-		ERR_FAIL_COND_V(!res, false);
+	for(int i=0;i<8;i++) {
 
-		res = far_plane.intersect_3(left_plane, top_plane, &far_endpoint_left);
+		Vector3 point;
+		bool res = planes[intersections[i][0]].intersect_3(planes[intersections[i][1]],planes[intersections[i][2]], &point);
 		ERR_FAIL_COND_V(!res, false);
+		p_8points[i]=p_transform.xform(point);
 	}
 
-	p_8points[0] = p_transform.xform(Vector3(near_endpoint_right.x, near_endpoint_right.y, near_endpoint_right.z));
-	p_8points[1] = p_transform.xform(Vector3(near_endpoint_right.x, -near_endpoint_right.y, near_endpoint_right.z));
-	p_8points[2] = p_transform.xform(Vector3(near_endpoint_left.x, near_endpoint_left.y, near_endpoint_left.z));
-	p_8points[3] = p_transform.xform(Vector3(near_endpoint_left.x, -near_endpoint_left.y, near_endpoint_left.z));
-	p_8points[4] = p_transform.xform(Vector3(far_endpoint_right.x, far_endpoint_right.y, far_endpoint_right.z));
-	p_8points[5] = p_transform.xform(Vector3(far_endpoint_right.x, -far_endpoint_right.y, far_endpoint_right.z));
-	p_8points[6] = p_transform.xform(Vector3(far_endpoint_left.x, far_endpoint_left.y, far_endpoint_left.z));
-	p_8points[7] = p_transform.xform(Vector3(far_endpoint_left.x, -far_endpoint_left.y, far_endpoint_left.z));
-
 	return true;
+
 }
 
 Vector<Plane> CameraMatrix::get_projection_planes(const Transform &p_transform) const {
@@ -610,6 +562,12 @@ int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const {
 	return int((result.x * 0.5 + 0.5) * p_for_pixel_width);
 }
 
+bool CameraMatrix::is_orthogonal() const {
+
+	return matrix[3][3]==1.0;
+}
+
+
 real_t CameraMatrix::get_fov() const {
 	const real_t *matrix = (const real_t *)this->matrix;
 

+ 2 - 0
core/math/camera_matrix.h

@@ -69,6 +69,7 @@ struct CameraMatrix {
 	real_t get_z_near() const;
 	real_t get_aspect() const;
 	real_t get_fov() const;
+	bool is_orthogonal() const;
 
 	Vector<Plane> get_projection_planes(const Transform &p_transform) const;
 
@@ -83,6 +84,7 @@ struct CameraMatrix {
 	Plane xform4(const Plane &p_vec4) const;
 	_FORCE_INLINE_ Vector3 xform(const Vector3 &p_vec3) const;
 
+
 	operator String() const;
 
 	void scale_translate_to_fit(const Rect3 &p_aabb);

+ 15 - 0
core/math/matrix3.cpp

@@ -234,7 +234,22 @@ Basis Basis::scaled(const Vector3 &p_scale) const {
 	return m;
 }
 
+void Basis::set_scale(const Vector3 &p_scale) {
+
+	set_axis(0, get_axis(0).normalized() * p_scale.x);
+	set_axis(1, get_axis(1).normalized() * p_scale.y);
+	set_axis(2, get_axis(2).normalized() * p_scale.z);
+}
+
 Vector3 Basis::get_scale() const {
+
+	return Vector3(
+			Vector3(elements[0][0], elements[1][0], elements[2][0]).length(),
+			Vector3(elements[0][1], elements[1][1], elements[2][1]).length(),
+			Vector3(elements[0][2], elements[1][2], elements[2][2]).length());
+}
+
+Vector3 Basis::get_signed_scale() const {
 	// FIXME: We are assuming M = R.S (R is rotation and S is scaling), and use polar decomposition to extract R and S.
 	// A polar decomposition is M = O.P, where O is an orthogonal matrix (meaning rotation and reflection) and
 	// P is a positive semi-definite matrix (meaning it contains absolute values of scaling along its diagonal).

+ 2 - 0
core/math/matrix3.h

@@ -97,7 +97,9 @@ public:
 	void scale(const Vector3 &p_scale);
 	Basis scaled(const Vector3 &p_scale) const;
 
+	void set_scale(const Vector3 &p_scale);
 	Vector3 get_scale() const;
+	Vector3 get_signed_scale() const;
 
 	// transposed dot products
 	_FORCE_INLINE_ real_t tdotx(const Vector3 &v) const {

+ 6 - 6
core/math/transform.cpp

@@ -118,17 +118,17 @@ Transform Transform::interpolate_with(const Transform &p_transform, real_t p_c)
 
 	/* not sure if very "efficient" but good enough? */
 
-	Vector3 src_scale = basis.get_scale();
-	Quat src_rot = basis;
+	Vector3 src_scale = basis.get_signed_scale();
+	Quat src_rot = basis.orthonormalized();
 	Vector3 src_loc = origin;
 
-	Vector3 dst_scale = p_transform.basis.get_scale();
+	Vector3 dst_scale = p_transform.basis.get_signed_scale();
 	Quat dst_rot = p_transform.basis;
 	Vector3 dst_loc = p_transform.origin;
 
-	Transform dst;
-	dst.basis = src_rot.slerp(dst_rot, p_c);
-	dst.basis.scale(src_scale.linear_interpolate(dst_scale, p_c));
+	Transform dst; //this could be made faster by using a single function in Basis..
+	dst.basis = src_rot.slerp(dst_rot, p_c).normalized();
+	dst.basis.set_scale(src_scale.linear_interpolate(dst_scale, p_c));
 	dst.origin = src_loc.linear_interpolate(dst_loc, p_c);
 
 	return dst;

+ 0 - 12
core/object.h

@@ -567,12 +567,6 @@ public:
 
 	template <class T>
 	static T *cast_to(Object *p_object) {
-#ifdef DEBUG_ENABLED
-		// TODO there are some legitimate reasons to pass NULL as p_object.
-		// we need to figure out how to deal with that in debug mode.
-		// This code will return NULL for a NULL input in release mode also.
-		ERR_FAIL_COND_V(p_object == NULL, NULL);
-#endif
 #ifndef NO_SAFE_CAST
 		return dynamic_cast<T *>(p_object);
 #else
@@ -587,12 +581,6 @@ public:
 
 	template <class T>
 	static const T *cast_to(const Object *p_object) {
-#ifdef DEBUG_ENABLED
-		// TODO there are some legitimate reasons to pass NULL as p_object.
-		// we need to figure out how to deal with that in debug mode.
-		// This code will return NULL for a NULL input in release mode also.
-		ERR_FAIL_COND_V(p_object == NULL, NULL);
-#endif
 #ifndef NO_SAFE_CAST
 		return dynamic_cast<const T *>(p_object);
 #else

+ 1 - 2
core/resource.cpp

@@ -69,12 +69,11 @@ void Resource::set_path(const String &p_path, bool p_take_over) {
 			ResourceCache::resources.get(p_path)->set_name("");
 			ResourceCache::lock->write_unlock();
 		} else {
-			ERR_EXPLAIN("Another resource is loaded from path: " + p_path);
-
 			ResourceCache::lock->read_lock();
 			bool exists = ResourceCache::resources.has(p_path);
 			ResourceCache::lock->read_unlock();
 
+			ERR_EXPLAIN("Another resource is loaded from path: " + p_path);
 			ERR_FAIL_COND(exists);
 		}
 	}

+ 1 - 0
core/script_language.h

@@ -206,6 +206,7 @@ public:
 	virtual int find_function(const String &p_function, const String &p_code) const = 0;
 	virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const = 0;
 	virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; }
+	virtual bool overrides_external_editor() { return false; }
 
 	virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; }
 

+ 102 - 0
core/string_buffer.cpp

@@ -0,0 +1,102 @@
+/*************************************************************************/
+/*  string_buffer.cpp                                                    */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+#include "string_buffer.h"
+
+#include <string.h>
+
+StringBuffer &StringBuffer::append(CharType p_char) {
+	reserve(string_length + 2);
+	current_buffer_ptr()[string_length++] = p_char;
+	return *this;
+}
+
+StringBuffer &StringBuffer::append(const String &p_string) {
+	return append(p_string.c_str());
+}
+
+StringBuffer &StringBuffer::append(const char *p_str) {
+	int len = strlen(p_str);
+	reserve(string_length + len + 1);
+
+	CharType *buf = current_buffer_ptr();
+	for (const char *c_ptr = p_str; c_ptr; ++c_ptr) {
+		buf[string_length++] = *c_ptr;
+	}
+	return *this;
+}
+
+StringBuffer &StringBuffer::append(const CharType *p_str, int p_clip_to_len) {
+	int len = 0;
+	while ((p_clip_to_len < 0 || len < p_clip_to_len) && p_str[len]) {
+		++len;
+	}
+	reserve(string_length + len + 1);
+	memcpy(&(current_buffer_ptr()[string_length]), p_str, len * sizeof(CharType));
+	string_length += len;
+
+	return *this;
+}
+
+StringBuffer &StringBuffer::reserve(int p_size) {
+	if (p_size < SHORT_BUFFER_SIZE || p_size < buffer.size())
+		return *this;
+
+	bool need_copy = string_length > 0 && buffer.empty();
+	buffer.resize(next_power_of_2(p_size));
+	if (need_copy) {
+		memcpy(buffer.ptr(), short_buffer, string_length * sizeof(CharType));
+	}
+
+	return *this;
+}
+
+int StringBuffer::length() const {
+	return string_length;
+}
+
+String StringBuffer::as_string() {
+	current_buffer_ptr()[string_length] = '\0';
+	if (buffer.empty()) {
+		return String(short_buffer);
+	} else {
+		buffer.resize(string_length + 1);
+		return buffer;
+	}
+}
+
+double StringBuffer::as_double() {
+	current_buffer_ptr()[string_length] = '\0';
+	return String::to_double(current_buffer_ptr());
+}
+
+int64_t StringBuffer::as_int() {
+	current_buffer_ptr()[string_length] = '\0';
+	return String::to_int(current_buffer_ptr());
+}

+ 82 - 0
core/string_buffer.h

@@ -0,0 +1,82 @@
+/*************************************************************************/
+/*  string_buffer.h                                                      */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+#ifndef STRING_BUFFER_H
+#define STRING_BUFFER_H
+
+#include "ustring.h"
+
+class StringBuffer {
+	static const int SHORT_BUFFER_SIZE = 64;
+
+	CharType short_buffer[SHORT_BUFFER_SIZE];
+	String buffer;
+	int string_length = 0;
+
+	_FORCE_INLINE_ CharType *current_buffer_ptr() {
+		return static_cast<Vector<CharType> &>(buffer).empty() ? short_buffer : buffer.ptr();
+	}
+
+public:
+	StringBuffer &append(CharType p_char);
+	StringBuffer &append(const String &p_string);
+	StringBuffer &append(const char *p_str);
+	StringBuffer &append(const CharType *p_str, int p_clip_to_len = -1);
+
+	_FORCE_INLINE_ void operator+=(CharType p_char) {
+		append(p_char);
+	}
+
+	_FORCE_INLINE_ void operator+=(const String &p_string) {
+		append(p_string);
+	}
+
+	_FORCE_INLINE_ void operator+=(const char *p_str) {
+		append(p_str);
+	}
+
+	_FORCE_INLINE_ void operator+=(const CharType *p_str) {
+		append(p_str);
+	}
+
+	StringBuffer &reserve(int p_size);
+
+	int length() const;
+
+	String as_string();
+
+	double as_double();
+	int64_t as_int();
+
+	_FORCE_INLINE_ operator String() {
+		return as_string();
+	}
+};
+
+#endif

+ 94 - 0
core/string_builder.cpp

@@ -0,0 +1,94 @@
+/*************************************************************************/
+/*  string_builder.cpp                                                   */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+#include "string_builder.h"
+
+#include <string.h>
+
+StringBuilder &StringBuilder::append(const String &p_string) {
+
+	strings.push_back(p_string);
+	appended_strings.push_back(-1);
+
+	string_length += p_string.length();
+
+	return *this;
+}
+
+StringBuilder &StringBuilder::append(const char *p_cstring) {
+
+	int32_t len = strlen(p_cstring);
+
+	c_strings.push_back(p_cstring);
+	appended_strings.push_back(len);
+
+	string_length += len;
+
+	return *this;
+}
+
+String StringBuilder::as_string() const {
+
+	CharType *buffer = memnew_arr(CharType, string_length);
+
+	int current_position = 0;
+
+	int godot_string_elem = 0;
+	int c_string_elem = 0;
+
+	for (int i = 0; i < appended_strings.size(); i++) {
+		if (appended_strings[i] == -1) {
+			// Godot string
+			const String &s = strings[godot_string_elem];
+
+			memcpy(buffer + current_position, s.ptr(), s.length() * sizeof(CharType));
+
+			current_position += s.length();
+
+			godot_string_elem++;
+		} else {
+
+			const char *s = c_strings[c_string_elem];
+
+			for (int32_t j = 0; j < appended_strings[i]; j++) {
+				buffer[current_position + j] = s[j];
+			}
+
+			current_position += appended_strings[i];
+
+			c_string_elem++;
+		}
+	}
+
+	String final_string = String(buffer, string_length);
+
+	memdelete_arr(buffer);
+
+	return final_string;
+}

+ 36 - 25
scene/gui/button_group.h → core/string_builder.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  button_group.h                                                       */
+/*  string_builder.h                                                     */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -27,42 +27,53 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#ifndef BUTTON_GROUP_H
-#define BUTTON_GROUP_H
+#ifndef STRING_BUILDER_H
+#define STRING_BUILDER_H
 
-#include "scene/gui/box_container.h"
+#include "core/ustring.h"
 
-#if 0
-class BaseButton;
+#include "core/vector.h"
 
-class ButtonGroup : public BoxContainer {
+class StringBuilder {
 
-	GDCLASS(ButtonGroup,BoxContainer);
+	uint32_t string_length = 0;
 
+	Vector<String> strings;
+	Vector<const char *> c_strings;
 
-	Set<BaseButton*> buttons;
+	// -1 means it's a Godot String
+	// a natural number means C string.
+	Vector<int32_t> appended_strings;
 
+public:
+	StringBuilder &append(const String &p_string);
+	StringBuilder &append(const char *p_cstring);
 
-	Array _get_button_list() const;
-	void _pressed(Object *p_button);
+	_FORCE_INLINE_ StringBuilder &operator+(const String &p_string) {
+		return append(p_string);
+	}
 
-protected:
-friend class BaseButton;
+	_FORCE_INLINE_ StringBuilder &operator+(const char *p_cstring) {
+		return append(p_cstring);
+	}
 
-	void _add_button(BaseButton *p_button);
-	void _remove_button(BaseButton *p_button);
+	_FORCE_INLINE_ void operator+=(const String &p_string) {
+		append(p_string);
+	}
 
-	static void _bind_methods();
-public:
+	_FORCE_INLINE_ void operator+=(const char *p_cstring) {
+		append(p_cstring);
+	}
+
+	_FORCE_INLINE_ int num_strings_appended() const {
+		return appended_strings.size();
+	}
 
-	void get_button_list(List<BaseButton*> *p_buttons) const;
-	BaseButton *get_pressed_button() const;
-	BaseButton *get_focused_button() const;
-	void set_pressed_button(BaseButton *p_button);
-	int get_pressed_button_index() const;
+	String as_string() const;
 
-	ButtonGroup();
+	_FORCE_INLINE_ operator String() const {
+		return as_string();
+	}
 };
 
-#endif
-#endif // BUTTON_GROUP_H
+#endif // STRING_BUILDER_H

+ 2 - 0
core/variant_call.cpp

@@ -481,6 +481,7 @@ struct _VariantCall {
 	VCALL_LOCALMEM1(Array, erase);
 	VCALL_LOCALMEM0(Array, sort);
 	VCALL_LOCALMEM2(Array, sort_custom);
+	VCALL_LOCALMEM0R(Array, duplicate);
 	VCALL_LOCALMEM0(Array, invert);
 
 	static void _call_PoolByteArray_get_string_from_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) {
@@ -1575,6 +1576,7 @@ void register_variant_methods() {
 	ADDFUNC0(ARRAY, NIL, Array, sort, varray());
 	ADDFUNC2(ARRAY, NIL, Array, sort_custom, OBJECT, "obj", STRING, "func", varray());
 	ADDFUNC0(ARRAY, NIL, Array, invert, varray());
+	ADDFUNC0(ARRAY, ARRAY, Array, duplicate, varray());
 
 	ADDFUNC0(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray());
 	ADDFUNC2(POOL_BYTE_ARRAY, NIL, PoolByteArray, set, INT, "idx", INT, "byte", varray());

+ 12 - 10
core/variant_parser.cpp

@@ -29,6 +29,7 @@
 /*************************************************************************/
 #include "variant_parser.h"
 
+#include "core/string_buffer.h"
 #include "io/resource_loader.h"
 #include "os/input_event.h"
 #include "os/keyboard.h"
@@ -176,14 +177,15 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
 			};
 			case '#': {
 
-				String color_str = "#";
+				StringBuffer color_str;
+				color_str += '#';
 				while (true) {
 					CharType ch = p_stream->get_char();
 					if (p_stream->is_eof()) {
 						r_token.type = TK_EOF;
 						return OK;
 					} else if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
-						color_str += String::chr(ch);
+						color_str += ch;
 
 					} else {
 						p_stream->saved = ch;
@@ -191,7 +193,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
 					}
 				}
 
-				r_token.value = Color::html(color_str);
+				r_token.value = Color::html(color_str.as_string());
 				r_token.type = TK_COLOR;
 				return OK;
 			};
@@ -296,7 +298,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
 				if (cchar == '-' || (cchar >= '0' && cchar <= '9')) {
 					//a number
 
-					String num;
+					StringBuffer num;
 #define READING_SIGN 0
 #define READING_INT 1
 #define READING_DEC 2
@@ -359,7 +361,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
 
 						if (reading == READING_DONE)
 							break;
-						num += String::chr(c);
+						num += c;
 						c = p_stream->get_char();
 					}
 
@@ -368,19 +370,19 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
 					r_token.type = TK_NUMBER;
 
 					if (is_float)
-						r_token.value = num.to_double();
+						r_token.value = num.as_double();
 					else
-						r_token.value = num.to_int();
+						r_token.value = num.as_int();
 					return OK;
 
 				} else if ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_') {
 
-					String id;
+					StringBuffer id;
 					bool first = true;
 
 					while ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_' || (!first && cchar >= '0' && cchar <= '9')) {
 
-						id += String::chr(cchar);
+						id += cchar;
 						cchar = p_stream->get_char();
 						first = false;
 					}
@@ -388,7 +390,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
 					p_stream->saved = cchar;
 
 					r_token.type = TK_IDENTIFIER;
-					r_token.value = id;
+					r_token.value = id.as_string();
 					return OK;
 				} else {
 					r_err_str = "Unexpected character.";

文件差异内容过多而无法显示
+ 149 - 71
doc/base/classes.xml


+ 4 - 0
drivers/gles3/rasterizer_canvas_gles3.cpp

@@ -1115,6 +1115,10 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
 					_copy_texscreen(Rect2());
 				}
 
+				if (shader_ptr->canvas_item.uses_time) {
+					VisualServerRaster::redraw_request();
+				}
+
 				state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id);
 				state.canvas_shader.bind();
 

+ 46 - 37
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -32,6 +32,7 @@
 #include "os/os.h"
 #include "project_settings.h"
 #include "rasterizer_canvas_gles3.h"
+#include "servers/visual/visual_server_raster.h"
 
 #ifndef GLES_OVER_GL
 #define glClearDepth glClearDepthf
@@ -1939,6 +1940,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
 	bool prev_use_instancing = false;
 
 	storage->info.render.draw_call_count += p_element_count;
+	bool prev_opaque_prepass = false;
 
 	for (int i = 0; i < p_element_count; i++) {
 
@@ -2072,6 +2074,13 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
 			}
 		}
 
+		bool use_opaque_prepass = e->sort_key & RenderList::SORT_KEY_OPAQUE_PRE_PASS;
+
+		if (use_opaque_prepass != prev_opaque_prepass) {
+			state.scene_shader.set_conditional(SceneShaderGLES3::USE_OPAQUE_PREPASS, use_opaque_prepass);
+			rebind = true;
+		}
+
 		bool use_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH || e->instance->base_type == VS::INSTANCE_PARTICLES;
 
 		if (use_instancing != prev_use_instancing) {
@@ -2127,6 +2136,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
 		prev_shading = shading;
 		prev_skeleton = skeleton;
 		prev_use_instancing = use_instancing;
+		prev_opaque_prepass = use_opaque_prepass;
 		first = false;
 	}
 
@@ -2148,9 +2158,10 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
 	state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, false);
 	state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, false);
 	state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, false);
+	state.scene_shader.set_conditional(SceneShaderGLES3::USE_OPAQUE_PREPASS, false);
 }
 
-void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_shadow) {
+void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass) {
 
 	RasterizerStorageGLES3::Material *m = NULL;
 	RID m_src = p_instance->material_override.is_valid() ? p_instance->material_override : (p_material >= 0 ? p_instance->materials[p_material] : p_geometry->material);
@@ -2182,22 +2193,21 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo
 
 	ERR_FAIL_COND(!m);
 
-	_add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_shadow);
+	_add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass);
 
 	while (m->next_pass.is_valid()) {
 		m = storage->material_owner.getornull(m->next_pass);
 		if (!m || !m->shader || !m->shader->valid)
 			break;
-		_add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_shadow);
+		_add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass);
 	}
 }
 
-void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_shadow) {
+void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass) {
 
 	bool has_base_alpha = (p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.uses_screen_texture;
 	bool has_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX;
 	bool has_alpha = has_base_alpha || has_blend_alpha;
-	bool shadow = false;
 
 	bool mirror = p_instance->mirror;
 	bool no_cull = false;
@@ -2217,7 +2227,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
 		state.used_screen_texture = true;
 	}
 
-	if (p_shadow) {
+	if (p_depth_pass) {
 
 		if (has_blend_alpha || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS))
 			return; //bye
@@ -2252,14 +2262,14 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
 		e->geometry->index = current_geometry_index++;
 	}
 
-	if (!p_shadow && directional_light && (directional_light->light_ptr->cull_mask & e->instance->layer_mask) == 0) {
+	if (!p_depth_pass && directional_light && (directional_light->light_ptr->cull_mask & e->instance->layer_mask) == 0) {
 		e->sort_key |= SORT_KEY_NO_DIRECTIONAL_FLAG;
 	}
 
 	e->sort_key |= uint64_t(e->geometry->index) << RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT;
 	e->sort_key |= uint64_t(e->instance->base_type) << RenderList::SORT_KEY_GEOMETRY_TYPE_SHIFT;
 
-	if (!p_shadow) {
+	if (!p_depth_pass) {
 
 		if (e->material->last_pass != render_pass) {
 			e->material->last_pass = render_pass;
@@ -2269,17 +2279,6 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
 		e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
 		e->sort_key |= uint64_t(e->instance->depth_layer) << RenderList::SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT;
 
-		if (!has_blend_alpha && has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
-
-			//if nothing exists, add this element as opaque too
-			RenderList::Element *oe = render_list.add_element();
-
-			if (!oe)
-				return;
-
-			copymem(oe, e, sizeof(RenderList::Element));
-		}
-
 		if (e->instance->gi_probe_instances.size()) {
 			e->sort_key |= SORT_KEY_GI_PROBES_FLAG;
 		}
@@ -2302,24 +2301,21 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
 
 	//e->light_type=0xFF; // no lights!
 
-	if (shadow || p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
-
+	if (p_depth_pass || p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
 		e->sort_key |= SORT_KEY_UNSHADED_FLAG;
 	}
 
-	if (!shadow && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) {
+	if (p_depth_pass && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
+		e->sort_key |= RenderList::SORT_KEY_OPAQUE_PRE_PASS;
+	}
+
+	if (!p_depth_pass && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) {
 
 		e->sort_key |= SORT_KEY_VERTEX_LIT_FLAG;
 	}
 
-	if (!shadow && has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
-		//depth prepass for alpha
-		RenderList::Element *eo = render_list.add_element();
-
-		eo->instance = e->instance;
-		eo->geometry = e->geometry;
-		eo->material = e->material;
-		eo->sort_key = e->sort_key;
+	if (p_material->shader->spatial.uses_time) {
+		VisualServerRaster::redraw_request();
 	}
 }
 
@@ -2603,7 +2599,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform
 				}
 			}
 
-			ubo_data.shadow_split_offsets[j] = 1.0 / li->shadow_transform[j].split;
+			ubo_data.shadow_split_offsets[j] = li->shadow_transform[j].split;
 
 			Transform modelview = (p_camera_inverse_transform * li->shadow_transform[j].transform).inverse();
 
@@ -3032,7 +3028,7 @@ void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) {
 	storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false);
 }
 
-void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_shadow) {
+void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass) {
 
 	current_geometry_index = 0;
 	current_material_index = 0;
@@ -3057,7 +3053,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
 
 					int mat_idx = inst->materials[i].is_valid() ? i : -1;
 					RasterizerStorageGLES3::Surface *s = mesh->surfaces[i];
-					_add_geometry(s, inst, NULL, mat_idx, p_shadow);
+					_add_geometry(s, inst, NULL, mat_idx, p_depth_pass);
 				}
 
 				//mesh->last_pass=frame;
@@ -3080,7 +3076,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
 				for (int i = 0; i < ssize; i++) {
 
 					RasterizerStorageGLES3::Surface *s = mesh->surfaces[i];
-					_add_geometry(s, inst, multi_mesh, -1, p_shadow);
+					_add_geometry(s, inst, multi_mesh, -1, p_depth_pass);
 				}
 
 			} break;
@@ -3089,7 +3085,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
 				RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getptr(inst->base);
 				ERR_CONTINUE(!immediate);
 
-				_add_geometry(immediate, inst, NULL, -1, p_shadow);
+				_add_geometry(immediate, inst, NULL, -1, p_depth_pass);
 
 			} break;
 			case VS::INSTANCE_PARTICLES: {
@@ -3111,7 +3107,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
 					for (int j = 0; j < ssize; j++) {
 
 						RasterizerStorageGLES3::Surface *s = mesh->surfaces[j];
-						_add_geometry(s, inst, particles, -1, p_shadow);
+						_add_geometry(s, inst, particles, -1, p_depth_pass);
 					}
 				}
 
@@ -3178,6 +3174,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 		for (int i = 0; i < storage->frame.current_rt->effects.ssao.depth_mipmap_fbos.size(); i++) {
 
 			state.ssao_minify_shader.set_conditional(SsaoMinifyShaderGLES3::MINIFY_START, i == 0);
+			state.ssao_minify_shader.set_conditional(SsaoMinifyShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
 			state.ssao_minify_shader.bind();
 			state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
 			state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
@@ -3207,6 +3204,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 		glDepthFunc(GL_GREATER);
 		// do SSAO!
 		state.ssao_shader.set_conditional(SsaoShaderGLES3::ENABLE_RADIUS2, env->ssao_radius2 > 0.001);
+		state.ssao_shader.set_conditional(SsaoShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
 		state.ssao_shader.bind();
 		state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
 		state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
@@ -3316,6 +3314,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->effects.ssao.blur_fbo[0]);
 		glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
 
+		state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
 		state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_11_SAMPLES, subsurface_scatter_quality == SSS_QUALITY_LOW);
 		state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_17_SAMPLES, subsurface_scatter_quality == SSS_QUALITY_MEDIUM);
 		state.sss_shader.set_conditional(SubsurfScatteringShaderGLES3::USE_25_SAMPLES, subsurface_scatter_quality == SSS_QUALITY_HIGH);
@@ -3370,6 +3369,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
 		//perform SSR
 
 		state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::REFLECT_ROUGHNESS, env->ssr_roughness);
+		state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
 
 		state.ssr_shader.bind();
 
@@ -3523,6 +3523,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		int vp_h = storage->frame.current_rt->height;
 		int vp_w = storage->frame.current_rt->width;
 
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, true);
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_LOW);
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM);
@@ -3565,6 +3566,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, false);
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, false);
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, false);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, false);
 
 		composite_from = storage->frame.current_rt->effects.mip_maps[0].color;
 	}
@@ -3577,6 +3579,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		int vp_h = storage->frame.current_rt->height;
 		int vp_w = storage->frame.current_rt->width;
 
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR, true);
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP, true);
 
@@ -3652,6 +3655,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, false);
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, false);
 		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, false);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, false);
 
 		composite_from = storage->frame.current_rt->effects.mip_maps[0].color;
 	}
@@ -3743,6 +3747,8 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
 		SWAP(exposure_shrink[exposure_shrink.size() - 1].color, storage->frame.current_rt->exposure.color);
 
 		glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
+
+		VisualServerRaster::redraw_request(); //if using auto exposure, redraw must happen
 	}
 
 	int max_glow_level = -1;
@@ -4159,7 +4165,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 
 		clear_color = env->bg_color.to_linear();
 		storage->frame.clear_request = false;
-	} else if (env->bg_mode == VS::ENV_BG_SKY) {
+	} else if (env->bg_mode == VS::ENV_BG_SKY || env->bg_mode == VS::ENV_BG_COLOR_SKY) {
 
 		sky = storage->sky_owner.getornull(env->sky);
 
@@ -4167,6 +4173,9 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
 			env_radiance_tex = sky->radiance;
 		}
 		storage->frame.clear_request = false;
+		if (env->bg_mode == VS::ENV_BG_COLOR_SKY) {
+			clear_color = env->bg_color.to_linear();
+		}
 
 	} else {
 		storage->frame.clear_request = false;

+ 4 - 3
drivers/gles3/rasterizer_scene_gles3.h

@@ -664,6 +664,7 @@ public:
 			//bits 12-8 geometry type
 			SORT_KEY_GEOMETRY_TYPE_SHIFT = 8,
 			//bits 0-7 for flags
+			SORT_KEY_OPAQUE_PRE_PASS = 8,
 			SORT_KEY_CULL_DISABLED_FLAG = 4,
 			SORT_KEY_SKELETON_FLAG = 2,
 			SORT_KEY_MIRROR_FLAG = 1
@@ -805,9 +806,9 @@ public:
 
 	void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows);
 
-	_FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_shadow);
+	_FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_passs);
 
-	_FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_shadow);
+	_FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass);
 
 	void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale, float p_energy);
 
@@ -820,7 +821,7 @@ public:
 	void _copy_to_front_buffer(Environment *env);
 	void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug
 
-	void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_shadow);
+	void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass);
 
 	void _blur_effect_buffer();
 	void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection);

+ 19 - 0
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -1584,6 +1584,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
 			shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv;
 			shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv;
 			shaders.actions_canvas.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->canvas_item.uses_screen_texture;
+			shaders.actions_canvas.usage_flag_pointers["TIME"] = &p_shader->canvas_item.uses_time;
 
 			actions = &shaders.actions_canvas;
 			actions->uniforms = &p_shader->uniforms;
@@ -1632,6 +1633,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
 			shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"] = &p_shader->spatial.uses_sss;
 			shaders.actions_scene.usage_flag_pointers["DISCARD"] = &p_shader->spatial.uses_discard;
 			shaders.actions_scene.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->spatial.uses_screen_texture;
+			shaders.actions_scene.usage_flag_pointers["TIME"] = &p_shader->spatial.uses_time;
 
 			shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
 			shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
@@ -4471,6 +4473,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type) {
 	light->omni_shadow_mode = VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
 	light->omni_shadow_detail = VS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL;
 	light->directional_blend_splits = false;
+	light->directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE;
 	light->reverse_cull = false;
 	light->version = 0;
 
@@ -4623,6 +4626,22 @@ VS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_sha
 	return light->directional_shadow_mode;
 }
 
+void RasterizerStorageGLES3::light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) {
+
+	Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND(!light);
+
+	light->directional_range_mode=p_range_mode;
+}
+
+VS::LightDirectionalShadowDepthRangeMode RasterizerStorageGLES3::light_directional_get_shadow_depth_range_mode(RID p_light) const {
+
+	const Light *light = light_owner.getornull(p_light);
+	ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE);
+
+	return light->directional_range_mode;
+}
+
 VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const {
 
 	const Light *light = light_owner.getornull(p_light);

+ 6 - 0
drivers/gles3/rasterizer_storage_gles3.h

@@ -410,6 +410,7 @@ public:
 			int light_mode;
 			bool uses_screen_texture;
 			bool uses_screen_uv;
+			bool uses_time;
 
 		} canvas_item;
 
@@ -449,6 +450,7 @@ public:
 			bool uses_discard;
 			bool uses_sss;
 			bool uses_screen_texture;
+			bool uses_time;
 			bool writes_modelview_or_projection;
 			bool uses_vertex_lighting;
 
@@ -877,6 +879,7 @@ public:
 		VS::LightOmniShadowMode omni_shadow_mode;
 		VS::LightOmniShadowDetail omni_shadow_detail;
 		VS::LightDirectionalShadowMode directional_shadow_mode;
+		VS::LightDirectionalShadowDepthRangeMode directional_range_mode;
 		bool directional_blend_splits;
 		uint64_t version;
 	};
@@ -904,6 +907,9 @@ public:
 	virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
 	virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
 
+	virtual void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode);
+	virtual VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const;
+
 	virtual bool light_has_shadow(RID p_light) const;
 
 	virtual VS::LightType light_get_type(RID p_light) const;

+ 43 - 10
drivers/gles3/shader_compiler_gles3.cpp

@@ -438,26 +438,44 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
 			SL::BlockNode *bnode = (SL::BlockNode *)p_node;
 
 			//variables
-			code += _mktab(p_level - 1) + "{\n";
-			for (Map<StringName, SL::BlockNode::Variable>::Element *E = bnode->variables.front(); E; E = E->next()) {
-
-				code += _mktab(p_level) + _prestr(E->get().precision) + _typestr(E->get().type) + " " + _mkid(E->key()) + ";\n";
+			if (!bnode->single_statement) {
+				code += _mktab(p_level - 1) + "{\n";
 			}
-
+	
 			for (int i = 0; i < bnode->statements.size(); i++) {
 
 				String scode = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions);
 
-				if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW) {
-					// FIXME: if (A || A) ? I am hesitant to delete one of them, could be copy-paste error.
+				if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement ) {
 					code += scode; //use directly
 				} else {
 					code += _mktab(p_level) + scode + ";\n";
 				}
 			}
-			code += _mktab(p_level - 1) + "}\n";
+			if (!bnode->single_statement) {
+				code += _mktab(p_level - 1) + "}\n";
+			}
 
 		} break;
+		case SL::Node::TYPE_VARIABLE_DECLARATION: {
+			SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node;
+
+			String declaration = _prestr(vdnode->precision) + _typestr(vdnode->datatype);
+			for(int i=0;i<vdnode->declarations.size();i++) {
+				if (i>0) {
+					declaration+=",";
+				} else {
+					declaration+=" ";
+				}
+				declaration +=  _mkid(vdnode->declarations[i].name);
+				if (vdnode->declarations[i].initializer) {
+					declaration+="=";
+					declaration+=_dump_node_code(vdnode->declarations[i].initializer, p_level, r_gen_code, p_actions, p_default_actions);
+				}
+			}
+
+			code+=declaration;
+		} break;
 		case SL::Node::TYPE_VARIABLE: {
 			SL::VariableNode *vnode = (SL::VariableNode *)p_node;
 
@@ -600,6 +618,13 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
 
 				code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions) + ")\n";
 				code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions);
+			} else if (cfnode->flow_op == SL::FLOW_OP_FOR) {
+
+				String left = _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions);
+				String middle = _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions);
+				String right = _dump_node_code(cfnode->expressions[1], p_level, r_gen_code, p_actions, p_default_actions);
+				code += _mktab(p_level) + "for (" +left+";"+middle+";"+right+")\n";
+				code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions);
 
 			} else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
 
@@ -611,6 +636,12 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
 			} else if (cfnode->flow_op == SL::FLOW_OP_DISCARD) {
 
 				code = "discard;";
+			} else if (cfnode->flow_op == SL::FLOW_OP_CONTINUE) {
+
+				code = "continue;";
+			} else if (cfnode->flow_op == SL::FLOW_OP_BREAK) {
+
+				code = "break;";
 			}
 
 		} break;
@@ -751,8 +782,9 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
 	actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss";
 	actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy";
 	actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
-	actions[VS::SHADER_SPATIAL].renames["SSS_SPREAD"] = "sss_spread";
+	//actions[VS::SHADER_SPATIAL].renames["SSS_SPREAD"] = "sss_spread";
 	actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
+	actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission";
 	actions[VS::SHADER_SPATIAL].renames["AO"] = "ao";
 	actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission";
 	//actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
@@ -782,6 +814,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
 	actions[VS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n";
 
 	actions[VS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
+	actions[VS::SHADER_SPATIAL].usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n";
 	actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
 	actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
 
@@ -792,7 +825,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
 
 	actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
 	actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
-	actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_half_lambert"] = "#define DIFFUSE_HALF_LAMBERT\n";
+	actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
 	actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
 
 	actions[VS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n";

+ 2 - 2
drivers/gles3/shaders/canvas.glsl

@@ -116,7 +116,7 @@ void main() {
 
 #ifdef USE_TEXTURE_RECT
 
-	if (dst_rect.z < 0) { // Transpose is encoded as negative dst_rect.z
+	if (dst_rect.z < 0.0) { // Transpose is encoded as negative dst_rect.z
 		uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.yx;
 	} else {
 		uv_interp = src_rect.xy + abs(src_rect.zw) * vertex;
@@ -139,7 +139,7 @@ void main() {
 	float frame_w = 1.0/float(h_frames);
 	float frame_h = 1.0/float(v_frames);
 	uv_interp.x = uv_interp.x * frame_w + frame_w * float(frame % h_frames);
-	uv_interp.y = uv_interp.y * frame_h + frame_h * float(frame / v_frames);
+	uv_interp.y = uv_interp.y * frame_h + frame_h * float(frame / h_frames);
 
 #endif
 

+ 12 - 1
drivers/gles3/shaders/effect_blur.glsl

@@ -168,7 +168,11 @@ void main() {
 
 	float depth = textureLod( dof_source_depth, uv_interp, 0.0).r;
 	depth = depth * 2.0 - 1.0;
+#ifdef USE_ORTHOGONAL_PROJECTION
+	depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
+#else
 	depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
+#endif
 
 	float amount = smoothstep(dof_begin,dof_end,depth);
 	float k_accum=0.0;
@@ -182,8 +186,11 @@ void main() {
 
 		float tap_depth = texture( dof_source_depth, tap_uv, 0.0).r;
 		tap_depth = tap_depth * 2.0 - 1.0;
+#ifdef USE_ORTHOGONAL_PROJECTION
+		tap_depth = ((tap_depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
+#else
 		tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
-
+#endif
 		float tap_amount = mix(smoothstep(dof_begin,dof_end,tap_depth),1.0,int_ofs==0);
 		tap_amount*=tap_amount*tap_amount; //prevent undesired glow effect
 
@@ -221,7 +228,11 @@ void main() {
 
 		float tap_depth = texture( dof_source_depth, tap_uv, 0.0).r;
 		tap_depth = tap_depth * 2.0 - 1.0;
+#ifdef USE_ORTHOGONAL_PROJECTION	
+		tap_depth = ((tap_depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
+#else
 		tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
+#endif
 		float tap_amount = 1.0-smoothstep(dof_end,dof_begin,tap_depth);
 		tap_amount*=tap_amount*tap_amount; //prevent undesired glow effect
 

+ 55 - 29
drivers/gles3/shaders/scene.glsl

@@ -484,7 +484,7 @@ VERTEX_SHADER_CODE
 
 	vec3 directional_diffuse = vec3(0.0);
 	vec3 directional_specular = vec3(0.0);
-	light_compute(normal_interp,-light_direction_attenuation.xyz,-normalize( vertex_interp ),normal_interp,roughness,directional_diffuse,directional_specular);
+	light_compute(normal_interp,-light_direction_attenuation.xyz,-normalize( vertex_interp ),light_color_energy.rgb,roughness,directional_diffuse,directional_specular);
 
 	float diff_avg = dot(diffuse_light_interp.rgb,vec3(0.33333));
 	float diff_dir_avg = dot(directional_diffuse,vec3(0.33333));
@@ -887,7 +887,7 @@ float GTR1(float NdotH, float a)
 
 
 
-void light_compute(vec3 N, vec3 L,vec3 V,vec3 B, vec3 T,vec3 light_color,vec3 diffuse_color,  float specular_blob_intensity, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse, inout vec3 specular) {
+void light_compute(vec3 N, vec3 L,vec3 V,vec3 B, vec3 T,vec3 light_color,vec3 diffuse_color, vec3 transmission,  float specular_blob_intensity, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse, inout vec3 specular) {
 
 #if defined(USE_LIGHT_SHADER_CODE)
 //light is written by the light shader
@@ -900,10 +900,16 @@ LIGHT_SHADER_CODE
 
 	float dotNL = max(dot(N,L), 0.0 );
 
-#if defined(DIFFUSE_HALF_LAMBERT)
+#if defined(DIFFUSE_OREN_NAYAR)
+	vec3 light_amount;
+#else
+	float light_amount;
+#endif
 
-	float hl = dot(N,L) * 0.5 + 0.5;
-	diffuse += hl * light_color * diffuse_color;
+
+#if defined(DIFFUSE_LAMBERT_WRAP)
+	//energy conserving lambert wrap shader
+	light_amount = max(0.0,(dot(N,L) + roughness) / ((1.0 + roughness) * (1.0 + roughness)));
 
 #elif defined(DIFFUSE_OREN_NAYAR)
 
@@ -919,12 +925,12 @@ LIGHT_SHADER_CODE
 		vec3 A = 1.0 + sigma2 * (diffuse_color / (sigma2 + 0.13) + 0.5 / (sigma2 + 0.33));
 		float B = 0.45 * sigma2 / (sigma2 + 0.09);
 
-		diffuse += diffuse_color * max(0.0, NdotL) * (A + vec3(B) * s / t) / M_PI;
+		light_amount = max(0.0, NdotL) * (A + vec3(B) * s / t) / M_PI;
 	}
 
 #elif defined(DIFFUSE_TOON)
 
-	diffuse += smoothstep(-roughness,max(roughness,0.01),dot(N,L)) * light_color * diffuse_color;
+	light_amount = smoothstep(-roughness,max(roughness,0.01),dot(N,L));
 
 #elif defined(DIFFUSE_BURLEY)
 
@@ -939,11 +945,17 @@ LIGHT_SHADER_CODE
 		float lightScatter = f0 + (fd90 - f0) * pow(1.0 - NdotL, 5.0);
 		float viewScatter = f0 + (fd90 - f0) * pow(1.0 - NdotV, 5.0);
 
-		diffuse+= light_color * diffuse_color * lightScatter * viewScatter * energyFactor;
+		light_amount = lightScatter * viewScatter * energyFactor;
 	}
 #else
 	//lambert
-	diffuse += dotNL * light_color * diffuse_color;
+	light_amount = dotNL;
+#endif
+
+#if defined(TRANSMISSION_USED)
+	diffuse += light_color * diffuse_color * mix(vec3(light_amount),vec3(1.0),transmission);
+#else
+	diffuse += light_color * diffuse_color * light_amount;
 #endif
 
 
@@ -1116,7 +1128,7 @@ vec3 light_transmittance(float translucency,vec3 light_vec, vec3 normal, vec3 po
 }
 #endif
 
-void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,float p_blob_intensity,inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, vec3 transmission, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,float p_blob_intensity,inout vec3 diffuse_light, inout vec3 specular_light) {
 
 	vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex;
 	float light_length = length( light_rel_vec );
@@ -1170,11 +1182,11 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 bino
 		light_attenuation*=mix(omni_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow);
 	}
 
-	light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb*light_attenuation,albedo,omni_lights[idx].light_params.z*p_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
+	light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb*light_attenuation,albedo,transmission,omni_lights[idx].light_params.z*p_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
 
 }
 
-void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent,vec3 albedo, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent,vec3 albedo, vec3 transmission,float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,float p_blob_intensity, inout vec3 diffuse_light, inout vec3 specular_light) {
 
 	vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz-vertex;
 	float light_length = length( light_rel_vec );
@@ -1204,7 +1216,7 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi
 		light_attenuation*=mix(spot_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow);
 	}
 
-	light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,spot_lights[idx].light_params.z*p_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
+	light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,transmission,spot_lights[idx].light_params.z*p_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
 
 }
 
@@ -1499,6 +1511,7 @@ void main() {
 	//lay out everything, whathever is unused is optimized away anyway
 	highp vec3 vertex = vertex_interp;
 	vec3 albedo = vec3(0.8,0.8,0.8);
+	vec3 transmission = vec3(0.0);
 	float metallic = 0.0;
 	float specular = 0.5;
 	vec3 emission = vec3(0.0,0.0,0.0);
@@ -1577,6 +1590,12 @@ FRAGMENT_SHADER_CODE
 	}
 #endif
 
+#ifdef USE_OPAQUE_PREPASS
+
+	if (alpha<0.99) {
+		discard;
+	}
+#endif
 
 #if defined(ENABLE_NORMALMAP)
 
@@ -1678,9 +1697,16 @@ FRAGMENT_SHADER_CODE
 
 	vec3 light_attenuation=vec3(1.0);
 
+	float depth_z = -vertex.z;
 #ifdef LIGHT_DIRECTIONAL_SHADOW
 
-	if (gl_FragCoord.w > shadow_split_offsets.w) {
+#ifdef LIGHT_USE_PSSM4
+	if (depth_z < shadow_split_offsets.w) {
+#elif defined(LIGHT_USE_PSSM2)
+	if (depth_z < shadow_split_offsets.y) {
+#else
+	if (depth_z < shadow_split_offsets.x) {
+#endif //LIGHT_USE_PSSM4
 
 	vec3 pssm_coord;
 	float pssm_fade=0.0;
@@ -1689,17 +1715,15 @@ FRAGMENT_SHADER_CODE
 	float pssm_blend;
 	vec3 pssm_coord2;
 	bool use_blend=true;
-	vec3 light_pssm_split_inv = 1.0/shadow_split_offsets.xyz;
-	float w_inv = 1.0/gl_FragCoord.w;
 #endif
 
 
 #ifdef LIGHT_USE_PSSM4
 
 
-	if (gl_FragCoord.w > shadow_split_offsets.y) {
+	if (depth_z < shadow_split_offsets.y) {
 
-		if (gl_FragCoord.w > shadow_split_offsets.x) {
+		if (depth_z < shadow_split_offsets.x) {
 
 			highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
 			pssm_coord=splane.xyz/splane.w;
@@ -1709,7 +1733,7 @@ FRAGMENT_SHADER_CODE
 
 			splane=(shadow_matrix2 * vec4(vertex,1.0));
 			pssm_coord2=splane.xyz/splane.w;
-			pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv);
+			pssm_blend=smoothstep(0.0,shadow_split_offsets.x,depth_z);
 #endif
 
 		} else {
@@ -1720,14 +1744,14 @@ FRAGMENT_SHADER_CODE
 #if defined(LIGHT_USE_PSSM_BLEND)
 			splane=(shadow_matrix3 * vec4(vertex,1.0));
 			pssm_coord2=splane.xyz/splane.w;
-			pssm_blend=smoothstep(light_pssm_split_inv.x,light_pssm_split_inv.y,w_inv);
+			pssm_blend=smoothstep(shadow_split_offsets.x,shadow_split_offsets.y,depth_z);
 #endif
 
 		}
 	} else {
 
 
-		if (gl_FragCoord.w > shadow_split_offsets.z) {
+		if (depth_z < shadow_split_offsets.z) {
 
 			highp vec4 splane=(shadow_matrix3 * vec4(vertex,1.0));
 			pssm_coord=splane.xyz/splane.w;
@@ -1735,13 +1759,14 @@ FRAGMENT_SHADER_CODE
 #if defined(LIGHT_USE_PSSM_BLEND)
 			splane=(shadow_matrix4 * vec4(vertex,1.0));
 			pssm_coord2=splane.xyz/splane.w;
-			pssm_blend=smoothstep(light_pssm_split_inv.y,light_pssm_split_inv.z,w_inv);
+			pssm_blend=smoothstep(shadow_split_offsets.y,shadow_split_offsets.z,depth_z);
 #endif
 
 		} else {
+
 			highp vec4 splane=(shadow_matrix4 * vec4(vertex,1.0));
 			pssm_coord=splane.xyz/splane.w;
-			pssm_fade = smoothstep(shadow_split_offsets.z,shadow_split_offsets.w,gl_FragCoord.w);
+			pssm_fade = smoothstep(shadow_split_offsets.z,shadow_split_offsets.w,depth_z);
 
 #if defined(LIGHT_USE_PSSM_BLEND)
 			use_blend=false;
@@ -1757,7 +1782,7 @@ FRAGMENT_SHADER_CODE
 
 #ifdef LIGHT_USE_PSSM2
 
-	if (gl_FragCoord.w > shadow_split_offsets.x) {
+	if (depth_z < shadow_split_offsets.x) {
 
 		highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
 		pssm_coord=splane.xyz/splane.w;
@@ -1767,13 +1792,13 @@ FRAGMENT_SHADER_CODE
 
 		splane=(shadow_matrix2 * vec4(vertex,1.0));
 		pssm_coord2=splane.xyz/splane.w;
-		pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv);
+		pssm_blend=smoothstep(0.0,shadow_split_offsets.x,depth_z);
 #endif
 
 	} else {
 		highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0));
 		pssm_coord=splane.xyz/splane.w;
-		pssm_fade = smoothstep(shadow_split_offsets.x,shadow_split_offsets.y,gl_FragCoord.w);
+		pssm_fade = smoothstep(shadow_split_offsets.x,shadow_split_offsets.y,depth_z);
 #if defined(LIGHT_USE_PSSM_BLEND)
 		use_blend=false;
 
@@ -1815,6 +1840,7 @@ FRAGMENT_SHADER_CODE
 
 	}
 
+
 #endif //LIGHT_DIRECTIONAL_SHADOW
 
 #ifdef USE_VERTEX_LIGHTING
@@ -1822,7 +1848,7 @@ FRAGMENT_SHADER_CODE
 	specular_light*=mix(vec3(1.0),light_attenuation,specular_light_interp.a);
 
 #else
-	light_compute(normal,-light_direction_attenuation.xyz,eye_vec,binormal,tangent,light_color_energy.rgb*light_attenuation,albedo,light_params.z*specular_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
+	light_compute(normal,-light_direction_attenuation.xyz,eye_vec,binormal,tangent,light_color_energy.rgb*light_attenuation,albedo,transmission,light_params.z*specular_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
 #endif
 
 
@@ -1860,11 +1886,11 @@ FRAGMENT_SHADER_CODE
 #else
 
 	for(int i=0;i<omni_light_count;i++) {
-		light_process_omni(omni_light_indices[i],vertex,eye_vec,normal,binormal,tangent,albedo,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,specular_blob_intensity,diffuse_light,specular_light);
+		light_process_omni(omni_light_indices[i],vertex,eye_vec,normal,binormal,tangent,albedo,transmission,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,specular_blob_intensity,diffuse_light,specular_light);
 	}
 
 	for(int i=0;i<spot_light_count;i++) {
-		light_process_spot(spot_light_indices[i],vertex,eye_vec,normal,binormal,tangent,albedo,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,specular_blob_intensity,diffuse_light,specular_light);
+		light_process_spot(spot_light_indices[i],vertex,eye_vec,normal,binormal,tangent,albedo,transmission,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,specular_blob_intensity,diffuse_light,specular_light);
 	}
 
 #endif //USE_VERTEX_LIGHTING

+ 5 - 1
drivers/gles3/shaders/screen_space_reflection.glsl

@@ -56,7 +56,6 @@ vec2 view_to_screen(vec3 view_pos,out float w) {
 
 #define M_PI 3.14159265359
 
-
 void main() {
 
 
@@ -158,8 +157,13 @@ void main() {
 		w+=w_advance;
 
 		//convert to linear depth
+
 		depth = texture(source_depth, pos*pixel_size).r * 2.0 - 1.0;
+#ifdef USE_ORTHOGONAL_PROJECTION
+		depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
+#else
 		depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
+#endif
 		depth=-depth;
 
 		z_from = z_to;

+ 19 - 2
drivers/gles3/shaders/ssao.glsl

@@ -65,7 +65,12 @@ layout(location = 0) out float visibility;
 uniform vec4 proj_info;
 
 vec3 reconstructCSPosition(vec2 S, float z) {
-    return vec3((S.xy * proj_info.xy + proj_info.zw) * z, z);
+#ifdef USE_ORTHOGONAL_PROJECTION
+	return vec3((S.xy * proj_info.xy + proj_info.zw), z);
+#else
+	return vec3((S.xy * proj_info.xy + proj_info.zw) * z, z);
+
+#endif
 }
 
 vec3 getPosition(ivec2 ssP) {
@@ -73,7 +78,11 @@ vec3 getPosition(ivec2 ssP) {
     P.z = texelFetch(source_depth, ssP, 0).r;
 
     P.z = P.z * 2.0 - 1.0;
+#ifdef USE_ORTHOGONAL_PROJECTION
+    P.z = ((P.z + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
+#else
     P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near));
+#endif
     P.z = -P.z;
 
     // Offset to pixel center
@@ -118,7 +127,12 @@ vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) {
 		//read from depth buffer
 		P.z = texelFetch(source_depth, mipP, 0).r;
 		P.z = P.z * 2.0 - 1.0;
+#ifdef USE_ORTHOGONAL_PROJECTION
+		P.z = ((P.z + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
+#else
 		P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near));
+
+#endif
 		P.z = -P.z;
 
 	} else {
@@ -214,8 +228,11 @@ void main() {
 
 	// Choose the screen-space sample radius
 	// proportional to the projected area of the sphere
+#ifdef USE_ORTHOGONAL_PROJECTION
+	float ssDiskRadius = -proj_scale * radius;
+#else
 	float ssDiskRadius = -proj_scale * radius / C.z;
-
+#endif
 	float sum = 0.0;
 	for (int i = 0; i < NUM_SAMPLES; ++i) {
 		sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius,i, randomPatternRotationAngle);

+ 4 - 0
drivers/gles3/shaders/ssao_minify.glsl

@@ -41,7 +41,11 @@ void main() {
 #ifdef MINIFY_START
 	float fdepth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r;
 	fdepth = fdepth * 2.0 - 1.0;
+#ifdef USE_ORTHOGONAL_PROJECTION
+	fdepth = ((fdepth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
+#else
 	fdepth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - fdepth * (camera_z_far - camera_z_near));
+#endif
 	fdepth /= camera_z_far;
 	depth = uint(clamp(fdepth*65535.0,0.0,65535.0));
 

+ 68 - 58
drivers/gles3/shaders/subsurf_scattering.glsl

@@ -17,36 +17,36 @@ void main() {
 
 //#define QUALIFIER uniform // some guy on the interweb says it may be faster with this
 #define QUALIFIER const
+
 #ifdef USE_25_SAMPLES
 
 const int kernel_size=25;
-
 QUALIFIER vec2 kernel[25] = vec2[] (
-vec2(0.099654,0.0),
-vec2(0.001133,-3.0),
-vec2(0.002316,-2.52083),
-vec2(0.00445,-2.08333),
-vec2(0.008033,-1.6875),
-vec2(0.013627,-1.33333),
-vec2(0.021724,-1.02083),
-vec2(0.032542,-0.75),
-vec2(0.04581,-0.520833),
-vec2(0.0606,-0.333333),
-vec2(0.075333,-0.1875),
-vec2(0.088001,-0.0833333),
-vec2(0.096603,-0.0208333),
-vec2(0.096603,0.0208333),
-vec2(0.088001,0.0833333),
-vec2(0.075333,0.1875),
-vec2(0.0606,0.333333),
-vec2(0.04581,0.520833),
-vec2(0.032542,0.75),
-vec2(0.021724,1.02083),
-vec2(0.013627,1.33333),
-vec2(0.008033,1.6875),
-vec2(0.00445,2.08333),
-vec2(0.002316,2.52),
-vec2(0.001133,3.0)
+    vec2(0.530605, 0.0),
+    vec2(0.000973794, -3.0),
+    vec2(0.00333804, -2.52083),
+    vec2(0.00500364, -2.08333),
+    vec2(0.00700976,  -1.6875),
+    vec2(0.0094389, -1.33333),
+    vec2(0.0128496,  -1.02083),
+    vec2(0.017924,  -0.75),
+    vec2(0.0263642,  -0.520833),
+    vec2(0.0410172, -0.333333),
+    vec2(0.0493588, -0.1875),
+    vec2(0.0402784, -0.0833333),
+    vec2(0.0211412,  -0.0208333),
+    vec2(0.0211412,  0.0208333),
+    vec2(0.0402784,  0.0833333),
+    vec2(0.0493588,  0.1875),
+    vec2(0.0410172,  0.333333),
+    vec2(0.0263642,  0.520833),
+    vec2(0.017924,  0.75),
+    vec2(0.0128496, 1.02083),
+    vec2(0.0094389,  1.33333),
+    vec2(0.00700976,  1.6875),
+    vec2(0.00500364,  2.08333),
+    vec2(0.00333804,  2.52083),
+    vec2(0.000973794,  3.0)
 );
 
 #endif //USE_25_SAMPLES
@@ -56,23 +56,23 @@ vec2(0.001133,3.0)
 const int kernel_size=17;
 
 QUALIFIER vec2 kernel[17] = vec2[](
-vec2(0.197417,0.0),
-vec2(0.000078,-2.0),
-vec2(0.000489,-1.53125),
-vec2(0.002403,-1.125),
-vec2(0.009245,-0.78125),
-vec2(0.027835,-0.5),
-vec2(0.065592,-0.28125),
-vec2(0.12098,-0.125),
-vec2(0.17467,-0.03125),
-vec2(0.17467,0.03125),
-vec2(0.12098,0.125),
-vec2(0.065592,0.28125),
-vec2(0.027835,0.5),
-vec2(0.009245,0.78125),
-vec2(0.002403,1.125),
-vec2(0.000489,1.53125),
-vec2(0.000078,2.0)
+    vec2(0.536343,  0.0),
+    vec2(0.00317394,  -2.0),
+    vec2(0.0100386, -1.53125),
+    vec2(0.0144609, -1.125),
+    vec2(0.0216301,  -0.78125),
+    vec2(0.0347317, -0.5),
+    vec2(0.0571056,  -0.28125),
+    vec2(0.0582416,  -0.125),
+    vec2(0.0324462, -0.03125),
+    vec2(0.0324462, 0.03125),
+    vec2(0.0582416, 0.125),
+    vec2(0.0571056,  0.28125),
+    vec2(0.0347317, 0.5),
+    vec2(0.0216301, 0.78125),
+    vec2(0.0144609,  1.125),
+    vec2(0.0100386,  1.53125),
+    vec2(0.00317394,2.0)
 );
 
 #endif //USE_17_SAMPLES
@@ -82,23 +82,24 @@ vec2(0.000078,2.0)
 
 const int kernel_size=11;
 
-QUALIFIER vec2 kernel[kernel_size] = vec2[](
-vec2(0.198596,0.0),
-vec2(0.0093,-2.0),
-vec2(0.028002,-1.28),
-vec2(0.065984,-0.72),
-vec2(0.121703,-0.32),
-vec2(0.175713,-0.08),
-vec2(0.175713,0.08),
-vec2(0.121703,0.32),
-vec2(0.065984,0.72),
-vec2(0.028002,1.28),
-vec2(0.0093,2.0)
+QUALIFIER vec4 kernel[11] = vec4[](
+    vec4(0.560479,  0.0),
+    vec4(0.00471691,  -2.0),
+    vec4(0.0192831, -1.28),
+    vec4(0.03639, -0.72),
+    vec4(0.0821904,  -0.32),
+    vec4(0.0771802, -0.08),
+    vec4(0.0771802,  0.08),
+    vec4(0.0821904, 0.32),
+    vec4(0.03639, 0.72),
+    vec4(0.0192831, 1.28),
+    vec4(0.00471691,2.0)
 );
 
 #endif //USE_11_SAMPLES
 
 
+
 uniform float max_radius;
 uniform float camera_z_far;
 uniform float camera_z_near;
@@ -126,12 +127,16 @@ void main() {
 
 		// Fetch linear depth of current pixel:
 		float depth = texture(source_depth, uv_interp).r * 2.0 - 1.0;
+#ifdef USE_ORTHOGONAL_PROJECTION
+		depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
+		float scale = unit_size; //remember depth is negative by default in OpenGL
+#else
 		depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
+		float scale = unit_size / depth; //remember depth is negative by default in OpenGL
+#endif
 
 
 
-		float scale = unit_size / depth; //remember depth is negative by default in OpenGL
-
 		// Calculate the final step to fetch the surrounding pixels:
 		vec2 step = max_radius * scale * dir;
 		step *= strength; // Modulate it using the alpha channel.
@@ -153,9 +158,14 @@ void main() {
 #ifdef ENABLE_FOLLOW_SURFACE
 			// If the difference in depth is huge, we lerp color back to "colorM":
 			float depth_cmp = texture(source_depth, offset).r *2.0 - 1.0;
+
+#ifdef USE_ORTHOGONAL_PROJECTION
+			depth_cmp = ((depth_cmp + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0;
+#else
 			depth_cmp = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth_cmp * (camera_z_far - camera_z_near));
+#endif
 
-			float s = clamp(300.0f * distance *
+			float s = clamp(300.0f * scale *
 					       max_radius * abs(depth - depth_cmp),0.0,1.0);
 			color = mix(color, base_color.rgb, s);
 #endif

+ 27 - 15
drivers/unix/dir_access_unix.cpp

@@ -211,36 +211,48 @@ Error DirAccessUnix::make_dir(String p_dir) {
 Error DirAccessUnix::change_dir(String p_dir) {
 
 	GLOBAL_LOCK_FUNCTION
+
 	p_dir = fix_path(p_dir);
 
+	// prev_dir is the directory we are changing out of
+	String prev_dir;
 	char real_current_dir_name[2048];
 	getcwd(real_current_dir_name, 2048);
-	String prev_dir;
 	if (prev_dir.parse_utf8(real_current_dir_name))
 		prev_dir = real_current_dir_name; //no utf8, maybe latin?
 
-	chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants
-	bool worked = (chdir(p_dir.utf8().get_data()) == 0); // we can only give this utf8
+	//print_line("directory we are changing out of (prev_dir): " + prev_dir);
 
-	String base = _get_root_path();
-	if (base != "") {
+	// try_dir is the directory we are trying to change into
+	String try_dir = "";
+	if (p_dir.is_rel_path()) {
+		String next_dir = current_dir + "/" + p_dir;
+		//print_line("p_dir is relative: " + p_dir + " about to simplfy: " + next_dir);
+		next_dir = next_dir.simplify_path();
+		try_dir = next_dir;
+	} else {
+		try_dir = p_dir;
+		//print_line("p_dir is absolute: " + p_dir);
+	}
 
-		getcwd(real_current_dir_name, 2048);
-		String new_dir;
-		new_dir.parse_utf8(real_current_dir_name);
-		if (!new_dir.begins_with(base))
-			worked = false;
+	// if try_dir is nothing, it is not changing directory so change it to a "." otherwise chdir will fail
+	if (try_dir == "") {
+		try_dir = ".";
 	}
 
-	if (worked) {
+	//print_line("directory we are changing in to (try_dir): " + try_dir);
 
-		getcwd(real_current_dir_name, 2048);
-		if (current_dir.parse_utf8(real_current_dir_name))
-			current_dir = real_current_dir_name; //no utf8, maybe latin?
+	bool worked = (chdir(try_dir.utf8().get_data()) == 0); // we can only give this utf8
+	if (!worked) {
+		//print_line("directory does not exist");
+		return ERR_INVALID_PARAMETER;
 	}
 
+	// the directory exists, so set current_dir to try_dir
+	current_dir = try_dir;
 	chdir(prev_dir.utf8().get_data());
-	return worked ? OK : ERR_INVALID_PARAMETER;
+	//print_line("directory exists, setting current_dir to: " + current_dir);
+	return OK;
 }
 
 String DirAccessUnix::get_current_dir() {

+ 66 - 27
drivers/unix/file_access_unix.cpp

@@ -36,12 +36,17 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#if defined(UNIX_ENABLED)
+#include <unistd.h>
+#endif
+
 #ifndef ANDROID_ENABLED
 #include <sys/statvfs.h>
 #endif
 
 #ifdef MSVC
 #define S_ISREG(m) ((m)&_S_IFREG)
+#include <io.h>
 #endif
 #ifndef S_ISREG
 #define S_ISREG(m) ((m)&S_IFREG)
@@ -85,13 +90,18 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
 
 	//printf("opening %s as %s\n", p_path.utf8().get_data(), path.utf8().get_data());
 	struct stat st;
-	if (stat(path.utf8().get_data(), &st) == 0) {
-
-		if (!S_ISREG(st.st_mode))
-			return ERR_FILE_CANT_OPEN;
-	};
+	int err = stat(path.utf8().get_data(), &st);
+	if (!err) {
+		switch (st.st_mode & S_IFMT) {
+			case S_IFLNK:
+			case S_IFREG:
+				break;
+			default:
+				return ERR_FILE_CANT_OPEN;
+		}
+	}
 
-	if (is_backup_save_enabled() && p_mode_flags & WRITE && !(p_mode_flags & READ)) {
+	if (is_backup_save_enabled() && (p_mode_flags & WRITE) && !(p_mode_flags & READ)) {
 		save_path = path;
 		path = path + ".tmp";
 		//print_line("saving instead to "+path);
@@ -108,15 +118,19 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
 		return OK;
 	}
 }
+
 void FileAccessUnix::close() {
 
 	if (!f)
 		return;
+
 	fclose(f);
 	f = NULL;
+
 	if (close_notification_func) {
 		close_notification_func(path, flags);
 	}
+
 	if (save_path != "") {
 
 		//unlink(save_path.utf8().get_data());
@@ -131,10 +145,12 @@ void FileAccessUnix::close() {
 		ERR_FAIL_COND(rename_error != 0);
 	}
 }
+
 bool FileAccessUnix::is_open() const {
 
 	return (f != NULL);
 }
+
 void FileAccessUnix::seek(size_t p_position) {
 
 	ERR_FAIL_COND(!f);
@@ -143,29 +159,37 @@ void FileAccessUnix::seek(size_t p_position) {
 	if (fseek(f, p_position, SEEK_SET))
 		check_errors();
 }
+
 void FileAccessUnix::seek_end(int64_t p_position) {
 
 	ERR_FAIL_COND(!f);
+
 	if (fseek(f, p_position, SEEK_END))
 		check_errors();
 }
+
 size_t FileAccessUnix::get_pos() const {
 
-	size_t aux_position = 0;
-	if (!(aux_position = ftell(f))) {
+	ERR_FAIL_COND_V(!f, 0);
+
+	int pos = ftell(f);
+	if (pos < 0) {
 		check_errors();
-	};
-	return aux_position;
+		ERR_FAIL_V(0);
+	}
+	return pos;
 }
+
 size_t FileAccessUnix::get_len() const {
 
 	ERR_FAIL_COND_V(!f, 0);
 
-	FileAccessUnix *fau = const_cast<FileAccessUnix *>(this);
-	int pos = fau->get_pos();
-	fau->seek_end();
-	int size = fau->get_pos();
-	fau->seek(pos);
+	int pos = ftell(f);
+	ERR_FAIL_COND_V(pos < 0, 0);
+	ERR_FAIL_COND_V(fseek(f, 0, SEEK_END), 0);
+	int size = ftell(f);
+	ERR_FAIL_COND_V(size < 0, 0);
+	ERR_FAIL_COND_V(fseek(f, pos, SEEK_SET), 0);
 
 	return size;
 }
@@ -181,8 +205,8 @@ uint8_t FileAccessUnix::get_8() const {
 	uint8_t b;
 	if (fread(&b, 1, 1, f) == 0) {
 		check_errors();
-	};
-
+		b = '\0';
+	}
 	return b;
 }
 
@@ -202,22 +226,36 @@ Error FileAccessUnix::get_error() const {
 void FileAccessUnix::store_8(uint8_t p_dest) {
 
 	ERR_FAIL_COND(!f);
-	fwrite(&p_dest, 1, 1, f);
+	ERR_FAIL_COND(fwrite(&p_dest, 1, 1, f) != 1);
 }
 
 bool FileAccessUnix::file_exists(const String &p_path) {
 
-	FILE *g;
-	//printf("opening file %s\n", p_fname.c_str());
+	int err;
+	struct stat st;
 	String filename = fix_path(p_path);
-	g = fopen(filename.utf8().get_data(), "rb");
-	if (g == NULL) {
 
+	// Does the name exist at all?
+	err = stat(filename.utf8().get_data(), &st);
+	if (err)
 		return false;
-	} else {
 
-		fclose(g);
-		return true;
+#ifdef UNIX_ENABLED
+	// See if we have access to the file
+	if (access(filename.utf8().get_data(), F_OK))
+		return false;
+#else
+	if (_access(filename.utf8().get_data(), 4) == -1)
+		return false;
+#endif
+
+	// See if this is a regular file
+	switch (st.st_mode & S_IFMT) {
+		case S_IFLNK:
+		case S_IFREG:
+			return true;
+		default:
+			return false;
 	}
 }
 
@@ -225,9 +263,9 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
 
 	String file = fix_path(p_file);
 	struct stat flags;
-	bool success = (stat(file.utf8().get_data(), &flags) == 0);
+	int err = stat(file.utf8().get_data(), &flags);
 
-	if (success) {
+	if (!err) {
 		return flags.st_mtime;
 	} else {
 		print_line("ERROR IN: " + p_file);
@@ -249,6 +287,7 @@ FileAccessUnix::FileAccessUnix() {
 	flags = 0;
 	last_error = OK;
 }
+
 FileAccessUnix::~FileAccessUnix() {
 
 	close();

+ 52 - 8
editor/SCsub

@@ -155,31 +155,71 @@ def make_authors_header(target, source, env):
     g.write("#define _EDITOR_AUTHORS_H\n")
 
     current_section = ""
-    name_count = -1
+    reading = False
 
     def close_section():
         g.write("\t0\n")
         g.write("};\n")
-        g.write("#define " + current_section.upper() + "_COUNT " + str(name_count) + "\n")
 
     for line in f:
-        if name_count >= 0:
+        if reading:
             if line.startswith("    "):
                 g.write("\t\"" + line.strip() + "\",\n")
-                name_count += 1
                 continue
         if line.startswith("## "):
-            if name_count >= 0:
+            if reading:
                 close_section()
-                name_count = -1
+                reading = False
             for i in range(len(sections)):
                 if line.strip().endswith(sections[i]):
                     current_section = sections_id[i]
-                    name_count = 0
+                    reading = True
                     g.write("static const char *" + current_section + "[] = {\n")
                     break
 
-    if name_count >= 0:
+    if reading:
+        close_section()
+
+    g.write("#endif\n")
+
+def make_donors_header(target, source, env):
+
+    sections = ["Platinum sponsors", "Gold sponsors", "Mini sponsors", "Gold donors", "Silver donors", "Bronze donors"]
+    sections_id = ["donor_s_plat", "donor_s_gold", "donor_s_mini", "donor_gold", "donor_silver", "donor_bronze"]
+
+    src = source[0].srcnode().abspath
+    dst = target[0].srcnode().abspath
+    f = open_utf8(src, "r")
+    g = open_utf8(dst, "w")
+
+    g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+    g.write("#ifndef _EDITOR_DONORS_H\n")
+    g.write("#define _EDITOR_DONORS_H\n")
+
+    current_section = ""
+    reading = False
+
+    def close_section():
+        g.write("\t0\n")
+        g.write("};\n")
+
+    for line in f:
+        if reading >= 0:
+            if line.startswith("    "):
+                g.write("\t\"" + line.strip() + "\",\n")
+                continue
+        if line.startswith("## "):
+            if reading:
+                close_section()
+                reading = False
+            for i in range(len(sections)):
+                if line.strip().endswith(sections[i]):
+                    current_section = sections_id[i]
+                    reading = True
+                    g.write("static const char *" + current_section + "[] = {\n")
+                    break
+
+    if reading:
         close_section()
 
     g.write("#endif\n")
@@ -393,6 +433,10 @@ if (env["tools"] == "yes"):
     env.Depends('#editor/authors.gen.h', "../AUTHORS.md")
     env.Command('#editor/authors.gen.h', "../AUTHORS.md", make_authors_header)
 
+    # Donors
+    env.Depends('#editor/donors.gen.h', "../DONORS.md")
+    env.Command('#editor/donors.gen.h', "../DONORS.md", make_donors_header)
+
     # License
     env.Depends('#editor/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"])
     env.Command('#editor/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"], make_license_header)

+ 8 - 1
editor/doc/doc_data.cpp

@@ -634,6 +634,9 @@ static Error _parse_methods(Ref<XMLParser> &parser, Vector<DocData::MethodDoc> &
 
 							ERR_FAIL_COND_V(!parser->has_attribute("type"), ERR_FILE_CORRUPT);
 							method.return_type = parser->get_attribute_value("type");
+							if (parser->has_attribute("enum")) {
+								method.return_enum = parser->get_attribute_value("enum");
+							}
 						} else if (name == "argument") {
 
 							DocData::ArgumentDoc argument;
@@ -916,7 +919,11 @@ Error DocData::save(const String &p_path) {
 
 			if (m.return_type != "") {
 
-				_write_string(f, 3, "<return type=\"" + m.return_type + "\">");
+				String enum_text;
+				if (m.return_enum != String()) {
+					enum_text = " enum=\"" + m.return_enum + "\"";
+				}
+				_write_string(f, 3, "<return type=\"" + m.return_type + "\"" + enum_text + ">");
 				_write_string(f, 3, "</return>");
 			}
 

+ 59 - 29
editor/editor_about.cpp

@@ -30,6 +30,7 @@
 #include "editor_about.h"
 
 #include "authors.gen.h"
+#include "donors.gen.h"
 #include "license.gen.h"
 #include "version.h"
 #include "version_hash.gen.h"
@@ -51,6 +52,47 @@ TextureRect *EditorAbout::get_logo() const {
 	return _logo;
 }
 
+ScrollContainer *EditorAbout::_populate_list(const String &p_name, const List<String> &p_sections, const char **p_src[]) {
+
+	ScrollContainer *sc = memnew(ScrollContainer);
+	sc->set_name(p_name);
+	sc->set_v_size_flags(Control::SIZE_EXPAND);
+
+	VBoxContainer *vbc = memnew(VBoxContainer);
+	vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+	sc->add_child(vbc);
+
+	for (int i = 0; i < p_sections.size(); i++) {
+
+		const char **names_ptr = p_src[i];
+		if (*names_ptr) {
+
+			Label *lbl = memnew(Label);
+			lbl->set_text(p_sections[i]);
+			vbc->add_child(lbl);
+
+			ItemList *il = memnew(ItemList);
+			il->set_max_columns(16);
+			il->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+			il->set_same_column_width(true);
+			il->set_auto_height(true);
+			while (*names_ptr) {
+				il->add_item(String::utf8(*names_ptr++), NULL, false);
+			}
+			vbc->add_child(il);
+			if (il->get_item_count() == 2) {
+				il->set_fixed_column_width(200 * EDSCALE);
+			}
+
+			HSeparator *hs = memnew(HSeparator);
+			hs->set_modulate(Color(0, 0, 0, 0));
+			vbc->add_child(hs);
+		}
+	}
+
+	return sc;
+}
+
 EditorAbout::EditorAbout() {
 
 	set_title(TTR("Thanks from the Godot community!"));
@@ -84,43 +126,29 @@ EditorAbout::EditorAbout() {
 	tc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	vbc->add_child(tc);
 
-	ScrollContainer *dev_base = memnew(ScrollContainer);
-	dev_base->set_name(TTR("Authors"));
-	dev_base->set_v_size_flags(Control::SIZE_EXPAND);
-	tc->add_child(dev_base);
-
-	VBoxContainer *dev_vbc = memnew(VBoxContainer);
-	dev_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-	dev_base->add_child(dev_vbc);
+	// Authors
 
 	List<String> dev_sections;
 	dev_sections.push_back(TTR("Project Founders"));
 	dev_sections.push_back(TTR("Lead Developer"));
 	dev_sections.push_back(TTR("Project Manager"));
 	dev_sections.push_back(TTR("Developers"));
-
 	const char **dev_src[] = { dev_founders, dev_lead, dev_manager, dev_names };
+	tc->add_child(_populate_list(TTR("Authors"), dev_sections, dev_src));
 
-	for (int i = 0; i < dev_sections.size(); i++) {
-
-		Label *lbl = memnew(Label);
-		lbl->set_text(dev_sections[i]);
-		dev_vbc->add_child(lbl);
-
-		ItemList *il = memnew(ItemList);
-		il->set_max_columns(16);
-		il->set_h_size_flags(Control::SIZE_EXPAND_FILL);
-		il->set_fixed_column_width(230 * EDSCALE);
-		il->set_auto_height(true);
-		const char **dev_names_ptr = dev_src[i];
-		while (*dev_names_ptr)
-			il->add_item(String::utf8(*dev_names_ptr++), NULL, false);
-		dev_vbc->add_child(il);
-
-		HSeparator *hs = memnew(HSeparator);
-		hs->set_modulate(Color(0, 0, 0, 0));
-		dev_vbc->add_child(hs);
-	}
+	// Donors
+
+	List<String> donor_sections;
+	donor_sections.push_back(TTR("Platinum Sponsors"));
+	donor_sections.push_back(TTR("Gold Sponsors"));
+	donor_sections.push_back(TTR("Mini Sponsors"));
+	donor_sections.push_back(TTR("Gold Donors"));
+	donor_sections.push_back(TTR("Silver Donors"));
+	donor_sections.push_back(TTR("Bronze Donors"));
+	const char **donor_src[] = { donor_s_plat, donor_s_gold, donor_s_mini, donor_gold, donor_silver, donor_bronze };
+	tc->add_child(_populate_list(TTR("Donors"), donor_sections, donor_src));
+
+	// License
 
 	TextEdit *license = memnew(TextEdit);
 	license->set_name(TTR("License"));
@@ -131,6 +159,8 @@ EditorAbout::EditorAbout() {
 	license->set_text(String::utf8(about_license));
 	tc->add_child(license);
 
+	// Thirdparty License
+
 	VBoxContainer *license_thirdparty = memnew(VBoxContainer);
 	license_thirdparty->set_name(TTR("Thirdparty License"));
 	license_thirdparty->set_h_size_flags(Control::SIZE_EXPAND_FILL);

+ 1 - 0
editor/editor_about.h

@@ -52,6 +52,7 @@ class EditorAbout : public AcceptDialog {
 
 private:
 	void _license_tree_selected();
+	ScrollContainer *_populate_list(const String &p_name, const List<String> &p_sections, const char **p_src[]);
 
 	Tree *_tpl_tree;
 	TextEdit *_tpl_text;

+ 35 - 85
editor/editor_dir_dialog.cpp

@@ -31,50 +31,40 @@
 
 #include "editor/editor_file_system.h"
 #include "editor/editor_settings.h"
+#include "editor_scale.h"
 #include "os/keyboard.h"
 #include "os/os.h"
-
-void EditorDirDialog::_update_dir(TreeItem *p_item) {
+void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p_dir, const String &p_select_path) {
 
 	updating = true;
-	p_item->clear_children();
-	DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
-	String cdir = p_item->get_metadata(0);
-
-	da->change_dir(cdir);
-	da->list_dir_begin();
-	String p = da->get_next();
 
-	List<String> dirs;
-	bool ishidden;
-	bool show_hidden = EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files");
+	String path = p_dir->get_path();
 
-	while (p != "") {
+	p_item->set_metadata(0, p_dir->get_path());
+	p_item->set_icon(0, get_icon("Folder", "EditorIcons"));
 
-		ishidden = da->current_is_hidden();
+	if (!p_item->get_parent()) {
+		p_item->set_text(0, "res://");
+	} else {
 
-		if (show_hidden || !ishidden) {
-			if (da->current_is_dir() && !p.begins_with(".")) {
-				dirs.push_back(p);
-			}
+		if (!opened_paths.has(path) && (p_select_path == String() || !p_select_path.begins_with(path))) {
+			p_item->set_collapsed(true);
 		}
-		p = da->get_next();
+
+		p_item->set_text(0, p_dir->get_name());
 	}
 
-	dirs.sort();
+	//this should be handled by EditorFileSystem already
+	//bool show_hidden = EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files");
+	updating = false;
+	for (int i = 0; i < p_dir->get_subdir_count(); i++) {
 
-	for (List<String>::Element *E = dirs.front(); E; E = E->next()) {
 		TreeItem *ti = tree->create_item(p_item);
-		ti->set_text(0, E->get());
-		ti->set_icon(0, get_icon("Folder", "EditorIcons"));
-		ti->set_collapsed(true);
+		_update_dir(ti, p_dir->get_subdir(i));
 	}
-
-	memdelete(da);
-	updating = false;
 }
 
-void EditorDirDialog::reload() {
+void EditorDirDialog::reload(const String &p_with_path) {
 
 	if (!is_visible_in_tree()) {
 		must_reload = true;
@@ -83,10 +73,7 @@ void EditorDirDialog::reload() {
 
 	tree->clear();
 	TreeItem *root = tree->create_item();
-	root->set_metadata(0, "res://");
-	root->set_icon(0, get_icon("Folder", "EditorIcons"));
-	root->set_text(0, "/");
-	_update_dir(root);
+	_update_dir(root, EditorFileSystem::get_singleton()->get_filesystem(), p_with_path);
 	_item_collapsed(root);
 	must_reload = false;
 }
@@ -94,6 +81,7 @@ void EditorDirDialog::reload() {
 void EditorDirDialog::_notification(int p_what) {
 
 	if (p_what == NOTIFICATION_ENTER_TREE) {
+		EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "reload");
 		reload();
 
 		if (!tree->is_connected("item_collapsed", this, "_item_collapsed")) {
@@ -105,6 +93,10 @@ void EditorDirDialog::_notification(int p_what) {
 		}
 	}
 
+	if (p_what == NOTIFICATION_EXIT_TREE) {
+		EditorFileSystem::get_singleton()->disconnect("filesystem_changed", this, "reload");
+	}
+
 	if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
 		if (must_reload && is_visible_in_tree()) {
 			reload();
@@ -116,57 +108,13 @@ void EditorDirDialog::_item_collapsed(Object *p_item) {
 
 	TreeItem *item = Object::cast_to<TreeItem>(p_item);
 
-	if (updating || item->is_collapsed())
+	if (updating)
 		return;
 
-	TreeItem *ci = item->get_children();
-	while (ci) {
-
-		String p = ci->get_metadata(0);
-		if (p == "") {
-			String pp = item->get_metadata(0);
-			ci->set_metadata(0, pp.plus_file(ci->get_text(0)));
-			_update_dir(ci);
-		}
-		ci = ci->get_next();
-	}
-}
-
-void EditorDirDialog::set_current_path(const String &p_path) {
-
-	reload();
-	String p = p_path;
-	if (p.begins_with("res://"))
-		p = p.replace_first("res://", "");
-
-	Vector<String> dirs = p.split("/", false);
-
-	TreeItem *r = tree->get_root();
-	for (int i = 0; i < dirs.size(); i++) {
-
-		String d = dirs[i];
-		TreeItem *p = r->get_children();
-		while (p) {
-
-			if (p->get_text(0) == d)
-				break;
-			p = p->get_next();
-		}
-
-		ERR_FAIL_COND(!p);
-		String pp = p->get_metadata(0);
-		if (pp == "") {
-			p->set_metadata(0, String(r->get_metadata(0)).plus_file(d));
-			_update_dir(p);
-		}
-		updating = true;
-		p->set_collapsed(false);
-		updating = false;
-		_item_collapsed(p);
-		r = p;
-	}
-
-	r->select(0);
+	if (item->is_collapsed())
+		opened_paths.erase(item->get_metadata(0));
+	else
+		opened_paths.insert(item->get_metadata(0));
 }
 
 void EditorDirDialog::ok_pressed() {
@@ -201,14 +149,16 @@ void EditorDirDialog::_make_dir_confirm() {
 
 	String dir = ti->get_metadata(0);
 
-	DirAccess *d = DirAccess::open(dir);
+	DirAccessRef d = DirAccess::open(dir);
 	ERR_FAIL_COND(!d);
 	Error err = d->make_dir(makedirname->get_text());
 
 	if (err != OK) {
-		mkdirerr->popup_centered_minsize(Size2(250, 80));
+		mkdirerr->popup_centered_minsize(Size2(250, 80) * EDSCALE);
 	} else {
-		set_current_path(dir.plus_file(makedirname->get_text()));
+		opened_paths.insert(dir);
+		//reload(dir.plus_file(makedirname->get_text()));
+		EditorFileSystem::get_singleton()->scan_changes(); //we created a dir, so rescan changes
 	}
 	makedirname->set_text(""); // reset label
 }
@@ -218,7 +168,7 @@ void EditorDirDialog::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("_item_collapsed"), &EditorDirDialog::_item_collapsed);
 	ClassDB::bind_method(D_METHOD("_make_dir"), &EditorDirDialog::_make_dir);
 	ClassDB::bind_method(D_METHOD("_make_dir_confirm"), &EditorDirDialog::_make_dir_confirm);
-	ClassDB::bind_method(D_METHOD("reload"), &EditorDirDialog::reload);
+	ClassDB::bind_method(D_METHOD("reload"), &EditorDirDialog::reload, DEFVAL(""));
 
 	ADD_SIGNAL(MethodInfo("dir_selected", PropertyInfo(Variant::STRING, "dir")));
 }

+ 4 - 3
editor/editor_dir_dialog.h

@@ -30,6 +30,7 @@
 #ifndef EDITOR_DIR_DIALOG_H
 #define EDITOR_DIR_DIALOG_H
 
+#include "editor/editor_file_system.h"
 #include "os/dir_access.h"
 #include "scene/gui/dialogs.h"
 #include "scene/gui/tree.h"
@@ -42,12 +43,13 @@ class EditorDirDialog : public ConfirmationDialog {
 	AcceptDialog *mkdirerr;
 
 	Button *makedir;
+	Set<String> opened_paths;
 
 	Tree *tree;
 	bool updating;
 
 	void _item_collapsed(Object *p_item);
-	void _update_dir(TreeItem *p_item);
+	void _update_dir(TreeItem *p_item, EditorFileSystemDirectory *p_dir, const String &p_select_path = String());
 
 	void _make_dir();
 	void _make_dir_confirm();
@@ -61,8 +63,7 @@ protected:
 	static void _bind_methods();
 
 public:
-	void set_current_path(const String &p_path);
-	void reload();
+	void reload(const String &p_path = "");
 	EditorDirDialog();
 };
 

+ 8 - 5
editor/editor_fonts.cpp

@@ -72,11 +72,14 @@ static Ref<BitmapFont> make_font(int p_height, int p_ascent, int p_valign, int p
 	m_name->add_fallback(FontJapanese); \
 	m_name->add_fallback(FontFallback);
 
-#define MAKE_DEFAULT_FONT(m_name, m_size) \
-	Ref<DynamicFont> m_name;              \
-	m_name.instance();                    \
-	m_name->set_size(m_size);             \
-	m_name->set_font_data(DefaultFont);   \
+// the custom spacings might only work with Noto Sans
+#define MAKE_DEFAULT_FONT(m_name, m_size)                 \
+	Ref<DynamicFont> m_name;                              \
+	m_name.instance();                                    \
+	m_name->set_size(m_size);                             \
+	m_name->set_font_data(DefaultFont);                   \
+	m_name->set_spacing(DynamicFont::SPACING_TOP, -1);    \
+	m_name->set_spacing(DynamicFont::SPACING_BOTTOM, -1); \
 	MAKE_FALLBACKS(m_name);
 
 void editor_register_fonts(Ref<Theme> p_theme) {

+ 13 - 11
editor/editor_help.cpp

@@ -1712,9 +1712,8 @@ void EditorHelp::_notification(int p_what) {
 		} break;
 
 		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
-			Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
-			style->set_bg_color(EditorSettings::get_singleton()->get("text_editor/highlighting/background_color"));
-			background_panel->add_style_override("panel", style);
+
+			class_desc->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
 		} break;
 
 		default: break;
@@ -1786,14 +1785,12 @@ EditorHelp::EditorHelp() {
 
 	{
 		background_panel = memnew(Panel);
-		Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
-		style->set_bg_color(EditorSettings::get_singleton()->get("text_editor/highlighting/background_color"));
 		background_panel->set_v_size_flags(SIZE_EXPAND_FILL);
-		background_panel->add_style_override("panel", style); //get_stylebox("normal","TextEdit"));
 		vbc->add_child(background_panel);
 		class_desc = memnew(RichTextLabel);
 		background_panel->add_child(class_desc);
-		class_desc->set_area_as_parent_rect(8);
+		class_desc->set_area_as_parent_rect();
+		class_desc->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
 		class_desc->connect("meta_clicked", this, "_class_desc_select");
 		class_desc->connect("gui_input", this, "_class_desc_input");
 	}
@@ -1882,8 +1879,13 @@ void EditorHelpBit::_bind_methods() {
 
 void EditorHelpBit::_notification(int p_what) {
 
-	if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
-		add_style_override("panel", get_stylebox("ScriptPanel", "EditorStyles"));
+	switch (p_what) {
+		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+
+			rich_text->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
+		} break;
+
+		default: break;
 	}
 }
 
@@ -1897,8 +1899,8 @@ EditorHelpBit::EditorHelpBit() {
 
 	rich_text = memnew(RichTextLabel);
 	add_child(rich_text);
-	rich_text->set_area_as_parent_rect(8 * EDSCALE);
+	rich_text->set_area_as_parent_rect();
 	rich_text->connect("meta_clicked", this, "_meta_clicked");
+	rich_text->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
 	set_custom_minimum_size(Size2(0, 70 * EDSCALE));
-	add_style_override("panel", EditorNode::get_singleton()->get_gui_base()->get_stylebox("ScriptPanel", "EditorStyles"));
 }

+ 1 - 2
editor/editor_log.cpp

@@ -59,7 +59,6 @@ void EditorLog::_notification(int p_what) {
 
 	if (p_what == NOTIFICATION_ENTER_TREE) {
 
-		log->add_color_override("default_color", get_color("font_color", "Tree"));
 		//button->set_icon(get_icon("Console","EditorIcons"));
 	}
 	if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
@@ -91,7 +90,7 @@ void EditorLog::add_message(const String &p_msg, bool p_error) {
 
 	log->add_newline();
 	if (p_error) {
-		log->push_color(get_color("fg_error", "Editor"));
+		log->push_color(get_color("error_color", "Editor"));
 		Ref<Texture> icon = get_icon("Error", "EditorIcons");
 		log->add_image(icon);
 		//button->set_icon(icon);

+ 54 - 15
editor/editor_node.cpp

@@ -283,13 +283,22 @@ void EditorNode::_notification(int p_what) {
 		scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
 		property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/capitalize_properties", true)));
 		Ref<Theme> theme = create_editor_theme(theme_base->get_theme());
+
 		theme_base->set_theme(theme);
+
 		gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles"));
 		play_button_panel->add_style_override("panel", gui_base->get_stylebox("PlayButtonPanel", "EditorStyles"));
 		scene_root_parent->add_style_override("panel", gui_base->get_stylebox("Content", "EditorStyles"));
 		bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer"));
 		scene_tabs->add_style_override("tab_fg", gui_base->get_stylebox("SceneTabFG", "EditorStyles"));
 		scene_tabs->add_style_override("tab_bg", gui_base->get_stylebox("SceneTabBG", "EditorStyles"));
+
+		file_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+		project_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+		debug_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+		settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+		help_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+
 		if (bool(EDITOR_DEF("interface/scene_tabs/resize_if_many_tabs", true))) {
 			scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE);
 		} else {
@@ -1368,6 +1377,16 @@ void EditorNode::_set_editing_top_editors(Object *p_current_object) {
 	editor_plugins_over->edit(p_current_object);
 }
 
+static bool overrides_external_editor(Object *p_object) {
+
+	Script *script = Object::cast_to<Script>(p_object);
+
+	if (!script)
+		return false;
+
+	return script->get_language()->overrides_external_editor();
+}
+
 void EditorNode::_edit_current() {
 
 	uint32_t current = editor_history.get_current();
@@ -1434,7 +1453,7 @@ void EditorNode::_edit_current() {
 	if (main_plugin) {
 
 		// special case if use of external editor is true
-		if (main_plugin->get_name() == "Script" && bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) {
+		if (main_plugin->get_name() == "Script" && (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor")) || overrides_external_editor(current_obj))) {
 			main_plugin->edit(current_obj);
 		}
 
@@ -1442,6 +1461,7 @@ void EditorNode::_edit_current() {
 			// update screen main_plugin
 
 			if (!changing_scene) {
+
 				if (editor_plugin_screen)
 					editor_plugin_screen->make_visible(false);
 				editor_plugin_screen = main_plugin;
@@ -2721,6 +2741,14 @@ Dictionary EditorNode::_get_main_scene_state() {
 	state["property_edit_offset"] = get_property_editor()->get_scene_tree()->get_vscroll_bar()->get_value();
 	state["saved_version"] = saved_version;
 	state["node_filter"] = scene_tree_dock->get_filter();
+	int current = -1;
+	for (int i = 0; i < editor_table.size(); i++) {
+		if (editor_plugin_screen == editor_table[i]) {
+			current = i;
+			break;
+		}
+	}
+	state["editor_index"] = current;
 	return state;
 }
 
@@ -2731,8 +2759,9 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
 
 	changing_scene = false;
 
-	if (get_edited_scene()) {
+	if (p_state.has("editor_index")) {
 
+		int index = p_state["editor_index"];
 		int current = -1;
 		for (int i = 0; i < editor_table.size(); i++) {
 			if (editor_plugin_screen == editor_table[i]) {
@@ -2741,15 +2770,18 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
 			}
 		}
 
-		if (current < 2) {
-			//use heuristic instead
-
-			int n2d = 0, n3d = 0;
-			_find_node_types(get_edited_scene(), n2d, n3d);
-			if (n2d > n3d) {
-				_editor_select(EDITOR_2D);
-			} else if (n3d > n2d) {
-				_editor_select(EDITOR_3D);
+		if (current < 2) { //if currently in spatial/2d, only switch to spatial/2d. if curently in script, stay there
+			if (index < 2 || !get_edited_scene()) {
+				_editor_select(index);
+			} else {
+				//use heuristic instead
+				int n2d = 0, n3d = 0;
+				_find_node_types(get_edited_scene(), n2d, n3d);
+				if (n2d > n3d) {
+					_editor_select(EDITOR_2D);
+				} else if (n3d > n2d) {
+					_editor_select(EDITOR_3D);
+				}
 			}
 		}
 	}
@@ -4818,9 +4850,10 @@ EditorNode::EditorNode() {
 	}
 
 	file_menu = memnew(MenuButton);
+	file_menu->set_flat(false);
 	file_menu->set_text(TTR("Scene"));
-	left_menu_hb->add_child(file_menu);
 	file_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+	left_menu_hb->add_child(file_menu);
 
 	prev_scene = memnew(ToolButton);
 	prev_scene->set_icon(gui_base->get_icon("PrevScene", "EditorIcons"));
@@ -4908,6 +4941,7 @@ EditorNode::EditorNode() {
 	p->add_item(TTR("Quit"), FILE_QUIT, KEY_MASK_CMD + KEY_Q);
 
 	project_menu = memnew(MenuButton);
+	project_menu->set_flat(false);
 	project_menu->set_tooltip(TTR("Miscellaneous project or scene-wide tools."));
 	project_menu->set_text(TTR("Project"));
 	project_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
@@ -4941,9 +4975,11 @@ EditorNode::EditorNode() {
 	menu_hb->add_child(editor_region);
 
 	debug_menu = memnew(MenuButton);
+	debug_menu->set_flat(false);
 	debug_menu->set_text(TTR("Debug"));
 	debug_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
 	left_menu_hb->add_child(debug_menu);
+
 	p = debug_menu->get_popup();
 	p->set_hide_on_item_selection(false);
 	p->add_check_item(TTR("Deploy with Remote Debug"), RUN_DEPLOY_REMOTE_DEBUG);
@@ -4965,9 +5001,10 @@ EditorNode::EditorNode() {
 	menu_hb->add_spacer();
 
 	settings_menu = memnew(MenuButton);
-	left_menu_hb->add_child(settings_menu);
+	settings_menu->set_flat(false);
 	settings_menu->set_text(TTR("Editor"));
 	settings_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+	left_menu_hb->add_child(settings_menu);
 	p = settings_menu->get_popup();
 
 	p->add_item(TTR("Editor Settings"), SETTINGS_PREFERENCES);
@@ -4982,10 +5019,12 @@ EditorNode::EditorNode() {
 	p->add_item(TTR("Manage Export Templates"), SETTINGS_MANAGE_EXPORT_TEMPLATES);
 
 	// Help Menu
-	MenuButton *help_menu = memnew(MenuButton);
-	left_menu_hb->add_child(help_menu);
+	help_menu = memnew(MenuButton);
+	help_menu->set_flat(false);
 	help_menu->set_text(TTR("Help"));
 	help_menu->add_style_override("hover", gui_base->get_stylebox("MenuHover", "EditorStyles"));
+	left_menu_hb->add_child(help_menu);
+
 	p = help_menu->get_popup();
 	p->connect("id_pressed", this, "_menu_option");
 	p->add_icon_item(gui_base->get_icon("ClassList", "EditorIcons"), TTR("Classes"), HELP_CLASSES);

+ 2 - 1
editor/editor_node.h

@@ -236,11 +236,12 @@ private:
 	MenuButton *file_menu;
 	MenuButton *project_menu;
 	MenuButton *debug_menu;
+	MenuButton *settings_menu;
+	MenuButton *help_menu;
 	PopupMenu *tool_menu;
 	ToolButton *export_button;
 	ToolButton *prev_scene;
 	MenuButton *object_menu;
-	MenuButton *settings_menu;
 	ToolButton *play_button;
 	MenuButton *native_play_button;
 	ToolButton *pause_button;

+ 0 - 1
editor/editor_settings.cpp

@@ -603,7 +603,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 	hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Default");
 
 	set("text_editor/theme/line_spacing", 4);
-	set("text_editor/theme/adapted_code_editor_background_color", true);
 
 	_load_default_text_editor_theme();
 

+ 20 - 23
editor/editor_themes.cpp

@@ -198,6 +198,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	bool highlight_tabs = EDITOR_DEF("interface/theme/highlight_tabs", false);
 	int border_size = EDITOR_DEF("interface/theme/border_size", 1);
 
+	Color script_bg_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0));
+
 	switch (preset) {
 		case 0: { // Default
 			highlight_color = Color::html("#699ce8");
@@ -235,8 +237,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	Color dark_color_2 = base_color.linear_interpolate(Color(0, 0, 0, 1), contrast * 1.5);
 	Color dark_color_3 = base_color.linear_interpolate(Color(0, 0, 0, 1), contrast * 2);
 
-	Color contrast_color_1 = base_color.linear_interpolate((dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)), 0.3);
-	Color contrast_color_2 = base_color.linear_interpolate((dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)), 0.5);
+	Color contrast_color_1 = base_color.linear_interpolate((dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)), MAX(contrast, default_contrast));
+	Color contrast_color_2 = base_color.linear_interpolate((dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)), MAX(contrast * 1.5, default_contrast * 1.5));
 
 	Color font_color = dark_theme ? Color(1, 1, 1) : Color(0, 0, 0);
 	Color font_color_disabled = dark_theme ? Color(0.6, 0.6, 0.6) : Color(0.45, 0.45, 0.45);
@@ -279,8 +281,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	editor_register_fonts(theme);
 
 	// Editor background
-	Ref<StyleBoxFlat> style_panel = make_flat_stylebox(dark_color_2, 4, 4, 4, 4);
-	theme->set_stylebox("Background", "EditorStyles", style_panel);
+	theme->set_stylebox("Background", "EditorStyles", make_flat_stylebox(dark_color_2, 4, 4, 4, 4));
 
 	// Focus
 	Ref<StyleBoxFlat> focus_sbt = make_flat_stylebox(contrast_color_1, 4, 4, 4, 4);
@@ -302,12 +303,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	Ref<StyleBoxFlat> style_menu_hover_bg = make_flat_stylebox(dark_color_2, 4, 4, 4, 4);
 
 	style_menu_hover_border->set_draw_center(false);
-	style_menu_hover_border->set_border_width(MARGIN_BOTTOM, border_width);
+	style_menu_hover_border->set_border_width(MARGIN_BOTTOM, 2 * EDSCALE);
 	style_menu_hover_border->set_border_color_all(highlight_color);
-	style_menu_hover_border->set_expand_margin_size(MARGIN_BOTTOM, border_width);
 
 	theme->set_stylebox("normal", "MenuButton", style_menu);
-	theme->set_stylebox("hover", "MenuButton", style_menu_hover_border);
+	theme->set_stylebox("hover", "MenuButton", style_menu);
 	theme->set_stylebox("pressed", "MenuButton", style_menu);
 	theme->set_stylebox("focus", "MenuButton", style_menu);
 	theme->set_stylebox("disabled", "MenuButton", style_menu);
@@ -333,10 +333,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	theme->set_stylebox("MenuHover", "EditorStyles", style_menu_hover_border);
 
 	// Content of each tab
-	Ref<StyleBoxFlat> style_content_panel = make_flat_stylebox(base_color, 4, 5, 4, 4);
+	Ref<StyleBoxFlat> style_content_panel = make_flat_stylebox(base_color, 4, 4, 4, 4);
 	style_content_panel->set_border_color_all(base_color);
 	style_content_panel->set_border_width_all(border_width);
-	Ref<StyleBoxFlat> style_content_panel_vp = make_flat_stylebox(base_color, border_width, 5, border_width, border_width);
+	Ref<StyleBoxFlat> style_content_panel_vp = make_flat_stylebox(base_color, border_width, 4, border_width, border_width);
 	style_content_panel_vp->set_border_color_all(base_color);
 	style_content_panel_vp->set_border_width_all(border_width);
 	theme->set_stylebox("panel", "TabContainer", style_content_panel);
@@ -357,6 +357,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	theme->set_stylebox("pressed", "Button", change_border_color(style_button_type, highlight_color));
 	theme->set_stylebox("focus", "Button", change_border_color(style_button_type, highlight_color));
 	theme->set_stylebox("disabled", "Button", style_button_type_disabled);
+
 	theme->set_color("font_color", "Button", button_font_color);
 	theme->set_color("font_color_hover", "Button", HIGHLIGHT_COLOR_FONT);
 	theme->set_color("font_color_pressed", "Button", highlight_color);
@@ -366,13 +367,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	theme->set_color("icon_color_pressed", "Button", Color(highlight_color.r * 1.15, highlight_color.g * 1.15, highlight_color.b * 1.15, highlight_color.a));
 
 	// OptionButton
-	Ref<StyleBoxFlat> style_option_button = make_flat_stylebox(dark_color_1, 4, 4, 4, 4);
-	style_option_button->set_border_width_all(border_width);
+	theme->set_stylebox("normal", "OptionButton", style_button_type);
 	theme->set_stylebox("hover", "OptionButton", change_border_color(style_button_type, contrast_color_1));
 	theme->set_stylebox("pressed", "OptionButton", change_border_color(style_button_type, HIGHLIGHT_COLOR_FONT));
 	theme->set_stylebox("focus", "OptionButton", change_border_color(style_button_type, highlight_color));
 	theme->set_stylebox("disabled", "OptionButton", style_button_type_disabled);
-	theme->set_stylebox("normal", "OptionButton", style_button_type);
+
 	theme->set_color("font_color", "OptionButton", button_font_color);
 	theme->set_color("font_color_hover", "OptionButton", HIGHLIGHT_COLOR_FONT);
 	theme->set_color("font_color_pressed", "OptionButton", highlight_color);
@@ -385,6 +385,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	// CheckButton
 	theme->set_icon("on", "CheckButton", theme->get_icon("GuiToggleOn", "EditorIcons"));
 	theme->set_icon("off", "CheckButton", theme->get_icon("GuiToggleOff", "EditorIcons"));
+
 	theme->set_color("font_color", "CheckButton", button_font_color);
 	theme->set_color("font_color_hover", "CheckButton", HIGHLIGHT_COLOR_FONT);
 	theme->set_color("font_color_pressed", "CheckButton", highlight_color);
@@ -424,12 +425,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	style_tree_bg->set_border_color_all(dark_color_3);
 	theme->set_stylebox("bg", "Tree", style_tree_bg);
 
-	// Script background
-	Ref<StyleBoxFlat> style_script_bg = make_flat_stylebox(dark_color_1, 0, 0, 0, 0);
-	style_script_bg->set_border_width_all(border_width);
-	style_script_bg->set_border_color_all(dark_color_3);
-	theme->set_stylebox("ScriptPanel", "EditorStyles", style_script_bg);
-
 	// Tree
 	theme->set_icon("checked", "Tree", theme->get_icon("GuiChecked", "EditorIcons"));
 	theme->set_icon("unchecked", "Tree", theme->get_icon("GuiUnchecked", "EditorIcons"));
@@ -441,7 +436,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox());
 	theme->set_stylebox("custom_button_hover", "Tree", style_button_type);
 	theme->set_color("custom_button_font_highlight", "Tree", HIGHLIGHT_COLOR_FONT);
-	theme->set_color("font_color", "Tree", font_color_disabled);
+	theme->set_color("font_color", "Tree", font_color);
 	theme->set_color("font_color_selected", "Tree", font_color);
 
 	Ref<StyleBox> style_tree_btn = make_flat_stylebox(contrast_color_1, 2, 4, 2, 4);
@@ -471,8 +466,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	theme->set_color("prop_category", "Editor", prop_category_color);
 	theme->set_color("prop_section", "Editor", prop_section_color);
 	theme->set_color("prop_subsection", "Editor", prop_subsection_color);
-	theme->set_color("fg_selected", "Editor", HIGHLIGHT_COLOR_BG);
-	theme->set_color("fg_error", "Editor", error_color);
 	theme->set_color("drop_position_color", "Tree", highlight_color);
 
 	// ItemList
@@ -531,6 +524,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 
 	// LineEdit
 	Ref<StyleBoxFlat> style_line_edit = make_flat_stylebox(dark_color_1, 6, 4, 6, 4);
+	style_line_edit->set_border_width_all(border_width);
 	style_line_edit = change_border_color(style_line_edit, contrast_color_1);
 	Ref<StyleBoxFlat> style_line_edit_disabled = change_border_color(style_line_edit, dark_color_1);
 	style_line_edit_disabled->set_bg_color(Color(0, 0, 0, .1));
@@ -614,11 +608,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
 	theme->set_icon("grabber_highlight", "VSlider", theme->get_icon("GuiSliderGrabberHl", "EditorIcons"));
 
 	//RichTextLabel
-	theme->set_color("font_color", "RichTextLabel", font_color);
+	Color rtl_combined_bg_color = dark_color_1.linear_interpolate(script_bg_color, script_bg_color.a);
+	Color rtl_font_color = (rtl_combined_bg_color.r + rtl_combined_bg_color.g + rtl_combined_bg_color.b > 0.5 * 3) ? Color(0, 0, 0) : Color(1, 1, 1);
+	theme->set_color("default_color", "RichTextLabel", rtl_font_color);
 	theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox());
+	theme->set_stylebox("normal", "RichTextLabel", make_flat_stylebox(script_bg_color, 6, 6, 6, 6));
 
 	// Panel
-	theme->set_stylebox("panel", "Panel", style_panel);
+	theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4));
 
 	// Label
 	theme->set_color("font_color", "Label", font_color);

+ 14 - 2
editor/filesystem_dock.cpp

@@ -828,7 +828,12 @@ void FileSystemDock::_move_operation(const String &p_to_path) {
 	//make list of remaps
 	Map<String, String> renames;
 	String repfrom = path == "res://" ? path : String(path + "/");
-	String repto = p_to_path == "res://" ? p_to_path : String(p_to_path + "/");
+	String repto = p_to_path;
+	if (!repto.ends_with("/")) {
+		repto += "/";
+	}
+
+	print_line("reprfrom: " + repfrom + " repto " + repto);
 
 	for (int i = 0; i < move_files.size(); i++) {
 		renames[move_files[i]] = move_files[i].replace_first(repfrom, repto);
@@ -868,6 +873,13 @@ void FileSystemDock::_move_operation(const String &p_to_path) {
 		if (err != OK) {
 			EditorNode::get_singleton()->add_io_error(TTR("Error moving file:\n") + move_files[i] + "\n");
 		}
+		if (FileAccess::exists(move_files[i] + ".import")) { //move imported files too
+			//@todo should remove the files in .import folder
+			err = da->rename(move_files[i] + ".import", to + ".import");
+			if (err != OK) {
+				EditorNode::get_singleton()->add_io_error(TTR("Error moving file:\n") + move_files[i] + ".import\n");
+			}
+		}
 	}
 
 	for (int i = 0; i < move_dirs.size(); i++) {
@@ -1827,7 +1839,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
 
 	path = "res://";
 
-	add_constant_override("separation", 3);
+	add_constant_override("separation", 4);
 }
 
 FileSystemDock::~FileSystemDock() {

+ 8 - 1
editor/import/resource_importer_texture.cpp

@@ -33,7 +33,7 @@
 #include "io/config_file.h"
 #include "io/image_loader.h"
 #include "scene/resources/texture.h"
-
+#include "editor/editor_node.h"
 void ResourceImporterTexture::_texture_reimport_srgb(const Ref<StreamTexture> &p_tex) {
 
 	singleton->mutex->lock();
@@ -411,10 +411,14 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
 	if (compress_mode == COMPRESS_VIDEO_RAM) {
 		//must import in all formats, in order of priority (so platform choses the best supported one. IE, etc2 over etc).
 		//Android, GLES 2.x
+
+		bool ok_on_pc=false;
+
 		if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_s3tc")) {
 
 			_save_stex(image, p_save_path + ".s3tc.stex", compress_mode, lossy, Image::COMPRESS_S3TC, mipmaps, tex_flags, stream, detect_3d, detect_srgb, force_rgbe, detect_normal, force_normal);
 			r_platform_variants->push_back("s3tc");
+			ok_on_pc=true;
 		}
 
 		if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_etc2")) {
@@ -434,6 +438,9 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
 			r_platform_variants->push_back("pvrtc");
 		}
 
+		if (!ok_on_pc) {
+			EditorNode::add_io_error("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correcly on PC.");
+		}
 	} else {
 		//import normally
 		_save_stex(image, p_save_path + ".stex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, tex_flags, stream, detect_3d, detect_srgb, force_rgbe, detect_normal, force_normal);

+ 73 - 17
editor/plugins/canvas_item_editor_plugin.cpp

@@ -1019,6 +1019,51 @@ void CanvasItemEditor::_list_select(const Ref<InputEventMouseButton> &b) {
 	}
 }
 
+void CanvasItemEditor::_update_cursor() {
+
+	CursorShape c = CURSOR_ARROW;
+	switch (drag) {
+		case DRAG_NONE:
+			if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
+				c = CURSOR_DRAG;
+			} else {
+				switch (tool) {
+					case TOOL_MOVE:
+						c = CURSOR_MOVE;
+						break;
+					case TOOL_EDIT_PIVOT:
+						c = CURSOR_CROSS;
+						break;
+					case TOOL_PAN:
+						c = CURSOR_DRAG;
+						break;
+				}
+			}
+			break;
+		case DRAG_LEFT:
+		case DRAG_RIGHT:
+			c = CURSOR_HSIZE;
+			break;
+		case DRAG_TOP:
+		case DRAG_BOTTOM:
+			c = CURSOR_VSIZE;
+			break;
+		case DRAG_TOP_LEFT:
+		case DRAG_BOTTOM_RIGHT:
+			c = CURSOR_FDIAGSIZE;
+			break;
+		case DRAG_TOP_RIGHT:
+		case DRAG_BOTTOM_LEFT:
+			c = CURSOR_BDIAGSIZE;
+			break;
+		case DRAG_ALL:
+		case DRAG_NODE_2D:
+			c = CURSOR_MOVE;
+			break;
+	}
+	viewport->set_default_cursor_shape(c);
+}
+
 void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
 
 	{
@@ -1457,6 +1502,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
 	Ref<InputEventMouseMotion> m = p_event;
 	if (m.is_valid()) {
 		// Mouse motion event
+		_update_cursor();
 
 		if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
 			viewport->call_deferred("grab_focus");
@@ -2223,6 +2269,9 @@ void CanvasItemEditor::_notification(int p_what) {
 
 	if (p_what == NOTIFICATION_FIXED_PROCESS) {
 
+
+		EditorNode::get_singleton()->get_scene_root()->set_snap_controls_to_pixels(GLOBAL_GET("gui/common/snap_controls_to_pixels"));
+
 		List<Node *> &selection = editor_selection->get_selected_node_list();
 
 		bool all_control = true;
@@ -3562,29 +3611,31 @@ void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) cons
 				Sprite *sprite = memnew(Sprite);
 				sprite->set_texture(texture);
 				sprite->set_modulate(Color(1, 1, 1, 0.7f));
-				preview->add_child(sprite);
+				preview_node->add_child(sprite);
 				label->show();
 				label_desc->show();
 			} else {
 				if (scene.is_valid()) {
 					Node *instance = scene->instance();
 					if (instance) {
-						preview->add_child(instance);
+						preview_node->add_child(instance);
 					}
 				}
 			}
-			editor->get_scene_root()->add_child(preview);
+			editor->get_scene_root()->add_child(preview_node);
 		}
 	}
 }
 
 void CanvasItemEditorViewport::_remove_preview() {
-	if (preview->get_parent()) {
-		editor->get_scene_root()->remove_child(preview);
-		for (int i = preview->get_child_count() - 1; i >= 0; i--) {
-			Node *node = preview->get_child(i);
-			memdelete(node);
+	if (preview_node->get_parent()) {
+		for (int i = preview_node->get_child_count() - 1; i >= 0; i--) {
+			Node *node = preview_node->get_child(i);
+			node->queue_delete();
+			preview_node->remove_child(node);
 		}
+		editor->get_scene_root()->remove_child(preview_node);
+
 		label->hide();
 		label_desc->hide();
 	}
@@ -3794,11 +3845,11 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
 				break;
 			}
 			if (can_instance) {
-				if (!preview->get_parent()) { // create preview only once
+				if (!preview_node->get_parent()) { // create preview only once
 					_create_preview(files);
 				}
 				Transform2D trans = canvas->get_canvas_transform();
-				preview->set_position((p_point - trans.get_origin()) / trans.get_scale().x);
+				preview_node->set_position((p_point - trans.get_origin()) / trans.get_scale().x);
 				label->set_text(vformat(TTR("Adding %s..."), default_type));
 			}
 			return can_instance;
@@ -3820,11 +3871,16 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p
 
 	List<Node *> list = editor->get_editor_selection()->get_selected_node_list();
 	if (list.size() == 0) {
-		accept->get_ok()->set_text(TTR("OK :("));
-		accept->set_text(TTR("No parent to instance a child at."));
-		accept->popup_centered_minsize();
-		_remove_preview();
-		return;
+		Node *root_node = editor->get_edited_scene();
+		if (root_node) {
+			list.push_back(root_node);
+		} else {
+			accept->get_ok()->set_text(TTR("OK :("));
+			accept->set_text(TTR("No parent to instance a child at."));
+			accept->popup_centered_minsize();
+			_remove_preview();
+			return;
+		}
 	}
 	if (list.size() != 1) {
 		accept->get_ok()->set_text(TTR("I see.."));
@@ -3891,7 +3947,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
 	editor = p_node;
 	editor_data = editor->get_scene_tree_dock()->get_editor_data();
 	canvas = p_canvas;
-	preview = memnew(Node2D);
+	preview_node = memnew(Node2D);
 	accept = memnew(AcceptDialog);
 	editor->get_gui_base()->add_child(accept);
 
@@ -3945,5 +4001,5 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
 }
 
 CanvasItemEditorViewport::~CanvasItemEditorViewport() {
-	memdelete(preview);
+	memdelete(preview_node);
 }

+ 2 - 2
editor/plugins/canvas_item_editor_plugin.h

@@ -34,7 +34,6 @@
 #include "editor/editor_plugin.h"
 #include "scene/2d/canvas_item.h"
 #include "scene/gui/box_container.h"
-#include "scene/gui/button_group.h"
 #include "scene/gui/check_box.h"
 #include "scene/gui/label.h"
 #include "scene/gui/panel_container.h"
@@ -324,6 +323,7 @@ class CanvasItemEditor : public VBoxContainer {
 	bool updating_scroll;
 	void _update_scroll(float);
 	void _update_scrollbars();
+	void _update_cursor();
 	void incbeg(float &beg, float &end, float inc, float minsize, bool p_symmetric);
 	void incend(float &beg, float &end, float inc, float minsize, bool p_symmetric);
 
@@ -459,7 +459,7 @@ class CanvasItemEditorViewport : public Control {
 	EditorNode *editor;
 	EditorData *editor_data;
 	CanvasItemEditor *canvas;
-	Node2D *preview;
+	Node2D *preview_node;
 	AcceptDialog *accept;
 	WindowDialog *selector;
 	Label *selector_label;

+ 0 - 1
editor/plugins/collision_polygon_2d_editor_plugin.h

@@ -33,7 +33,6 @@
 #include "editor/editor_node.h"
 #include "editor/editor_plugin.h"
 #include "scene/2d/collision_polygon_2d.h"
-#include "scene/gui/button_group.h"
 #include "scene/gui/tool_button.h"
 
 /**

+ 0 - 1
editor/plugins/collision_polygon_editor_plugin.h

@@ -35,7 +35,6 @@
 #include "scene/3d/collision_polygon.h"
 #include "scene/3d/immediate_geometry.h"
 #include "scene/3d/mesh_instance.h"
-#include "scene/gui/button_group.h"
 #include "scene/gui/tool_button.h"
 
 /**

+ 4 - 3
editor/plugins/cube_grid_theme_editor_plugin.cpp

@@ -88,7 +88,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
 		if (mesh.is_null())
 			continue;
 
-		int id = p_library->find_item_name(mi->get_name());
+		int id = p_library->find_item_by_name(mi->get_name());
 		if (id < 0) {
 
 			id = p_library->get_last_unused_item_id();
@@ -111,7 +111,8 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
 			sb->get_shape_owners(&shapes);
 
 			for (List<uint32_t>::Element *E = shapes.front(); E; E = E->next()) {
-				if (sb->is_shape_owner_disabled(E->get())) continue;
+				if (sb->is_shape_owner_disabled(E->get()))
+					continue;
 
 				//Transform shape_transform = sb->shape_owner_get_transform(E->get());
 
@@ -120,7 +121,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
 				for (int k = 0; k < sb->shape_owner_get_shape_count(E->get()); k++) {
 
 					Ref<Shape> collision = sb->shape_owner_get_shape(E->get(), k);
-					if (collision.is_valid())
+					if (!collision.is_valid())
 						continue;
 					MeshLibrary::ShapeData shape_data;
 					shape_data.shape = collision;

+ 0 - 1
editor/plugins/light_occluder_2d_editor_plugin.h

@@ -33,7 +33,6 @@
 #include "editor/editor_node.h"
 #include "editor/editor_plugin.h"
 #include "scene/2d/light_occluder_2d.h"
-#include "scene/gui/button_group.h"
 #include "scene/gui/tool_button.h"
 
 /**

+ 0 - 1
editor/plugins/line_2d_editor_plugin.h

@@ -34,7 +34,6 @@
 #include "editor/editor_plugin.h"
 #include "scene/2d/line_2d.h"
 #include "scene/2d/path_2d.h"
-#include "scene/gui/button_group.h"
 #include "scene/gui/tool_button.h"
 
 class CanvasItemEditor;

+ 0 - 1
editor/plugins/navigation_polygon_editor_plugin.h

@@ -33,7 +33,6 @@
 #include "editor/editor_node.h"
 #include "editor/editor_plugin.h"
 #include "scene/2d/navigation_polygon.h"
-#include "scene/gui/button_group.h"
 #include "scene/gui/tool_button.h"
 
 /**

+ 0 - 1
editor/plugins/path_2d_editor_plugin.h

@@ -33,7 +33,6 @@
 #include "editor/editor_node.h"
 #include "editor/editor_plugin.h"
 #include "scene/2d/path_2d.h"
-#include "scene/gui/button_group.h"
 #include "scene/gui/tool_button.h"
 
 /**

+ 0 - 1
editor/plugins/polygon_2d_editor_plugin.h

@@ -33,7 +33,6 @@
 #include "editor/editor_node.h"
 #include "editor/editor_plugin.h"
 #include "scene/2d/polygon_2d.h"
-#include "scene/gui/button_group.h"
 #include "scene/gui/tool_button.h"
 
 /**

+ 19 - 8
editor/plugins/script_editor_plugin.cpp

@@ -972,6 +972,14 @@ void ScriptEditor::_menu_option(int p_option) {
 					EditorNode::get_singleton()->show_warning("Can't obtain the script for running");
 					break;
 				}
+
+				current->apply_code();
+				Error err = scr->reload(false); //hard reload script before running always
+
+				if (err != OK) {
+					EditorNode::get_singleton()->show_warning("Script failed reloading, check console for errors.");
+					return;
+				}
 				if (!scr->is_tool()) {
 
 					EditorNode::get_singleton()->show_warning("Script is not in tool mode, will not be able to run");
@@ -1149,8 +1157,6 @@ void ScriptEditor::_notification(int p_what) {
 
 		case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
 
-			tab_container->add_style_override("panel", editor->get_gui_base()->get_stylebox("ScriptPanel", "EditorStyles"));
-
 			help_search->set_icon(get_icon("HelpSearch", "EditorIcons"));
 			site_search->set_icon(get_icon("Instance", "EditorIcons"));
 			class_search->set_icon(get_icon("ClassList", "EditorIcons"));
@@ -1417,7 +1423,7 @@ void ScriptEditor::_update_script_colors() {
 			int non_zero_hist_size = (hist_size == 0) ? 1 : hist_size;
 			float v = Math::ease((edit_pass - pass) / float(non_zero_hist_size), 0.4);
 
-			script_list->set_item_custom_bg_color(i, hot_color.linear_interpolate(cold_color, v));
+			script_list->set_item_custom_fg_color(i, hot_color.linear_interpolate(cold_color, v));
 		}
 	}
 }
@@ -1539,8 +1545,14 @@ bool ScriptEditor::edit(const Ref<Script> &p_script, int p_line, int p_col, bool
 
 	bool open_dominant = EditorSettings::get_singleton()->get("text_editor/files/open_dominant_script_on_scene_change");
 
+	if (p_script->get_language()->overrides_external_editor()) {
+		Error err = p_script->get_language()->open_in_external_editor(p_script, p_line >= 0 ? p_line : 0, p_col);
+		if (err != OK)
+			ERR_PRINT("Couldn't open script in the overridden external text editor");
+		return false;
+	}
+
 	if ((debugger->get_dump_stack_script() != p_script || debugger->get_debug_with_external_editor()) &&
-			p_script->get_language()->open_in_external_editor(p_script, p_line >= 0 ? p_line : 0, p_col) == OK &&
 			p_script->get_path().is_resource_file() &&
 			bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) {
 
@@ -2210,7 +2222,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
 	members_overview->set_v_size_flags(SIZE_EXPAND_FILL);
 
 	tab_container = memnew(TabContainer);
-	tab_container->add_style_override("panel", p_editor->get_gui_base()->get_stylebox("ScriptPanel", "EditorStyles"));
 	tab_container->set_tabs_visible(false);
 	script_split->add_child(tab_container);
 
@@ -2506,9 +2517,9 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
 	EDITOR_DEF("text_editor/open_scripts/script_temperature_enabled", true);
 	EDITOR_DEF("text_editor/open_scripts/highlight_current_script", true);
 	EDITOR_DEF("text_editor/open_scripts/script_temperature_history_size", 15);
-	EDITOR_DEF("text_editor/open_scripts/script_temperature_hot_color", Color(1, 0, 0, 0.3));
-	EDITOR_DEF("text_editor/open_scripts/script_temperature_cold_color", Color(0, 0, 1, 0.3));
-	EDITOR_DEF("text_editor/open_scripts/current_script_background_color", Color(0.81, 0.81, 0.14, 0.63));
+	EDITOR_DEF("text_editor/open_scripts/script_temperature_hot_color", Color::html("ed5e5e"));
+	EDITOR_DEF("text_editor/open_scripts/script_temperature_cold_color", Color(1, 1, 1, 0.3));
+	EDITOR_DEF("text_editor/open_scripts/current_script_background_color", Color(1, 1, 1, 0.5));
 	EDITOR_DEF("text_editor/open_scripts/group_help_pages", true);
 	EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "text_editor/open_scripts/sort_scripts_by", PROPERTY_HINT_ENUM, "Name,Path"));
 	EDITOR_DEF("text_editor/open_scripts/sort_scripts_by", 0);

+ 2 - 7
editor/plugins/script_text_editor.cpp

@@ -75,14 +75,9 @@ void ScriptTextEditor::_load_theme_settings() {
 
 	text_edit->clear_colors();
 
-	/* color from color_theme or from editor color */
-
-	Color background_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0));
-	if (EDITOR_DEF("text_editor/theme/adapted_code_editor_background_color", false))
-		background_color = get_color("dark_color_1", "Editor");
-
 	/* keyword color */
-	text_edit->add_color_override("background_color", background_color);
+
+	text_edit->add_color_override("background_color", EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0)));
 	text_edit->add_color_override("completion_background_color", EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0, 0, 0, 0)));
 	text_edit->add_color_override("completion_selected_color", EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244")));
 	text_edit->add_color_override("completion_existing_color", EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf")));

+ 2 - 0
editor/plugins/shader_editor_plugin.cpp

@@ -289,6 +289,8 @@ void ShaderEditor::_editor_settings_changed() {
 	shader_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
 	shader_editor->get_text_edit()->add_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing"));
 	shader_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
+	shader_editor->get_text_edit()->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/open_scripts/smooth_scrolling"));
+	shader_editor->get_text_edit()->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/open_scripts/v_scroll_speed"));
 }
 
 void ShaderEditor::_bind_methods() {

+ 316 - 3
editor/plugins/spatial_editor_plugin.cpp

@@ -35,12 +35,15 @@
 #include "editor/editor_node.h"
 #include "editor/editor_settings.h"
 #include "editor/plugins/animation_player_editor_plugin.h"
+#include "editor/plugins/script_editor_plugin.h"
+#include "editor/script_editor_debugger.h"
 #include "editor/spatial_editor_gizmos.h"
 #include "os/keyboard.h"
 #include "print_string.h"
 #include "project_settings.h"
 #include "scene/3d/camera.h"
 #include "scene/3d/visual_instance.h"
+#include "scene/resources/packed_scene.h"
 #include "scene/resources/surface_tool.h"
 #include "sort.h"
 
@@ -77,7 +80,7 @@ void SpatialEditorViewport::_update_camera(float p_interp_delta) {
 	Transform old_transform = camera->get_global_transform();
 	Transform transform;
 
-	bool disable_interp = (Input::get_singleton()->get_mouse_button_mask() & (2 | 4)) || Input::get_singleton()->is_key_pressed(KEY_SHIFT) || Input::get_singleton()->is_key_pressed(KEY_ALT) || Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+	bool disable_interp = orthogonal || (Input::get_singleton()->get_mouse_button_mask() & (2 | 4)) || Input::get_singleton()->is_key_pressed(KEY_SHIFT) || Input::get_singleton()->is_key_pressed(KEY_ALT) || Input::get_singleton()->is_key_pressed(KEY_CONTROL);
 
 	if (p_interp_delta && !disable_interp) {
 		//interpolate
@@ -228,7 +231,7 @@ Vector3 SpatialEditorViewport::_get_camera_normal() const {
 	return -_get_camera_transform().basis.get_axis(2);
 }
 
-Vector3 SpatialEditorViewport::_get_ray(const Vector2 &p_pos) {
+Vector3 SpatialEditorViewport::_get_ray(const Vector2 &p_pos) const {
 
 	return camera->project_ray_normal(p_pos);
 }
@@ -700,6 +703,11 @@ void SpatialEditorViewport::_smouseenter() {
 		surface->grab_focus();
 }
 
+void SpatialEditorViewport::_smouseexit() {
+
+	_remove_preview();
+}
+
 void SpatialEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
 
 	_find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->get_shift());
@@ -1895,6 +1903,7 @@ void SpatialEditorViewport::_notification(int p_what) {
 		surface->connect("draw", this, "_draw");
 		surface->connect("gui_input", this, "_sinput");
 		surface->connect("mouse_entered", this, "_smouseenter");
+		surface->connect("mouse_exited", this, "_smouseexit");
 		info->add_style_override("panel", get_stylebox("panel", "Panel"));
 		preview_camera->set_icon(get_icon("Camera", "EditorIcons"));
 		_init_gizmo_instance(index);
@@ -2425,6 +2434,7 @@ void SpatialEditorViewport::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("_draw"), &SpatialEditorViewport::_draw);
 	ClassDB::bind_method(D_METHOD("_smouseenter"), &SpatialEditorViewport::_smouseenter);
+	ClassDB::bind_method(D_METHOD("_smouseexit"), &SpatialEditorViewport::_smouseexit);
 	ClassDB::bind_method(D_METHOD("_sinput"), &SpatialEditorViewport::_sinput);
 	ClassDB::bind_method(D_METHOD("_menu_option"), &SpatialEditorViewport::_menu_option);
 	ClassDB::bind_method(D_METHOD("_toggle_camera_preview"), &SpatialEditorViewport::_toggle_camera_preview);
@@ -2432,6 +2442,8 @@ void SpatialEditorViewport::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("update_transform_gizmo_view"), &SpatialEditorViewport::update_transform_gizmo_view);
 	ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &SpatialEditorViewport::_selection_result_pressed);
 	ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &SpatialEditorViewport::_selection_menu_hide);
+	ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &SpatialEditorViewport::can_drop_data_fw);
+	ClassDB::bind_method(D_METHOD("drop_data_fw"), &SpatialEditorViewport::drop_data_fw);
 
 	ADD_SIGNAL(MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport")));
 }
@@ -2481,6 +2493,293 @@ void SpatialEditorViewport::focus_selection() {
 	cursor.pos = center;
 }
 
+void SpatialEditorViewport::assign_pending_data_pointers(Spatial *p_preview_node, Rect3 *p_preview_bounds, AcceptDialog *p_accept) {
+	preview_node = p_preview_node;
+	preview_bounds = p_preview_bounds;
+	accept = p_accept;
+}
+
+Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const {
+	const float MAX_DISTANCE = 10;
+
+	Vector3 world_ray = _get_ray(p_pos);
+	Vector3 world_pos = _get_ray_pos(p_pos);
+
+	Vector<ObjectID> instances = VisualServer::get_singleton()->instances_cull_ray(world_pos, world_ray, get_tree()->get_root()->get_world()->get_scenario());
+	Set<Ref<SpatialEditorGizmo> > found_gizmos;
+
+	float closest_dist = MAX_DISTANCE;
+
+	Vector3 point = world_pos + world_ray * MAX_DISTANCE;
+	Vector3 normal = Vector3(0.0, 0.0, 0.0);
+
+	for (int i = 0; i < instances.size(); i++) {
+
+		MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(ObjectDB::get_instance(instances[i]));
+
+		if (!mesh_instance)
+			continue;
+
+		Ref<SpatialEditorGizmo> seg = mesh_instance->get_gizmo();
+
+		if ((!seg.is_valid()) || found_gizmos.has(seg)) {
+			continue;
+		}
+
+		found_gizmos.insert(seg);
+
+		int handle = -1;
+		Vector3 hit_point;
+		Vector3 hit_normal;
+		bool inters = seg->intersect_ray(camera, p_pos, hit_point, hit_normal, NULL, false);
+
+		if (!inters)
+			continue;
+
+		float dist = world_pos.distance_to(hit_point);
+
+		if (dist < 0)
+			continue;
+
+		if (dist < closest_dist) {
+			closest_dist = dist;
+			point = hit_point;
+			normal = hit_normal;
+		}
+	}
+	Vector3 center = preview_bounds->get_size() * 0.5;
+	return point + (center * normal);
+}
+
+Rect3 SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, const Rect3 p_bounds) {
+	Rect3 bounds = p_bounds;
+	for (int i = 0; i < p_parent->get_child_count(); i++) {
+		Spatial *child = Object::cast_to<Spatial>(p_parent->get_child(i));
+		if (child) {
+			MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(child);
+			if (mesh_instance) {
+				Rect3 mesh_instance_bounds = mesh_instance->get_aabb();
+				mesh_instance_bounds.position += mesh_instance->get_global_transform().origin - p_parent->get_global_transform().origin;
+				bounds.merge_with(mesh_instance_bounds);
+			}
+			bounds = _calculate_spatial_bounds(child, bounds);
+		}
+	}
+	return bounds;
+}
+
+void SpatialEditorViewport::_create_preview(const Vector<String> &files) const {
+	for (int i = 0; i < files.size(); i++) {
+		String path = files[i];
+		RES res = ResourceLoader::load(path);
+		Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
+		if (scene != NULL) {
+			if (scene.is_valid()) {
+				Node *instance = scene->instance();
+				if (instance) {
+					preview_node->add_child(instance);
+				}
+			}
+			editor->get_scene_root()->add_child(preview_node);
+		}
+	}
+	*preview_bounds = _calculate_spatial_bounds(preview_node, Rect3());
+}
+
+void SpatialEditorViewport::_remove_preview() {
+	if (preview_node->get_parent()) {
+		for (int i = preview_node->get_child_count() - 1; i >= 0; i--) {
+			Node *node = preview_node->get_child(i);
+			node->queue_delete();
+			preview_node->remove_child(node);
+		}
+		editor->get_scene_root()->remove_child(preview_node);
+	}
+}
+
+bool SpatialEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) {
+	if (p_desired_node->get_filename() == p_target_scene_path) {
+		return true;
+	}
+
+	int childCount = p_desired_node->get_child_count();
+	for (int i = 0; i < childCount; i++) {
+		Node *child = p_desired_node->get_child(i);
+		if (_cyclical_dependency_exists(p_target_scene_path, child)) {
+			return true;
+		}
+	}
+	return false;
+}
+
+bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) {
+	Ref<PackedScene> sdata = ResourceLoader::load(path);
+	if (!sdata.is_valid()) { // invalid scene
+		return false;
+	}
+
+	Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
+	if (!instanced_scene) { // error on instancing
+		return false;
+	}
+
+	if (editor->get_edited_scene()->get_filename() != "") { // cyclical instancing
+		if (_cyclical_dependency_exists(editor->get_edited_scene()->get_filename(), instanced_scene)) {
+			memdelete(instanced_scene);
+			return false;
+		}
+	}
+
+	instanced_scene->set_filename(ProjectSettings::get_singleton()->localize_path(path));
+
+	editor_data->get_undo_redo().add_do_method(parent, "add_child", instanced_scene);
+	editor_data->get_undo_redo().add_do_method(instanced_scene, "set_owner", editor->get_edited_scene());
+	editor_data->get_undo_redo().add_do_reference(instanced_scene);
+	editor_data->get_undo_redo().add_undo_method(parent, "remove_child", instanced_scene);
+
+	String new_name = parent->validate_child_name(instanced_scene);
+	ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
+	editor_data->get_undo_redo().add_do_method(sed, "live_debug_instance_node", editor->get_edited_scene()->get_path_to(parent), path, new_name);
+	editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name));
+
+	Transform global_transform;
+	Spatial *parent_spatial = Object::cast_to<Spatial>(parent);
+	if (parent_spatial)
+		global_transform = parent_spatial->get_global_transform();
+
+	global_transform.origin = _get_instance_position(p_point);
+
+	editor_data->get_undo_redo().add_do_method(instanced_scene, "set_global_transform", global_transform);
+
+	return true;
+}
+
+void SpatialEditorViewport::_perform_drop_data() {
+	_remove_preview();
+
+	Vector<String> error_files;
+
+	editor_data->get_undo_redo().create_action(TTR("Create Node"));
+
+	for (int i = 0; i < selected_files.size(); i++) {
+		String path = selected_files[i];
+		RES res = ResourceLoader::load(path);
+		if (res.is_null()) {
+			continue;
+		}
+		Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
+		if (scene != NULL) {
+			bool success = _create_instance(target_node, path, drop_pos);
+			if (!success) {
+				error_files.push_back(path);
+			}
+		}
+	}
+
+	editor_data->get_undo_redo().commit_action();
+
+	if (error_files.size() > 0) {
+		String files_str;
+		for (int i = 0; i < error_files.size(); i++) {
+			files_str += error_files[i].get_file().get_basename() + ",";
+		}
+		files_str = files_str.substr(0, files_str.length() - 1);
+		accept->get_ok()->set_text(TTR("Ugh"));
+		accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str()));
+		accept->popup_centered_minsize();
+	}
+}
+
+bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
+
+	bool can_instance = false;
+
+	if (!preview_node->is_inside_tree()) {
+		Dictionary d = p_data;
+		if (d.has("type") && (String(d["type"]) == "files")) {
+			Vector<String> files = d["files"];
+
+			List<String> scene_extensions;
+			ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions);
+
+			for (int i = 0; i < files.size(); i++) {
+				if (scene_extensions.find(files[i].get_extension())) {
+					RES res = ResourceLoader::load(files[i]);
+					if (res.is_null()) {
+						continue;
+					}
+
+					String type = res->get_class();
+					if (type == "PackedScene") {
+						Ref<PackedScene> sdata = ResourceLoader::load(files[i]);
+						Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
+						if (!instanced_scene) {
+							continue;
+						}
+						memdelete(instanced_scene);
+					}
+					can_instance = true;
+					break;
+				}
+			}
+			if (can_instance) {
+				_create_preview(files);
+			}
+		}
+	} else {
+		can_instance = true;
+	}
+
+	if (can_instance) {
+		Transform global_transform = Transform(Basis(), _get_instance_position(p_point));
+		preview_node->set_global_transform(global_transform);
+	}
+
+	return can_instance;
+}
+
+void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
+	if (!can_drop_data_fw(p_point, p_data, p_from))
+		return;
+
+	bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
+
+	selected_files.clear();
+	Dictionary d = p_data;
+	if (d.has("type") && String(d["type"]) == "files") {
+		selected_files = d["files"];
+	}
+
+	List<Node *> list = editor->get_editor_selection()->get_selected_node_list();
+	if (list.size() == 0) {
+		Node *root_node = editor->get_edited_scene();
+		if (root_node) {
+			list.push_back(root_node);
+		} else {
+			accept->get_ok()->set_text(TTR("OK :("));
+			accept->set_text(TTR("No parent to instance a child at."));
+			accept->popup_centered_minsize();
+			_remove_preview();
+			return;
+		}
+	}
+	if (list.size() != 1) {
+		accept->get_ok()->set_text(TTR("I see.."));
+		accept->set_text(TTR("This operation requires a single selected node."));
+		accept->popup_centered_minsize();
+		_remove_preview();
+		return;
+	}
+
+	target_node = list[0];
+	if (is_shift && target_node != editor->get_edited_scene()) {
+		target_node = target_node->get_parent();
+	}
+	drop_pos = p_point;
+
+	_perform_drop_data();
+}
+
 SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index) {
 
 	_edit.mode = TRANSFORM_NONE;
@@ -2491,6 +2790,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
 
 	index = p_index;
 	editor = p_editor;
+	editor_data = editor->get_scene_tree_dock()->get_editor_data();
 	editor_selection = editor->get_editor_selection();
 	undo_redo = editor->get_undo_redo();
 	clicked = 0;
@@ -2509,6 +2809,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
 
 	c->add_child(viewport);
 	surface = memnew(Control);
+	surface->set_drag_forwarding(this);
 	add_child(surface);
 	surface->set_area_as_parent_rect();
 	surface->set_clip_contents(true);
@@ -2573,9 +2874,10 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
 	preview_camera->hide();
 	preview_camera->connect("toggled", this, "_toggle_camera_preview");
 	previewing = NULL;
-	preview = NULL;
 	gizmo_scale = 1.0;
 
+	preview_node = NULL;
+
 	info = memnew(PanelContainer);
 	info->set_self_modulate(Color(1, 1, 1, 0.4));
 	surface->add_child(info);
@@ -2583,6 +2885,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
 	info->add_child(info_label);
 	info->hide();
 
+	accept = NULL;
+
 	freelook_active = false;
 
 	selection_menu = memnew(PopupMenu);
@@ -4000,6 +4304,10 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
 	vs = memnew(VSeparator);
 	hbc_menu->add_child(vs);
 
+	// Drag and drop support;
+	preview_node = memnew(Spatial);
+	preview_bounds = Rect3();
+
 	ED_SHORTCUT("spatial_editor/bottom_view", TTR("Bottom View"), KEY_MASK_ALT + KEY_KP_7);
 	ED_SHORTCUT("spatial_editor/top_view", TTR("Top View"), KEY_KP_7);
 	ED_SHORTCUT("spatial_editor/rear_view", TTR("Rear View"), KEY_MASK_ALT + KEY_KP_1);
@@ -4044,6 +4352,9 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
 
 	p = view_menu->get_popup();
 
+	accept = memnew(AcceptDialog);
+	editor->get_gui_base()->add_child(accept);
+
 	p->add_check_shortcut(ED_SHORTCUT("spatial_editor/1_viewport", TTR("1 Viewport"), KEY_MASK_CMD + KEY_1), MENU_VIEW_USE_1_VIEWPORT);
 	p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports", TTR("2 Viewports"), KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS);
 	p->add_check_shortcut(ED_SHORTCUT("spatial_editor/2_viewports_alt", TTR("2 Viewports (Alt)"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_2), MENU_VIEW_USE_2_VIEWPORTS_ALT);
@@ -4078,6 +4389,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
 
 		viewports[i] = memnew(SpatialEditorViewport(this, editor, i));
 		viewports[i]->connect("toggle_maximize_view", this, "_toggle_maximize_view");
+		viewports[i]->assign_pending_data_pointers(preview_node, &preview_bounds, accept);
 		viewport_base->add_child(viewports[i]);
 	}
 	//vbc->add_child(viewport_base);
@@ -4212,6 +4524,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
 }
 
 SpatialEditor::~SpatialEditor() {
+	memdelete(preview_node);
 }
 
 void SpatialEditorPlugin::make_visible(bool p_visible) {

+ 34 - 1
editor/plugins/spatial_editor_plugin.h

@@ -106,7 +106,16 @@ private:
 	void _menu_option(int p_option);
 	Size2 prev_size;
 
+	Spatial *preview_node;
+	Rect3 *preview_bounds;
+	Vector<String> selected_files;
+	AcceptDialog *accept;
+
+	Node *target_node;
+	Point2 drop_pos;
+
 	EditorNode *editor;
+	EditorData *editor_data;
 	EditorSelection *editor_selection;
 	UndoRedo *undo_redo;
 
@@ -143,7 +152,7 @@ private:
 	ObjectID _select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle = NULL, bool p_alt_select = false);
 	void _find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select = false);
 	Vector3 _get_ray_pos(const Vector2 &p_pos) const;
-	Vector3 _get_ray(const Vector2 &p_pos);
+	Vector3 _get_ray(const Vector2 &p_pos) const;
 	Point2 _point_to_screen(const Vector3 &p_point);
 	Transform _get_camera_transform() const;
 	int get_selected_count() const;
@@ -250,6 +259,7 @@ private:
 	void _draw();
 
 	void _smouseenter();
+	void _smouseexit();
 	void _sinput(const Ref<InputEvent> &p_event);
 	void _update_freelook(real_t delta);
 	SpatialEditor *spatial_editor;
@@ -266,6 +276,17 @@ private:
 	void _list_select(Ref<InputEventMouseButton> b);
 	Point2i _get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const;
 
+	Vector3 _get_instance_position(const Point2 &p_pos) const;
+	static Rect3 _calculate_spatial_bounds(const Spatial *p_parent, const Rect3 p_bounds);
+	void _create_preview(const Vector<String> &files) const;
+	void _remove_preview();
+	bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
+	bool _create_instance(Node *parent, String &path, const Point2 &p_point);
+	void _perform_drop_data();
+
+	bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
+	void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
+
 protected:
 	void _notification(int p_what);
 	static void _bind_methods();
@@ -281,6 +302,11 @@ public:
 
 	void focus_selection();
 
+	void assign_pending_data_pointers(
+			Spatial *p_preview_node,
+			Rect3 *p_preview_bounds,
+			AcceptDialog *p_accept);
+
 	Viewport *get_viewport_node() { return viewport; }
 
 	SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index);
@@ -396,6 +422,10 @@ private:
 	Ref<SpatialMaterial> indicator_mat;
 	Ref<SpatialMaterial> cursor_material;
 
+	// Scene drag and drop support
+	Spatial *preview_node;
+	Rect3 preview_bounds;
+
 	/*
 	struct Selected {
 		AABB aabb;
@@ -442,6 +472,8 @@ private:
 	MenuButton *transform_menu;
 	MenuButton *view_menu;
 
+	AcceptDialog *accept;
+
 	ConfirmationDialog *snap_dialog;
 	ConfirmationDialog *xform_dialog;
 	ConfirmationDialog *settings_dialog;
@@ -559,6 +591,7 @@ public:
 	Camera *get_camera() { return NULL; }
 	void edit(Spatial *p_spatial);
 	void clear();
+
 	SpatialEditor(EditorNode *p_editor);
 	~SpatialEditor();
 };

+ 14 - 0
editor/plugins/sprite_frames_editor_plugin.cpp

@@ -244,8 +244,22 @@ void SpriteFramesEditor::_down_pressed() {
 
 void SpriteFramesEditor::_delete_pressed() {
 
+	ERR_FAIL_COND(!frames->has_animation(edited_anim));
+
 	if (tree->get_current() < 0)
 		return;
+
+	int to_delete = tree->get_current();
+	if (to_delete < 0 || to_delete >= frames->get_frame_count(edited_anim)) {
+		return;
+	}
+
+	undo_redo->create_action(TTR("Delete Resource"));
+	undo_redo->add_do_method(frames, "remove_frame", edited_anim, to_delete);
+	undo_redo->add_undo_method(frames, "add_frame", edited_anim, frames->get_frame(edited_anim, to_delete), to_delete);
+	undo_redo->add_do_method(this, "_update_library");
+	undo_redo->add_undo_method(this, "_update_library");
+	undo_redo->commit_action();
 }
 
 void SpriteFramesEditor::_animation_select() {

+ 0 - 1
editor/plugins/theme_editor_plugin.h

@@ -30,7 +30,6 @@
 #ifndef THEME_EDITOR_PLUGIN_H
 #define THEME_EDITOR_PLUGIN_H
 
-#include "scene/gui/button_group.h"
 #include "scene/gui/check_box.h"
 #include "scene/gui/file_dialog.h"
 #include "scene/gui/option_button.h"

+ 46 - 21
editor/project_settings_editor.cpp

@@ -182,8 +182,8 @@ void ProjectSettingsEditor::_device_input_add() {
 	Ref<InputEvent> ie;
 	String name = add_at;
 	int idx = edit_idx;
-	Variant old_val = ProjectSettings::get_singleton()->get(name);
-	Array arr = old_val;
+	Array old_val = ProjectSettings::get_singleton()->get(name);
+	Array arr = old_val.duplicate();
 
 	switch (add_type) {
 
@@ -285,8 +285,8 @@ void ProjectSettingsEditor::_press_a_key_confirm() {
 	String name = add_at;
 	int idx = edit_idx;
 
-	Variant old_val = ProjectSettings::get_singleton()->get(name);
-	Array arr = old_val;
+	Array old_val = ProjectSettings::get_singleton()->get(name);
+	Array arr = old_val.duplicate();
 
 	for (int i = 0; i < arr.size(); i++) {
 
@@ -700,6 +700,8 @@ void ProjectSettingsEditor::_update_actions() {
 			action->set_meta("__input", ie);
 		}
 	}
+
+	_action_check(action_name->get_text());
 }
 
 void ProjectSettingsEditor::popup_project_settings() {
@@ -809,28 +811,41 @@ void ProjectSettingsEditor::_item_del() {
 	undo_redo->commit_action();
 }
 
-void ProjectSettingsEditor::_action_adds(String) {
+void ProjectSettingsEditor::_action_check(String p_action) {
 
-	_action_add();
-}
+	if (p_action == "") {
 
-void ProjectSettingsEditor::_action_add() {
+		action_add->set_disabled(true);
+	} else {
 
-	String action = action_name->get_text();
-	if (action.find("/") != -1 || action.find(":") != -1 || action == "") {
-		message->set_text(TTR("Invalid action (anything goes but '/' or ':')."));
-		message->popup_centered(Size2(300, 100) * EDSCALE);
-		return;
+		if (p_action.find("/") != -1 || p_action.find(":") != -1) {
+			action_add->set_text(TTR("Can't contain '/' or ':'"));
+			action_add->set_disabled(true);
+			return;
+		}
+		if (ProjectSettings::get_singleton()->has("input/" + p_action)) {
+			action_add->set_text(TTR("Already existing"));
+			action_add->set_disabled(true);
+			return;
+		}
+
+		action_add->set_disabled(false);
 	}
 
-	if (ProjectSettings::get_singleton()->has("input/" + action)) {
-		message->set_text(vformat(TTR("Action '%s' already exists!"), action));
-		message->popup_centered(Size2(300, 100) * EDSCALE);
-		return;
+	action_add->set_text(TTR("Add"));
+}
+
+void ProjectSettingsEditor::_action_adds(String) {
+
+	if (!action_add->is_disabled()) {
+		_action_add();
 	}
+}
+
+void ProjectSettingsEditor::_action_add() {
 
 	Array va;
-	String name = "input/" + action;
+	String name = "input/" + action_name->get_text();
 	undo_redo->create_action(TTR("Add Input Action Event"));
 	undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, va);
 	undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name);
@@ -854,6 +869,7 @@ void ProjectSettingsEditor::_action_add() {
 		return;
 	r->select(0);
 	input_editor->ensure_cursor_is_visible();
+	action_add->set_text(TTR("Add"));
 }
 
 void ProjectSettingsEditor::_item_checked(const String &p_item, bool p_check) {
@@ -1321,6 +1337,11 @@ void ProjectSettingsEditor::set_plugins_page() {
 	tab_container->set_current_tab(plugin_settings->get_index());
 }
 
+TabContainer *ProjectSettingsEditor::get_tabs() {
+
+	return tab_container;
+}
+
 void ProjectSettingsEditor::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("_item_selected"), &ProjectSettingsEditor::_item_selected);
@@ -1331,6 +1352,7 @@ void ProjectSettingsEditor::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("_save"), &ProjectSettingsEditor::_save);
 	ClassDB::bind_method(D_METHOD("_action_add"), &ProjectSettingsEditor::_action_add);
 	ClassDB::bind_method(D_METHOD("_action_adds"), &ProjectSettingsEditor::_action_adds);
+	ClassDB::bind_method(D_METHOD("_action_check"), &ProjectSettingsEditor::_action_check);
 	ClassDB::bind_method(D_METHOD("_action_selected"), &ProjectSettingsEditor::_action_selected);
 	ClassDB::bind_method(D_METHOD("_action_edited"), &ProjectSettingsEditor::_action_edited);
 	ClassDB::bind_method(D_METHOD("_action_activated"), &ProjectSettingsEditor::_action_activated);
@@ -1361,6 +1383,8 @@ void ProjectSettingsEditor::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("_toggle_search_bar"), &ProjectSettingsEditor::_toggle_search_bar);
 
 	ClassDB::bind_method(D_METHOD("_copy_to_platform_about_to_show"), &ProjectSettingsEditor::_copy_to_platform_about_to_show);
+
+	ClassDB::bind_method(D_METHOD("get_tabs"), &ProjectSettingsEditor::get_tabs);
 }
 
 ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
@@ -1475,9 +1499,8 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
 	get_ok()->set_text(TTR("Close"));
 	set_hide_on_ok(true);
 
-	message = memnew(ConfirmationDialog);
+	message = memnew(AcceptDialog);
 	add_child(message);
-	message->set_hide_on_ok(true);
 
 	Control *input_base = memnew(Control);
 	input_base->set_name(TTR("Input Map"));
@@ -1493,7 +1516,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
 
 	l = memnew(Label);
 	vbc->add_child(l);
-	l->set_position(Point2(6, 5) * EDSCALE);
 	l->set_text(TTR("Action:"));
 
 	hbc = memnew(HBoxContainer);
@@ -1503,12 +1525,15 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
 	action_name->set_h_size_flags(SIZE_EXPAND_FILL);
 	hbc->add_child(action_name);
 	action_name->connect("text_entered", this, "_action_adds");
+	action_name->connect("text_changed", this, "_action_check");
 
 	add = memnew(Button);
 	hbc->add_child(add);
 	add->set_custom_minimum_size(Size2(150, 0) * EDSCALE);
 	add->set_text(TTR("Add"));
+	add->set_disabled(true);
 	add->connect("pressed", this, "_action_add");
+	action_add = add;
 
 	input_editor = memnew(Tree);
 	vbc->add_child(input_editor);

+ 5 - 1
editor/project_settings_editor.h

@@ -66,7 +66,7 @@ class ProjectSettingsEditor : public AcceptDialog {
 	ToolButton *clear_button;
 
 	HBoxContainer *add_prop_bar;
-	ConfirmationDialog *message;
+	AcceptDialog *message;
 	LineEdit *category;
 	LineEdit *property;
 	OptionButton *type;
@@ -80,6 +80,7 @@ class ProjectSettingsEditor : public AcceptDialog {
 	MenuButton *popup_copy_to_feature;
 
 	LineEdit *action_name;
+	Button *action_add;
 	Tree *input_editor;
 	bool setting;
 	bool updating_translations;
@@ -108,6 +109,7 @@ class ProjectSettingsEditor : public AcceptDialog {
 	void _add_item(int p_item, Ref<InputEvent> p_exiting_event = NULL);
 	void _edit_item(Ref<InputEvent> p_exiting_event);
 
+	void _action_check(String p_action);
 	void _action_adds(String);
 	void _action_add();
 	void _device_input_add();
@@ -159,6 +161,8 @@ public:
 	void popup_project_settings();
 	void set_plugins_page();
 
+	TabContainer *get_tabs();
+
 	void queue_save();
 
 	ProjectSettingsEditor(EditorData *p_data);

+ 35 - 17
editor/quick_open.cpp

@@ -171,33 +171,50 @@ void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd, Vector<Pair<Str
 			Pair<String, Ref<Texture> > pair;
 			pair.first = file;
 			pair.second = get_icon((has_icon(efsd->get_file_type(i), ei) ? efsd->get_file_type(i) : ot), ei);
+			list.push_back(pair);
+		}
+	}
+
+	if (add_directories) {
+		for (int i = 0; i < efsd->get_subdir_count(); i++) {
 
-			if (search_text != String() && list.size() > 0) {
+			_parse_fs(efsd->get_subdir(i), list);
+		}
+	}
+}
 
-				float this_sim = _path_cmp(search_text, file);
-				float other_sim = _path_cmp(list[0].first, file);
-				int pos = 1;
+Vector<Pair<String, Ref<Texture> > > EditorQuickOpen::_sort_fs(Vector<Pair<String, Ref<Texture> > > &list) {
 
-				while (pos < list.size() && this_sim <= other_sim) {
-					other_sim = _path_cmp(list[pos++].first, file);
-				}
+	String search_text = search_box->get_text();
+	Vector<Pair<String, Ref<Texture> > > sorted_list;
 
-				pos = this_sim >= other_sim ? pos - 1 : pos;
-				list.insert(pos, pair);
+	if (search_text == String() || list.size() == 0)
+		return sorted_list;
 
-			} else {
+	Vector<float> scores;
+	scores.resize(list.size());
+	for (int i = 0; i < list.size(); i++)
+		scores[i] = _path_cmp(search_text, list[i].first);
 
-				list.push_back(pair);
-			}
-		}
-	}
+	while (list.size() > 0) {
 
-	if (add_directories) {
-		for (int i = 0; i < efsd->get_subdir_count(); i++) {
+		float best_score = 0.0f;
+		int best_idx = 0;
 
-			_parse_fs(efsd->get_subdir(i), list);
+		for (int i = 0; i < list.size(); i++) {
+			float current_score = scores[i];
+			if (current_score > best_score) {
+				best_score = current_score;
+				best_idx = i;
+			}
 		}
+
+		sorted_list.push_back(list[best_idx]);
+		list.remove(best_idx);
+		scores.remove(best_idx);
 	}
+
+	return sorted_list;
 }
 
 void EditorQuickOpen::_update_search() {
@@ -208,6 +225,7 @@ void EditorQuickOpen::_update_search() {
 	Vector<Pair<String, Ref<Texture> > > list;
 
 	_parse_fs(efsd, list);
+	list = _sort_fs(list);
 
 	for (int i = 0; i < list.size(); i++) {
 		TreeItem *ti = search_options->create_item(root);

+ 1 - 0
editor/quick_open.h

@@ -49,6 +49,7 @@ class EditorQuickOpen : public ConfirmationDialog {
 
 	void _sbox_input(const Ref<InputEvent> &p_ie);
 	void _parse_fs(EditorFileSystemDirectory *efsd, Vector<Pair<String, Ref<Texture> > > &list);
+	Vector<Pair<String, Ref<Texture> > > _sort_fs(Vector<Pair<String, Ref<Texture> > > &list);
 	float _path_cmp(String search, String path) const;
 
 	void _confirmed();

+ 1 - 1
editor/settings_config_dialog.cpp

@@ -165,7 +165,7 @@ void EditorSettingsDialog::_update_shortcuts() {
 			section->set_custom_bg_color(1, get_color("prop_subsection", "Editor"));
 		}
 
-		if (shortcut_filter.is_subsequence_ofi(sc->get_name())) {
+		if (shortcut_filter.is_subsequence_ofi(sc->get_name()) || shortcut_filter.is_subsequence_ofi(sc->get_as_text())) {
 			TreeItem *item = shortcuts->create_item(section);
 
 			item->set_text(0, sc->get_name());

+ 6 - 0
main/main.cpp

@@ -1325,6 +1325,7 @@ bool Main::start() {
 			int shadow_atlas_q2_subdiv = GLOBAL_GET("rendering/quality/shadow_atlas/quadrant_2_subdiv");
 			int shadow_atlas_q3_subdiv = GLOBAL_GET("rendering/quality/shadow_atlas/quadrant_3_subdiv");
 
+
 			sml->get_root()->set_shadow_atlas_size(shadow_atlas_size);
 			sml->get_root()->set_shadow_atlas_quadrant_subdiv(0, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q0_subdiv));
 			sml->get_root()->set_shadow_atlas_quadrant_subdiv(1, Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q1_subdiv));
@@ -1333,6 +1334,9 @@ bool Main::start() {
 			Viewport::Usage usage = Viewport::Usage(int(GLOBAL_GET("rendering/quality/intended_usage/framebuffer_allocation")));
 			sml->get_root()->set_usage(usage);
 
+			bool snap_controls = GLOBAL_DEF("gui/common/snap_controls_to_pixels", true);
+			sml->get_root()->set_snap_controls_to_pixels(snap_controls);
+
 		} else {
 			GLOBAL_DEF("display/window/stretch/mode", "disabled");
 			ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/mode", PropertyInfo(Variant::STRING, "display/window/stretch/mode", PROPERTY_HINT_ENUM, "disabled,2d,viewport"));
@@ -1342,6 +1346,8 @@ bool Main::start() {
 			ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/shrink", PropertyInfo(Variant::STRING, "display/window/stretch/shrink", PROPERTY_HINT_RANGE, "1,8,1"));
 			sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true));
 			sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true));
+			GLOBAL_DEF("gui/common/snap_controls_to_pixels", true);
+
 		}
 
 		String local_game_path;

+ 1 - 2
modules/etc/image_etc.cpp

@@ -37,7 +37,6 @@
 
 static Image::Format _get_etc2_mode(Image::DetectChannels format) {
 	switch (format) {
-		case Image::DETECTED_L:
 		case Image::DETECTED_R:
 			return Image::FORMAT_ETC2_R11;
 
@@ -47,7 +46,7 @@ static Image::Format _get_etc2_mode(Image::DetectChannels format) {
 		case Image::DETECTED_RGB:
 			return Image::FORMAT_ETC2_RGB8;
 
-		case Image::DETECTED_RGBA:
+		default:
 			return Image::FORMAT_ETC2_RGBA8;
 
 			// TODO: would be nice if we could use FORMAT_ETC2_RGB8A1 for FORMAT_RGBA5551

+ 8 - 4
modules/gdnative/SCsub

@@ -2,12 +2,16 @@
 
 Import('env')
 
-env.add_source_files(env.modules_sources, "*.cpp")
-env.add_source_files(env.modules_sources, "godot/*.cpp")
+gdn_env = env.Clone()
 
-env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN'])
-env.Append(CPPPATH=['#modules/gdnative/'])
+gdn_env.add_source_files(env.modules_sources, "*.cpp")
+gdn_env.add_source_files(env.modules_sources, "gdnative/*.cpp")
+gdn_env.add_source_files(env.modules_sources, "nativescript/*.cpp")
+
+gdn_env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN'])
+gdn_env.Append(CPPPATH=['#modules/gdnative/include/'])
 
 if "platform" in env and env["platform"] == "x11": # there has to be a better solution?
     env.Append(LINKFLAGS=["-rdynamic"])
+
 env.use_ptrcall = True

+ 5 - 1
modules/gdnative/gdnative.cpp

@@ -100,6 +100,11 @@ GDNativeLibrary::~GDNativeLibrary() {
 void GDNativeLibrary::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_library_path", "platform", "path"), &GDNativeLibrary::set_library_path);
 	ClassDB::bind_method(D_METHOD("get_library_path", "platform"), &GDNativeLibrary::get_library_path);
+
+	ClassDB::bind_method(D_METHOD("is_singleton_gdnative"), &GDNativeLibrary::is_singleton_gdnative);
+	ClassDB::bind_method(D_METHOD("set_singleton_gdnative", "singleton"), &GDNativeLibrary::set_singleton_gdnative);
+
+	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "singleton_gdnative"), "set_singleton_gdnative", "is_singleton_gdnative");
 }
 
 bool GDNativeLibrary::_set(const StringName &p_name, const Variant &p_value) {
@@ -175,7 +180,6 @@ GDNative::GDNative() {
 }
 
 GDNative::~GDNative() {
-	// TODO(karroffel): implement ALL the things!
 }
 
 extern "C" void _api_anchor();

+ 6 - 1
modules/gdnative/gdnative.h

@@ -35,7 +35,7 @@
 #include "os/thread_safe.h"
 #include "resource.h"
 
-#include <godot/gdnative.h>
+#include "gdnative/gdnative.h"
 
 class GDNativeLibrary : public Resource {
 	GDCLASS(GDNativeLibrary, Resource)
@@ -77,6 +77,8 @@ class GDNativeLibrary : public Resource {
 
 	String library_paths[NUM_PLATFORMS];
 
+	bool singleton_gdnative = false;
+
 protected:
 	bool _set(const StringName &p_name, const Variant &p_value);
 	bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -92,6 +94,9 @@ public:
 	String get_library_path(StringName p_platform) const;
 
 	String get_active_library_path() const;
+
+	_FORCE_INLINE_ bool is_singleton_gdnative() const { return singleton_gdnative; }
+	_FORCE_INLINE_ void set_singleton_gdnative(bool p_singleton) { singleton_gdnative = p_singleton; }
 };
 
 typedef godot_variant (*native_call_cb)(void *, godot_string *, godot_array *);

+ 1 - 1
modules/gdnative/godot/array.cpp → modules/gdnative/gdnative/array.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/array.h>
+#include "gdnative/array.h"
 
 #include "core/array.h"
 #include "core/os/memory.h"

+ 1 - 1
modules/gdnative/godot/basis.cpp → modules/gdnative/gdnative/basis.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/basis.h>
+#include "gdnative/basis.h"
 
 #include "core/math/matrix3.h"
 #include "core/variant.h"

+ 1 - 1
modules/gdnative/godot/color.cpp → modules/gdnative/gdnative/color.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/color.h>
+#include "gdnative/color.h"
 
 #include "core/color.h"
 #include "core/variant.h"

+ 1 - 1
modules/gdnative/godot/dictionary.cpp → modules/gdnative/gdnative/dictionary.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/dictionary.h>
+#include "gdnative/dictionary.h"
 
 #include "core/variant.h"
 // core/variant.h before to avoid compile errors with MSVC

+ 1 - 2
modules/gdnative/godot/gdnative.cpp → modules/gdnative/gdnative/gdnative.cpp

@@ -27,11 +27,10 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/gdnative.h>
+#include "gdnative/gdnative.h"
 
 #include "class_db.h"
 #include "error_macros.h"
-#include "gdnative.h"
 #include "global_constants.h"
 #include "os/os.h"
 #include "project_settings.h"

+ 1 - 1
modules/gdnative/godot/node_path.cpp → modules/gdnative/gdnative/node_path.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/node_path.h>
+#include "gdnative/node_path.h"
 
 #include "core/node_path.h"
 #include "core/variant.h"

+ 1 - 1
modules/gdnative/godot/plane.cpp → modules/gdnative/gdnative/plane.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/plane.h>
+#include "gdnative/plane.h"
 
 #include "core/math/plane.h"
 #include "core/variant.h"

+ 1 - 1
modules/gdnative/godot/pool_arrays.cpp → modules/gdnative/gdnative/pool_arrays.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/pool_arrays.h>
+#include "gdnative/pool_arrays.h"
 
 #include "array.h"
 #include "core/variant.h"

+ 1 - 1
modules/gdnative/godot/quat.cpp → modules/gdnative/gdnative/quat.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/quat.h>
+#include "gdnative/quat.h"
 
 #include "core/math/quat.h"
 #include "core/variant.h"

+ 1 - 1
modules/gdnative/godot/rect2.cpp → modules/gdnative/gdnative/rect2.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/rect2.h>
+#include "gdnative/rect2.h"
 
 #include "core/math/math_2d.h"
 #include "core/variant.h"

+ 1 - 1
modules/gdnative/godot/rect3.cpp → modules/gdnative/gdnative/rect3.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/rect3.h>
+#include "gdnative/rect3.h"
 
 #include "core/math/rect3.h"
 #include "core/variant.h"

+ 1 - 1
modules/gdnative/godot/rid.cpp → modules/gdnative/gdnative/rid.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/rid.h>
+#include "gdnative/rid.h"
 
 #include "core/resource.h"
 #include "core/rid.h"

+ 1 - 1
modules/gdnative/godot/string.cpp → modules/gdnative/gdnative/string.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/string.h>
+#include "gdnative/string.h"
 
 #include "core/variant.h"
 #include "string_db.h"

+ 1 - 1
modules/gdnative/godot/transform.cpp → modules/gdnative/gdnative/transform.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/transform.h>
+#include "gdnative/transform.h"
 
 #include "core/math/transform.h"
 #include "core/variant.h"

+ 1 - 1
modules/gdnative/godot/transform2d.cpp → modules/gdnative/gdnative/transform2d.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/transform2d.h>
+#include "gdnative/transform2d.h"
 
 #include "core/math/math_2d.h"
 #include "core/variant.h"

+ 1 - 1
modules/gdnative/godot/variant.cpp → modules/gdnative/gdnative/variant.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/variant.h>
+#include "gdnative/variant.h"
 
 #include "core/variant.h"
 

+ 1 - 1
modules/gdnative/godot/vector2.cpp → modules/gdnative/gdnative/vector2.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/vector2.h>
+#include "gdnative/vector2.h"
 
 #include "core/math/math_2d.h"
 #include "core/variant.h"

+ 1 - 1
modules/gdnative/godot/vector3.cpp → modules/gdnative/gdnative/vector3.cpp

@@ -27,7 +27,7 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#include <godot/vector3.h>
+#include "gdnative/vector3.h"
 
 #include "core/variant.h"
 #include "core/vector.h"

+ 0 - 23
modules/gdnative/godot/icon.png.import

@@ -1,23 +0,0 @@
-[remap]
-
-importer="texture"
-type="StreamTexture"
-path="res://.import/icon.png-aa47d037a37fb38b3b7e7828e4eec407.stex"
-
-[params]
-
-compress/mode=0
-compress/lossy_quality=0.7
-compress/hdr_mode=0
-compress/normal_map=0
-flags/repeat=0
-flags/filter=true
-flags/mipmaps=false
-flags/anisotropic=false
-flags/srgb=2
-process/fix_alpha_border=true
-process/premult_alpha=false
-process/HDR_as_SRGB=false
-stream=false
-size_limit=0
-detect_3d=true

+ 3 - 3
modules/gdnative/godot/array.h → modules/gdnative/include/gdnative/array.h

@@ -46,10 +46,10 @@ typedef struct {
 } godot_array;
 #endif
 
-#include <godot/pool_arrays.h>
-#include <godot/variant.h>
+#include <gdnative/pool_arrays.h>
+#include <gdnative/variant.h>
 
-#include <godot/gdnative.h>
+#include <gdnative/gdnative.h>
 
 void GDAPI godot_array_new(godot_array *r_dest);
 void GDAPI godot_array_new_copy(godot_array *r_dest, const godot_array *p_src);

+ 3 - 3
modules/gdnative/godot/basis.h → modules/gdnative/include/gdnative/basis.h

@@ -45,9 +45,9 @@ typedef struct {
 } godot_basis;
 #endif
 
-#include <godot/gdnative.h>
-#include <godot/quat.h>
-#include <godot/vector3.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/quat.h>
+#include <gdnative/vector3.h>
 
 void GDAPI godot_basis_new_with_rows(godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis);
 void GDAPI godot_basis_new_with_axis_and_angle(godot_basis *r_dest, const godot_vector3 *p_axis, const godot_real p_phi);

+ 2 - 2
modules/gdnative/godot/color.h → modules/gdnative/include/gdnative/color.h

@@ -45,8 +45,8 @@ typedef struct {
 } godot_color;
 #endif
 
-#include <godot/gdnative.h>
-#include <godot/string.h>
+#include <gdnative/gdnative.h>
+#include <gdnative/string.h>
 
 void GDAPI godot_color_new_rgba(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a);
 void GDAPI godot_color_new_rgb(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b);

部分文件因为文件数量过多而无法显示