Browse Source

Merge branch 'master' of github.com:okamstudio/godot

Anton Yabchinskiy 10 years ago
parent
commit
16746f157f
100 changed files with 1174 additions and 206 deletions
  1. 69 68
      bin/tests/test_string.cpp
  2. 90 1
      core/bind/core_bind.cpp
  3. 20 0
      core/bind/core_bind.h
  4. 13 5
      core/event_queue.cpp
  5. 1 0
      core/global_constants.cpp
  6. 4 0
      core/io/file_access_pack.cpp
  7. 1 0
      core/io/file_access_pack.h
  8. 2 2
      core/math/geometry.h
  9. 1 0
      core/os/dir_access.h
  10. 22 2
      core/os/os.h
  11. 20 34
      core/ustring.cpp
  12. 1 1
      core/ustring.h
  13. 5 5
      core/variant_call.cpp
  14. 10 6
      core/variant_op.cpp
  15. BIN
      demos/2d/area_input/box_area.png
  16. BIN
      demos/2d/area_input/circle_area.png
  17. 4 0
      demos/2d/area_input/engine.cfg
  18. 16 0
      demos/2d/area_input/input.gd
  19. BIN
      demos/2d/area_input/input.scn
  20. 11 0
      demos/2d/fog_of_war/.fscache
  21. 12 0
      demos/2d/fog_of_war/engine.cfg
  22. BIN
      demos/2d/fog_of_war/floor.png
  23. 86 0
      demos/2d/fog_of_war/fog.gd
  24. BIN
      demos/2d/fog_of_war/fog.png
  25. BIN
      demos/2d/fog_of_war/fog.scn
  26. 29 0
      demos/2d/fog_of_war/fog.xml
  27. BIN
      demos/2d/fog_of_war/icon.png
  28. 1 0
      demos/2d/fog_of_war/icon.png.flags
  29. BIN
      demos/2d/fog_of_war/tile_edit.scn
  30. 43 0
      demos/2d/fog_of_war/troll.gd
  31. BIN
      demos/2d/fog_of_war/troll.png
  32. BIN
      demos/2d/fog_of_war/troll.scn
  33. 26 0
      demos/2d/hdr/beach_cave.gd
  34. BIN
      demos/2d/hdr/beach_cave.scn
  35. 13 0
      demos/2d/hdr/engine.cfg
  36. BIN
      demos/2d/hdr/ocean_beach.png
  37. 1 0
      demos/2d/hdr/ocean_beach.png.flags
  38. BIN
      demos/2d/hdr/ocean_cave.png
  39. 1 0
      demos/2d/hdr/ocean_cave.png.flags
  40. BIN
      demos/2d/isometric/dungeon.scn
  41. BIN
      demos/2d/isometric_light/cubio.scn
  42. 4 0
      demos/2d/isometric_light/engine.cfg
  43. BIN
      demos/2d/isometric_light/faceNormal.png
  44. BIN
      demos/2d/isometric_light/floor_shader.res
  45. BIN
      demos/2d/isometric_light/light2.png
  46. BIN
      demos/2d/isometric_light/map.scn
  47. BIN
      demos/2d/isometric_light/tileset_scene.scn
  48. BIN
      demos/2d/isometric_light/torch.scn
  49. BIN
      demos/2d/isometric_light/torch_light.png
  50. BIN
      demos/2d/isometric_light/wall_shader.res
  51. BIN
      demos/2d/light_mask/burano.png
  52. 8 0
      demos/2d/light_mask/engine.cfg
  53. BIN
      demos/2d/light_mask/lightmask.scn
  54. BIN
      demos/2d/light_mask/splat.png
  55. BIN
      demos/2d/lights_shadows/bg.png
  56. BIN
      demos/2d/lights_shadows/caster.png
  57. 8 0
      demos/2d/lights_shadows/engine.cfg
  58. BIN
      demos/2d/lights_shadows/light.png
  59. BIN
      demos/2d/lights_shadows/light_shadows.scn
  60. BIN
      demos/2d/lights_shadows/spot.png
  61. BIN
      demos/2d/normalmaps/diffuse.jpg
  62. BIN
      demos/2d/normalmaps/diffuse.png
  63. 4 0
      demos/2d/normalmaps/engine.cfg
  64. BIN
      demos/2d/normalmaps/light.png
  65. BIN
      demos/2d/normalmaps/normal.png
  66. BIN
      demos/2d/normalmaps/normal_material.res
  67. BIN
      demos/2d/normalmaps/normalmap.scn
  68. 14 10
      demos/2d/platformer/stage.xml
  69. BIN
      demos/2d/sdf_font/KaushanScript-Regular.otf
  70. 4 0
      demos/2d/sdf_font/engine.cfg
  71. BIN
      demos/2d/sdf_font/font.fnt
  72. BIN
      demos/2d/sdf_font/sdf.scn
  73. BIN
      demos/2d/sprite_shaders/cubio.png
  74. 4 0
      demos/2d/sprite_shaders/engine.cfg
  75. BIN
      demos/2d/sprite_shaders/sprite_shaders.scn
  76. BIN
      demos/2d/texscreen/OpenCV_Chessboard.png
  77. BIN
      demos/2d/texscreen/bubble.png
  78. 17 0
      demos/2d/texscreen/bubbles.gd
  79. BIN
      demos/2d/texscreen/bubbles.scn
  80. BIN
      demos/2d/texscreen/burano.png
  81. 4 0
      demos/2d/texscreen/engine.cfg
  82. 37 0
      demos/2d/texscreen/lens.gd
  83. BIN
      demos/2d/texscreen/lens.scn
  84. BIN
      demos/gui/drag_and_drop/drag_and_drop.scn
  85. 24 0
      demos/gui/drag_and_drop/drag_drop_script.gd
  86. 4 0
      demos/gui/drag_and_drop/engine.cfg
  87. 177 0
      demos/misc/window_management/control.gd
  88. 19 0
      demos/misc/window_management/engine.cfg
  89. BIN
      demos/misc/window_management/icon.png
  90. 1 0
      demos/misc/window_management/icon.png.flags
  91. 79 0
      demos/misc/window_management/observer/observer.gd
  92. BIN
      demos/misc/window_management/observer/observer.scn
  93. BIN
      demos/misc/window_management/window_management.scn
  94. 25 24
      demos/viewport/gui_in_3d/gui_3d.gd
  95. BIN
      demos/viewport/gui_in_3d/gui_3d.scn
  96. 26 3
      doc/base/classes.xml
  97. 1 1
      drivers/etc1/rg_etc1.cpp
  98. 199 44
      drivers/gles2/rasterizer_gles2.cpp
  99. 5 0
      drivers/gles2/rasterizer_gles2.h
  100. 8 0
      drivers/gles2/shader_compiler_gles2.cpp

+ 69 - 68
bin/tests/test_string.cpp

@@ -519,12 +519,13 @@ bool test_28() {
 	char output_format[] = "\tTest:\t%ls => %ls (%s)\n";
 	String format, output;
 	Array args;
+	bool error;
 	
 	// %%
 	format = "fish %% frog";
 	args.clear();
-	output = format.sprintf(args);
-	success = (output == String("fish % frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish % frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -534,8 +535,8 @@ bool test_28() {
 	format = "fish %d frog";
 	args.clear();
 	args.push_back(5);
-	output = format.sprintf(args);
-	success = (output == String("fish 5 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 5 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -543,8 +544,8 @@ bool test_28() {
 	format = "fish %05d frog";
 	args.clear();
 	args.push_back(5);
-	output = format.sprintf(args);
-	success = (output == String("fish 00005 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 00005 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -552,8 +553,8 @@ bool test_28() {
 	format = "fish %5d frog";
 	args.clear();
 	args.push_back(5);
-	output = format.sprintf(args);
-	success = (output == String("fish     5 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish     5 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -561,8 +562,8 @@ bool test_28() {
 	format = "fish %-5d frog";
 	args.clear();
 	args.push_back(5);
-	output = format.sprintf(args);
-	success = (output == String("fish 5     frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 5     frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -570,8 +571,8 @@ bool test_28() {
 	format = "fish %+d frog";
 	args.clear();
 	args.push_back(5);
-	output = format.sprintf(args);
-	success = (output == String("fish +5 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish +5 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -579,8 +580,8 @@ bool test_28() {
 	format = "fish %d frog";
 	args.clear();
 	args.push_back(-5);
-	output = format.sprintf(args);
-	success = (output == String("fish -5 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish -5 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -588,8 +589,8 @@ bool test_28() {
 	format = "fish %x frog";
 	args.clear();
 	args.push_back(45);
-	output = format.sprintf(args);
-	success = (output == String("fish 2d frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 2d frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -597,8 +598,8 @@ bool test_28() {
 	format = "fish %X frog";
 	args.clear();
 	args.push_back(45);
-	output = format.sprintf(args);
-	success = (output == String("fish 2D frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 2D frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -606,8 +607,8 @@ bool test_28() {
 	format = "fish %o frog";
 	args.clear();
 	args.push_back(99);
-	output = format.sprintf(args);
-	success = (output == String("fish 143 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 143 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -617,8 +618,8 @@ bool test_28() {
 	format = "fish %f frog";
 	args.clear();
 	args.push_back(99.99);
-	output = format.sprintf(args);
-	success = (output == String("fish 99.990000 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 99.990000 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -626,8 +627,8 @@ bool test_28() {
 	format = "fish %11f frog";
 	args.clear();
 	args.push_back(99.99);
-	output = format.sprintf(args);
-	success = (output == String("fish   99.990000 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish   99.990000 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -635,8 +636,8 @@ bool test_28() {
 	format = "fish %-11f frog";
 	args.clear();
 	args.push_back(99.99);
-	output = format.sprintf(args);
-	success = (output == String("fish 99.990000   frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 99.990000   frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -644,8 +645,8 @@ bool test_28() {
 	format = "fish %f frog";
 	args.clear();
 	args.push_back(99);
-	output = format.sprintf(args);
-	success = (output == String("fish 99.000000 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 99.000000 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -653,8 +654,8 @@ bool test_28() {
 	format = "fish %+f frog";
 	args.clear();
 	args.push_back(99.99);
-	output = format.sprintf(args);
-	success = (output == String("fish +99.990000 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish +99.990000 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -662,8 +663,8 @@ bool test_28() {
 	format = "fish %.1f frog";
 	args.clear();
 	args.push_back(99.99);
-	output = format.sprintf(args);
-	success = (output == String("fish 100.0 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 100.0 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -671,8 +672,8 @@ bool test_28() {
 	format = "fish %.12f frog";
 	args.clear();
 	args.push_back(99.99);
-	output = format.sprintf(args);
-	success = (output == String("fish 99.990000000000 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 99.990000000000 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -680,8 +681,8 @@ bool test_28() {
 	format = "fish %.f frog";
 	args.clear();
 	args.push_back(99.99);
-	output = format.sprintf(args);
-	success = (output == String("fish 100 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish 100 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -691,8 +692,8 @@ bool test_28() {
 	format = "fish %s frog";
 	args.clear();
 	args.push_back("cheese");
-	output = format.sprintf(args);
-	success = (output == String("fish cheese frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish cheese frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -700,8 +701,8 @@ bool test_28() {
 	format = "fish %10s frog";
 	args.clear();
 	args.push_back("cheese");
-	output = format.sprintf(args);
-	success = (output == String("fish     cheese frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish     cheese frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -709,8 +710,8 @@ bool test_28() {
 	format = "fish %-10s frog";
 	args.clear();
 	args.push_back("cheese");
-	output = format.sprintf(args);
-	success = (output == String("fish cheese     frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish cheese     frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -720,8 +721,8 @@ bool test_28() {
 	format = "fish %c frog";
 	args.clear();
 	args.push_back("A");
-	output = format.sprintf(args);
-	success = (output == String("fish A frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish A frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -729,8 +730,8 @@ bool test_28() {
 	format = "fish %c frog";
 	args.clear();
 	args.push_back(65);
-	output = format.sprintf(args);
-	success = (output == String("fish A frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish A frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -741,8 +742,8 @@ bool test_28() {
 	args.clear();
 	args.push_back(10);
 	args.push_back("cheese");
-	output = format.sprintf(args);
-	success = (output == String("fish     cheese frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish     cheese frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -751,8 +752,8 @@ bool test_28() {
 	args.clear();
 	args.push_back(10);
 	args.push_back(99);
-	output = format.sprintf(args);
-	success = (output == String("fish         99 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish         99 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -762,8 +763,8 @@ bool test_28() {
 	args.push_back(10);
 	args.push_back(3);
 	args.push_back(99.99);
-	output = format.sprintf(args);
-	success = (output == String("fish     99.990 frog"));
+	output = format.sprintf(args, &error);
+	success = (output == String("fish     99.990 frog") && !error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -773,8 +774,8 @@ bool test_28() {
 	format = "fish %s %s frog";
 	args.clear();
 	args.push_back("cheese");
-	output = format.sprintf(args);
-	success = (output == "");
+	output = format.sprintf(args, &error);
+	success = (output == "not enough arguments for format string" && error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -783,8 +784,8 @@ bool test_28() {
 	args.clear();
 	args.push_back("hello");
 	args.push_back("cheese");
-	output = format.sprintf(args);
-	success = (output == "");
+	output = format.sprintf(args, &error);
+	success = (output == "not all arguments converted during string formatting" && error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -792,8 +793,8 @@ bool test_28() {
 	format = "fish %10";
 	args.clear();
 	args.push_back("cheese");
-	output = format.sprintf(args);
-	success = (output == "");
+	output = format.sprintf(args, &error);
+	success = (output == "incomplete format" && error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -801,8 +802,8 @@ bool test_28() {
 	format = "fish %&f frog";
 	args.clear();
 	args.push_back("cheese");
-	output = format.sprintf(args);
-	success = (output == "");
+	output = format.sprintf(args, &error);
+	success = (output == "unsupported format character" && error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -810,8 +811,8 @@ bool test_28() {
 	format = "fish %2.2.2f frog";
 	args.clear();
 	args.push_back(99.99);
-	output = format.sprintf(args);
-	success = (output == "");
+	output = format.sprintf(args, &error);
+	success = (output == "too many decimal points in format" && error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -820,8 +821,8 @@ bool test_28() {
 	args.clear();
 	args.push_back("cheese");
 	args.push_back(99.99);
-	output = format.sprintf(args);
-	success = (output == "");
+	output = format.sprintf(args, &error);
+	success = (output == "* wants number" && error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -829,8 +830,8 @@ bool test_28() {
 	format = "fish %c frog";
 	args.clear();
 	args.push_back("sc");
-	output = format.sprintf(args);
-	success = (output == "");
+	output = format.sprintf(args, &error);
+	success = (output == "%c requires number or single-character string" && error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 
@@ -838,8 +839,8 @@ bool test_28() {
 	format = "fish %c frog";
 	args.clear();
 	args.push_back(Array());
-	output = format.sprintf(args);
-	success = (output == "");
+	output = format.sprintf(args, &error);
+	success = (output == "%c requires number or single-character string" && error);
 	OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL");
 	if (!success) state = false;
 

+ 90 - 1
core/bind/core_bind.cpp

@@ -176,6 +176,76 @@ bool _OS::is_video_mode_fullscreen(int p_screen) const {
 
 }
 
+
+int _OS::get_screen_count() const {
+	return OS::get_singleton()->get_screen_count();
+}
+
+int _OS::get_current_screen() const {
+	return OS::get_singleton()->get_current_screen();
+}
+
+void _OS::set_current_screen(int p_screen) {
+	OS::get_singleton()->set_current_screen(p_screen);
+}
+
+Point2 _OS::get_screen_position(int p_screen) const {
+	return OS::get_singleton()->get_screen_position(p_screen);
+}
+
+Size2 _OS::get_screen_size(int p_screen) const {
+	return OS::get_singleton()->get_screen_size(p_screen);
+}
+
+Point2 _OS::get_window_position() const {
+	return OS::get_singleton()->get_window_position();
+}
+
+void _OS::set_window_position(const Point2& p_position) {
+	OS::get_singleton()->set_window_position(p_position);
+}
+
+Size2 _OS::get_window_size() const {
+	return OS::get_singleton()->get_window_size();
+}
+
+void _OS::set_window_size(const Size2& p_size) {
+	OS::get_singleton()->set_window_size(p_size);
+}
+
+void _OS::set_window_fullscreen(bool p_enabled) {
+	OS::get_singleton()->set_window_fullscreen(p_enabled);
+}
+
+bool _OS::is_window_fullscreen() const {
+	return OS::get_singleton()->is_window_fullscreen();
+}
+
+void _OS::set_window_resizable(bool p_enabled) {
+	OS::get_singleton()->set_window_resizable(p_enabled);
+}
+
+bool _OS::is_window_resizable() const {
+	return OS::get_singleton()->is_window_resizable();
+}
+
+void _OS::set_window_minimized(bool p_enabled) {
+	OS::get_singleton()->set_window_minimized(p_enabled);
+}
+
+bool _OS::is_window_minimized() const {
+	return OS::get_singleton()->is_window_minimized();
+}
+
+void _OS::set_window_maximized(bool p_enabled) {
+	OS::get_singleton()->set_window_maximized(p_enabled);
+}
+
+bool _OS::is_window_maximized() const {
+	return OS::get_singleton()->is_window_maximized();
+}
+
+
 void _OS::set_use_file_access_save_and_swap(bool p_enable) {
 
 	FileAccess::set_backup_save(p_enable);
@@ -186,7 +256,6 @@ bool _OS::is_video_mode_resizable(int p_screen) const {
 	OS::VideoMode vm;
 	vm = OS::get_singleton()->get_video_mode(p_screen);
 	return vm.resizable;
-
 }
 
 Array _OS::get_fullscreen_mode_list(int p_screen) const {
@@ -637,6 +706,26 @@ void _OS::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0));
 	ObjectTypeDB::bind_method(_MD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0));
 
+
+	ObjectTypeDB::bind_method(_MD("get_screen_count"),&_OS::get_screen_count);
+	ObjectTypeDB::bind_method(_MD("get_current_screen"),&_OS::get_current_screen);
+	ObjectTypeDB::bind_method(_MD("set_current_screen"),&_OS::set_current_screen);
+	ObjectTypeDB::bind_method(_MD("get_screen_position"),&_OS::get_screen_position,DEFVAL(0));
+	ObjectTypeDB::bind_method(_MD("get_screen_size"),&_OS::get_screen_size,DEFVAL(0));
+	ObjectTypeDB::bind_method(_MD("get_window_position"),&_OS::get_window_position);
+	ObjectTypeDB::bind_method(_MD("set_window_position"),&_OS::set_window_position);
+	ObjectTypeDB::bind_method(_MD("get_window_size"),&_OS::get_window_size);
+	ObjectTypeDB::bind_method(_MD("set_window_size"),&_OS::set_window_size);
+	ObjectTypeDB::bind_method(_MD("set_window_fullscreen","enabled"),&_OS::set_window_fullscreen);
+	ObjectTypeDB::bind_method(_MD("is_window_fullscreen"),&_OS::is_window_fullscreen);
+	ObjectTypeDB::bind_method(_MD("set_window_resizable","enabled"),&_OS::set_window_resizable);
+	ObjectTypeDB::bind_method(_MD("is_window_resizable"),&_OS::is_window_resizable);
+	ObjectTypeDB::bind_method(_MD("set_window_minimized", "enabled"),&_OS::set_window_minimized);
+	ObjectTypeDB::bind_method(_MD("is_window_minimized"),&_OS::is_window_minimized);
+	ObjectTypeDB::bind_method(_MD("set_window_maximized", "enabled"),&_OS::set_window_maximized);
+	ObjectTypeDB::bind_method(_MD("is_window_maximized"),&_OS::is_window_maximized);
+
+
 	ObjectTypeDB::bind_method(_MD("set_iterations_per_second","iterations_per_second"),&_OS::set_iterations_per_second);
 	ObjectTypeDB::bind_method(_MD("get_iterations_per_second"),&_OS::get_iterations_per_second);
 	ObjectTypeDB::bind_method(_MD("set_target_fps","target_fps"),&_OS::set_target_fps);

+ 20 - 0
core/bind/core_bind.h

@@ -108,6 +108,26 @@ public:
 	bool is_video_mode_resizable(int p_screen=0) const;
 	Array get_fullscreen_mode_list(int p_screen=0) const;
 
+
+	virtual int get_screen_count() const;
+	virtual int get_current_screen() const;
+	virtual void set_current_screen(int p_screen);
+	virtual Point2 get_screen_position(int p_screen=0) const;
+	virtual Size2 get_screen_size(int p_screen=0) const;
+	virtual Point2 get_window_position() const;
+	virtual void set_window_position(const Point2& p_position);
+	virtual Size2 get_window_size() const;
+	virtual void set_window_size(const Size2& p_size);
+	virtual void set_window_fullscreen(bool p_enabled);
+	virtual bool is_window_fullscreen() const;
+	virtual void set_window_resizable(bool p_enabled);
+	virtual bool is_window_resizable() const;
+	virtual void set_window_minimized(bool p_enabled);
+	virtual bool is_window_minimized() const;
+	virtual void set_window_maximized(bool p_enabled);
+	virtual bool is_window_maximized() const;
+
+
 	Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
 	bool native_video_is_playing();
 	void native_video_pause();

+ 13 - 5
core/event_queue.cpp

@@ -56,28 +56,36 @@ Error EventQueue::push_call(uint32_t p_instance_ID, const StringName& p_method,
 	
 	buffer_end+=sizeof(Event);
 	
-	if (args==1) {
+	if (args>=1) {
 	
 		Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
 		buffer_end+=sizeof(Variant);
 		*v=p_arg1;
-	} else if (args==2) {
+	}
+
+	if (args>=2) {
 	
 		Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
 		buffer_end+=sizeof(Variant);
 		*v=p_arg2;
-	} else if (args==3) {
+	}
+
+	if (args>=3) {
 	
 		Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
 		buffer_end+=sizeof(Variant);
 		*v=p_arg3;
 		
-	} else if (args==4) {
+	}
+
+	if (args>=4) {
 	
 		Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
 		buffer_end+=sizeof(Variant);
 		*v=p_arg4;
-	} else if (args==5) {
+	}
+
+	if (args>=5) {
 	
 		Variant * v = memnew_placement( &event_buffer[ buffer_end ], Variant );
 		buffer_end+=sizeof(Variant);

+ 1 - 0
core/global_constants.cpp

@@ -313,6 +313,7 @@ static _GlobalConstant _global_constants[]={
 	BIND_GLOBAL_CONSTANT( KEY_MASK_ALT   ),
 	BIND_GLOBAL_CONSTANT( KEY_MASK_META   ),
 	BIND_GLOBAL_CONSTANT( KEY_MASK_CTRL   ),
+	BIND_GLOBAL_CONSTANT( KEY_MASK_CMD   ),
 	BIND_GLOBAL_CONSTANT( KEY_MASK_KPAD   ),
 	BIND_GLOBAL_CONSTANT( KEY_MASK_GROUP_SWITCH   ),
 

+ 4 - 0
core/io/file_access_pack.cpp

@@ -362,6 +362,10 @@ bool DirAccessPack::current_is_dir() const{
 
 	return cdir;
 }
+bool DirAccessPack::current_is_hidden() const{
+
+	return false;
+}
 void DirAccessPack::list_dir_end() {
 
 	list_dirs.clear();

+ 1 - 0
core/io/file_access_pack.h

@@ -208,6 +208,7 @@ public:
 	virtual bool list_dir_begin();
 	virtual String get_next();
 	virtual bool current_is_dir() const;
+	virtual bool current_is_hidden() const;
 	virtual void list_dir_end();
 
 	virtual int get_drive_count();

+ 2 - 2
core/math/geometry.h

@@ -519,9 +519,9 @@ public:
 
 	    bool s_ab = (b.x-a.x)*as_y-(b.y-a.y)*as_x > 0;
 
-	    if((c.x-a.x)*as_y-(c.y-a.y)*as_x > 0 == s_ab) return false;
+	    if(((c.x-a.x)*as_y-(c.y-a.y)*as_x > 0) == s_ab) return false;
 
-	    if((c.x-b.x)*(s.y-b.y)-(c.y-b.y)*(s.x-b.x) > 0 != s_ab) return false;
+	    if(((c.x-b.x)*(s.y-b.y)-(c.y-b.y)*(s.x-b.x) > 0) != s_ab) return false;
 
 	    return true;
 	}

+ 1 - 0
core/os/dir_access.h

@@ -78,6 +78,7 @@ public:
 	virtual String get_next(bool* p_is_dir); // compatibility
 	virtual String get_next()=0;
 	virtual bool current_is_dir() const=0;
+	virtual bool current_is_hidden() const=0;
 	
 	virtual void list_dir_end()=0; ///< 
 	

+ 22 - 2
core/os/os.h

@@ -73,7 +73,7 @@ public:
 		bool fullscreen;
 		bool resizable;
 		float get_aspect() const { return (float)width/(float)height; }
-		VideoMode(int p_width=640,int p_height=480,bool p_fullscreen=false, bool p_resizable = true) { width=p_width; height=p_height; fullscreen=p_fullscreen; resizable = p_resizable; }
+		VideoMode(int p_width=640,int p_height=480,bool p_fullscreen=false, bool p_resizable = true) {width=p_width; height=p_height; fullscreen=p_fullscreen; resizable = p_resizable; }
 	};
 protected:
 friend class Main;
@@ -149,7 +149,27 @@ public:
 	virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0)=0;
 	virtual VideoMode get_video_mode(int p_screen=0) const=0;
 	virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const=0;
-	
+
+
+	virtual int get_screen_count() const{ return 1; }
+	virtual int get_current_screen() const { return 0; }
+	virtual void set_current_screen(int p_screen) { }
+	virtual Point2 get_screen_position(int p_screen=0)  { return Point2(); }
+	virtual Size2 get_screen_size(int p_screen=0) const { return get_window_size(); }
+	virtual Point2 get_window_position() const { return Vector2(); }
+	virtual void set_window_position(const Point2& p_position) {}
+	virtual Size2 get_window_size() const=0;
+	virtual void set_window_size(const Size2 p_size){}
+	virtual void set_window_fullscreen(bool p_enabled) {}
+	virtual bool is_window_fullscreen() const { return true; }
+	virtual void set_window_resizable(bool p_enabled) {}
+	virtual bool is_window_resizable() const { return false; }
+	virtual void set_window_minimized(bool p_enabled) {}
+	virtual bool is_window_minimized() const { return false; }
+	virtual void set_window_maximized(bool p_enabled) {}
+	virtual bool is_window_maximized() const { return true; }
+
+
 	virtual void set_iterations_per_second(int p_ips);
 	virtual int get_iterations_per_second() const;
 

+ 20 - 34
core/ustring.cpp

@@ -3550,8 +3550,8 @@ String String::lpad(int min_length, const String& character) const {
 // sprintf is implemented in GDScript via:
 //   "fish %s pie" % "frog"
 //   "fish %s %d pie" % ["frog", 12]
-String String::sprintf(const Array& values) const {
-
+// In case of an error, the string returned is the error description and "error" is true.
+String String::sprintf(const Array& values, bool* error) const {
 	String formatted;
 	CharType* self = (CharType*)c_str();
 	int num_items = values.size();
@@ -3564,6 +3564,7 @@ String String::sprintf(const Array& values) const {
 	bool left_justified;
 	bool show_sign;
 
+	*error = true;
 
 	for (; *self; self++) {
 		const CharType c = *self;
@@ -3580,13 +3581,11 @@ String String::sprintf(const Array& values) const {
 				case 'x': // Hexadecimal (lowercase)
 				case 'X': { // Hexadecimal (uppercase)
 					if (value_index >= values.size()) {
-						ERR_EXPLAIN("not enough arguments for format string");
-						ERR_FAIL_V("");
+						return "not enough arguments for format string";
 					}
 
 					if (!values[value_index].is_num()) {
-						ERR_EXPLAIN("a number is required");
-						ERR_FAIL_V("");
+						return "a number is required";
 					}
 					
 					int64_t value = values[value_index];
@@ -3622,13 +3621,11 @@ String String::sprintf(const Array& values) const {
 				}
 				case 'f': { // Float
 					if (value_index >= values.size()) {
-						ERR_EXPLAIN("not enough arguments for format string");
-						ERR_FAIL_V("");
+						return "not enough arguments for format string";
 					}
 
 					if (!values[value_index].is_num()) {
-						ERR_EXPLAIN("a number is required");
-						ERR_FAIL_V("");
+						return "a number is required";
 					}
 
 					double value = values[value_index];
@@ -3657,8 +3654,7 @@ String String::sprintf(const Array& values) const {
 				}
 				case 's': { // String
 					if (value_index >= values.size()) {
-						ERR_EXPLAIN("not enough arguments for format string");
-						ERR_FAIL_V("");
+						return "not enough arguments for format string";
 					}
 
 					String str = values[value_index];
@@ -3676,8 +3672,7 @@ String String::sprintf(const Array& values) const {
 				}
 				case 'c': {
 					if (value_index >= values.size()) {
-						ERR_EXPLAIN("not enough arguments for format string");
-						ERR_FAIL_V("");
+						return "not enough arguments for format string";
 					}
 
 					// Convert to character.
@@ -3685,22 +3680,18 @@ String String::sprintf(const Array& values) const {
 					if (values[value_index].is_num()) {
 						int value = values[value_index];
 						if (value < 0) {
-							ERR_EXPLAIN("unsigned byte integer is lower than maximum")
-							ERR_FAIL_V("");
+							return "unsigned byte integer is lower than maximum";
 						} else if (value > 255) {
-							ERR_EXPLAIN("unsigned byte integer is greater than maximum")
-							ERR_FAIL_V("");
+							return "unsigned byte integer is greater than maximum";
 						}
 						str = chr(values[value_index]);
 					} else if (values[value_index].get_type() == Variant::STRING) {
 						str = values[value_index];
 						if (str.length() != 1) {
-							ERR_EXPLAIN("%c requires number or single-character string");
-							ERR_FAIL_V("");
+							return "%c requires number or single-character string";
 						}
 					} else {
-						ERR_EXPLAIN("%c requires number or single-character string");
-						ERR_FAIL_V("");
+						return "%c requires number or single-character string";
 					}
 
 					// Padding.
@@ -3741,8 +3732,7 @@ String String::sprintf(const Array& values) const {
 				}
 				case '.': { // Float separtor.
 					if (in_decimals) {
-						ERR_EXPLAIN("too many decimal points in format");
-						ERR_FAIL_V("");
+						return "too many decimal points in format";
 					}
 					in_decimals = true;
 					min_decimals = 0; // We want to add the value manually.
@@ -3751,13 +3741,11 @@ String String::sprintf(const Array& values) const {
 
 				case '*': { // Dyanmic width, based on value.
 					if (value_index >= values.size()) {
-						ERR_EXPLAIN("not enough arguments for format string");
-						ERR_FAIL_V("");
+						return "not enough arguments for format string";
 					}
 
 					if (!values[value_index].is_num()) {
-						ERR_EXPLAIN("* wants number");
-						ERR_FAIL_V("");
+						return "* wants number";
 					}
 
 					int size = values[value_index];
@@ -3773,8 +3761,7 @@ String String::sprintf(const Array& values) const {
 				}
 
 				default: {
-					ERR_EXPLAIN("unsupported format character");
-  					ERR_FAIL_V("");
+					return "unsupported format character";
   				}
 			}
 		} else { // Not in format string.
@@ -3796,14 +3783,13 @@ String String::sprintf(const Array& values) const {
 	}
 
 	if (in_format) {
-		ERR_EXPLAIN("incomplete format");
-  		ERR_FAIL_V("");
+		return "incomplete format";
 	}
 
 	if (value_index != values.size()) {
-		ERR_EXPLAIN("not all arguments converted during string formatting");
-  		ERR_FAIL_V("");
+		return "not all arguments converted during string formatting";
 	}
 
+	*error = false;
 	return formatted;
 }

+ 1 - 1
core/ustring.h

@@ -130,7 +130,7 @@ public:
 	String pad_zeros(int p_digits) const;
 	String lpad(int min_length,const String& character=" ") const;
 	String rpad(int min_length,const String& character=" ") const;
-	String sprintf(const Array& values) const;
+	String sprintf(const Array& values, bool* error) const;
 	static String num(double p_num,int p_decimals=-1);
 	static String num_scientific(double p_num);
 	static String num_real(double p_num);

+ 5 - 5
core/variant_call.cpp

@@ -511,7 +511,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
 	VCALL_LOCALMEM1(ColorArray,append_array);
 
 #define VCALL_PTR0(m_type,m_method)\
-static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(); }
+static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(); }
 #define VCALL_PTR0R(m_type,m_method)\
 static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(); }
 #define VCALL_PTR1(m_type,m_method)\
@@ -519,7 +519,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
 #define VCALL_PTR1R(m_type,m_method)\
 static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0]); }
 #define VCALL_PTR2(m_type,m_method)\
-static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1]); }
+static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1]); }
 #define VCALL_PTR2R(m_type,m_method)\
 static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1]); }
 #define VCALL_PTR3(m_type,m_method)\
@@ -531,7 +531,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
 #define VCALL_PTR4R(m_type,m_method)\
 static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3]); }
 #define VCALL_PTR5(m_type,m_method)\
-static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3],*p_args[4]); }
+static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3],*p_args[4]); }
 #define VCALL_PTR5R(m_type,m_method)\
 static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0],*p_args[1],*p_args[2],*p_args[3],*p_args[4]); }
 
@@ -685,7 +685,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
 	VCALL_PTR0R( InputEvent, is_pressed );
 	VCALL_PTR1R( InputEvent, is_action );
 	VCALL_PTR0R( InputEvent, is_echo );
-	//VCALL_PTR2( InputEvent, set_as_action );
+    VCALL_PTR2( InputEvent, set_as_action );
 
 	struct ConstructData {
 
@@ -1496,7 +1496,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
 	ADDFUNC0(INPUT_EVENT,BOOL,InputEvent,is_pressed,varray());
 	ADDFUNC1(INPUT_EVENT,BOOL,InputEvent,is_action,STRING,"action",varray());
 	ADDFUNC0(INPUT_EVENT,BOOL,InputEvent,is_echo,varray());
-	//ADDFUNC2(INPUT_EVENT,NIL,InputEvent,set_as_action,STRING,"action",BOOL,"pressed",varray());
+    ADDFUNC2(INPUT_EVENT,NIL,InputEvent,set_as_action,STRING,"action",BOOL,"pressed",varray());
 
 	/* REGISTER CONSTRUCTORS */
 

+ 10 - 6
core/variant_op.cpp

@@ -741,18 +741,22 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
 				_RETURN( p_a._data._int % p_b._data._int );
 				
 			} else if (p_a.type==STRING) {
-				const String *str=reinterpret_cast<const String*>(p_a._data._mem);
+				const String* format=reinterpret_cast<const String*>(p_a._data._mem);
 
+				String result;
+				bool error;
 				if (p_b.type==ARRAY) {
 					// e.g. "frog %s %d" % ["fish", 12]
-					const Array *arr=reinterpret_cast<const Array*>(p_b._data._mem);
-					_RETURN(str->sprintf(*arr));
+					const Array* args=reinterpret_cast<const Array*>(p_b._data._mem);
+					result=format->sprintf(*args, &error);
 				} else {
 					// e.g. "frog %d" % 12
-					Array arr;
-					arr.push_back(p_b);
-					_RETURN(str->sprintf(arr));
+					Array args;
+					args.push_back(p_b);
+					result=format->sprintf(args, &error);
 				}
+				r_valid = !error;
+				_RETURN(result);
 			}
 
 			r_valid=false;

BIN
demos/2d/area_input/box_area.png


BIN
demos/2d/area_input/circle_area.png


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

@@ -0,0 +1,4 @@
+[application]
+
+name="Area 2D Input Events"
+main_scene="res://input.scn"

+ 16 - 0
demos/2d/area_input/input.gd

@@ -0,0 +1,16 @@
+
+extends Area2D
+
+#virtual from CollisionObject2D (also available as signal)
+func _input_event(viewport, event, shape_idx):
+	#convert event to local coordinates
+	if (event.type==InputEvent.MOUSE_MOTION):
+		event = make_input_local( event )
+		get_node("label").set_text(str(event.pos))
+		
+#virtual from CollisionObject2D (also available as signal)
+func _mouse_exit():
+		get_node("label").set_text("")
+		
+
+

BIN
demos/2d/area_input/input.scn


+ 11 - 0
demos/2d/fog_of_war/.fscache

@@ -0,0 +1,11 @@
+::res://::1422910453
+floor.png::ImageTexture::1422910453::
+fog.gd::GDScript::1422910025::
+fog.png::ImageTexture::1422908128::
+fog.scn::PackedScene::1422909435::
+fog.xml::TileSet::1422909324::
+icon.png::ImageTexture::1422811193::
+tile_edit.scn::PackedScene::1422909313::
+troll.gd::GDScript::1422909940::
+troll.png::ImageTexture::1418669358::
+troll.scn::PackedScene::1418669358::

+ 12 - 0
demos/2d/fog_of_war/engine.cfg

@@ -0,0 +1,12 @@
+[application]
+
+name="Fog of War"
+main_scene="res://fog.scn"
+icon="icon.png"
+
+[input]
+
+move_up=[key(Up)]
+move_bottom=[key(Down)]
+move_left=[key(Left)]
+move_right=[key(Right)]

BIN
demos/2d/fog_of_war/floor.png


+ 86 - 0
demos/2d/fog_of_war/fog.gd

@@ -0,0 +1,86 @@
+
+extends TileMap
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+# boundarys for the fog rectangle
+var x_min = -20 # left start tile
+var x_max = 20 # right end tile
+var y_min = -20 # top start tile
+var y_max = 20 # bottom end tile
+
+var position # players position
+
+# iteration variables
+var x
+var y
+
+# variable to check if player moved
+var x_old
+var y_old
+
+# array to build up the visible area like a square
+# first value determines the width/height of the tip
+# here it would be 2*2 + 1 = 5 tiles wide/high
+# second value determines the total squares size
+# here it would be 5*2 + 1 = 10 tiles wide/high
+var l = range(2,5)
+
+# process that runs in realtime
+func _fixed_process(delta):
+	position = get_node("../troll").get_pos()
+	
+	# calculate the corresponding tile
+	# from the players position
+	x = int(position.x/get_cell_size().x)
+	# switching from positive to negative tile positions
+	# causes problems because of rounding problems
+	if position.x < 0:
+		x -= 1 # correct negative values
+	
+	y = int(position.y/get_cell_size().y)
+	if position.y < 0:
+		y -= 1
+		
+	# check if the player moved one tile further
+	if (x_old != x) or (y_old != y):
+		
+		# create the transparent part (visited area)
+		var end = l.size()-1
+		var start = 0
+		for steps in range(l.size()):
+			for m in range(x-l[end]-1,x+l[end]+2):
+				for n in range(y-l[start]-1,y+l[start]+2):
+					if get_cell(m,n) != 0:
+						set_cell(m,n,1,0,0)
+			end -= 1
+			start += 1
+	
+		# create the actual and active visible part
+		var end = l.size()-1
+		var start = 0
+		for steps in range(l.size()):
+			for m in range(x-l[end],x+l[end]+1):
+				for n in range(y-l[start],y+l[start]+1):
+					set_cell(m,n,-1)
+			end -= 1
+			start += 1
+		
+	x_old = x
+	y_old = y
+	
+	pass
+
+func _ready():
+	# Initalization here
+	
+	# create a square filled with the 100% opaque fog
+	for x in range(x_min,x_max):
+		for y in range(y_min,y_max):
+			set_cell(x,y,0,0,0)
+	set_fixed_process(true)
+	pass
+
+

BIN
demos/2d/fog_of_war/fog.png


BIN
demos/2d/fog_of_war/fog.scn


+ 29 - 0
demos/2d/fog_of_war/fog.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<resource_file type="TileSet" subresource_count="3" version="1.0" version_name="Godot Engine v1.0.stable.custom_build">
+	<ext_resource path="res://floor.png" type="Texture"></ext_resource>
+	<ext_resource path="res://fog.png" type="Texture"></ext_resource>
+	<main_resource>
+		<string name="0/name"> "fog opaque" </string>
+		<resource name="0/texture" resource_type="Texture" path="res://fog.png">  </resource>
+		<vector2 name="0/tex_offset"> -48, -48 </vector2>
+		<vector2 name="0/shape_offset"> 0, 0 </vector2>
+		<rect2 name="0/region"> 0, 0, 144, 144 </rect2>
+		<array name="0/shapes" len="0" shared="false">
+		</array>
+		<string name="1/name"> "fog transparent" </string>
+		<resource name="1/texture" resource_type="Texture" path="res://fog.png">  </resource>
+		<vector2 name="1/tex_offset"> -48, -48 </vector2>
+		<vector2 name="1/shape_offset"> 0, 0 </vector2>
+		<rect2 name="1/region"> 144, 0, 144, 144 </rect2>
+		<array name="1/shapes" len="0" shared="false">
+		</array>
+		<string name="2/name"> "floor" </string>
+		<resource name="2/texture" resource_type="Texture" path="res://floor.png">  </resource>
+		<vector2 name="2/tex_offset"> 0, 0 </vector2>
+		<vector2 name="2/shape_offset"> 0, 0 </vector2>
+		<rect2 name="2/region"> 0, 0, 0, 0 </rect2>
+		<array name="2/shapes" len="0" shared="false">
+		</array>
+
+	</main_resource>
+</resource_file>

BIN
demos/2d/fog_of_war/icon.png


+ 1 - 0
demos/2d/fog_of_war/icon.png.flags

@@ -0,0 +1 @@
+gen_mipmaps=true

BIN
demos/2d/fog_of_war/tile_edit.scn


+ 43 - 0
demos/2d/fog_of_war/troll.gd

@@ -0,0 +1,43 @@
+
+extends KinematicBody2D
+
+# This is a simple collision demo showing how
+# the kinematic cotroller works.
+# move() will allow to move the node, and will
+# always move it to a non-colliding spot, 
+# as long as it starts from a non-colliding spot too.
+
+
+#pixels / second
+const MOTION_SPEED=160
+
+func _fixed_process(delta):
+
+	var motion = Vector2()
+	
+	if (Input.is_action_pressed("move_up")):
+		motion+=Vector2(0,-1)
+	if (Input.is_action_pressed("move_bottom")):
+		motion+=Vector2(0,1)
+	if (Input.is_action_pressed("move_left")):
+		motion+=Vector2(-1,0)
+	if (Input.is_action_pressed("move_right")):
+		motion+=Vector2(1,0)
+	
+	motion = motion.normalized() * MOTION_SPEED * delta
+	motion = move(motion)
+	
+	#make character slide nicely through the world	
+	var slide_attempts = 4
+	while(is_colliding() and slide_attempts>0):
+		motion = get_collision_normal().slide(motion)
+		motion=move(motion)
+		slide_attempts-=1
+	
+
+func _ready():
+	# Initalization here
+	set_fixed_process(true)
+	pass
+
+

BIN
demos/2d/fog_of_war/troll.png


BIN
demos/2d/fog_of_war/troll.scn


+ 26 - 0
demos/2d/hdr/beach_cave.gd

@@ -0,0 +1,26 @@
+
+extends Node2D
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+const CAVE_LIMIT=1000
+
+func _input(ev):
+	if (ev.type==InputEvent.MOUSE_MOTION and ev.button_mask&1):
+		var rel_x = ev.relative_x
+		var cavepos = get_node("cave").get_pos()
+		cavepos.x+=rel_x
+		if (cavepos.x<-CAVE_LIMIT):
+			cavepos.x=-CAVE_LIMIT
+		elif (cavepos.x>0):
+			cavepos.x=0
+		get_node("cave").set_pos(cavepos)
+			
+
+func _ready():
+	set_process_input(true)
+	# Initialization here
+	pass
+
+

BIN
demos/2d/hdr/beach_cave.scn


+ 13 - 0
demos/2d/hdr/engine.cfg

@@ -0,0 +1,13 @@
+[application]
+
+name="HDR for 2D"
+main_scene="res://beach_cave.scn"
+
+[display]
+
+width=1080
+height=720
+
+[rasterizer]
+
+blur_buffer_size=128

BIN
demos/2d/hdr/ocean_beach.png


+ 1 - 0
demos/2d/hdr/ocean_beach.png.flags

@@ -0,0 +1 @@
+tolinear=true

BIN
demos/2d/hdr/ocean_cave.png


+ 1 - 0
demos/2d/hdr/ocean_cave.png.flags

@@ -0,0 +1 @@
+tolinear=true

BIN
demos/2d/isometric/dungeon.scn


BIN
demos/2d/isometric_light/cubio.scn


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

@@ -9,6 +9,10 @@ down=[key(S), key(Down)]
 left=[key(Left), key(A)]
 right=[key(Right), key(D)]
 
+[rasterizer]
+
+shadow_filter=0
+
 [render]
 
 default_clear_color=#ff000000

BIN
demos/2d/isometric_light/faceNormal.png


BIN
demos/2d/isometric_light/floor_shader.res


BIN
demos/2d/isometric_light/light2.png


BIN
demos/2d/isometric_light/map.scn


BIN
demos/2d/isometric_light/tileset_scene.scn


BIN
demos/2d/isometric_light/torch.scn


BIN
demos/2d/isometric_light/torch_light.png


BIN
demos/2d/isometric_light/wall_shader.res


BIN
demos/2d/light_mask/burano.png


+ 8 - 0
demos/2d/light_mask/engine.cfg

@@ -0,0 +1,8 @@
+[application]
+
+name="Using Lights As Mask"
+main_scene="res://lightmask.scn"
+
+[rasterizer]
+
+shadow_filter=3

BIN
demos/2d/light_mask/lightmask.scn


BIN
demos/2d/light_mask/splat.png


BIN
demos/2d/lights_shadows/bg.png


BIN
demos/2d/lights_shadows/caster.png


+ 8 - 0
demos/2d/lights_shadows/engine.cfg

@@ -0,0 +1,8 @@
+[application]
+
+name="2D Lighting"
+main_scene="res://light_shadows.scn"
+
+[rasterizer]
+
+shadow_filter=2

BIN
demos/2d/lights_shadows/light.png


BIN
demos/2d/lights_shadows/light_shadows.scn


BIN
demos/2d/lights_shadows/spot.png


BIN
demos/2d/normalmaps/diffuse.jpg


BIN
demos/2d/normalmaps/diffuse.png


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

@@ -0,0 +1,4 @@
+[application]
+
+name="2D Normal Mapping"
+main_scene="res://normalmap.scn"

BIN
demos/2d/normalmaps/light.png


BIN
demos/2d/normalmaps/normal.png


BIN
demos/2d/normalmaps/normal_material.res


BIN
demos/2d/normalmaps/normalmap.scn


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


BIN
demos/2d/sdf_font/KaushanScript-Regular.otf


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

@@ -0,0 +1,4 @@
+[application]
+
+name="Signed Distance Field Font"
+main_scene="res://sdf.scn"

BIN
demos/2d/sdf_font/font.fnt


BIN
demos/2d/sdf_font/sdf.scn


BIN
demos/2d/sprite_shaders/cubio.png


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

@@ -0,0 +1,4 @@
+[application]
+
+name="2D Shaders for Sprites"
+main_scene="res://sprite_shaders.scn"

BIN
demos/2d/sprite_shaders/sprite_shaders.scn


BIN
demos/2d/texscreen/OpenCV_Chessboard.png


BIN
demos/2d/texscreen/bubble.png


+ 17 - 0
demos/2d/texscreen/bubbles.gd

@@ -0,0 +1,17 @@
+
+extends Control
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+
+const MAX_BUBBLES=10
+
+func _ready():
+	# Initialization here
+	for i in range(MAX_BUBBLES):
+		var bubble = preload("res://lens.scn").instance()
+		add_child(bubble)
+	pass
+
+

BIN
demos/2d/texscreen/bubbles.scn


BIN
demos/2d/texscreen/burano.png


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

@@ -0,0 +1,4 @@
+[application]
+
+name="Glass Bubbles (Texscreen)"
+main_scene="res://bubbles.scn"

+ 37 - 0
demos/2d/texscreen/lens.gd

@@ -0,0 +1,37 @@
+
+extends BackBufferCopy
+
+# member variables here, example:
+# var a=2
+# var b="textvar"
+const MOTION_SPEED=150
+
+var vsize;
+var dir;
+
+func _process(delta):
+	var pos = get_pos() + dir * delta * MOTION_SPEED
+	
+	if (pos.x<0):
+		dir.x=abs(dir.x)
+	elif (pos.x>vsize.x):
+		dir.x=-abs(dir.x)
+
+	if (pos.y<0):
+		dir.y=abs(dir.y)
+	elif (pos.y>vsize.y):
+		dir.y=-abs(dir.y)
+		
+	set_pos(pos)
+
+func _ready():
+	vsize = get_viewport_rect().size
+	var pos = vsize * Vector2(randf(),randf());
+	set_pos(pos);
+	dir = Vector2(randf()*2.0-1,randf()*2.0-1).normalized()
+	set_process(true)
+	
+	# Initialization here
+	pass
+
+

BIN
demos/2d/texscreen/lens.scn


BIN
demos/gui/drag_and_drop/drag_and_drop.scn


+ 24 - 0
demos/gui/drag_and_drop/drag_drop_script.gd

@@ -0,0 +1,24 @@
+
+extends ColorPickerButton
+
+
+#virtual function
+func get_drag_data(pos):
+	
+	#use another colorpicker as drag preview
+	var cpb = ColorPickerButton.new()
+	cpb.set_color( get_color() )
+	cpb.set_size(Vector2(50,50))
+	set_drag_preview(cpb)
+	#return color as drag data
+	return get_color()
+
+#virtual function	
+func can_drop_data(pos, data):
+	return typeof(data)==TYPE_COLOR
+
+#virtual function
+func drop_data(pos, data):
+	set_color(data)
+		
+

+ 4 - 0
demos/gui/drag_and_drop/engine.cfg

@@ -0,0 +1,4 @@
+[application]
+
+name="Drag &amp; Drop (GUI)"
+main_scene="res://drag_and_drop.scn"

+ 177 - 0
demos/misc/window_management/control.gd

@@ -0,0 +1,177 @@
+
+extends Control
+
+func _fixed_process(delta):
+
+	var modetext = "Mode:\n"
+	
+	if(OS.is_window_fullscreen()):
+		modetext += "Fullscreen\n"
+	else:
+		modetext += "Windowed\n"
+		
+	if(!OS.is_window_resizable()):
+		modetext += "FixedSize\n"
+	
+	if(OS.is_window_minimized()):
+		modetext += "Minimized\n"
+	
+	if(OS.is_window_maximized()):
+		modetext += "Maximized\n"
+	
+	if(Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED):
+		modetext += "MouseGrab\n"
+		get_node("Label_MouseGrab_KeyInfo").show()
+	else:
+		get_node("Label_MouseGrab_KeyInfo").hide()
+	
+	get_node("Label_Mode").set_text(modetext)
+	
+	get_node("Label_Position").set_text( str("Position:\n", OS.get_window_position() ) )
+	
+	get_node("Label_Size").set_text(str("Size:\n", OS.get_window_size() ) )
+	
+	get_node("Label_MousePosition").set_text(str("Mouse Position:\n", Input.get_mouse_pos() ) )
+	
+	get_node("Label_Screen_Count").set_text( str("Screen_Count:\n", OS.get_screen_count() ) )
+	
+	get_node("Label_Screen_Current").set_text( str("Screen:\n", OS.get_current_screen() ) )
+	
+	get_node("Label_Screen0_Resolution").set_text( str("Screen0 Resolution:\n", OS.get_screen_size() ) )
+	
+	get_node("Label_Screen0_Position").set_text(str("Screen0 Position:\n",OS.get_screen_position() ) )
+	
+	if(OS.get_screen_count() > 1):
+		get_node("Button_Screen0").show()
+		get_node("Button_Screen1").show()
+		get_node("Label_Screen1_Resolution").show()
+		get_node("Label_Screen1_Position").show()
+		get_node("Label_Screen1_Resolution").set_text( str("Screen1 Resolution:\n", OS.get_screen_size(1) ) )
+		get_node("Label_Screen1_Position").set_text( str("Screen1 Position:\n", OS.get_screen_position(1) ) )
+	else:
+		get_node("Button_Screen0").hide()
+		get_node("Button_Screen1").hide()
+		get_node("Label_Screen1_Resolution").hide()
+		get_node("Label_Screen1_Position").hide()
+		
+	get_node("Button_Fullscreen").set_pressed( OS.is_window_fullscreen() )
+	get_node("Button_FixedSize").set_pressed( !OS.is_window_resizable() )
+	get_node("Button_Minimized").set_pressed( OS.is_window_minimized() )
+	get_node("Button_Maximized").set_pressed( OS.is_window_maximized() )
+	get_node("Button_Mouse_Grab").set_pressed( Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED )
+
+
+func check_wm_api():
+	var s = ""
+	if( !OS.has_method("get_screen_count") ):
+		s += " - get_screen_count()\n"
+	
+	if( !OS.has_method("get_current_screen") ):
+		s += " - get_current_screen()\n"
+	
+	if( !OS.has_method("set_current_screen") ):
+		s += " - set_current_screen()\n"
+	
+	if( !OS.has_method("get_screen_position") ):
+		s += " - get_screen_position()\n"
+	
+	if( !OS.has_method("get_screen_size") ):
+		s += " - get_screen_size()\n"
+	
+	if( !OS.has_method("get_window_position") ):
+		s += " - get_window_position()\n"
+	
+	if( !OS.has_method("set_window_position") ):
+		s += " - set_window_position()\n"
+	
+	if( !OS.has_method("get_window_size") ):
+		s += " - get_window_size()\n"
+	
+	if( !OS.has_method("set_window_size") ):
+		s += " - set_window_size()\n"
+	
+	if( !OS.has_method("set_window_fullscreen") ):
+		s += " - set_window_fullscreen()\n"
+	
+	if( !OS.has_method("is_window_fullscreen") ):
+		s += " - is_window_fullscreen()\n"
+	
+	if( !OS.has_method("set_window_resizable") ):
+		s += " - set_window_resizable()\n"
+	
+	if( !OS.has_method("is_window_resizable") ):
+		s += " - is_window_resizable()\n"
+	
+	if( !OS.has_method("set_window_minimized") ):
+		s += " - set_window_minimized()\n"
+	
+	if( !OS.has_method("is_window_minimized") ):
+		s += " - is_window_minimized()\n"
+	
+	if( !OS.has_method("set_window_maximized") ):
+		s += " - set_window_maximized()\n"
+	
+	if( !OS.has_method("is_window_maximized") ):
+		s += " - is_window_maximized()\n"
+	
+	if( s.length() == 0 ):
+		return true
+	else:
+		var text = get_node("ImplementationDialog/Text").get_text()
+		get_node("ImplementationDialog/Text").set_text( text + s )
+		get_node("ImplementationDialog").show()
+		return false
+
+
+func _ready():
+	if( check_wm_api() ):
+		set_fixed_process(true)
+
+
+func _on_Button_MoveTo_pressed():
+	OS.set_window_position( Vector2(100,100) )
+
+
+func _on_Button_Resize_pressed():
+	OS.set_window_size( Vector2(1024,768) )
+
+
+func _on_Button_Screen0_pressed():
+	OS.set_current_screen(0)
+
+
+func _on_Button_Screen1_pressed():
+	OS.set_current_screen(1)
+
+
+func _on_Button_Fullscreen_pressed():
+	if(OS.is_window_fullscreen()):
+		OS.set_window_fullscreen(false)
+	else:
+		OS.set_window_fullscreen(true)
+
+
+func _on_Button_FixedSize_pressed():
+	if(OS.is_window_resizable()):
+		OS.set_window_resizable(false)
+	else:
+		OS.set_window_resizable(true)
+
+
+func _on_Button_Minimized_pressed():
+	if(OS.is_window_minimized()):
+		OS.set_window_minimized(false)
+	else:
+		OS.set_window_minimized(true)
+
+
+func _on_Button_Maximized_pressed():
+	if(OS.is_window_maximized()):
+		OS.set_window_maximized(false)
+	else:
+		OS.set_window_maximized(true)
+
+
+func _on_Button_Mouse_Grab_pressed():
+	var observer = get_node("../Observer")
+	observer.state = observer.STATE_GRAB

+ 19 - 0
demos/misc/window_management/engine.cfg

@@ -0,0 +1,19 @@
+[application]
+
+name="window_management"
+main_scene="res://window_management.scn"
+icon="icon.png"
+
+[display]
+
+fullscreen=false
+resizable=true
+width=800
+height=600
+
+[input]
+
+move_forward=[key(W)]
+move_backwards=[key(S)]
+move_left=[key(A)]
+move_right=[key(D)]

BIN
demos/misc/window_management/icon.png


+ 1 - 0
demos/misc/window_management/icon.png.flags

@@ -0,0 +1 @@
+gen_mipmaps=false

+ 79 - 0
demos/misc/window_management/observer/observer.gd

@@ -0,0 +1,79 @@
+
+extends Spatial
+
+var r_pos = Vector2()
+var state
+
+const STATE_MENU=0
+const STATE_GRAB=1
+
+func direction(vector):
+	var v = get_node("Camera").get_global_transform().basis * vector
+	v = v.normalized()
+	
+	return v
+
+
+func impulse(event, action):
+	if(event.is_action(action) && event.is_pressed() && !event.is_echo()):
+		return true
+	else:
+		return false
+
+
+func _fixed_process(delta):
+	
+	if(state != STATE_GRAB):
+		return
+	
+	if(Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED):
+		Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
+	
+	var dir = Vector3() 
+	var cam = get_global_transform()
+	var org = get_translation()
+	
+	if (Input.is_action_pressed("move_forward")):
+		dir += direction(Vector3(0,0,-1))
+	if (Input.is_action_pressed("move_backwards")):
+		dir += direction(Vector3(0,0,1))
+	if (Input.is_action_pressed("move_left")):
+		dir += direction(Vector3(-1,0,0))
+	if (Input.is_action_pressed("move_right")):
+		dir += direction(Vector3(1,0,0))
+	
+	dir = dir.normalized()
+	
+	move(dir * 10 * delta)
+	var d = delta * 0.1
+	
+	var yaw = get_transform().rotated(Vector3(0,1,0), d * r_pos.x)
+	set_transform(yaw)
+	
+	var cam = get_node("Camera")
+	var pitch = cam.get_transform().rotated(Vector3(1,0,0), d * r_pos.y)
+	cam.set_transform(pitch)
+	
+	r_pos.x = 0.0
+	r_pos.y = 0.0
+
+
+func _input( event ):
+	if(event.type == InputEvent.MOUSE_MOTION):
+		r_pos = event.relative_pos
+	
+	if(impulse(event, "ui_cancel")):
+		if(state == STATE_GRAB):
+			Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
+			state = STATE_MENU
+		else:
+			Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
+			state = STATE_GRAB
+
+
+func _ready():
+	set_fixed_process(true)
+	set_process_input(true)
+	
+	state = STATE_MENU
+

BIN
demos/misc/window_management/observer/observer.scn


BIN
demos/misc/window_management/window_management.scn


+ 25 - 24
demos/viewport/gui_in_3d/gui_3d.gd

@@ -7,38 +7,39 @@ extends Spatial
 
 var prev_pos=null
 
-func _input(ev):
-	if (ev.type in [InputEvent.MOUSE_BUTTON,InputEvent.MOUSE_MOTION]):
-		var pos = ev.pos
-		var rfrom = get_node("camera").project_ray_origin(pos)
-		var rnorm = get_node("camera").project_ray_normal(pos)
+
+func _input( ev ):
+	#all other (non-mouse) events
+	if (not ev.type in [InputEvent.MOUSE_BUTTON,InputEvent.MOUSE_MOTION,InputEvent.SCREEN_DRAG,InputEvent.SCREEN_TOUCH]):	
+		get_node("viewport").input(ev)
 		
-		#simple collision test against aligned plane
-		#for game UIs of this kind consider more complex collision against plane
-		var p = Plane(Vector3(0,0,1),0).intersects_ray(rfrom,rnorm)
-		if (p==null):
-			return
-			
-		pos.x=(p.x+1.5)*100
-		pos.y=(-p.y+0.75)*100
-		ev.pos=pos
-		ev.global_pos=pos
-		if (prev_pos==null):
-			prev_pos=pos
-		if (ev.type==InputEvent.MOUSE_MOTION):
-			ev.relative_pos=pos-prev_pos
+	
+#mouse events for area
+func _on_area_input_event( camera, ev, click_pos, click_normal, shape_idx ):
+	
+	#use click pos (click in 3d space, convert to area space
+	var pos = get_node("area").get_global_transform().affine_inverse() * click_pos
+	#convert to 2D
+	pos = Vector2(pos.x,pos.y)
+	#convert to viewport coordinate system		
+	pos.x=(pos.x+1.5)*100
+	pos.y=(-pos.y+0.75)*100
+	#set to event
+	ev.pos=pos
+	ev.global_pos=pos
+	if (prev_pos==null):
 		prev_pos=pos
+	if (ev.type==InputEvent.MOUSE_MOTION):
+		ev.relative_pos=pos-prev_pos
+	prev_pos=pos
 		
 	get_node("viewport").input(ev)
-		
-		
+	
 	
 
 func _ready():
 	# Initalization here
-	get_node("quad").get_material_override().set_texture(FixedMaterial.PARAM_DIFFUSE, get_node("viewport").get_render_target_texture() )
+	get_node("area/quad").get_material_override().set_texture(FixedMaterial.PARAM_DIFFUSE, get_node("viewport").get_render_target_texture() )
 	set_process_input(true)
-	
 	pass
 
-

BIN
demos/viewport/gui_in_3d/gui_3d.scn


+ 26 - 3
doc/base/classes.xml

@@ -257,13 +257,14 @@
 		<method name="lerp"  >
 			<return type="float">
 			</return>
-			<argument index="0" name="a" type="float">
+			<argument index="0" name="from" type="float">
 			</argument>
-			<argument index="1" name="b" type="float">
+			<argument index="1" name="to" type="float">
 			</argument>
-			<argument index="2" name="c" type="float">
+			<argument index="2" name="weight" type="float">
 			</argument>
 			<description>
+			Linear interpolates between two values by a normalized value.
 			</description>
 		</method>
 		<method name="dectime"  >
@@ -276,6 +277,7 @@
 			<argument index="2" name="step" type="float">
 			</argument>
 			<description>
+			Decreases time by a specified amount.
 			</description>
 		</method>
 		<method name="randomize"  >
@@ -421,6 +423,7 @@
 			<argument index="1" name="funcname" type="String">
 			</argument>
 			<description>
+			Returns a reference to the specified function
 			</description>
 		</method>
 		<method name="convert"  >
@@ -475,6 +478,7 @@
 			<argument index="1" name="..." type="var">
 			</argument>
 			<description>
+			Print one or more arguments to the console with a tab between each argument.
 			</description>
 		</method>
 		<method name="printerr"  >
@@ -499,6 +503,24 @@
 			Print one or more arguments to strings in the best way possible to console. No newline is added at the end.
 			</description>
 		</method>
+		<method name="var2str"  >
+			<return type="String">
+			</return>
+			<argument index="0" name="var" type="var">
+			</argument>
+			<description>
+			Converts the value of a variable to a String.
+			</description>
+		</method>
+		<method name="str2var:var"  >
+			<return type="String">
+			</return>
+			<argument index="0" name="str" type="String">
+			</argument>
+			<description>
+			Converts the value of a String to a variable.
+			</description>
+		</method>
 		<method name="range"  >
 			<return type="Array">
 			</return>
@@ -544,6 +566,7 @@
 			<argument index="0" name="var:var" type="var">
 			</argument>
 			<description>
+			Hashes the variable passed and returns an integer.
 			</description>
 		</method>
 		<method name="print_stack"  >

+ 1 - 1
drivers/etc1/rg_etc1.cpp

@@ -2367,7 +2367,7 @@ found_perfect_match:
       int dr = best_results[1].m_block_color_unscaled.r - best_results[0].m_block_color_unscaled.r;
       int dg = best_results[1].m_block_color_unscaled.g - best_results[0].m_block_color_unscaled.g;
       int db = best_results[1].m_block_color_unscaled.b - best_results[0].m_block_color_unscaled.b;
-      RG_ETC1_ASSERT(best_use_color4 || (rg_etc1::minimum(dr, dg, db) >= cETC1ColorDeltaMin) && (rg_etc1::maximum(dr, dg, db) <= cETC1ColorDeltaMax));
+      RG_ETC1_ASSERT(best_use_color4 || ((rg_etc1::minimum(dr, dg, db) >= cETC1ColorDeltaMin) && (rg_etc1::maximum(dr, dg, db) <= cETC1ColorDeltaMax)));
            
       if (best_use_color4)
       {

+ 199 - 44
drivers/gles2/rasterizer_gles2.cpp

@@ -989,8 +989,14 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
 
 	if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps)
 		glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR);
-	else
-		glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+	else {
+		if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
+			glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+		} else {
+			glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+		}
+	}
 
 	if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
 
@@ -1283,8 +1289,14 @@ void RasterizerGLES2::texture_set_flags(RID p_texture,uint32_t p_flags) {
 
 	if (texture->flags&VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps)
 		glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,use_fast_texture_filter?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR_MIPMAP_LINEAR);
-	else
-		glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+	else{
+		if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
+			glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+		} else {
+			glTexParameteri(texture->target,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+
+		}
+	}
 
 	if (texture->flags&VS::TEXTURE_FLAG_FILTER) {
 
@@ -4276,7 +4288,7 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) {
 
 void RasterizerGLES2::clear_viewport(const Color& p_color) {
 
-	if (current_rt) {
+	if (current_rt || using_canvas_bg) {
 
 		glScissor( 0, 0, viewport.width, viewport.height );
 	} else {
@@ -4599,6 +4611,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
 		if (fragment_flags.uses_texpixel_size) {
 			enablers.push_back("#define USE_TEXPIXEL_SIZE\n");
 		}
+		if (light_flags.uses_shadow_color) {
+			enablers.push_back("#define USE_LIGHT_SHADOW_COLOR\n");
+		}
 
 		if (vertex_flags.uses_worldvec) {
 			enablers.push_back("#define USE_WORLD_VEC\n");
@@ -6932,7 +6947,7 @@ void RasterizerGLES2::_draw_tex_bg() {
 
 	RID texture;
 
-	if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
+	if (current_env->bg_mode==VS::ENV_BG_TEXTURE) {
 		texture=current_env->bg_param[VS::ENV_BG_PARAM_TEXTURE];
 	} else {
 		texture=current_env->bg_param[VS::ENV_BG_PARAM_CUBEMAP];
@@ -6949,25 +6964,20 @@ void RasterizerGLES2::_draw_tex_bg() {
 
 	copy_shader.set_conditional(CopyShaderGLES2::USE_ENERGY,true);
 
-	if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
+	if (current_env->bg_mode==VS::ENV_BG_TEXTURE) {
 		copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP,false);
 
 	} else {
 		copy_shader.set_conditional(CopyShaderGLES2::USE_CUBEMAP,true);
 	}
 
-	if (current_env->bg_mode==VS::ENV_BG_CUBEMAP_RGBE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
-		copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,true);
-	} else {
-		copy_shader.set_conditional(CopyShaderGLES2::USE_RGBE,false);
-	}
 
 	copy_shader.set_conditional(CopyShaderGLES2::USE_CUSTOM_ALPHA,true);
 
 
 	copy_shader.bind();
 
-	if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
+	if (current_env->bg_mode==VS::ENV_BG_TEXTURE) {
 		glUniform1i( copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0);
 	} else {
 		glUniform1i( copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE_CUBE),0);
@@ -6994,7 +7004,7 @@ void RasterizerGLES2::_draw_tex_bg() {
 		Vector3( 0, 0, 0)
 	};
 
-	if (current_env->bg_mode==VS::ENV_BG_TEXTURE || current_env->bg_mode==VS::ENV_BG_TEXTURE_RGBE) {
+	if (current_env->bg_mode==VS::ENV_BG_TEXTURE) {
 
 		//regular texture
 		//adjust aspect
@@ -7064,7 +7074,7 @@ void RasterizerGLES2::end_scene() {
 	if (framebuffer.active) {
 
 		//detect when to use the framebuffer object
-		if (texscreen_used || framebuffer.scale!=1) {
+		if (using_canvas_bg || texscreen_used || framebuffer.scale!=1) {
 			use_fb=true;
 		} else if (current_env) {
 			use_fb=false;
@@ -7116,6 +7126,7 @@ void RasterizerGLES2::end_scene() {
 
 		switch(current_env->bg_mode) {
 
+			case VS::ENV_BG_CANVAS:
 			case VS::ENV_BG_KEEP: {
 				//copy from framebuffer if framebuffer
 				glClear(GL_DEPTH_BUFFER_BIT);
@@ -7128,7 +7139,7 @@ void RasterizerGLES2::end_scene() {
 					bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR];
 				else
 					bgcolor = Globals::get_singleton()->get("render/default_clear_color");
-				bgcolor = _convert_color(bgcolor);
+			bgcolor = _convert_color(bgcolor);
 				float a = use_fb ? float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]) : 1.0;
 				glClearColor(bgcolor.r,bgcolor.g,bgcolor.b,a);
 				_glClearDepth(1.0);
@@ -7136,9 +7147,7 @@ void RasterizerGLES2::end_scene() {
 
 			} break;
 			case VS::ENV_BG_TEXTURE:
-			case VS::ENV_BG_CUBEMAP:
-			case VS::ENV_BG_TEXTURE_RGBE:
-			case VS::ENV_BG_CUBEMAP_RGBE: {
+			case VS::ENV_BG_CUBEMAP: {
 
 
 				glClear(GL_DEPTH_BUFFER_BIT);
@@ -7357,8 +7366,12 @@ void RasterizerGLES2::end_scene() {
 		_debug_shadows();
 	}
 //	_debug_luminances();
-	_debug_samplers();
+//	_debug_samplers();
 
+	if (using_canvas_bg) {
+		using_canvas_bg=false;
+		glColorMask(1,1,1,1); //don't touch alpha
+	}
 
 }
 void RasterizerGLES2::end_shadow_map() {
@@ -7827,8 +7840,26 @@ void RasterizerGLES2::flush_frame() {
 
 /* CANVAS API */
 
+void RasterizerGLES2::begin_canvas_bg() {
+
+	if (framebuffer.active) {
+		using_canvas_bg=true;
+		glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo);
+		glViewport( 0,0,viewport.width , viewport.height );
+	} else {
+		using_canvas_bg=false;
+	}
+
+}
+
 void RasterizerGLES2::canvas_begin() {
 
+
+	if (using_canvas_bg) {
+		glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo);
+		glColorMask(1,1,1,0); //don't touch alpha
+	}
+
 	glDisable(GL_CULL_FACE);
 	glDisable(GL_DEPTH_TEST);
 	glDisable(GL_SCISSOR_TEST);
@@ -8531,6 +8562,7 @@ RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) {
 #ifdef GLEW_ENABLED
 		glDrawBuffer(GL_NONE);
 #endif
+
 	} else {
 		// We'll use a RGBA texture into which we pack the depth info
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cls->size, cls->height, 0,
@@ -8539,6 +8571,7 @@ RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) {
 		// Attach the RGBA texture to FBO color attachment point
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
 				       GL_TEXTURE_2D, cls->depth, 0);
+		cls->rgba=cls->depth;
 
 		// Allocate 16-bit depth buffer
 		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height);
@@ -8554,7 +8587,7 @@ RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) {
 	//printf("errnum: %x\n",status);
 #ifdef GLEW_ENABLED
 	if (read_depth_supported) {
-		glDrawBuffer(GL_BACK);
+		//glDrawBuffer(GL_BACK);
 	}
 #endif
 	glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer);
@@ -8563,7 +8596,7 @@ RID RasterizerGLES2::canvas_light_shadow_buffer_create(int p_width) {
 
 #ifdef GLEW_ENABLED
 	if (read_depth_supported) {
-		glDrawBuffer(GL_BACK);
+		//glDrawBuffer(GL_BACK);
 	}
 #endif
 
@@ -8817,10 +8850,14 @@ void RasterizerGLES2::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_s
 	int h = 10;
 	int w = viewport.width;
 	int ofs = h;
+
+	//print_line(" debug lights ");
 	while(light) {
 
+	//	print_line("debug light");
 		if (light->shadow_buffer.is_valid()) {
 
+	//		print_line("sb is valid");
 			CanvasLightShadow * sb = canvas_light_shadow_owner.get(light->shadow_buffer);
 			if (sb) {
 				glActiveTexture(GL_TEXTURE0);
@@ -9099,8 +9136,11 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
 	canvas_use_modulate=p_modulate!=Color(1,1,1,1);
 	canvas_modulate=p_modulate;
 	canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
+	canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,false);
+
 
 	bool reset_modulate=false;
+	bool prev_distance_field=false;
 
 	while(p_item_list) {
 
@@ -9116,12 +9156,22 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
 			canvas_use_modulate=p_modulate!=Color(1,1,1,1);
 			canvas_modulate=p_modulate;
 			canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
+			canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,false);
+			prev_distance_field=false;
 			rebind_shader=true;
 			reset_modulate=true;
 
 
 		}
 
+		if (prev_distance_field!=ci->distance_field) {
+
+			canvas_shader.set_conditional(CanvasShaderGLES2::USE_DISTANCE_FIELD,ci->distance_field);
+			prev_distance_field=ci->distance_field;
+			rebind_shader=true;
+		}
+
+
 		if (current_clip!=ci->final_clip_owner) {
 
 			current_clip=ci->final_clip_owner;
@@ -9138,6 +9188,40 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
 			}
 		}
 
+		if (ci->copy_back_buffer && framebuffer.active && framebuffer.scale==1) {
+
+			Rect2 rect;
+			int x,y,w,h;
+
+			if (ci->copy_back_buffer->full) {
+
+				x = viewport.x;
+				y = window_size.height-(viewport.height+viewport.y);
+				w = viewport.width;
+				h = viewport.height;
+			} else {
+				x = viewport.x+ci->copy_back_buffer->screen_rect.pos.x;
+				y = window_size.height-(viewport.y+ci->copy_back_buffer->screen_rect.pos.y+ci->copy_back_buffer->screen_rect.size.y);
+				w = ci->copy_back_buffer->screen_rect.size.x;
+				h = ci->copy_back_buffer->screen_rect.size.y;
+			}
+			glActiveTexture(GL_TEXTURE0+max_texture_units-1);
+			glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color);
+
+#ifdef GLEW_ENABLED
+			glReadBuffer(GL_COLOR_ATTACHMENT0);
+#endif
+			glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,w,h);
+//			if (current_clip) {
+//			//	print_line(" a clip ");
+//			}
+
+			canvas_texscreen_used=true;
+			glActiveTexture(GL_TEXTURE0);
+		}
+
+
+
 
 		//begin rect
 		CanvasItem *material_owner = ci->material_owner?ci->material_owner:ci;
@@ -9179,7 +9263,9 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
 			_canvas_item_setup_shader_uniforms(material,shader_cache);
 		}
 
-		if (material && material->unshaded) {
+		bool unshaded = material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED;
+
+		if (unshaded) {
 			canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,Color(1,1,1,1));
 			reset_modulate=true;
 		} else if (reset_modulate) {
@@ -9236,13 +9322,15 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
 
 		canvas_opacity = ci->final_opacity;
 
-		_canvas_item_render_commands<false>(ci,current_clip,reclip);
 
-		if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && (!material || !material->unshaded)) {
+		if (unshaded || (p_modulate.a>0.001 && (!material || material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT)))
+			_canvas_item_render_commands<false>(ci,current_clip,reclip);
+
+		if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && !unshaded) {
 
 			CanvasLight *light = p_light;
 			bool light_used=false;
-			bool subtract=false;
+			VS::CanvasLightMode mode=VS::CANVAS_LIGHT_MODE_ADD;
 
 
 			while(light) {
@@ -9251,21 +9339,28 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
 
 					//intersects this light
 
-					if (!light_used || subtract!=light->subtract) {
+					if (!light_used || mode!=light->mode) {
 
-						subtract=light->subtract;
+						mode=light->mode;
 
-						if (subtract) {
+						switch(mode) {
 
-							glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
-							glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+							case VS::CANVAS_LIGHT_MODE_ADD: {
+								glBlendEquation(GL_FUNC_ADD);
+								glBlendFunc(GL_SRC_ALPHA,GL_ONE);
 
-						} else {
-
-							glBlendEquation(GL_FUNC_ADD);
-							glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+							} break;
+							case VS::CANVAS_LIGHT_MODE_SUB: {
+								glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+								glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+							} break;
+							case VS::CANVAS_LIGHT_MODE_MIX: {
+								glBlendEquation(GL_FUNC_ADD);
+								glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
+							} break;
 						}
+
 					}
 
 					if (!light_used) {
@@ -9303,7 +9398,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
 
 					canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX,light->light_shader_xform);
 					canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS,light->light_shader_pos);
-					canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,light->color);
+					canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,Color(light->color.r*light->energy,light->color.g*light->energy,light->color.b*light->energy,light->color.a));
 					canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height);
 					canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse());
 
@@ -9783,9 +9878,9 @@ void RasterizerGLES2::free(const RID& p_rid) {
 		glDeleteFramebuffers(1,&cls->fbo);
 		glDeleteRenderbuffers(1,&cls->rbo);
 		glDeleteTextures(1,&cls->depth);
-		if (!read_depth_supported) {
-			glDeleteTextures(1,&cls->rgba);
-		}
+		//if (!read_depth_supported) {
+		//	glDeleteTextures(1,&cls->rgba);
+		//}
 
 		canvas_light_shadow_owner.free(p_rid);
 		memdelete(cls);
@@ -9904,7 +9999,7 @@ bool RasterizerGLES2::ShadowBuffer::init(int p_size,bool p_use_depth) {
 	//printf("errnum: %x\n",status);
 #ifdef GLEW_ENABLED
 	if (p_use_depth) {
-		glDrawBuffer(GL_BACK);
+		//glDrawBuffer(GL_BACK);
 	}
 #endif
 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -9913,7 +10008,7 @@ bool RasterizerGLES2::ShadowBuffer::init(int p_size,bool p_use_depth) {
 
 #ifdef GLEW_ENABLED
 	if (p_use_depth) {
-		glDrawBuffer(GL_BACK);
+		//glDrawBuffer(GL_BACK);
 	}
 #endif
 
@@ -10291,6 +10386,62 @@ void RasterizerGLES2::_update_blur_buffer() {
 
 }
 #endif
+
+
+bool RasterizerGLES2::_test_depth_shadow_buffer() {
+
+
+	int size=16;
+
+	GLuint fbo;
+	GLuint rbo;
+	GLuint depth;
+
+	glActiveTexture(GL_TEXTURE0);
+
+	glGenFramebuffers(1, &fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+	// Create a render buffer
+	glGenRenderbuffers(1, &rbo);
+	glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+
+	// Create a texture for storing the depth
+	glGenTextures(1, &depth);
+	glBindTexture(GL_TEXTURE_2D, depth);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+	// Remove artifact on the edges of the shadowmap
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+
+
+	// We'll use a depth texture to store the depths in the shadow map
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size, size, 0,
+		     GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+
+#ifdef GLEW_ENABLED
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#endif
+
+	// Attach the depth texture to FBO depth attachment point
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+			       GL_TEXTURE_2D, depth, 0);
+
+
+	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+	glDeleteFramebuffers(1,&fbo);
+	glDeleteRenderbuffers(1,&rbo);
+	glDeleteTextures(1,&depth);
+
+	return status == GL_FRAMEBUFFER_COMPLETE;
+
+}
+
 void RasterizerGLES2::init() {
 
 #ifdef GLEW_ENABLED
@@ -10363,7 +10514,7 @@ void RasterizerGLES2::init() {
 
 #ifdef GLEW_ENABLED
 
-	read_depth_supported=true;
+
 	pvr_supported=false;
 	etc_supported=false;
 	use_depth24 =true;
@@ -10381,7 +10532,10 @@ void RasterizerGLES2::init() {
 	use_anisotropic_filter=true;
 	float_linear_supported=true;
 	float_supported=true;
-	use_rgba_shadowmaps=false;
+
+	read_depth_supported=_test_depth_shadow_buffer();
+	use_rgba_shadowmaps=!read_depth_supported;
+	//print_line("read depth support? "+itos(read_depth_supported));
 
 	glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&anisotropic_level);
 	anisotropic_level=MIN(anisotropic_level,float(GLOBAL_DEF("rasterizer/anisotropic_filter_level",4.0)));
@@ -10504,6 +10658,7 @@ void RasterizerGLES2::init() {
 	shadow_mat_ptr = material_owner.get(shadow_material);
 	overdraw_material = create_overdraw_debug_material();
 	copy_shader.set_conditional(CopyShaderGLES2::USE_8BIT_HDR,!use_fp16_fb);
+	canvas_shader.set_conditional(CanvasShaderGLES2::USE_DEPTH_SHADOWS,read_depth_supported);
 
 	canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP,GLOBAL_DEF("rasterizer/use_pixel_snap",false));
 
@@ -10521,7 +10676,7 @@ void RasterizerGLES2::init() {
 	glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
 
 
-
+	using_canvas_bg=false;
 	_update_framebuffer();
 	DEBUG_TEST_ERROR("Initializing");
 }

+ 5 - 0
drivers/gles2/rasterizer_gles2.h

@@ -677,6 +677,7 @@ class RasterizerGLES2 : public Rasterizer {
 			bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0;
 			bg_param[VS::ENV_BG_PARAM_SCALE]=1.0;
 			bg_param[VS::ENV_BG_PARAM_GLOW]=0.0;
+			bg_param[VS::ENV_BG_PARAM_CANVAS_MAX_LAYER]=0;
 
 			for(int i=0;i<VS::ENV_FX_MAX;i++)
 				fx_enabled[i]=false;
@@ -1258,6 +1259,7 @@ class RasterizerGLES2 : public Rasterizer {
 	void _process_hdr();
 	void _draw_tex_bg();
 
+	bool using_canvas_bg;
 	Size2 window_size;
 	VS::ViewportRect viewport;
 	double last_time;
@@ -1286,6 +1288,7 @@ class RasterizerGLES2 : public Rasterizer {
 	void _copy_screen_quad();
 	void _copy_to_texscreen();
 
+	bool _test_depth_shadow_buffer();
 
 	Vector3 chunk_vertex;
 	Vector3 chunk_normal;
@@ -1600,6 +1603,8 @@ public:
 
 	/* CANVAS API */
 
+	virtual void begin_canvas_bg();
+
 	virtual void canvas_begin();
 	virtual void canvas_disable_blending();
 

+ 8 - 0
drivers/gles2/shader_compiler_gles2.cpp

@@ -266,6 +266,9 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
 					uses_normal=true;
 				}
 
+				if (vnode->name==vname_shadow) {
+					uses_shadow_color=true;
+				}
 
 			}
 
@@ -616,6 +619,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
 	uses_texpixel_size=false;
 	uses_worldvec=false;
 	vertex_code_writes_vertex=false;
+	uses_shadow_color=false;
 	uniforms=r_uniforms;
 	flags=&r_flags;
 	r_flags.use_color_interp=false;
@@ -651,6 +655,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
 	r_flags.uses_normal=uses_normal;
 	r_flags.uses_texpixel_size=uses_texpixel_size;
 	r_flags.uses_worldvec=uses_worldvec;
+	r_flags.uses_shadow_color=uses_shadow_color;
 	r_code_line=code;
 	r_globals_line=global_code;
 
@@ -827,7 +832,9 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
 	mode_replace_table[5]["LIGHT_VEC"]="light_vec";
 	mode_replace_table[5]["LIGHT_HEIGHT"]="light_height";
 	mode_replace_table[5]["LIGHT_COLOR"]="light";
+	mode_replace_table[5]["LIGHT_UV"]="light_uv";
 	mode_replace_table[5]["LIGHT"]="light_out";
+	mode_replace_table[5]["SHADOW"]="shadow_color";
 	mode_replace_table[5]["SCREEN_UV"]="screen_uv";
 	mode_replace_table[5]["POINT_COORD"]="gl_PointCoord";
 	mode_replace_table[5]["TIME"]="time";
@@ -857,5 +864,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
 	vname_normal="NORMAL";
 	vname_texpixel_size="TEXTURE_PIXEL_SIZE";
 	vname_world_vec="WORLD_VERTEX";
+	vname_shadow="SHADOW";
 
 }

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