Browse Source

Bug Fixes
-=-=-=-=-

-Fixed problem with scaling shapes (#827), related to not taking scale in consideration for calculating the moment of inertia
-Added support for multiline strings (or comments) using """
-Save subscene bug, properties not being saved in root node (#806)
-Fix Crash in CollisionPolygon2DEditor (#814)
-Restored Ability to compile without 3D (#795)
-Fix InterpolatedCamera (#803)
-Fix UV Import for OBJ Meshes (#771)
-Fixed issue with modifier gizmos (#794)
-Fixed CapsuleShape gizmo handle (#50)
-Fixed Import Button (not properly working in 3D) (#733)
-Many misc fixes (though no new features)

Juan Linietsky 11 years ago
parent
commit
d85b67be53
56 changed files with 1647 additions and 403 deletions
  1. 10 0
      core/bind/core_bind.cpp
  2. 2 0
      core/bind/core_bind.h
  3. 1 0
      core/object.h
  4. 5 0
      core/undo_redo.cpp
  5. 210 158
      doc/base/classes.xml
  6. 93 67
      drivers/gles2/rasterizer_gles2.cpp
  7. 2 1
      drivers/gles2/rasterizer_gles2.h
  8. 3 0
      drivers/png/image_loader_png.cpp
  9. 37 0
      drivers/png/resource_saver_png.cpp
  10. 27 9
      drivers/theoraplayer/video_stream_theoraplayer.cpp
  11. 3 2
      drivers/theoraplayer/video_stream_theoraplayer.h
  12. 14 10
      modules/gdscript/gd_compiler.cpp
  13. 2 2
      modules/gdscript/gd_compiler.h
  14. 1 0
      modules/gdscript/gd_editor.cpp
  15. 1 1
      modules/gdscript/gd_parser.cpp
  16. 1 0
      modules/gdscript/gd_parser.h
  17. 1 0
      modules/gdscript/gd_script.cpp
  18. 21 9
      modules/gdscript/gd_tokenizer.cpp
  19. 7 0
      modules/gdscript/gd_tokenizer.h
  20. 32 5
      platform/osx/audio_driver_osx.cpp
  21. 4 0
      platform/osx/audio_driver_osx.h
  22. 10 0
      platform/windows/detect.py
  23. 4 4
      scene/2d/collision_object_2d.cpp
  24. 17 11
      scene/3d/body_shape.cpp
  25. 5 1
      scene/3d/body_shape.h
  26. 4 4
      scene/3d/collision_object.cpp
  27. 2 2
      scene/3d/interpolated_camera.cpp
  28. 8 0
      scene/gui/base_button.cpp
  29. 12 8
      scene/gui/base_button.h
  30. 10 15
      scene/gui/video_player.cpp
  31. 44 3
      scene/io/resource_format_image.cpp
  32. 15 1
      scene/main/node.cpp
  33. 4 3
      scene/main/viewport.cpp
  34. 8 6
      scene/register_scene_types.cpp
  35. 1 1
      scene/resources/animation.cpp
  36. 219 0
      scene/resources/mesh.cpp
  37. 2 0
      scene/resources/mesh.h
  38. 4 0
      scene/resources/packed_scene.cpp
  39. 2 2
      scene/resources/video_stream.h
  40. 7 1
      servers/physics_2d/body_2d_sw.cpp
  41. 1 0
      servers/physics_2d/collision_solver_2d_sat.cpp
  42. 18 15
      servers/physics_2d/shape_2d_sw.cpp
  43. 19 14
      servers/physics_2d/shape_2d_sw.h
  44. 1 1
      servers/visual/visual_server_raster.cpp
  45. 45 2
      tools/editor/editor_node.cpp
  46. 1 0
      tools/editor/editor_node.h
  47. 7 5
      tools/editor/io_plugins/editor_import_collada.cpp
  48. 1 1
      tools/editor/io_plugins/editor_import_collada.h
  49. 1 1
      tools/editor/io_plugins/editor_mesh_import_plugin.cpp
  50. 595 14
      tools/editor/io_plugins/editor_scene_import_plugin.cpp
  51. 16 4
      tools/editor/io_plugins/editor_scene_import_plugin.h
  52. 19 18
      tools/editor/plugins/baked_light_baker_cmpxchg.cpp
  53. 6 1
      tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
  54. 55 0
      tools/editor/plugins/mesh_editor_plugin.cpp
  55. 6 0
      tools/editor/plugins/mesh_editor_plugin.h
  56. 1 1
      tools/editor/spatial_editor_gizmos.cpp

+ 10 - 0
core/bind/core_bind.cpp

@@ -597,7 +597,15 @@ void _OS::native_video_stop() {
 	OS::get_singleton()->native_video_stop();
 	OS::get_singleton()->native_video_stop();
 };
 };
 
 
+bool _OS::is_debug_build() const {
 
 
+#ifdef DEBUG_ENABLED
+	return true;
+#else
+	return false;
+#endif
+
+}
 String _OS::get_custom_level() const {
 String _OS::get_custom_level() const {
 
 
 	return OS::get_singleton()->get_custom_level();
 	return OS::get_singleton()->get_custom_level();
@@ -668,6 +676,8 @@ void _OS::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("can_use_threads"),&_OS::can_use_threads);
 	ObjectTypeDB::bind_method(_MD("can_use_threads"),&_OS::can_use_threads);
 
 
+	ObjectTypeDB::bind_method(_MD("is_debug_build"),&_OS::is_debug_build);
+
 	//ObjectTypeDB::bind_method(_MD("get_mouse_button_state"),&_OS::get_mouse_button_state);
 	//ObjectTypeDB::bind_method(_MD("get_mouse_button_state"),&_OS::get_mouse_button_state);
 
 
 	ObjectTypeDB::bind_method(_MD("dump_memory_to_file","file"),&_OS::dump_memory_to_file);
 	ObjectTypeDB::bind_method(_MD("dump_memory_to_file","file"),&_OS::dump_memory_to_file);

+ 2 - 0
core/bind/core_bind.h

@@ -154,6 +154,8 @@ public:
 
 
 	bool has_touchscreen_ui_hint() const;
 	bool has_touchscreen_ui_hint() const;
 
 
+	bool is_debug_build() const;
+
 	String get_unique_ID() const;
 	String get_unique_ID() const;
 
 
 	/*
 	/*

+ 1 - 0
core/object.h

@@ -81,6 +81,7 @@ enum PropertyUsageFlags {
 	PROPERTY_USAGE_BUNDLE=128, //used for optimized bundles
 	PROPERTY_USAGE_BUNDLE=128, //used for optimized bundles
 	PROPERTY_USAGE_CATEGORY=256,
 	PROPERTY_USAGE_CATEGORY=256,
 	PROPERTY_USAGE_STORE_IF_NONZERO=512, //only store if nonzero
 	PROPERTY_USAGE_STORE_IF_NONZERO=512, //only store if nonzero
+	PROPERTY_USAGE_NO_INSTANCE_STATE=1024,
 
 
 	PROPERTY_USAGE_DEFAULT=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK,
 	PROPERTY_USAGE_DEFAULT=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK,
 	PROPERTY_USAGE_DEFAULT_INTL=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_INTERNATIONALIZED,
 	PROPERTY_USAGE_DEFAULT_INTL=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_INTERNATIONALIZED,

+ 5 - 0
core/undo_redo.cpp

@@ -243,6 +243,11 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
 			case Operation::TYPE_PROPERTY: {
 			case Operation::TYPE_PROPERTY: {
 
 
 				obj->set(op.name,op.args[0]);
 				obj->set(op.name,op.args[0]);
+#ifdef TOOLS_ENABLED
+				Resource* res = obj->cast_to<Resource>();
+				if (res)
+					res->set_edited(true);
+#endif
 			} break;
 			} break;
 			case Operation::TYPE_REFERENCE: {
 			case Operation::TYPE_REFERENCE: {
 				//do nothing
 				//do nothing

File diff suppressed because it is too large
+ 210 - 158
doc/base/classes.xml


+ 93 - 67
drivers/gles2/rasterizer_gles2.cpp

@@ -360,17 +360,19 @@ void RasterizerGLES2::_draw_primitive(int p_points, const Vector3 *p_vertices, c
 
 
 /* TEXTURE API */
 /* TEXTURE API */
 
 
-Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed) {
+Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,GLenum& r_gl_internal_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed) {
 
 
 	r_has_alpha_cache=false;
 	r_has_alpha_cache=false;
 	r_compressed=false;
 	r_compressed=false;
+	r_gl_format=0;
 	Image image=p_image;
 	Image image=p_image;
 
 
 	switch(p_format) {
 	switch(p_format) {
 
 
 		case Image::FORMAT_GRAYSCALE: {
 		case Image::FORMAT_GRAYSCALE: {
 			r_gl_components=1;
 			r_gl_components=1;
-			r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_NV:GL_LUMINANCE;
+			r_gl_format=GL_LUMINANCE;
+			r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_NV:GL_LUMINANCE;
 
 
 		} break;
 		} break;
 		case Image::FORMAT_INTENSITY: {
 		case Image::FORMAT_INTENSITY: {
@@ -378,14 +380,16 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 			if (!image.empty())
 			if (!image.empty())
 				image.convert(Image::FORMAT_RGBA);
 				image.convert(Image::FORMAT_RGBA);
 			r_gl_components=4;
 			r_gl_components=4;
-			r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA;
+			r_gl_format=GL_RGBA;
+			r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_ALPHA_EXT:GL_RGBA;
 			r_has_alpha_cache=true;
 			r_has_alpha_cache=true;
 		} break;
 		} break;
 		case Image::FORMAT_GRAYSCALE_ALPHA: {
 		case Image::FORMAT_GRAYSCALE_ALPHA: {
 
 
 			//image.convert(Image::FORMAT_RGBA);
 			//image.convert(Image::FORMAT_RGBA);
 			r_gl_components=2;
 			r_gl_components=2;
-			r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_ALPHA_NV:GL_LUMINANCE_ALPHA;
+			r_gl_format=GL_LUMINANCE_ALPHA;
+			r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_SLUMINANCE_ALPHA_NV:GL_LUMINANCE_ALPHA;
 			r_has_alpha_cache=true;
 			r_has_alpha_cache=true;
 		} break;
 		} break;
 
 
@@ -394,7 +398,8 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 			if (!image.empty())
 			if (!image.empty())
 				image.convert(Image::FORMAT_RGB);
 				image.convert(Image::FORMAT_RGB);
 			r_gl_components=3;
 			r_gl_components=3;
-			r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_EXT:GL_RGB;
+			r_gl_format=GL_RGB;
+			r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_GL_SRGB_EXT:GL_RGB;
 
 
 		} break;
 		} break;
 
 
@@ -407,14 +412,15 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 			if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 			if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 				if (srgb_supported) {
 				if (srgb_supported) {
-					r_gl_format=_GL_SRGB_ALPHA_EXT;
-				} else {
 					r_gl_format=GL_RGBA;
 					r_gl_format=GL_RGBA;
+					r_gl_internal_format=_GL_SRGB_ALPHA_EXT;
+				} else {
+					r_gl_internal_format=GL_RGBA;
 					if (!image.empty())
 					if (!image.empty())
 						image.srgb_to_linear();
 						image.srgb_to_linear();
 				}
 				}
 			} else {
 			} else {
-				r_gl_format=GL_RGBA;
+				r_gl_internal_format=GL_RGBA;
 			}
 			}
 			r_has_alpha_cache=true;
 			r_has_alpha_cache=true;
 
 
@@ -426,14 +432,15 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 			if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 			if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 				if (srgb_supported) {
 				if (srgb_supported) {
-					r_gl_format=_GL_SRGB_EXT;
-				} else {
+					r_gl_internal_format=_GL_SRGB_EXT;
 					r_gl_format=GL_RGB;
 					r_gl_format=GL_RGB;
+				} else {
+					r_gl_internal_format=GL_RGB;
 					if (!image.empty())
 					if (!image.empty())
 						image.srgb_to_linear();
 						image.srgb_to_linear();
 				}
 				}
 			} else {
 			} else {
-				r_gl_format=GL_RGB;
+				r_gl_internal_format=GL_RGB;
 			}
 			}
 		} break;
 		} break;
 		case Image::FORMAT_RGBA: {
 		case Image::FORMAT_RGBA: {
@@ -442,14 +449,16 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 			if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 			if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 				if (srgb_supported) {
 				if (srgb_supported) {
-					r_gl_format=_GL_SRGB_ALPHA_EXT;
-				} else {
+					r_gl_internal_format=_GL_SRGB_ALPHA_EXT;
 					r_gl_format=GL_RGBA;
 					r_gl_format=GL_RGBA;
+					//r_gl_internal_format=GL_RGBA;
+				} else {
+					r_gl_internal_format=GL_RGBA;
 					if (!image.empty())
 					if (!image.empty())
 						image.srgb_to_linear();
 						image.srgb_to_linear();
 				}
 				}
 			} else {
 			} else {
-				r_gl_format=GL_RGBA;
+				r_gl_internal_format=GL_RGBA;
 			}
 			}
 
 
 			r_has_alpha_cache=true;
 			r_has_alpha_cache=true;
@@ -465,21 +474,22 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 					if (srgb_supported) {
 					if (srgb_supported) {
-						r_gl_format=_GL_SRGB_ALPHA_EXT;
-					} else {
 						r_gl_format=GL_RGBA;
 						r_gl_format=GL_RGBA;
+						r_gl_internal_format=_GL_SRGB_ALPHA_EXT;
+					} else {
+						r_gl_internal_format=GL_RGBA;
 						if (!image.empty())
 						if (!image.empty())
 							image.srgb_to_linear();
 							image.srgb_to_linear();
 					}
 					}
 				} else {
 				} else {
-					r_gl_format=GL_RGBA;
+					r_gl_internal_format=GL_RGBA;
 				}
 				}
 				r_has_alpha_cache=true;
 				r_has_alpha_cache=true;
 
 
 			} else {
 			} else {
 
 
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
-				r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+				r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
 				r_compressed=true;
 				r_compressed=true;
 			};
 			};
 
 
@@ -495,20 +505,21 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 					if (srgb_supported) {
 					if (srgb_supported) {
-						r_gl_format=_GL_SRGB_ALPHA_EXT;
-					} else {
 						r_gl_format=GL_RGBA;
 						r_gl_format=GL_RGBA;
+						r_gl_internal_format=_GL_SRGB_ALPHA_EXT;
+					} else {
+						r_gl_internal_format=GL_RGBA;
 						if (!image.empty())
 						if (!image.empty())
 							image.srgb_to_linear();
 							image.srgb_to_linear();
 					}
 					}
 				} else {
 				} else {
-					r_gl_format=GL_RGBA;
+					r_gl_internal_format=GL_RGBA;
 				}
 				}
 				r_has_alpha_cache=true;
 				r_has_alpha_cache=true;
 
 
 			} else {
 			} else {
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
-				r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+				r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT;
 
 
 				r_has_alpha_cache=true;
 				r_has_alpha_cache=true;
 				r_compressed=true;
 				r_compressed=true;
@@ -526,20 +537,21 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 					if (srgb_supported) {
 					if (srgb_supported) {
-						r_gl_format=_GL_SRGB_ALPHA_EXT;
-					} else {
 						r_gl_format=GL_RGBA;
 						r_gl_format=GL_RGBA;
+						r_gl_internal_format=_GL_SRGB_ALPHA_EXT;
+					} else {
+						r_gl_internal_format=GL_RGBA;
 						if (!image.empty())
 						if (!image.empty())
 							image.srgb_to_linear();
 							image.srgb_to_linear();
 					}
 					}
 				} else {
 				} else {
-					r_gl_format=GL_RGBA;
+					r_gl_internal_format=GL_RGBA;
 				}
 				}
 				r_has_alpha_cache=true;
 				r_has_alpha_cache=true;
 
 
 			} else {
 			} else {
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
-				r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+				r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV:_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT;
 				r_has_alpha_cache=true;
 				r_has_alpha_cache=true;
 				r_compressed=true;
 				r_compressed=true;
 			};
 			};
@@ -556,20 +568,21 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 					if (srgb_supported) {
 					if (srgb_supported) {
-						r_gl_format=_GL_SRGB_ALPHA_EXT;
-					} else {
 						r_gl_format=GL_RGBA;
 						r_gl_format=GL_RGBA;
+						r_gl_internal_format=_GL_SRGB_ALPHA_EXT;
+					} else {
+						r_gl_internal_format=GL_RGBA;
 						if (!image.empty())
 						if (!image.empty())
 							image.srgb_to_linear();
 							image.srgb_to_linear();
 					}
 					}
 				} else {
 				} else {
-					r_gl_format=GL_RGBA;
+					r_gl_internal_format=GL_RGBA;
 				}
 				}
 				r_has_alpha_cache=true;
 				r_has_alpha_cache=true;
 
 
 			} else {
 			} else {
 
 
-				r_gl_format=_EXT_COMPRESSED_LUMINANCE_LATC1_EXT;
+				r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_LATC1_EXT;
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
 				r_compressed=true;
 				r_compressed=true;
 			};
 			};
@@ -586,19 +599,20 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 					if (srgb_supported) {
 					if (srgb_supported) {
-						r_gl_format=_GL_SRGB_ALPHA_EXT;
-					} else {
 						r_gl_format=GL_RGBA;
 						r_gl_format=GL_RGBA;
+						r_gl_internal_format=_GL_SRGB_ALPHA_EXT;
+					} else {
+						r_gl_internal_format=GL_RGBA;
 						if (!image.empty())
 						if (!image.empty())
 							image.srgb_to_linear();
 							image.srgb_to_linear();
 					}
 					}
 				} else {
 				} else {
-					r_gl_format=GL_RGBA;
+					r_gl_internal_format=GL_RGBA;
 				}
 				}
 				r_has_alpha_cache=true;
 				r_has_alpha_cache=true;
 
 
 			} else {
 			} else {
-				r_gl_format=_EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
+				r_gl_internal_format=_EXT_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
 				r_compressed=true;
 				r_compressed=true;
 			};
 			};
@@ -614,21 +628,22 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 					if (srgb_supported) {
 					if (srgb_supported) {
-						r_gl_format=_GL_SRGB_ALPHA_EXT;
-					} else {
 						r_gl_format=GL_RGBA;
 						r_gl_format=GL_RGBA;
+						r_gl_internal_format=_GL_SRGB_ALPHA_EXT;
+					} else {
+						r_gl_internal_format=GL_RGBA;
 						if (!image.empty())
 						if (!image.empty())
 							image.srgb_to_linear();
 							image.srgb_to_linear();
 					}
 					}
 				} else {
 				} else {
-					r_gl_format=GL_RGBA;
+					r_gl_internal_format=GL_RGBA;
 				}
 				}
 				r_has_alpha_cache=true;
 				r_has_alpha_cache=true;
 
 
 
 
 			} else {
 			} else {
 
 
-				r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
+				r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
 				r_compressed=true;
 				r_compressed=true;
 
 
@@ -645,22 +660,23 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 					if (srgb_supported) {
 					if (srgb_supported) {
-						r_gl_format=_GL_SRGB_ALPHA_EXT;
-					} else {
 						r_gl_format=GL_RGBA;
 						r_gl_format=GL_RGBA;
+						r_gl_internal_format=_GL_SRGB_ALPHA_EXT;
+					} else {
+						r_gl_internal_format=GL_RGBA;
 						if (!image.empty())
 						if (!image.empty())
 							image.srgb_to_linear();
 							image.srgb_to_linear();
 					}
 					}
 				} else {
 				} else {
-					r_gl_format=GL_RGBA;
+					r_gl_internal_format=GL_RGBA;
 				}
 				}
 				r_has_alpha_cache=true;
 				r_has_alpha_cache=true;
 
 
 
 
 			} else {
 			} else {
 
 
-				r_gl_format=_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
-				r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
+				r_gl_internal_format=_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
+				r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
 				r_compressed=true;
 				r_compressed=true;
 
 
@@ -677,19 +693,20 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 					if (srgb_supported) {
 					if (srgb_supported) {
-						r_gl_format=_GL_SRGB_ALPHA_EXT;
-					} else {
 						r_gl_format=GL_RGBA;
 						r_gl_format=GL_RGBA;
+						r_gl_internal_format=_GL_SRGB_ALPHA_EXT;
+					} else {
+						r_gl_internal_format=GL_RGBA;
 						if (!image.empty())
 						if (!image.empty())
 							image.srgb_to_linear();
 							image.srgb_to_linear();
 					}
 					}
 				} else {
 				} else {
-					r_gl_format=GL_RGBA;
+					r_gl_internal_format=GL_RGBA;
 				}
 				}
 				r_has_alpha_cache=true;
 				r_has_alpha_cache=true;
 			} else {
 			} else {
 
 
-				r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
+				r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
 				r_compressed=true;
 				r_compressed=true;
 			}
 			}
@@ -705,19 +722,20 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 					if (srgb_supported) {
 					if (srgb_supported) {
-						r_gl_format=_GL_SRGB_ALPHA_EXT;
-					} else {
 						r_gl_format=GL_RGBA;
 						r_gl_format=GL_RGBA;
+						r_gl_internal_format=_GL_SRGB_ALPHA_EXT;
+					} else {
+						r_gl_internal_format=GL_RGBA;
 						if (!image.empty())
 						if (!image.empty())
 							image.srgb_to_linear();
 							image.srgb_to_linear();
 					}
 					}
 				} else {
 				} else {
-					r_gl_format=GL_RGBA;
+					r_gl_internal_format=GL_RGBA;
 				}
 				}
 				r_has_alpha_cache=true;
 				r_has_alpha_cache=true;
 
 
 			} else {
 			} else {
-				r_gl_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
+				r_gl_internal_format=(srgb_supported && p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR)?_EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:_EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
 				r_compressed=true;
 				r_compressed=true;
 			}
 			}
@@ -734,21 +752,22 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 				if (p_flags&VS::TEXTURE_FLAG_CONVERT_TO_LINEAR) {
 
 
 					if (srgb_supported) {
 					if (srgb_supported) {
-						r_gl_format=_GL_SRGB_EXT;
-					} else {
 						r_gl_format=GL_RGB;
 						r_gl_format=GL_RGB;
+						r_gl_internal_format=_GL_SRGB_EXT;
+					} else {
+						r_gl_internal_format=GL_RGB;
 						if (!image.empty())
 						if (!image.empty())
 							image.srgb_to_linear();
 							image.srgb_to_linear();
 					}
 					}
 				} else {
 				} else {
-					r_gl_format=GL_RGB;
+					r_gl_internal_format=GL_RGB;
 				}
 				}
-				r_gl_format=GL_RGB;
+				r_gl_internal_format=GL_RGB;
 
 
 
 
 			} else {
 			} else {
 
 
-				r_gl_format=_EXT_ETC1_RGB8_OES;
+				r_gl_internal_format=_EXT_ETC1_RGB8_OES;
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
 				r_compressed=true;
 				r_compressed=true;
 			}
 			}
@@ -762,12 +781,12 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 					image.decompress();
 					image.decompress();
 				}
 				}
 				r_gl_components=3;
 				r_gl_components=3;
-				r_gl_format=GL_RGB;
+				r_gl_internal_format=GL_RGB;
 
 
 
 
 			} else {
 			} else {
 
 
-				r_gl_format=_EXT_ATC_RGB_AMD;
+				r_gl_internal_format=_EXT_ATC_RGB_AMD;
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
 				r_compressed=true;
 				r_compressed=true;
 			}
 			}
@@ -781,12 +800,12 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 					image.decompress();
 					image.decompress();
 				}
 				}
 				r_gl_components=4;
 				r_gl_components=4;
-				r_gl_format=GL_RGBA;
+				r_gl_internal_format=GL_RGBA;
 
 
 
 
 			} else {
 			} else {
 
 
-				r_gl_format=_EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD;
+				r_gl_internal_format=_EXT_ATC_RGBA_EXPLICIT_ALPHA_AMD;
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
 				r_compressed=true;
 				r_compressed=true;
 			}
 			}
@@ -800,12 +819,12 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 					image.decompress();
 					image.decompress();
 				}
 				}
 				r_gl_components=4;
 				r_gl_components=4;
-				r_gl_format=GL_RGBA;
+				r_gl_internal_format=GL_RGBA;
 
 
 
 
 			} else {
 			} else {
 
 
-				r_gl_format=_EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD;
+				r_gl_internal_format=_EXT_ATC_RGBA_INTERPOLATED_ALPHA_AMD;
 				r_gl_components=1; //doesn't matter much
 				r_gl_components=1; //doesn't matter much
 				r_compressed=true;
 				r_compressed=true;
 			}
 			}
@@ -816,7 +835,7 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 
 
 			if (!image.empty())
 			if (!image.empty())
 				image.convert(Image::FORMAT_RGB);
 				image.convert(Image::FORMAT_RGB);
-			r_gl_format=GL_RGB;
+			r_gl_internal_format=GL_RGB;
 			r_gl_components=3;
 			r_gl_components=3;
 
 
 		} break;
 		} break;
@@ -827,6 +846,10 @@ Image RasterizerGLES2::_get_gl_image_and_format(const Image& p_image, Image::For
 		}
 		}
 	}
 	}
 
 
+	if (r_gl_format==0) {
+		r_gl_format=r_gl_internal_format;
+	}
+
 	return image;
 	return image;
 }
 }
 
 
@@ -858,6 +881,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I
 	bool has_alpha_cache;
 	bool has_alpha_cache;
 	int components;
 	int components;
 	GLenum format;
 	GLenum format;
+	GLenum internal_format;
 	bool compressed;
 	bool compressed;
 
 
 	int po2_width =  nearest_power_of_2(p_width);
 	int po2_width =  nearest_power_of_2(p_width);
@@ -876,7 +900,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I
 	texture->flags=p_flags;
 	texture->flags=p_flags;
 	texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
 	texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
 
 
-	_get_gl_image_and_format(Image(),texture->format,texture->flags,format,components,has_alpha_cache,compressed);
+	_get_gl_image_and_format(Image(),texture->format,texture->flags,format,internal_format,components,has_alpha_cache,compressed);
 
 
 	bool scale_textures = !compressed && !(p_flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && (!npo2_textures_available || p_flags&VS::TEXTURE_FLAG_MIPMAPS);
 	bool scale_textures = !compressed && !(p_flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && (!npo2_textures_available || p_flags&VS::TEXTURE_FLAG_MIPMAPS);
 
 
@@ -894,6 +918,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I
 
 
 	texture->gl_components_cache=components;
 	texture->gl_components_cache=components;
 	texture->gl_format_cache=format;
 	texture->gl_format_cache=format;
+	texture->gl_internal_format_cache=internal_format;
 	texture->format_has_alpha=has_alpha_cache;
 	texture->format_has_alpha=has_alpha_cache;
 	texture->compressed=compressed;
 	texture->compressed=compressed;
 	texture->has_alpha=false; //by default it doesn't have alpha unless something with alpha is blitteds
 	texture->has_alpha=false; //by default it doesn't have alpha unless something with alpha is blitteds
@@ -908,7 +933,7 @@ void RasterizerGLES2::texture_allocate(RID p_texture,int p_width, int p_height,I
 
 
 	if (p_flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) {
 	if (p_flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) {
 		//prealloc if video
 		//prealloc if video
-		glTexImage2D(texture->target, 0, format, p_width, p_height, 0, format, GL_UNSIGNED_BYTE,NULL);
+		glTexImage2D(texture->target, 0, internal_format, p_width, p_height, 0, format, GL_UNSIGNED_BYTE,NULL);
 	}
 	}
 
 
 	texture->active=true;
 	texture->active=true;
@@ -926,6 +951,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
 
 
 	int components;
 	int components;
 	GLenum format;
 	GLenum format;
+	GLenum internal_format;
 	bool alpha;
 	bool alpha;
 	bool compressed;
 	bool compressed;
 
 
@@ -933,7 +959,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
 		texture->image[p_cube_side]=p_image;
 		texture->image[p_cube_side]=p_image;
 	}
 	}
 
 
-	Image img = _get_gl_image_and_format(p_image, p_image.get_format(),texture->flags,format,components,alpha,compressed);
+	Image img = _get_gl_image_and_format(p_image, p_image.get_format(),texture->flags,format,internal_format,components,alpha,compressed);
 
 
 	if (texture->alloc_width != img.get_width() || texture->alloc_height != img.get_height()) {
 	if (texture->alloc_width != img.get_width() || texture->alloc_height != img.get_height()) {
 
 
@@ -1017,7 +1043,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu
 			if (texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) {
 			if (texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) {
 				glTexSubImage2D( blit_target, i, 0,0,w,h,format,GL_UNSIGNED_BYTE,&read[ofs] );
 				glTexSubImage2D( blit_target, i, 0,0,w,h,format,GL_UNSIGNED_BYTE,&read[ofs] );
 			} else {
 			} else {
-				glTexImage2D(blit_target, i, format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]);
+				glTexImage2D(blit_target, i, internal_format, w, h, 0, format, GL_UNSIGNED_BYTE,&read[ofs]);
 			}
 			}
 
 
 		}
 		}

+ 2 - 1
drivers/gles2/rasterizer_gles2.h

@@ -106,7 +106,7 @@ class RasterizerGLES2 : public Rasterizer {
 
 
 	Vector<float> skel_default;
 	Vector<float> skel_default;
 
 
-	Image _get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed);
+	Image _get_gl_image_and_format(const Image& p_image, Image::Format p_format, uint32_t p_flags,GLenum& r_gl_format,GLenum& r_gl_internal_format,int &r_gl_components,bool &r_has_alpha_cache,bool &r_compressed);
 
 
 	class RenderTarget;
 	class RenderTarget;
 
 
@@ -119,6 +119,7 @@ class RasterizerGLES2 : public Rasterizer {
 
 
 		GLenum target;
 		GLenum target;
 		GLenum gl_format_cache;
 		GLenum gl_format_cache;
+		GLenum gl_internal_format_cache;
 		int gl_components_cache;
 		int gl_components_cache;
 		int data_size; //original data size, useful for retrieving back
 		int data_size; //original data size, useful for retrieving back
 		bool has_alpha;
 		bool has_alpha;

+ 3 - 0
drivers/png/image_loader_png.cpp

@@ -102,6 +102,9 @@ Error ImageLoaderPNG::_load_image(void *rf_up,png_rw_ptr p_func,Image *p_image)
 	png_read_info(png, info);
 	png_read_info(png, info);
 	png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);
 	png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);
 
 
+	png_textp t;
+	//https://svn.gov.pt/projects/ccidadao/repository/middleware-offline/trunk/_src/eidmw/FreeImagePTEiD/Source/FreeImage/PluginPNG.cpp
+	//png_get_text(png,info,)
 	/*
 	/*
 	printf("Image width:%i\n", width);
 	printf("Image width:%i\n", width);
 	printf("Image Height:%i\n", height);
 	printf("Image Height:%i\n", height);

+ 37 - 0
drivers/png/resource_saver_png.cpp

@@ -30,6 +30,7 @@
 #include "scene/resources/texture.h"
 #include "scene/resources/texture.h"
 #include "drivers/png/png.h"
 #include "drivers/png/png.h"
 #include "os/file_access.h"
 #include "os/file_access.h"
+#include "globals.h"
 
 
 static void _write_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length) {
 static void _write_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length) {
 
 
@@ -165,6 +166,42 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t
 	memdelete(f);
 	memdelete(f);
 
 
 
 
+	if (true) {
+
+		bool global_filter = Globals::get_singleton()->get("image_loader/filter");
+		bool global_mipmaps = Globals::get_singleton()->get("image_loader/gen_mipmaps");
+		bool global_repeat = Globals::get_singleton()->get("image_loader/repeat");
+
+		String text;
+
+		if (global_filter!=bool(texture->get_flags()&Texture::FLAG_FILTER)) {
+			text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"filter=true\n":"filter=false\n";
+		}
+		if (global_mipmaps!=bool(texture->get_flags()&Texture::FLAG_MIPMAPS)) {
+			text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"gen_mipmaps=true\n":"gen_mipmaps=false\n";
+		}
+		if (global_repeat!=bool(texture->get_flags()&Texture::FLAG_REPEAT)) {
+			text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"repeat=true\n":"repeat=false\n";
+		}
+		if (bool(texture->get_flags()&Texture::FLAG_ANISOTROPIC_FILTER)) {
+			text+="anisotropic=true\n";
+		}
+		if (bool(texture->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR)) {
+			text+="tolinear=true\n";
+		}
+
+		if (text!="" || FileAccess::exists(p_path+".flags")) {
+
+			f = FileAccess::open(p_path+".flags",FileAccess::WRITE);
+			if (f) {
+
+				f->store_string(text);
+				memdelete(f);
+			}
+		}
+	}
+
+
 	/* cleanup heap allocation */
 	/* cleanup heap allocation */
 
 
 	return OK;
 	return OK;

+ 27 - 9
drivers/theoraplayer/video_stream_theoraplayer.cpp

@@ -306,18 +306,28 @@ int VideoStreamTheoraplayer::get_pending_frame_count() const {
 	if (!clip)
 	if (!clip)
 		return 0;
 		return 0;
 
 
-	if (!frame.empty())
-		return 1;
+	TheoraVideoFrame* f = clip->getNextFrame();
+	return f ? 1 : 0;
+};
+
+
+void VideoStreamTheoraplayer::pop_frame(Ref<ImageTexture> p_tex) {
 
 
 	TheoraVideoFrame* f = clip->getNextFrame();
 	TheoraVideoFrame* f = clip->getNextFrame();
-	if (!f)
-		return 0;
+	if (!f) {
+		return;
+	};
+
+#ifdef GLES2_ENABLED
+//	RasterizerGLES2* r = RasterizerGLES2::get_singleton();
+//	r->_texture_set_data(p_tex, f->mBpp == 3 ? Image::Format_RGB : Image::Format_RGBA, f->mBpp, w, h, f->getBuffer());
+
+#endif
 
 
 	float w=clip->getWidth(),h=clip->getHeight();
 	float w=clip->getWidth(),h=clip->getHeight();
     int imgsize = w * h * f->mBpp;
     int imgsize = w * h * f->mBpp;
 
 
 	int size = f->getStride() * f->getHeight() * f->mBpp;
 	int size = f->getStride() * f->getHeight() * f->mBpp;
-	DVector<uint8_t> data;
 	data.resize(imgsize);
 	data.resize(imgsize);
 	DVector<uint8_t>::Write wr = data.write();
 	DVector<uint8_t>::Write wr = data.write();
     uint8_t* ptr = wr.ptr();
     uint8_t* ptr = wr.ptr();
@@ -329,24 +339,32 @@ int VideoStreamTheoraplayer::get_pending_frame_count() const {
         copymem(ptr + dstofs, f->getBuffer() + dstofs, w * f->mBpp);
         copymem(ptr + dstofs, f->getBuffer() + dstofs, w * f->mBpp);
     };
     };
      */
      */
-	frame = Image();
+	Image frame = Image();
 	frame.create(w, h, 0, f->mBpp == 3 ? Image::FORMAT_RGB : Image::FORMAT_RGBA, data);
 	frame.create(w, h, 0, f->mBpp == 3 ? Image::FORMAT_RGB : Image::FORMAT_RGBA, data);
 
 
 	clip->popFrame();
 	clip->popFrame();
 
 
-	return 1;
+	if (p_tex->get_width() == 0) {
+		p_tex->create(frame.get_width(),frame.get_height(),frame.get_format(),Texture::FLAG_VIDEO_SURFACE|Texture::FLAG_FILTER);
+		p_tex->set_data(frame);
+	} else {
+
+		p_tex->set_data(frame);
+	};
 };
 };
 
 
+/*
 Image VideoStreamTheoraplayer::pop_frame() {
 Image VideoStreamTheoraplayer::pop_frame() {
 
 
 	Image ret = frame;
 	Image ret = frame;
 	frame = Image();
 	frame = Image();
 	return ret;
 	return ret;
 };
 };
+*/
 
 
 Image VideoStreamTheoraplayer::peek_frame() const {
 Image VideoStreamTheoraplayer::peek_frame() const {
 
 
-	return frame;
+	return Image();
 };
 };
 
 
 void VideoStreamTheoraplayer::update(float p_time) {
 void VideoStreamTheoraplayer::update(float p_time) {
@@ -386,7 +404,7 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) {
 	if (p_file.find(".mp4") != -1) {
 	if (p_file.find(".mp4") != -1) {
 		
 		
 		std::string file = p_file.replace("res://", "").utf8().get_data();
 		std::string file = p_file.replace("res://", "").utf8().get_data();
-		clip = mgr->createVideoClip(file);
+		clip = mgr->createVideoClip(file, TH_BGRX, 16);
 		memdelete(f);
 		memdelete(f);
 
 
 	} else {
 	} else {

+ 3 - 2
drivers/theoraplayer/video_stream_theoraplayer.h

@@ -3,6 +3,7 @@
 
 
 #include "scene/resources/video_stream.h"
 #include "scene/resources/video_stream.h"
 #include "io/resource_loader.h"
 #include "io/resource_loader.h"
+#include "scene/resources/texture.h"
 
 
 class TheoraVideoManager;
 class TheoraVideoManager;
 class TheoraVideoClip;
 class TheoraVideoClip;
@@ -11,7 +12,7 @@ class VideoStreamTheoraplayer : public VideoStream {
 
 
 	OBJ_TYPE(VideoStreamTheoraplayer,VideoStream);
 	OBJ_TYPE(VideoStreamTheoraplayer,VideoStream);
 
 
-	mutable Image frame;
+	mutable DVector<uint8_t> data;
 	TheoraVideoManager* mgr;
 	TheoraVideoManager* mgr;
 	TheoraVideoClip* clip;
 	TheoraVideoClip* clip;
 	bool started;
 	bool started;
@@ -37,7 +38,7 @@ public:
 	virtual float get_length() const;
 	virtual float get_length() const;
 
 
 	virtual int get_pending_frame_count() const;
 	virtual int get_pending_frame_count() const;
-	virtual Image pop_frame();
+	virtual void pop_frame(Ref<ImageTexture> p_tex);
 	virtual Image peek_frame() const;
 	virtual Image peek_frame() const;
 
 
 	void update(float p_time);
 	void update(float p_time);

+ 14 - 10
modules/gdscript/gd_compiler.cpp

@@ -65,18 +65,18 @@ bool GDCompiler::_create_unary_operator(CodeGen& codegen,const GDParser::Operato
 	return true;
 	return true;
 }
 }
 
 
-bool GDCompiler::_create_binary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level) {
+bool GDCompiler::_create_binary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level,bool p_initializer) {
 
 
 	ERR_FAIL_COND_V(on->arguments.size()!=2,false);
 	ERR_FAIL_COND_V(on->arguments.size()!=2,false);
 
 
 
 
-	int src_address_a = _parse_expression(codegen,on->arguments[0],p_stack_level);
+	int src_address_a = _parse_expression(codegen,on->arguments[0],p_stack_level,false,p_initializer);
 	if (src_address_a<0)
 	if (src_address_a<0)
 		return false;
 		return false;
 	if (src_address_a&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS)
 	if (src_address_a&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS)
 		p_stack_level++; //uses stack for return, increase stack
 		p_stack_level++; //uses stack for return, increase stack
 
 
-	int src_address_b = _parse_expression(codegen,on->arguments[1],p_stack_level);
+	int src_address_b = _parse_expression(codegen,on->arguments[1],p_stack_level,false,p_initializer);
 	if (src_address_b<0)
 	if (src_address_b<0)
 		return false;
 		return false;
 
 
@@ -111,6 +111,7 @@ int GDCompiler::_parse_assign_right_expression(CodeGen& codegen,const GDParser::
 
 
 	Variant::Operator var_op=Variant::OP_MAX;
 	Variant::Operator var_op=Variant::OP_MAX;
 
 
+
 	switch(p_expression->op) {
 	switch(p_expression->op) {
 
 
 		case GDParser::OperatorNode::OP_ASSIGN_ADD: var_op=Variant::OP_ADD; break;
 		case GDParser::OperatorNode::OP_ASSIGN_ADD: var_op=Variant::OP_ADD; break;
@@ -123,6 +124,7 @@ int GDCompiler::_parse_assign_right_expression(CodeGen& codegen,const GDParser::
 		case GDParser::OperatorNode::OP_ASSIGN_BIT_AND: var_op=Variant::OP_BIT_AND; break;
 		case GDParser::OperatorNode::OP_ASSIGN_BIT_AND: var_op=Variant::OP_BIT_AND; break;
 		case GDParser::OperatorNode::OP_ASSIGN_BIT_OR: var_op=Variant::OP_BIT_OR; break;
 		case GDParser::OperatorNode::OP_ASSIGN_BIT_OR: var_op=Variant::OP_BIT_OR; break;
 		case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR: var_op=Variant::OP_BIT_XOR; break;
 		case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR: var_op=Variant::OP_BIT_XOR; break;
+		case GDParser::OperatorNode::OP_INIT_ASSIGN:
 		case GDParser::OperatorNode::OP_ASSIGN: {
 		case GDParser::OperatorNode::OP_ASSIGN: {
 
 
 			//none
 			//none
@@ -133,12 +135,14 @@ int GDCompiler::_parse_assign_right_expression(CodeGen& codegen,const GDParser::
 		}
 		}
 	}
 	}
 
 
+	bool initializer = p_expression->op==GDParser::OperatorNode::OP_INIT_ASSIGN;
+
 	if (var_op==Variant::OP_MAX) {
 	if (var_op==Variant::OP_MAX) {
 
 
-		return _parse_expression(codegen,p_expression->arguments[1],p_stack_level);
+		return _parse_expression(codegen,p_expression->arguments[1],p_stack_level,false,initializer);
 	}
 	}
 
 
-	if (!_create_binary_operator(codegen,p_expression,var_op,p_stack_level))
+	if (!_create_binary_operator(codegen,p_expression,var_op,p_stack_level,initializer))
 		return -1;
 		return -1;
 
 
 	int dst_addr=(p_stack_level)|(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
 	int dst_addr=(p_stack_level)|(GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS);
@@ -148,7 +152,7 @@ int GDCompiler::_parse_assign_right_expression(CodeGen& codegen,const GDParser::
 
 
 }
 }
 
 
-int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root) {
+int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root,bool p_initializer) {
 
 
 
 
 	switch(p_expression->type) {
 	switch(p_expression->type) {
@@ -165,17 +169,16 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
 			StringName identifier = in->name;
 			StringName identifier = in->name;
 
 
 			// TRY STACK!
 			// TRY STACK!
-			if (codegen.stack_identifiers.has(identifier)) {
+			if (!p_initializer && codegen.stack_identifiers.has(identifier)) {
 
 
 				int pos = codegen.stack_identifiers[identifier];
 				int pos = codegen.stack_identifiers[identifier];
 				return pos|(GDFunction::ADDR_TYPE_STACK_VARIABLE<<GDFunction::ADDR_BITS);
 				return pos|(GDFunction::ADDR_TYPE_STACK_VARIABLE<<GDFunction::ADDR_BITS);
 
 
 			}
 			}
-			//TRY ARGUMENTS!
+			//TRY MEMBERS!
 			if (!codegen.function_node || !codegen.function_node->_static) {
 			if (!codegen.function_node || !codegen.function_node->_static) {
 
 
 				// TRY MEMBER VARIABLES!
 				// TRY MEMBER VARIABLES!
-
 				//static function
 				//static function
 				if (codegen.script->member_indices.has(identifier)) {
 				if (codegen.script->member_indices.has(identifier)) {
 
 
@@ -686,6 +689,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
 				case GDParser::OperatorNode::OP_ASSIGN_BIT_AND:
 				case GDParser::OperatorNode::OP_ASSIGN_BIT_AND:
 				case GDParser::OperatorNode::OP_ASSIGN_BIT_OR:
 				case GDParser::OperatorNode::OP_ASSIGN_BIT_OR:
 				case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR:
 				case GDParser::OperatorNode::OP_ASSIGN_BIT_XOR:
+				case GDParser::OperatorNode::OP_INIT_ASSIGN:
 				case GDParser::OperatorNode::OP_ASSIGN: {
 				case GDParser::OperatorNode::OP_ASSIGN: {
 
 
 					ERR_FAIL_COND_V(on->arguments.size()!=2,-1);
 					ERR_FAIL_COND_V(on->arguments.size()!=2,-1);
@@ -843,7 +847,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre
 
 
 						int slevel = p_stack_level;
 						int slevel = p_stack_level;
 
 
-						int dst_address_a = _parse_expression(codegen,on->arguments[0],slevel);
+						int dst_address_a = _parse_expression(codegen,on->arguments[0],slevel,false,on->op==GDParser::OperatorNode::OP_INIT_ASSIGN);
 						if (dst_address_a<0)
 						if (dst_address_a<0)
 							return -1;
 							return -1;
 
 

+ 2 - 2
modules/gdscript/gd_compiler.h

@@ -153,11 +153,11 @@ class GDCompiler {
 	void _set_error(const String& p_error,const GDParser::Node *p_node);
 	void _set_error(const String& p_error,const GDParser::Node *p_node);
 
 
 	bool _create_unary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level);
 	bool _create_unary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level);
-	bool _create_binary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level);
+	bool _create_binary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level,bool p_initializer=false);
 
 
 	//int _parse_subexpression(CodeGen& codegen,const GDParser::BlockNode *p_block,const GDParser::Node *p_expression);
 	//int _parse_subexpression(CodeGen& codegen,const GDParser::BlockNode *p_block,const GDParser::Node *p_expression);
 	int _parse_assign_right_expression(CodeGen& codegen,const GDParser::OperatorNode *p_expression, int p_stack_level);
 	int _parse_assign_right_expression(CodeGen& codegen,const GDParser::OperatorNode *p_expression, int p_stack_level);
-	int _parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root=false);
+	int _parse_expression(CodeGen& codegen,const GDParser::Node *p_expression, int p_stack_level,bool p_root=false,bool p_initializer=false);
 	Error _parse_block(CodeGen& codegen,const GDParser::BlockNode *p_block,int p_stack_level=0,int p_break_addr=-1,int p_continue_addr=-1);
 	Error _parse_block(CodeGen& codegen,const GDParser::BlockNode *p_block,int p_stack_level=0,int p_break_addr=-1,int p_continue_addr=-1);
 	Error _parse_function(GDScript *p_script,const GDParser::ClassNode *p_class,const GDParser::FunctionNode *p_func);
 	Error _parse_function(GDScript *p_script,const GDParser::ClassNode *p_class,const GDParser::FunctionNode *p_func);
 	Error _parse_class(GDScript *p_script,GDScript *p_owner,const GDParser::ClassNode *p_class);
 	Error _parse_class(GDScript *p_script,GDScript *p_owner,const GDParser::ClassNode *p_class);

+ 1 - 0
modules/gdscript/gd_editor.cpp

@@ -33,6 +33,7 @@
 void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
 void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
 
 
 	p_delimiters->push_back("#");
 	p_delimiters->push_back("#");
+	p_delimiters->push_back("\"\"\"");
 
 
 }
 }
 void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const {
 void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const {

+ 1 - 1
modules/gdscript/gd_parser.cpp

@@ -2429,7 +2429,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
 					id->name=member.identifier;
 					id->name=member.identifier;
 
 
 					OperatorNode *op = alloc_node<OperatorNode>();
 					OperatorNode *op = alloc_node<OperatorNode>();
-					op->op=OperatorNode::OP_ASSIGN;
+					op->op=OperatorNode::OP_INIT_ASSIGN;
 					op->arguments.push_back(id);
 					op->arguments.push_back(id);
 					op->arguments.push_back(subexpr);
 					op->arguments.push_back(subexpr);
 
 

+ 1 - 0
modules/gdscript/gd_parser.h

@@ -215,6 +215,7 @@ public:
 			OP_MOD,
 			OP_MOD,
 			OP_SHIFT_LEFT,
 			OP_SHIFT_LEFT,
 			OP_SHIFT_RIGHT,
 			OP_SHIFT_RIGHT,
+			OP_INIT_ASSIGN,
 			OP_ASSIGN,
 			OP_ASSIGN,
 			OP_ASSIGN_ADD,
 			OP_ASSIGN_ADD,
 			OP_ASSIGN_SUB,
 			OP_ASSIGN_SUB,

+ 1 - 0
modules/gdscript/gd_script.cpp

@@ -2448,6 +2448,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const  {
 		"if"	,
 		"if"	,
 		"in"	,
 		"in"	,
 		"null"	,
 		"null"	,
+		"not"	,
 		"return"	,
 		"return"	,
 		"self"	,
 		"self"	,
 		"while"	,
 		"while"	,

+ 21 - 9
modules/gdscript/gd_tokenizer.cpp

@@ -239,8 +239,7 @@ void GDTokenizerText::_advance() {
 
 
 
 
 		bool is_node_path  = false;
 		bool is_node_path  = false;
-		bool is_string     = false;
-		bool is_string_alt = false;
+		StringMode string_mode=STRING_DOUBLE_QUOTE;
 
 
 		switch(GETCHAR(0)) {
 		switch(GETCHAR(0)) {
 			case 0:
 			case 0:
@@ -538,22 +537,35 @@ void GDTokenizerText::_advance() {
 				is_node_path=true;
 				is_node_path=true;
 				
 				
 			case '\'':
 			case '\'':
-			  is_string_alt = true;
+				string_mode=STRING_SINGLE_QUOTE;
 			case '"': {
 			case '"': {
-			  is_string = is_string_alt ? false : true;
 
 
 				int i=1;
 				int i=1;
+				if (string_mode==STRING_DOUBLE_QUOTE && GETCHAR(i)=='"' && GETCHAR(i+1)=='"') {
+					i+=2;
+					string_mode=STRING_MULTILINE;
+
+				}
+
+
 				String str;
 				String str;
 				while(true) {
 				while(true) {
-					if (CharType(GETCHAR(i)==0)) {
+					if (CharType(GETCHAR(i))==0) {
 
 
 						_make_error("Unterminated String");
 						_make_error("Unterminated String");
 						return;
 						return;
-					} else if( CharType(GETCHAR(i)=='"') && is_string ) {
+					} else if( string_mode==STRING_DOUBLE_QUOTE && CharType(GETCHAR(i))=='"' ) {
 						break;
 						break;
-					} else if( CharType(GETCHAR(i)=='\'') && is_string_alt ) {
-					  break;
-					} else if (CharType(GETCHAR(i)=='\\')) {
+					} else if( string_mode==STRING_SINGLE_QUOTE && CharType(GETCHAR(i))=='\'' ) {
+						break;
+					} else if( string_mode==STRING_MULTILINE && CharType(GETCHAR(i))=='\"' &&  CharType(GETCHAR(i+1))=='\"' && CharType(GETCHAR(i+2))=='\"') {
+						i+=2;
+						break;
+					} else if( string_mode!=STRING_MULTILINE && CharType(GETCHAR(i))=='\n') {
+						_make_error("Unexpected EOL at String.");
+						return;
+
+					} else if (CharType(GETCHAR(i))=='\\') {
 						//escaped characters...
 						//escaped characters...
 						i++;
 						i++;
 						CharType next = GETCHAR(i);
 						CharType next = GETCHAR(i);

+ 7 - 0
modules/gdscript/gd_tokenizer.h

@@ -122,6 +122,13 @@ public:
 	};
 	};
 
 
 protected:
 protected:
+
+	enum StringMode {
+		STRING_SINGLE_QUOTE,
+		STRING_DOUBLE_QUOTE,
+		STRING_MULTILINE
+	};
+
 	static const char* token_names[TK_MAX];
 	static const char* token_names[TK_MAX];
 public:
 public:
 	static const char *get_token_name(Token p_token);
 	static const char *get_token_name(Token p_token);

+ 32 - 5
platform/osx/audio_driver_osx.cpp

@@ -101,7 +101,16 @@ OSStatus AudioDriverOSX::output_callback(void *inRefCon,
 	AudioBuffer *abuf;
 	AudioBuffer *abuf;
 	AudioDriverOSX* ad = (AudioDriverOSX*)inRefCon;
 	AudioDriverOSX* ad = (AudioDriverOSX*)inRefCon;
 
 
-	if (!ad->active) {
+	bool mix = true;
+
+	if (!ad->active)
+		mix = false;
+	else if (ad->mutex) {
+		mix = ad->mutex->try_lock() == OK;
+	};
+
+
+	if (!mix) {
 		for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) {
 		for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) {
 			abuf = &ioData->mBuffers[i];
 			abuf = &ioData->mBuffers[i];
 			zeromem(abuf->mData, abuf->mDataByteSize);
 			zeromem(abuf->mData, abuf->mDataByteSize);
@@ -120,9 +129,9 @@ OSStatus AudioDriverOSX::output_callback(void *inRefCon,
 		while (frames_left) {
 		while (frames_left) {
 
 
 			int frames = MIN(frames_left, ad->buffer_frames);
 			int frames = MIN(frames_left, ad->buffer_frames);
-			ad->lock();
+			//ad->lock();
 			ad->audio_server_process(frames, ad->samples_in);
 			ad->audio_server_process(frames, ad->samples_in);
-			ad->unlock();
+			//ad->unlock();
 
 
 			for(int i = 0; i < frames * ad->channels; i++) {
 			for(int i = 0; i < frames * ad->channels; i++) {
 
 
@@ -134,6 +143,9 @@ OSStatus AudioDriverOSX::output_callback(void *inRefCon,
 		};
 		};
 	};
 	};
 
 
+	if (ad->mutex)
+		ad->mutex->unlock();
+
 	return 0;
 	return 0;
 };
 };
 
 
@@ -149,12 +161,27 @@ AudioDriverSW::OutputFormat AudioDriverOSX::get_output_format() const {
 	return OUTPUT_STEREO;
 	return OUTPUT_STEREO;
 };
 };
 
 
-void AudioDriverOSX::lock() {};
-void AudioDriverOSX::unlock() {};
+void AudioDriverOSX::lock() {
+	if (active && mutex)
+		mutex->lock();
+};
+void AudioDriverOSX::unlock() {
+	if (active && mutex)
+		mutex->unlock();
+};
 
 
 void AudioDriverOSX::finish() {
 void AudioDriverOSX::finish() {
 
 
 	memdelete_arr(samples_in);
 	memdelete_arr(samples_in);
 };
 };
 
 
+AudioDriverOSX::AudioDriverOSX() {
+
+	mutex=Mutex::create();//NULL;
+};
+
+AudioDriverOSX::~AudioDriverOSX() {
+
+};
+
 #endif
 #endif

+ 4 - 0
platform/osx/audio_driver_osx.h

@@ -39,6 +39,7 @@ class AudioDriverOSX : public AudioDriverSW {
 
 
 	AudioComponentInstance audio_unit;
 	AudioComponentInstance audio_unit;
 	bool active;
 	bool active;
+	Mutex *mutex;
 
 
 	int channels;
 	int channels;
 	int32_t* samples_in;
 	int32_t* samples_in;
@@ -64,6 +65,9 @@ public:
 	virtual void lock();
 	virtual void lock();
 	virtual void unlock();
 	virtual void unlock();
 	virtual void finish();
 	virtual void finish();
+
+	AudioDriverOSX();
+	~AudioDriverOSX();
 };
 };
 
 
 #endif
 #endif

+ 10 - 0
platform/windows/detect.py

@@ -209,6 +209,16 @@ def configure(env):
 		env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
 		env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
 		env.Append(CCFLAGS=['-DGLES2_ENABLED','-DGLES1_ENABLED','-DGLEW_ENABLED'])
 		env.Append(CCFLAGS=['-DGLES2_ENABLED','-DGLES1_ENABLED','-DGLEW_ENABLED'])
 		env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','wsock32','kernel32'])
 		env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','wsock32','kernel32'])
+
+		if (env["bits"]=="32" and env["mingw64_for_32"]!="yes"):
+#			env.Append(LIBS=['gcc_s'])
+			#--with-arch=i686
+			env.Append(CPPFLAGS=['-march=i686'])
+			env.Append(LINKFLAGS=['-march=i686'])
+
+
+
+
 		#'d3dx9d'
 		#'d3dx9d'
 		env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
 		env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
 		env.Append(LINKFLAGS=['-g'])
 		env.Append(LINKFLAGS=['-g'])

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

@@ -156,13 +156,13 @@ bool CollisionObject2D::_get(const StringName& p_name,Variant &r_ret) const {
 
 
 void CollisionObject2D::_get_property_list( List<PropertyInfo> *p_list) const {
 void CollisionObject2D::_get_property_list( List<PropertyInfo> *p_list) const {
 
 
-	p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR) );
+	p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) );
 
 
 	for(int i=0;i<shapes.size();i++) {
 	for(int i=0;i<shapes.size();i++) {
 		String path="shapes/"+itos(i)+"/";
 		String path="shapes/"+itos(i)+"/";
-		p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D",PROPERTY_USAGE_NOEDITOR) );
-		p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
-		p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
+		p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) );
+		p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) );
+		p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) );
 	}
 	}
 }
 }
 
 

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

@@ -44,7 +44,6 @@
 void CollisionShape::_update_body() {
 void CollisionShape::_update_body() {
 
 
 
 
-
 	if (get_parent() && get_parent()->cast_to<CollisionObject>())
 	if (get_parent() && get_parent()->cast_to<CollisionObject>())
 		get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children();
 		get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children();
 
 
@@ -72,7 +71,7 @@ void CollisionShape::make_convex_from_brothers() {
 	}
 	}
 
 
 }
 }
-
+/*
 
 
 void CollisionShape::_update_indicator() {
 void CollisionShape::_update_indicator() {
 
 
@@ -300,9 +299,12 @@ void CollisionShape::_update_indicator() {
 
 
 }
 }
 
 
-
+*/
 void CollisionShape::_add_to_collision_object(Object* p_cshape) {
 void CollisionShape::_add_to_collision_object(Object* p_cshape) {
 
 
+	if (unparenting)
+		return;
+
 	CollisionObject *co=p_cshape->cast_to<CollisionObject>();
 	CollisionObject *co=p_cshape->cast_to<CollisionObject>();
 	ERR_FAIL_COND(!co);
 	ERR_FAIL_COND(!co);
 
 
@@ -318,22 +320,25 @@ void CollisionShape::_notification(int p_what) {
 
 
 	switch(p_what) {
 	switch(p_what) {
 
 
-		case NOTIFICATION_ENTER_WORLD: {
-			indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
+		case NOTIFICATION_ENTER_SCENE: {
+			unparenting=false;
+
+			//indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario());
 		} break;
 		} break;
 		case NOTIFICATION_TRANSFORM_CHANGED: {
 		case NOTIFICATION_TRANSFORM_CHANGED: {
-			VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
+		//	VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform());
 			if (updating_body) {
 			if (updating_body) {
 				_update_body();
 				_update_body();
 			}
 			}
 		} break;
 		} break;
-		case NOTIFICATION_EXIT_WORLD: {
-			if (indicator_instance.is_valid()) {
+		case NOTIFICATION_EXIT_SCENE: {
+		/*	if (indicator_instance.is_valid()) {
 				VisualServer::get_singleton()->free(indicator_instance);
 				VisualServer::get_singleton()->free(indicator_instance);
 				indicator_instance=RID();
 				indicator_instance=RID();
-			}
+			}*/
 		} break;
 		} break;
 		case NOTIFICATION_UNPARENTED: {
 		case NOTIFICATION_UNPARENTED: {
+			unparenting=true;
 			if (updating_body)
 			if (updating_body)
 				_update_body();
 				_update_body();
 		} break;
 		} break;
@@ -411,15 +416,16 @@ bool CollisionShape::is_trigger() const{
 
 
 CollisionShape::CollisionShape() {
 CollisionShape::CollisionShape() {
 
 
-	indicator = VisualServer::get_singleton()->mesh_create();
+	//indicator = VisualServer::get_singleton()->mesh_create();
 	updating_body=true;
 	updating_body=true;
+	unparenting=false;
     trigger=false;
     trigger=false;
 }
 }
 
 
 CollisionShape::~CollisionShape() {
 CollisionShape::~CollisionShape() {
 	if (!shape.is_null())
 	if (!shape.is_null())
 		shape->unregister_owner(this);
 		shape->unregister_owner(this);
-	VisualServer::get_singleton()->free(indicator);
+	//VisualServer::get_singleton()->free(indicator);
 }
 }
 
 
 #if 0
 #if 0

+ 5 - 1
scene/3d/body_shape.h

@@ -37,19 +37,23 @@ class CollisionShape : public Spatial {
 	OBJ_TYPE( CollisionShape, Spatial );
 	OBJ_TYPE( CollisionShape, Spatial );
 	OBJ_CATEGORY("3D Physics Nodes");
 	OBJ_CATEGORY("3D Physics Nodes");
 
 
+	Ref<Shape> shape;
+
+	/*
 	RID _get_visual_instance_rid() const;
 	RID _get_visual_instance_rid() const;
 
 
-	Ref<Shape> shape;
 
 
 	void _update_indicator();
 	void _update_indicator();
 
 
 	RID material;
 	RID material;
 	RID indicator;
 	RID indicator;
 	RID indicator_instance;
 	RID indicator_instance;
+	*/
 
 
 	void resource_changed(RES res);
 	void resource_changed(RES res);
 
 
 	bool updating_body;
 	bool updating_body;
+	bool unparenting;
 	bool trigger;
 	bool trigger;
 
 
 	void _update_body();
 	void _update_body();

+ 4 - 4
scene/3d/collision_object.cpp

@@ -160,13 +160,13 @@ bool CollisionObject::_get(const StringName& p_name,Variant &r_ret) const {
 
 
 void CollisionObject::_get_property_list( List<PropertyInfo> *p_list) const {
 void CollisionObject::_get_property_list( List<PropertyInfo> *p_list) const {
 
 
-	p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR) );
+	p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) );
 
 
 	for(int i=0;i<shapes.size();i++) {
 	for(int i=0;i<shapes.size();i++) {
 		String path="shapes/"+itos(i)+"/";
 		String path="shapes/"+itos(i)+"/";
-		p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape",PROPERTY_USAGE_NOEDITOR) );
-		p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
-		p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
+		p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) );
+		p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) );
+		p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) );
 
 
 	}
 	}
 }
 }

+ 2 - 2
scene/3d/interpolated_camera.cpp

@@ -50,7 +50,7 @@ void InterpolatedCamera::_notification(int p_what) {
 
 
 				float delta = speed*get_process_delta_time();
 				float delta = speed*get_process_delta_time();
 				Transform target_xform = node->get_global_transform();
 				Transform target_xform = node->get_global_transform();
-				Transform local_transform = get_transform();
+				Transform local_transform = get_global_transform();
 				local_transform = local_transform.interpolate_with(target_xform,delta);
 				local_transform = local_transform.interpolate_with(target_xform,delta);
 				set_global_transform(local_transform);
 				set_global_transform(local_transform);
 
 
@@ -136,7 +136,7 @@ void InterpolatedCamera::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("set_target_path","target_path"),&InterpolatedCamera::set_target_path);
 	ObjectTypeDB::bind_method(_MD("set_target_path","target_path"),&InterpolatedCamera::set_target_path);
 	ObjectTypeDB::bind_method(_MD("get_target_path"),&InterpolatedCamera::get_target_path);
 	ObjectTypeDB::bind_method(_MD("get_target_path"),&InterpolatedCamera::get_target_path);
-	ObjectTypeDB::bind_method(_MD("set_target","target"),&InterpolatedCamera::_set_target);
+	ObjectTypeDB::bind_method(_MD("set_target","target:Camera"),&InterpolatedCamera::_set_target);
 
 
 	ObjectTypeDB::bind_method(_MD("set_speed","speed"),&InterpolatedCamera::set_speed);
 	ObjectTypeDB::bind_method(_MD("set_speed","speed"),&InterpolatedCamera::set_speed);
 	ObjectTypeDB::bind_method(_MD("get_speed"),&InterpolatedCamera::get_speed);
 	ObjectTypeDB::bind_method(_MD("get_speed"),&InterpolatedCamera::get_speed);

+ 8 - 0
scene/gui/base_button.cpp

@@ -346,6 +346,8 @@ bool BaseButton::get_click_on_press() const {
 }
 }
 
 
 
 
+
+
 void BaseButton::_bind_methods() {
 void BaseButton::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("_input_event"),&BaseButton::_input_event);
 	ObjectTypeDB::bind_method(_MD("_input_event"),&BaseButton::_input_event);
@@ -358,6 +360,7 @@ void BaseButton::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("is_disabled"),&BaseButton::is_disabled);
 	ObjectTypeDB::bind_method(_MD("is_disabled"),&BaseButton::is_disabled);
 	ObjectTypeDB::bind_method(_MD("set_click_on_press","enable"),&BaseButton::set_click_on_press);
 	ObjectTypeDB::bind_method(_MD("set_click_on_press","enable"),&BaseButton::set_click_on_press);
 	ObjectTypeDB::bind_method(_MD("get_click_on_press"),&BaseButton::get_click_on_press);
 	ObjectTypeDB::bind_method(_MD("get_click_on_press"),&BaseButton::get_click_on_press);
+	ObjectTypeDB::bind_method(_MD("get_draw_mode"),&BaseButton::get_draw_mode);
 
 
 	ADD_SIGNAL( MethodInfo("pressed" ) );
 	ADD_SIGNAL( MethodInfo("pressed" ) );
 	ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) );
 	ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) );
@@ -365,6 +368,11 @@ void BaseButton::_bind_methods() {
 	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode"));
 	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode"));
 	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "click_on_press"), _SCS("set_click_on_press"), _SCS("get_click_on_press"));
 	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "click_on_press"), _SCS("set_click_on_press"), _SCS("get_click_on_press"));
 
 
+	BIND_CONSTANT( DRAW_NORMAL );
+	BIND_CONSTANT( DRAW_PRESSED );
+	BIND_CONSTANT( DRAW_HOVER );
+	BIND_CONSTANT( DRAW_DISABLED );
+
 }
 }
 
 
 BaseButton::BaseButton() {
 BaseButton::BaseButton() {

+ 12 - 8
scene/gui/base_button.h

@@ -61,15 +61,8 @@ class BaseButton : public Control {
 		
 		
 protected:
 protected:
 
 
-	enum DrawMode {
-		DRAW_NORMAL,
-		DRAW_PRESSED,
-		DRAW_HOVER,
-		DRAW_DISABLED,
-	};
 
 
 
 
-	DrawMode get_draw_mode() const;
 	
 	
 	virtual void pressed();
 	virtual void pressed();
 	virtual void toggled(bool p_pressed);
 	virtual void toggled(bool p_pressed);
@@ -78,7 +71,16 @@ protected:
 	void _notification(int p_what);
 	void _notification(int p_what);
 
 
 public:
 public:
-	
+
+	enum DrawMode {
+		DRAW_NORMAL,
+		DRAW_PRESSED,
+		DRAW_HOVER,
+		DRAW_DISABLED,
+	};
+
+	DrawMode get_draw_mode() const;
+
 	/* Signals */
 	/* Signals */
 	
 	
 	bool is_pressed() const; ///< return wether button is pressed (toggled in)
 	bool is_pressed() const; ///< return wether button is pressed (toggled in)
@@ -101,4 +103,6 @@ public:
 
 
 };
 };
 
 
+VARIANT_ENUM_CAST( BaseButton::DrawMode );
+
 #endif
 #endif

+ 10 - 15
scene/gui/video_player.cpp

@@ -45,20 +45,15 @@ void VideoPlayer::_notification(int p_notification) {
 				return;
 				return;
 			if (paused)
 			if (paused)
 				return;
 				return;
+			if (!stream->is_playing())
+				return;
 
 
 			stream->update(get_scene()->get_idle_process_time());
 			stream->update(get_scene()->get_idle_process_time());
-			while (stream->get_pending_frame_count()) {
-
-				Image img = stream->pop_frame();
-				if (texture->get_width() == 0) {
-					texture->create(img.get_width(),img.get_height(),img.get_format(),Texture::FLAG_VIDEO_SURFACE|Texture::FLAG_FILTER);
-					update();
-					minimum_size_changed();
-				} else {
-
-					if (stream->get_pending_frame_count() == 0)
-						texture->set_data(img);
-				};
+			int prev_width = texture->get_width();
+			stream->pop_frame(texture);
+			if (prev_width == 0) {
+				update();
+				minimum_size_changed();
 			};
 			};
 
 
 		} break;
 		} break;
@@ -257,9 +252,9 @@ void VideoPlayer::_bind_methods() {
 VideoPlayer::VideoPlayer() {
 VideoPlayer::VideoPlayer() {
 
 
 	volume=1;
 	volume=1;
-	loops=false;
-	paused=false;
-	autoplay=false;
+	loops = false;
+	paused = false;
+	autoplay = false;
 	expand = true;
 	expand = true;
 	loops = false;
 	loops = false;
 };
 };

+ 44 - 3
scene/io/resource_format_image.cpp

@@ -131,14 +131,55 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina
 		
 		
 		
 		
 		uint32_t flags=0;
 		uint32_t flags=0;
-		if (bool(GLOBAL_DEF("image_loader/filter",true)))
+
+		FileAccess *f2 = FileAccess::open(p_path+".flags",FileAccess::READ);
+		Map<String,bool> flags_found;
+		if (f2) {
+
+			while(!f2->eof_reached()) {
+				String l2 = f2->get_line();
+				int eqpos = l2.find("=");
+				if (eqpos!=-1) {
+					String flag=l2.substr(0,eqpos).strip_edges();
+					String val=l2.substr(eqpos+1,l2.length()).strip_edges().to_lower();
+					flags_found[flag]=(val=="true" || val=="1")?true:false;
+				}
+			}
+			memdelete(f2);
+		}
+
+
+		if (flags_found.has("filter")) {
+			if (flags_found["filter"])
+				flags|=Texture::FLAG_FILTER;
+		} else if (bool(GLOBAL_DEF("image_loader/filter",true))) {
 			flags|=Texture::FLAG_FILTER;
 			flags|=Texture::FLAG_FILTER;
-		if (bool(GLOBAL_DEF("image_loader/gen_mipmaps",true)))
+		}
+
+
+		if (flags_found.has("gen_mipmaps")) {
+			if (flags_found["gen_mipmaps"])
+				flags|=Texture::FLAG_MIPMAPS;
+		} else if (bool(GLOBAL_DEF("image_loader/gen_mipmaps",true))) {
 			flags|=Texture::FLAG_MIPMAPS;
 			flags|=Texture::FLAG_MIPMAPS;
-		if (bool(GLOBAL_DEF("image_loader/repeat",false)))
+		}
+
+		if (flags_found.has("repeat")) {
+			if (flags_found["repeat"])
+				flags|=Texture::FLAG_REPEAT;
+		} else if (bool(GLOBAL_DEF("image_loader/repeat",true))) {
 			flags|=Texture::FLAG_REPEAT;
 			flags|=Texture::FLAG_REPEAT;
+		}
 
 
+		if (flags_found.has("anisotropic")) {
+			if (flags_found["anisotropic"])
+				flags|=Texture::FLAG_ANISOTROPIC_FILTER;
+		}
 
 
+		if (flags_found.has("tolinear")) {
+			if (flags_found["tolinear"])
+				flags|=Texture::FLAG_CONVERT_TO_LINEAR;
+		}
 
 
 		if (debug_load_times)
 		if (debug_load_times)
 			begtime=OS::get_singleton()->get_ticks_usec();
 			begtime=OS::get_singleton()->get_ticks_usec();

+ 15 - 1
scene/main/node.cpp

@@ -1234,7 +1234,7 @@ void Node::generate_instance_state() {
 	for( List<PropertyInfo>::Element *E=properties.front();E;E=E->next() ) {
 	for( List<PropertyInfo>::Element *E=properties.front();E;E=E->next() ) {
 
 
 		PropertyInfo &pi=E->get();
 		PropertyInfo &pi=E->get();
-		if (!(pi.usage&PROPERTY_USAGE_EDITOR) || !(pi.usage&PROPERTY_USAGE_STORAGE))
+		if ((pi.usage&PROPERTY_USAGE_NO_INSTANCE_STATE) || !(pi.usage&PROPERTY_USAGE_EDITOR) || !(pi.usage&PROPERTY_USAGE_STORAGE))
 			continue;
 			continue;
 
 
 		data.instance_state[pi.name]=get(pi.name);
 		data.instance_state[pi.name]=get(pi.name);
@@ -1424,6 +1424,20 @@ Node *Node::duplicate_and_reown(const Map<Node*,Node*>& p_reown_map) const {
 
 
 	node->set_name(get_name());
 	node->set_name(get_name());
 
 
+	List<PropertyInfo> plist;
+
+	get_property_list(&plist);
+
+	for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
+
+		if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
+			continue;
+		String name = E->get().name;
+		node->set( name, get(name) );
+
+	}
+
+
 	for(int i=0;i<get_child_count();i++) {
 	for(int i=0;i<get_child_count();i++) {
 
 
 		get_child(i)->_duplicate_and_reown(node,p_reown_map);
 		get_child(i)->_duplicate_and_reown(node,p_reown_map);

+ 4 - 3
scene/main/viewport.cpp

@@ -243,7 +243,7 @@ void Viewport::update_worlds() {
 
 
 
 
 void Viewport::_test_new_mouseover(ObjectID new_collider) {
 void Viewport::_test_new_mouseover(ObjectID new_collider) {
-
+#ifndef _3D_DISABLED
 	if (new_collider!=physics_object_over) {
 	if (new_collider!=physics_object_over) {
 
 
 		if (physics_object_over) {
 		if (physics_object_over) {
@@ -271,7 +271,7 @@ void Viewport::_test_new_mouseover(ObjectID new_collider) {
 		physics_object_over=new_collider;
 		physics_object_over=new_collider;
 
 
 	}
 	}
-
+#endif
 
 
 }
 }
 
 
@@ -353,7 +353,7 @@ void Viewport::_notification(int p_what) {
 		case NOTIFICATION_FIXED_PROCESS: {
 		case NOTIFICATION_FIXED_PROCESS: {
 
 
 			if (physics_object_picking) {
 			if (physics_object_picking) {
-
+#ifndef _3D_DISABLED
 				Vector2 last_pos(1e20,1e20);
 				Vector2 last_pos(1e20,1e20);
 				CollisionObject *last_object;
 				CollisionObject *last_object;
 				ObjectID last_id=0;
 				ObjectID last_id=0;
@@ -499,6 +499,7 @@ void Viewport::_notification(int p_what) {
 					}
 					}
 
 
 				}
 				}
+#endif
 			}
 			}
 
 
 		} break;
 		} break;

+ 8 - 6
scene/register_scene_types.cpp

@@ -397,6 +397,13 @@ void register_scene_types() {
 	ObjectTypeDB::register_type<BakedLightSampler>();
 	ObjectTypeDB::register_type<BakedLightSampler>();
 	ObjectTypeDB::register_type<WorldEnvironment>();
 	ObjectTypeDB::register_type<WorldEnvironment>();
 
 
+	ObjectTypeDB::register_virtual_type<Joint>();
+	ObjectTypeDB::register_type<PinJoint>();
+	ObjectTypeDB::register_type<HingeJoint>();
+	ObjectTypeDB::register_type<SliderJoint>();
+	ObjectTypeDB::register_type<ConeTwistJoint>();
+	ObjectTypeDB::register_type<Generic6DOFJoint>();
+
 	//scenariofx	
 	//scenariofx	
 
 
 	OS::get_singleton()->yield(); //may take time to init
 	OS::get_singleton()->yield(); //may take time to init
@@ -405,6 +412,7 @@ void register_scene_types() {
 	ObjectTypeDB::register_type<SpatialStreamPlayer>();
 	ObjectTypeDB::register_type<SpatialStreamPlayer>();
 	ObjectTypeDB::register_type<SoundRoomParams>();
 	ObjectTypeDB::register_type<SoundRoomParams>();
 
 
+
 #endif
 #endif
 	ObjectTypeDB::register_type<MeshLibrary>();
 	ObjectTypeDB::register_type<MeshLibrary>();
 	AcceptDialog::set_swap_ok_cancel( GLOBAL_DEF("display/swap_ok_cancel",bool(OS::get_singleton()->get_swap_ok_cancel())) );
 	AcceptDialog::set_swap_ok_cancel( GLOBAL_DEF("display/swap_ok_cancel",bool(OS::get_singleton()->get_swap_ok_cancel())) );
@@ -422,12 +430,6 @@ void register_scene_types() {
 	//ObjectTypeDB::register_type<PhysicsJointPin>();
 	//ObjectTypeDB::register_type<PhysicsJointPin>();
 
 
 
 
-	ObjectTypeDB::register_virtual_type<Joint>();
-	ObjectTypeDB::register_type<PinJoint>();
-	ObjectTypeDB::register_type<HingeJoint>();
-	ObjectTypeDB::register_type<SliderJoint>();
-	ObjectTypeDB::register_type<ConeTwistJoint>();
-	ObjectTypeDB::register_type<Generic6DOFJoint>();
 
 
 
 
 	ObjectTypeDB::register_type<StreamPlayer>();
 	ObjectTypeDB::register_type<StreamPlayer>();

+ 1 - 1
scene/resources/animation.cpp

@@ -1266,7 +1266,7 @@ T Animation::_interpolate( const Vector< TKey<T> >& p_keys, float p_time,  Inter
 		} 		
 		} 		
 	
 	
 	} else { // no loop 
 	} else { // no loop 
-	
+
 		if (idx>=0) {
 		if (idx>=0) {
 		
 		
 			if ((idx+1) < len) {
 			if ((idx+1) < len) {

+ 219 - 0
scene/resources/mesh.cpp

@@ -743,6 +743,225 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
 
 
 }
 }
 
 
+Ref<Mesh> Mesh::create_outline(float p_margin) const {
+
+
+	Array arrays;
+	int index_accum=0;
+	for(int i=0;i<get_surface_count();i++) {
+
+		if (surface_get_primitive_type(i)!=PRIMITIVE_TRIANGLES)
+			continue;
+
+		Array a = surface_get_arrays(i);
+		int vcount=0;
+
+		if (i==0) {
+			arrays=a;
+			DVector<Vector3> v=a[ARRAY_VERTEX];
+			index_accum+=v.size();
+		} else {
+
+			for(int j=0;j<arrays.size();j++) {
+
+				if (arrays[j].get_type()==Variant::NIL || a[j].get_type()==Variant::NIL) {
+					//mismatch, do not use
+					arrays[j]=Variant();
+					continue;
+				}
+
+				switch(j) {
+
+					case ARRAY_VERTEX:
+					case ARRAY_NORMAL:  {
+
+						DVector<Vector3> dst = arrays[j];
+						DVector<Vector3> src = a[j];
+						if (j==ARRAY_VERTEX)
+							vcount=src.size();
+						if (dst.size()==0 || src.size()==0) {
+							arrays[j]=Variant();
+							continue;
+						}
+						dst.append_array(src);
+						arrays[j]=dst;
+					} break;
+					case ARRAY_TANGENT:
+					case ARRAY_BONES:
+					case ARRAY_WEIGHTS: {
+
+						DVector<real_t> dst = arrays[j];
+						DVector<real_t> src = a[j];
+						if (dst.size()==0 || src.size()==0) {
+							arrays[j]=Variant();
+							continue;
+						}
+						dst.append_array(src);
+						arrays[j]=dst;
+
+					} break;
+					case ARRAY_COLOR: {
+						DVector<Color> dst = arrays[j];
+						DVector<Color> src = a[j];
+						if (dst.size()==0 || src.size()==0) {
+							arrays[j]=Variant();
+							continue;
+						}
+						dst.append_array(src);
+						arrays[j]=dst;
+
+					} break;
+					case ARRAY_TEX_UV:
+					case ARRAY_TEX_UV2: {
+						DVector<Vector2> dst = arrays[j];
+						DVector<Vector2> src = a[j];
+						if (dst.size()==0 || src.size()==0) {
+							arrays[j]=Variant();
+							continue;
+						}
+						dst.append_array(src);
+						arrays[j]=dst;
+
+					} break;
+					case ARRAY_INDEX: {
+						DVector<int> dst = arrays[j];
+						DVector<int> src = a[j];
+						if (dst.size()==0 || src.size()==0) {
+							arrays[j]=Variant();
+							continue;
+						}
+						{
+							int ss = src.size();
+							DVector<int>::Write w = src.write();
+							for(int k=0;k<ss;k++) {
+								w[k]+=index_accum;
+							}
+
+						}
+						dst.append_array(src);
+						arrays[j]=dst;
+						index_accum+=vcount;
+
+					} break;
+
+				}
+			}
+		}
+	}
+
+	{
+		int tc=0;
+		DVector<int>::Write ir;
+		DVector<int> indices =arrays[ARRAY_INDEX];
+		bool has_indices=false;
+		DVector<Vector3> vertices =arrays[ARRAY_VERTEX];
+		int vc = vertices.size();
+		ERR_FAIL_COND_V(!vc,Ref<Mesh>());
+		DVector<Vector3>::Write r=vertices.write();
+
+
+		if (indices.size()) {
+			vc=indices.size();
+			ir=indices.write();
+			has_indices=true;
+		}
+
+		Map<Vector3,Vector3> normal_accum;
+
+		//fill normals with triangle normals
+		for(int i=0;i<vc;i+=3) {
+
+
+			Vector3 t[3];
+
+			if (has_indices) {
+				t[0]=r[ir[i+0]];
+				t[1]=r[ir[i+1]];
+				t[2]=r[ir[i+2]];
+			} else {
+				t[0]=r[i+0];
+				t[1]=r[i+1];
+				t[2]=r[i+2];
+			}
+
+			Vector3 n = Plane(t[0],t[1],t[2]).normal;
+
+			for(int j=0;j<3;j++) {
+
+				Map<Vector3,Vector3>::Element *E=normal_accum.find(t[j]);
+				if (!E) {
+					normal_accum[t[j]]=n;
+				} else {
+					float d = n.dot(E->get());
+					if (d<1.0)
+						E->get()+=n*(1.0-d);
+					//E->get()+=n;
+				}
+			}
+		}
+
+		//normalize
+
+		for (Map<Vector3,Vector3>::Element *E=normal_accum.front();E;E=E->next()) {
+			E->get().normalize();
+		}
+
+
+		//displace normals
+		int vc2 = vertices.size();
+
+		for(int i=0;i<vc2;i++) {
+
+
+			Vector3 t=r[i];
+
+			Map<Vector3,Vector3>::Element *E=normal_accum.find(t);
+			ERR_CONTINUE(!E);
+
+			t+=E->get()*p_margin;
+			r[i]=t;
+		}
+
+		r = DVector<Vector3>::Write();
+		arrays[ARRAY_VERTEX]=vertices;
+
+		if (!has_indices) {
+
+			DVector<int> new_indices;
+			new_indices.resize(vertices.size());
+			DVector<int>::Write iw = new_indices.write();
+
+			for(int j=0;j<vc2;j+=3) {
+
+				iw[j]=j;
+				iw[j+1]=j+2;
+				iw[j+2]=j+1;
+			}
+
+			iw=DVector<int>::Write();
+			arrays[ARRAY_INDEX]=new_indices;
+
+		} else {
+
+			for(int j=0;j<vc;j+=3) {
+
+				SWAP(ir[j+1],ir[j+2]);
+			}
+			ir=DVector<int>::Write();
+			arrays[ARRAY_INDEX]=indices;
+
+		}
+	}
+
+
+
+
+	Ref<Mesh> newmesh = memnew( Mesh );
+	newmesh->add_surface(PRIMITIVE_TRIANGLES,arrays);
+	return newmesh;
+}
+
+
 void Mesh::_bind_methods() {
 void Mesh::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("add_morph_target","name"),&Mesh::add_morph_target);
 	ObjectTypeDB::bind_method(_MD("add_morph_target","name"),&Mesh::add_morph_target);

+ 2 - 0
scene/resources/mesh.h

@@ -166,6 +166,8 @@ public:
 	Ref<Shape> create_trimesh_shape() const;
 	Ref<Shape> create_trimesh_shape() const;
 	Ref<Shape> create_convex_shape() const;
 	Ref<Shape> create_convex_shape() const;
 
 
+	Ref<Mesh> create_outline(float p_margin) const;
+
 	void center_geometry();
 	void center_geometry();
 	void regen_normalmaps();
 	void regen_normalmaps();
 
 

+ 4 - 0
scene/resources/packed_scene.cpp

@@ -272,6 +272,10 @@ Error PackedScene::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<
 				continue;
 				continue;
 			}*/
 			}*/
 
 
+			if (E->get().usage & PROPERTY_USAGE_NO_INSTANCE_STATE) {
+				continue;
+			}
+
 			if (instance_state[name]==value) {
 			if (instance_state[name]==value) {
 				continue;
 				continue;
 			}
 			}

+ 2 - 2
scene/resources/video_stream.h

@@ -30,7 +30,7 @@
 #define VIDEO_STREAM_H
 #define VIDEO_STREAM_H
 
 
 #include "audio_stream_resampled.h"
 #include "audio_stream_resampled.h"
-
+#include "scene/resources/texture.h"
 
 
 
 
 class VideoStream : public Resource {
 class VideoStream : public Resource {
@@ -59,7 +59,7 @@ public:
 	virtual void seek_pos(float p_time)=0;
 	virtual void seek_pos(float p_time)=0;
 
 
 	virtual int get_pending_frame_count() const=0;
 	virtual int get_pending_frame_count() const=0;
-	virtual Image pop_frame()=0;
+	virtual void pop_frame(Ref<ImageTexture> p_tex)=0;
 	virtual Image peek_frame() const=0;
 	virtual Image peek_frame() const=0;
 
 
 	virtual void update(float p_time)=0;
 	virtual void update(float p_time)=0;

+ 7 - 1
servers/physics_2d/body_2d_sw.cpp

@@ -65,7 +65,13 @@ void Body2DSW::update_inertias() {
 
 
 				float mass = area * this->mass / total_area;
 				float mass = area * this->mass / total_area;
 
 
-				_inertia += shape->get_moment_of_inertia(mass) + mass * get_shape_transform(i).get_origin().length_squared();
+				Matrix32 mtx = get_shape_transform(i);
+				Vector2 scale = mtx.get_scale();
+				_inertia += shape->get_moment_of_inertia(mass,scale) + mass * mtx.get_origin().length_squared();
+				//Rect2 ab = get_shape_aabb(i);
+				//_inertia+=mass*ab.size.dot(ab.size)/12.0f;
+
+
 
 
 			}
 			}
 
 

+ 1 - 0
servers/physics_2d/collision_solver_2d_sat.cpp

@@ -1086,6 +1086,7 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matri
 
 
 	SeparatorAxisTest2D<RectangleShape2DSW,ConvexPolygonShape2DSW,castA,castB,withMargin> separator(rectangle_A,p_transform_a,convex_B,p_transform_b,p_collector,p_motion_a,p_motion_b,p_margin_A,p_margin_B);
 	SeparatorAxisTest2D<RectangleShape2DSW,ConvexPolygonShape2DSW,castA,castB,withMargin> separator(rectangle_A,p_transform_a,convex_B,p_transform_b,p_collector,p_motion_a,p_motion_b,p_margin_A,p_margin_B);
 
 
+
 	if (!separator.test_previous_axis())
 	if (!separator.test_previous_axis())
 		return;
 		return;
 
 

+ 18 - 15
servers/physics_2d/shape_2d_sw.cpp

@@ -131,7 +131,7 @@ bool LineShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_en
 	return true;
 	return true;
 }
 }
 
 
-real_t LineShape2DSW::get_moment_of_inertia(float p_mass) const {
+real_t LineShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const {
 
 
 	return 0;
 	return 0;
 }
 }
@@ -180,7 +180,7 @@ bool RayShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end
 
 
 }
 }
 
 
-real_t RayShape2DSW::get_moment_of_inertia(float p_mass) const {
+real_t RayShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const {
 
 
 	return 0; //rays are mass-less
 	return 0; //rays are mass-less
 }
 }
@@ -237,10 +237,12 @@ bool SegmentShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p
 	return true;
 	return true;
 }
 }
 
 
-real_t SegmentShape2DSW::get_moment_of_inertia(float p_mass) const {
+real_t SegmentShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const {
 
 
-	real_t l = b.distance_to(a);
-	Vector2 ofs = (a+b)*0.5;
+	Vector2 s[2]={a*p_scale,b*p_scale};
+
+	real_t l = s[1].distance_to(s[0]);
+	Vector2 ofs = (s[0]+s[1])*0.5;
 
 
 	return p_mass*(l*l/12.0f + ofs.length_squared());
 	return p_mass*(l*l/12.0f + ofs.length_squared());
 }
 }
@@ -312,9 +314,10 @@ bool CircleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_
 	return true;
 	return true;
 }
 }
 
 
-real_t CircleShape2DSW::get_moment_of_inertia(float p_mass) const {
+real_t CircleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const {
+
+	return (radius*radius)*(p_scale.x*0.5+p_scale.y*0.5);
 
 
-	return radius*radius;
 }
 }
 
 
 void CircleShape2DSW::set_data(const Variant& p_data) {
 void CircleShape2DSW::set_data(const Variant& p_data) {
@@ -377,9 +380,9 @@ bool RectangleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2&
 	return get_aabb().intersects_segment(p_begin,p_end,&r_point,&r_normal);
 	return get_aabb().intersects_segment(p_begin,p_end,&r_point,&r_normal);
 }
 }
 
 
-real_t RectangleShape2DSW::get_moment_of_inertia(float p_mass) const {
+real_t RectangleShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const {
 
 
-	Vector2 he2=half_extents*2;
+	Vector2 he2=half_extents*2*p_scale;
 	return p_mass*he2.dot(he2)/12.0f;
 	return p_mass*he2.dot(he2)/12.0f;
 }
 }
 
 
@@ -499,9 +502,9 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p
 	return collided; //todo
 	return collided; //todo
 }
 }
 
 
-real_t CapsuleShape2DSW::get_moment_of_inertia(float p_mass) const {
+real_t CapsuleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const {
 
 
-	Vector2 he2(radius*2,height+radius*2);
+	Vector2 he2=Vector2(radius*2,height+radius*2)*p_scale;
 	return p_mass*he2.dot(he2)/12.0f;
 	return p_mass*he2.dot(he2)/12.0f;
 }
 }
 
 
@@ -610,16 +613,16 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect
 	return inters; //todo
 	return inters; //todo
 }
 }
 
 
-real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass) const {
+real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const {
 
 
 	Rect2 aabb;
 	Rect2 aabb;
-	aabb.pos=points[0].pos;
+	aabb.pos=points[0].pos*p_scale;
 	for(int i=0;i<point_count;i++) {
 	for(int i=0;i<point_count;i++) {
 
 
-		aabb.expand_to(points[i].pos);
+		aabb.expand_to(points[i].pos*p_scale);
 	}
 	}
 
 
-	return p_mass*aabb.size.dot(aabb.size)/12.0f;
+	return p_mass*aabb.size.dot(aabb.size)/12.0f + p_mass * (aabb.pos+aabb.size*0.5).length_squared();
 }
 }
 
 
 void ConvexPolygonShape2DSW::set_data(const Variant& p_data) {
 void ConvexPolygonShape2DSW::set_data(const Variant& p_data) {

+ 19 - 14
servers/physics_2d/shape_2d_sw.h

@@ -84,7 +84,7 @@ public:
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const=0;
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const=0;
 
 
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const=0;
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const=0;
-	virtual real_t get_moment_of_inertia(float p_mass) const=0;
+	virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const=0;
 
 
 	virtual void set_data(const Variant& p_data)=0;
 	virtual void set_data(const Variant& p_data)=0;
 	virtual Variant get_data() const=0;
 	virtual Variant get_data() const=0;
@@ -173,7 +173,7 @@ public:
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 
 
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
-	virtual real_t get_moment_of_inertia(float p_mass) const;
+	virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
 
 
 	virtual void set_data(const Variant& p_data);
 	virtual void set_data(const Variant& p_data);
 	virtual Variant get_data() const;
 	virtual Variant get_data() const;
@@ -215,7 +215,7 @@ public:
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 
 
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
-	virtual real_t get_moment_of_inertia(float p_mass) const;
+	virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
 
 
 	virtual void set_data(const Variant& p_data);
 	virtual void set_data(const Variant& p_data);
 	virtual Variant get_data() const;
 	virtual Variant get_data() const;
@@ -262,7 +262,7 @@ public:
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 
 
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
-	virtual real_t get_moment_of_inertia(float p_mass) const;
+	virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
 
 
 	virtual void set_data(const Variant& p_data);
 	virtual void set_data(const Variant& p_data);
 	virtual Variant get_data() const;
 	virtual Variant get_data() const;
@@ -299,7 +299,7 @@ public:
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 
 
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
-	virtual real_t get_moment_of_inertia(float p_mass) const;
+	virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
 
 
 	virtual void set_data(const Variant& p_data);
 	virtual void set_data(const Variant& p_data);
 	virtual Variant get_data() const;
 	virtual Variant get_data() const;
@@ -338,20 +338,25 @@ public:
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 
 
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
-	virtual real_t get_moment_of_inertia(float p_mass) const;
+	virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
 
 
 	virtual void set_data(const Variant& p_data);
 	virtual void set_data(const Variant& p_data);
 	virtual Variant get_data() const;
 	virtual Variant get_data() const;
 
 
 	_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
 	_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
 		// no matter the angle, the box is mirrored anyway
 		// no matter the angle, the box is mirrored anyway
-		Vector2 local_normal=p_transform.basis_xform_inv(p_normal);
+		r_max=-1e20;
+		r_min=1e20;
+		for(int i=0;i<4;i++) {
 
 
-		float length = local_normal.abs().dot(half_extents);
-		float distance = p_normal.dot( p_transform.get_origin() );
+			real_t d=p_normal.dot(p_transform.xform(Vector2( ((i&1)*2-1)*half_extents.x, ((i>>1)*2-1)*half_extents.y )));
 
 
-		r_min = distance - length;
-		r_max = distance + length;
+			if (d>r_max)
+				r_max=d;
+			if (d<r_min)
+				r_min=d;
+
+		}
 	}
 	}
 
 
 
 
@@ -420,7 +425,7 @@ public:
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 
 
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
-	virtual real_t get_moment_of_inertia(float p_mass) const;
+	virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
 
 
 	virtual void set_data(const Variant& p_data);
 	virtual void set_data(const Variant& p_data);
 	virtual Variant get_data() const;
 	virtual Variant get_data() const;
@@ -482,7 +487,7 @@ public:
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 	virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
 
 
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
-	virtual real_t get_moment_of_inertia(float p_mass) const;
+	virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
 
 
 	virtual void set_data(const Variant& p_data);
 	virtual void set_data(const Variant& p_data);
 	virtual Variant get_data() const;
 	virtual Variant get_data() const;
@@ -570,7 +575,7 @@ public:
 
 
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
 	virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
 
 
-	virtual real_t get_moment_of_inertia(float p_mass) const { return 0; }
+	virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { return 0; }
 
 
 	virtual void set_data(const Variant& p_data);
 	virtual void set_data(const Variant& p_data);
 	virtual Variant get_data() const;
 	virtual Variant get_data() const;

+ 1 - 1
servers/visual/visual_server_raster.cpp

@@ -5621,7 +5621,7 @@ void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instan
 				if (distance>r)
 				if (distance>r)
 					distance=r;
 					distance=r;
 
 
-				float mult = powf(1.0-distance/r,att)*str;
+				float mult = Math::pow(1.0-distance/r,att)*str;
 				if (mult>0) {
 				if (mult>0) {
 					col.r*=mult;
 					col.r*=mult;
 					col.g*=mult;
 					col.g*=mult;

+ 45 - 2
tools/editor/editor_node.cpp

@@ -1310,6 +1310,8 @@ void EditorNode::_edit_current() {
 	p->add_item("Copy Params",OBJECT_COPY_PARAMS);
 	p->add_item("Copy Params",OBJECT_COPY_PARAMS);
 	p->add_item("Set Params",OBJECT_PASTE_PARAMS);
 	p->add_item("Set Params",OBJECT_PASTE_PARAMS);
 	p->add_separator();
 	p->add_separator();
+	p->add_item("Make Resources Unique",OBJECT_UNIQUE_RESOURCES);
+	p->add_separator();
 	p->add_icon_item(gui_base->get_icon("Help","EditorIcons"),"Class Reference",OBJECT_REQUEST_HELP);
 	p->add_icon_item(gui_base->get_icon("Help","EditorIcons"),"Class Reference",OBJECT_REQUEST_HELP);
 	List<MethodInfo> methods;
 	List<MethodInfo> methods;
 	current_obj->get_method_list(&methods);
 	current_obj->get_method_list(&methods);
@@ -2023,6 +2025,47 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
 				editor_data.paste_object_params(current);
 				editor_data.paste_object_params(current);
 			editor_data.get_undo_redo().clear_history();
 			editor_data.get_undo_redo().clear_history();
 		} break;
 		} break;
+		case OBJECT_UNIQUE_RESOURCES: {
+
+			editor_data.apply_changes_in_editors();;
+			if (current) {
+				List<PropertyInfo> props;
+				current->get_property_list(&props);
+				Map<RES,RES> duplicates;
+				for (List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
+
+					if (!(E->get().usage&PROPERTY_USAGE_STORAGE))
+						continue;
+
+					Variant v = current->get(E->get().name);
+					if (v.is_ref()) {
+						REF ref = v;
+						if (ref.is_valid()) {
+
+							RES res = ref;
+							if (res.is_valid()) {
+
+								if (!duplicates.has(res)) {
+									duplicates[res]=res->duplicate();
+								}
+								res=duplicates[res];
+
+								current->set(E->get().name,res);
+							}
+
+						}
+					}
+
+				}
+			}
+
+			editor_data.get_undo_redo().clear_history();
+			if (editor_plugin_screen) { //reload editor plugin
+				editor_plugin_over->edit(NULL);
+				editor_plugin_over->edit(current);
+			}
+
+		} break;
 		case OBJECT_CALL_METHOD: {
 		case OBJECT_CALL_METHOD: {
 		
 		
 			editor_data.apply_changes_in_editors();;
 			editor_data.apply_changes_in_editors();;
@@ -3950,8 +3993,8 @@ EditorNode::EditorNode() {
 	Ref<EditorSceneImportPlugin> _scene_import =  memnew(EditorSceneImportPlugin(this) );
 	Ref<EditorSceneImportPlugin> _scene_import =  memnew(EditorSceneImportPlugin(this) );
 	Ref<EditorSceneImporterCollada> _collada_import = memnew( EditorSceneImporterCollada);
 	Ref<EditorSceneImporterCollada> _collada_import = memnew( EditorSceneImporterCollada);
 	_scene_import->add_importer(_collada_import);
 	_scene_import->add_importer(_collada_import);
-	Ref<EditorSceneImporterFBXConv> _fbxconv_import = memnew( EditorSceneImporterFBXConv);
-	_scene_import->add_importer(_fbxconv_import);
+//	Ref<EditorSceneImporterFBXConv> _fbxconv_import = memnew( EditorSceneImporterFBXConv);
+//	_scene_import->add_importer(_fbxconv_import);
 	editor_import_export->add_import_plugin( _scene_import);
 	editor_import_export->add_import_plugin( _scene_import);
 	editor_import_export->add_import_plugin( Ref<EditorSceneAnimationImportPlugin>( memnew(EditorSceneAnimationImportPlugin(this))));
 	editor_import_export->add_import_plugin( Ref<EditorSceneAnimationImportPlugin>( memnew(EditorSceneAnimationImportPlugin(this))));
 	editor_import_export->add_import_plugin( Ref<EditorMeshImportPlugin>( memnew(EditorMeshImportPlugin(this))));
 	editor_import_export->add_import_plugin( Ref<EditorMeshImportPlugin>( memnew(EditorMeshImportPlugin(this))));

+ 1 - 0
tools/editor/editor_node.h

@@ -133,6 +133,7 @@ class EditorNode : public Node {
 		RESOURCE_COPY,
 		RESOURCE_COPY,
 		OBJECT_COPY_PARAMS,
 		OBJECT_COPY_PARAMS,
 		OBJECT_PASTE_PARAMS,
 		OBJECT_PASTE_PARAMS,
+		OBJECT_UNIQUE_RESOURCES,
 		OBJECT_CALL_METHOD,
 		OBJECT_CALL_METHOD,
 		OBJECT_REQUEST_HELP,
 		OBJECT_REQUEST_HELP,
 		RUN_PLAY,
 		RUN_PLAY,

+ 7 - 5
tools/editor/io_plugins/editor_import_collada.cpp

@@ -61,6 +61,7 @@ struct ColladaImport {
 	Color ambient;
 	Color ambient;
 	bool found_directional;
 	bool found_directional;
 	bool force_make_tangents;
 	bool force_make_tangents;
+	float bake_fps;
 
 
 
 
 
 
@@ -95,6 +96,7 @@ struct ColladaImport {
 		found_ambient=false;
 		found_ambient=false;
 		found_directional=false;
 		found_directional=false;
 		force_make_tangents=false;
 		force_make_tangents=false;
+		bake_fps=15;
 
 
 	}
 	}
 };
 };
@@ -1835,7 +1837,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
 	Vector<float> base_snapshots;
 	Vector<float> base_snapshots;
 
 
 	float f=0;
 	float f=0;
-	float snapshot_interval = 1.0/20.0; //should be customizable somewhere...
+	float snapshot_interval = 1.0/bake_fps; //should be customizable somewhere...
 
 
 	float anim_length=collada.state.animation_length;
 	float anim_length=collada.state.animation_length;
 	if (p_clip>=0 && collada.state.animation_clips[p_clip].end)
 	if (p_clip>=0 && collada.state.animation_clips[p_clip].end)
@@ -2142,14 +2144,14 @@ void EditorSceneImporterCollada::get_extensions(List<String> *r_extensions) cons
 
 
 	r_extensions->push_back("dae");
 	r_extensions->push_back("dae");
 }
 }
-Node* EditorSceneImporterCollada::import_scene(const String& p_path, uint32_t p_flags, List<String> *r_missing_deps, Error* r_err) {
-
+Node* EditorSceneImporterCollada::import_scene(const String& p_path, uint32_t p_flags,int p_bake_fps, List<String> *r_missing_deps, Error* r_err) {
 
 
 	ColladaImport state;
 	ColladaImport state;
 	uint32_t flags=Collada::IMPORT_FLAG_SCENE;
 	uint32_t flags=Collada::IMPORT_FLAG_SCENE;
 	if (p_flags&IMPORT_ANIMATION)
 	if (p_flags&IMPORT_ANIMATION)
 		flags|=Collada::IMPORT_FLAG_ANIMATION;
 		flags|=Collada::IMPORT_FLAG_ANIMATION;
 
 
+	state.bake_fps=p_bake_fps;
 
 
 	Error err = state.load(p_path,flags,p_flags&EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS);
 	Error err = state.load(p_path,flags,p_flags&EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS);
 
 
@@ -2174,7 +2176,7 @@ Node* EditorSceneImporterCollada::import_scene(const String& p_path, uint32_t p_
 
 
 	if (p_flags&IMPORT_ANIMATION) {
 	if (p_flags&IMPORT_ANIMATION) {
 
 
-		state.create_animations(p_flags&IMPORT_ANIMATION_FORCE_TRACKS_IN_ALL_BONES);
+		state.create_animations(p_flags&IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
 		AnimationPlayer *ap = memnew( AnimationPlayer );
 		AnimationPlayer *ap = memnew( AnimationPlayer );
 		for(int i=0;i<state.animations.size();i++) {
 		for(int i=0;i<state.animations.size();i++) {
 			String name;
 			String name;
@@ -2213,7 +2215,7 @@ Ref<Animation> EditorSceneImporterCollada::import_animation(const String& p_path
 	ERR_FAIL_COND_V(err!=OK,RES());
 	ERR_FAIL_COND_V(err!=OK,RES());
 
 
 
 
-	state.create_animations(p_flags&EditorSceneImporter::IMPORT_ANIMATION_FORCE_TRACKS_IN_ALL_BONES);
+	state.create_animations(p_flags&EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
 	if (state.scene)
 	if (state.scene)
 		memdelete(state.scene);
 		memdelete(state.scene);
 
 

+ 1 - 1
tools/editor/io_plugins/editor_import_collada.h

@@ -40,7 +40,7 @@ public:
 
 
 	virtual uint32_t get_import_flags() const;
 	virtual uint32_t get_import_flags() const;
 	virtual void get_extensions(List<String> *r_extensions) const;
 	virtual void get_extensions(List<String> *r_extensions) const;
-	virtual Node* import_scene(const String& p_path,uint32_t p_flags,List<String> *r_missing_deps=NULL,Error* r_err=NULL);
+	virtual Node* import_scene(const String& p_path,uint32_t p_flags,int p_bake_fps,List<String> *r_missing_deps=NULL,Error* r_err=NULL);
 	virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags);
 	virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags);
 
 
 	EditorSceneImporterCollada();
 	EditorSceneImporterCollada();

+ 1 - 1
tools/editor/io_plugins/editor_mesh_import_plugin.cpp

@@ -425,7 +425,7 @@ Error EditorMeshImportPlugin::import(const String& p_path, const Ref<ResourceImp
 			ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA);
 			ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA);
 			Vector2 uv;
 			Vector2 uv;
 			uv.x=v[1].to_float();
 			uv.x=v[1].to_float();
-			uv.y=v[2].to_float();
+			uv.y=1.0-v[2].to_float();
 			uvs.push_back(uv);
 			uvs.push_back(uv);
 
 
 		} else if (l.begins_with("vn ")) {
 		} else if (l.begins_with("vn ")) {

+ 595 - 14
tools/editor/io_plugins/editor_scene_import_plugin.cpp

@@ -78,12 +78,23 @@ class EditorImportAnimationOptions : public VBoxContainer {
 	OBJ_TYPE( EditorImportAnimationOptions, VBoxContainer );
 	OBJ_TYPE( EditorImportAnimationOptions, VBoxContainer );
 
 
 
 
+
+	TreeItem *fps;
+	TreeItem *clips_base;
+	TextEdit *filters;
+	Vector<TreeItem*> clips;
+
 	Tree *flags;
 	Tree *flags;
+	Tree *clips_tree;
 	Vector<TreeItem*> items;
 	Vector<TreeItem*> items;
 
 
 	bool updating;
 	bool updating;
+	bool validating;
 
 
 	void _changed();
 	void _changed();
+	void _item_edited();
+	void _button_action(Object *p_obj,int p_col,int p_id);
+
 protected:
 protected:
 	static void _bind_methods();
 	static void _bind_methods();
 	void _notification(int p_what);
 	void _notification(int p_what);
@@ -93,6 +104,14 @@ public:
 	void set_flags(uint32_t p_flags);
 	void set_flags(uint32_t p_flags);
 	uint32_t get_flags() const;
 	uint32_t get_flags() const;
 
 
+	void set_fps(int p_fps);
+	int get_fps() const;
+
+	void setup_clips(const Array& p_clips);
+	Array get_clips() const;
+
+	void set_filter(const String& p_filter);
+	String get_filter() const;
 
 
 	EditorImportAnimationOptions();
 	EditorImportAnimationOptions();
 
 
@@ -141,6 +160,9 @@ class EditorSceneImportDialog : public ConfirmationDialog  {
 	Map<Ref<Mesh>,Ref<Shape> > collision_map;
 	Map<Ref<Mesh>,Ref<Shape> > collision_map;
 	ConfirmationDialog *error_dialog;
 	ConfirmationDialog *error_dialog;
 
 
+	OptionButton *this_import;
+	OptionButton *next_import;
+
 	void _choose_file(const String& p_path);
 	void _choose_file(const String& p_path);
 	void _choose_save_file(const String& p_path);
 	void _choose_save_file(const String& p_path);
 	void _choose_script(const String& p_path);
 	void _choose_script(const String& p_path);
@@ -178,7 +200,7 @@ static const char *anim_flag_names[]={
 	"Detect Loop (-loop,-cycle)",
 	"Detect Loop (-loop,-cycle)",
 	"Keep Value Tracks",
 	"Keep Value Tracks",
 	"Optimize",
 	"Optimize",
-	"Force Tracks in All Bones",
+	"Force All Tracks in All Clips",
 	NULL
 	NULL
 };
 };
 
 
@@ -223,9 +245,101 @@ void EditorImportAnimationOptions::_changed() {
 }
 }
 
 
 
 
+void EditorImportAnimationOptions::_button_action(Object *p_obj,int p_col,int p_id) {
+
+	memdelete(p_obj);
+
+}
+
+
+void EditorImportAnimationOptions::_item_edited() {
+
+	if (validating)
+		return;
+
+	if (clips.size()==0)
+		return;
+	validating=true;
+	print_line("edited");
+	TreeItem *item = clips_tree->get_edited();
+	if (item==clips[clips.size()-1]) {
+		//add new
+		print_line("islast");
+		if (item->get_text(0).find("<")!=-1 || item->get_text(0).find(">")!=-1) {
+			validating=false;
+			return; //fuckit
+		}
+
+		item->set_editable(1,true);
+		item->set_editable(2,true);
+		item->add_button(0,EditorNode::get_singleton()->get_gui_base()->get_icon("Del","EditorIcons"));
+		item->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
+		item->set_range_config(1,0,3600,0.01);
+		item->set_range(1,0);
+		item->set_editable(1,true);
+		item->set_cell_mode(2,TreeItem::CELL_MODE_RANGE);
+		item->set_range_config(2,0,3600,0.01);
+		item->set_range(2,0);
+		item->set_cell_mode(3,TreeItem::CELL_MODE_CHECK);
+		item->set_editable(3,true);
+
+		TreeItem *newclip = clips_tree->create_item(clips_base);
+		newclip->set_text(0,"<new clip>");
+		newclip->set_editable(0,true);
+		newclip->set_editable(1,false);
+		newclip->set_editable(2,false);
+		clips.push_back(newclip);
+
+
+
+	}
+
+
+	//make name unique JUST IN CASE
+	String name = item->get_text(0);
+	name=name.replace("/","_").replace(":","_").strip_edges();
+	if (name=="")
+		name="New Clip";
+
+	if (clips.size()>2) {
+		int index=1;
+		while(true) {
+			bool valid = true;
+			String try_name=name;
+			if (index>1)
+				try_name+=" "+itos(index);
+
+			for(int i=0;i<clips.size()-1;i++) {
+
+				if (clips[i]==item)
+					continue;
+				if (clips[i]->get_text(0)==try_name) {
+					index++;
+					valid=false;
+					break;
+				}
+			}
+
+			if (valid) {
+				name=try_name;
+				break;
+			}
+
+		}
+	}
+
+	if (item->get_text(0)!=name)
+		item->set_text(0,name);
+
+	validating=false;
+
+}
+
 void EditorImportAnimationOptions::_bind_methods() {
 void EditorImportAnimationOptions::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method("_changed",&EditorImportAnimationOptions::_changed);
 	ObjectTypeDB::bind_method("_changed",&EditorImportAnimationOptions::_changed);
+	ObjectTypeDB::bind_method("_item_edited",&EditorImportAnimationOptions::_item_edited);
+	ObjectTypeDB::bind_method("_button_action",&EditorImportAnimationOptions::_button_action);
 //	ObjectTypeDB::bind_method("_changedp",&EditorImportAnimationOptions::_changedp);
 //	ObjectTypeDB::bind_method("_changedp",&EditorImportAnimationOptions::_changedp);
 
 
 	ADD_SIGNAL(MethodInfo("changed"));
 	ADD_SIGNAL(MethodInfo("changed"));
@@ -237,17 +351,84 @@ void EditorImportAnimationOptions::_notification(int p_what) {
 	if (p_what==NOTIFICATION_ENTER_SCENE) {
 	if (p_what==NOTIFICATION_ENTER_SCENE) {
 
 
 		flags->connect("item_edited",this,"_changed");
 		flags->connect("item_edited",this,"_changed");
+		clips_tree->connect("item_edited",this,"_item_edited");
+		clips_tree->connect("button_pressed",this,"_button_action",varray(),CONNECT_DEFERRED);
 //		format->connect("item_selected",this,"_changedp");
 //		format->connect("item_selected",this,"_changedp");
 	}
 	}
 }
 }
 
 
+
+Array EditorImportAnimationOptions::get_clips()  const {
+
+	Array arr;
+	for(int i=0;i<clips.size()-1;i++) {
+
+		arr.push_back(clips[i]->get_text(0));
+		arr.push_back(clips[i]->get_range(1));
+		arr.push_back(clips[i]->get_range(2));
+		arr.push_back(clips[i]->is_checked(3));
+	}
+
+	return arr;
+}
+
+
+void EditorImportAnimationOptions::setup_clips(const Array& p_clips) {
+
+	ERR_FAIL_COND(p_clips.size()%4!=0);
+	for(int i=0;i<clips.size();i++) {
+
+		memdelete(clips[i]);
+	}
+
+
+	clips.clear();
+
+	for(int i=0;i<p_clips.size();i+=4) {
+
+		TreeItem *clip = clips_tree->create_item(clips_base);
+		clip->set_text(0,p_clips[i]);
+		clip->add_button(0,EditorNode::get_singleton()->get_gui_base()->get_icon("Del","EditorIcons"));
+		clip->set_editable(0,true);
+		clip->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
+		clip->set_range_config(1,0,3600,0.01);
+		clip->set_range(1,p_clips[i+1]);
+		clip->set_editable(1,true);
+		clip->set_cell_mode(2,TreeItem::CELL_MODE_RANGE);
+		clip->set_range_config(2,0,3600,0.01);
+		clip->set_range(2,p_clips[i+2]);
+		clip->set_editable(2,true);
+		clip->set_cell_mode(3,TreeItem::CELL_MODE_CHECK);
+		clip->set_editable(3,true);
+		clip->set_checked(3,p_clips[i+3]);
+		clips.push_back(clip);
+
+	}
+
+	TreeItem *newclip = clips_tree->create_item(clips_base);
+	newclip->set_text(0,"<new clip>");
+	newclip->set_editable(0,true);
+	newclip->set_editable(1,false);
+	newclip->set_editable(2,false);
+	newclip->set_editable(3,false);
+	clips.push_back(newclip);
+
+}
+
+
 EditorImportAnimationOptions::EditorImportAnimationOptions() {
 EditorImportAnimationOptions::EditorImportAnimationOptions() {
 
 
 
 
 	updating=false;
 	updating=false;
+	validating=false;
+
+	TabContainer *tab= memnew(TabContainer);
+	add_margin_child("Animation Options",tab,true);
 
 
 	flags = memnew( Tree );
 	flags = memnew( Tree );
 	flags->set_hide_root(true);
 	flags->set_hide_root(true);
+	tab->add_child(flags);
+	flags->set_name("Flags");
 	TreeItem *root = flags->create_item();
 	TreeItem *root = flags->create_item();
 
 
 	const char ** fname=anim_flag_names;
 	const char ** fname=anim_flag_names;
@@ -263,14 +444,69 @@ EditorImportAnimationOptions::EditorImportAnimationOptions() {
 		items.push_back(ti);
 		items.push_back(ti);
 		fname++;
 		fname++;
 		fdescr++;
 		fdescr++;
-	}
+	}	
+
+
+	TreeItem *fps_base = flags->create_item(root);
+	fps_base->set_text(0,"Bake FPS:");
+	fps_base->set_editable(0,false);
+	fps = flags->create_item(fps_base);
+	fps->set_cell_mode(0,TreeItem::CELL_MODE_RANGE);
+	fps->set_editable(0,true);
+	fps->set_range(0,15);
+	fps->set_range_config(0,1,120,1);
+
+
+	clips_tree = memnew( Tree );
+	clips_tree->set_hide_root(true);
+	tab->add_child(clips_tree);
+	clips_tree->set_name("Clips");
+
+	clips_tree->set_columns(4);
+	clips_tree->set_column_expand(0,1);
+	clips_tree->set_column_expand(1,0);
+	clips_tree->set_column_expand(2,0);
+	clips_tree->set_column_expand(3,0);
+	clips_tree->set_column_min_width(1,60);
+	clips_tree->set_column_min_width(2,60);
+	clips_tree->set_column_min_width(3,40);
+	clips_tree->set_column_titles_visible(true);
+	clips_tree->set_column_title(0,"Name");
+	clips_tree->set_column_title(1,"Start(s)");
+	clips_tree->set_column_title(2,"End(s)");
+	clips_tree->set_column_title(3,"Loop");
+	clips_base =clips_tree->create_item(0);
+
+
+	setup_clips(Array());
+
+
+	filters = memnew( TextEdit );
+	tab->add_child(filters);
+	filters->set_name("Filters");
+}
 
 
 
 
-	add_margin_child("Animation Options",flags,true);
 
 
+void EditorImportAnimationOptions::set_fps(int p_fps) {
+
+	fps->set_range(0,p_fps);
 }
 }
 
 
+int EditorImportAnimationOptions::get_fps() const {
 
 
+	return fps->get_range(0);
+}
+
+void EditorImportAnimationOptions::set_filter(const String& p_filter) {
+
+	filters->set_text(p_filter);
+}
+
+String EditorImportAnimationOptions::get_filter() const {
+
+	return filters->get_text();
+}
 
 
 
 
 
 
@@ -413,7 +649,12 @@ void EditorSceneImportDialog::_import(bool p_and_open) {
 	rim->set_option("texture_format",texture_options->get_format());
 	rim->set_option("texture_format",texture_options->get_format());
 	rim->set_option("texture_quality",texture_options->get_quality());
 	rim->set_option("texture_quality",texture_options->get_quality());
 	rim->set_option("animation_flags",animation_options->get_flags());
 	rim->set_option("animation_flags",animation_options->get_flags());
+	rim->set_option("animation_bake_fps",animation_options->get_fps());
+	rim->set_option("animation_filters",animation_options->get_filter());
+	rim->set_option("animation_clips",animation_options->get_clips());
 	rim->set_option("post_import_script",script_path->get_text()!=String()?EditorImportPlugin::validate_source_path(script_path->get_text()):String());
 	rim->set_option("post_import_script",script_path->get_text()!=String()?EditorImportPlugin::validate_source_path(script_path->get_text()):String());
+	rim->set_option("import_this_time",this_import->get_selected());
+	rim->set_option("import_next_time",next_import->get_selected());
 	rim->set_option("reimport",true);
 	rim->set_option("reimport",true);
 
 
 	List<String> missing;
 	List<String> missing;
@@ -526,7 +767,7 @@ void EditorSceneImportDialog::_browse_script() {
 
 
 void EditorSceneImportDialog::popup_import(const String &p_from) {
 void EditorSceneImportDialog::popup_import(const String &p_from) {
 
 
-	popup_centered(Size2(700,500));
+	popup_centered(Size2(750,550));
 	if (p_from!="") {
 	if (p_from!="") {
 		Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
 		Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_from);
 		if (rimd.is_null())
 		if (rimd.is_null())
@@ -544,7 +785,17 @@ void EditorSceneImportDialog::popup_import(const String &p_from) {
 		texture_options->set_format(EditorTextureImportPlugin::ImageFormat(int(rimd->get_option("texture_format"))));
 		texture_options->set_format(EditorTextureImportPlugin::ImageFormat(int(rimd->get_option("texture_format"))));
 		texture_options->set_quality(rimd->get_option("texture_quality"));
 		texture_options->set_quality(rimd->get_option("texture_quality"));
 		animation_options->set_flags(rimd->get_option("animation_flags"));
 		animation_options->set_flags(rimd->get_option("animation_flags"));
+		if (rimd->has_option("animation_clips"))
+			animation_options->setup_clips(rimd->get_option("animation_clips"));
+		if (rimd->has_option("animation_filters"))
+			animation_options->set_filter(rimd->get_option("animation_filters"));
+		if (rimd->has_option("animation_bake_fps"))
+			animation_options->set_fps(rimd->get_option("animation_bake_fps"));
 		script_path->set_text(rimd->get_option("post_import_script"));
 		script_path->set_text(rimd->get_option("post_import_script"));
+		if (rimd->has_option("import_this_time"))
+			this_import->select(rimd->get_option("import_this_time"));
+		if (rimd->has_option("import_next_time"))
+			next_import->select(rimd->get_option("import_next_time"));
 
 
 		save_path->set_text(p_from.get_base_dir());
 		save_path->set_text(p_from.get_base_dir());
 		import_path->set_text(EditorImportPlugin::expand_source_path(rimd->get_source_path(0)));
 		import_path->set_text(EditorImportPlugin::expand_source_path(rimd->get_source_path(0)));
@@ -619,7 +870,7 @@ void EditorSceneImportDialog::_bind_methods() {
 	ObjectTypeDB::bind_method("_choose_file",&EditorSceneImportDialog::_choose_file);
 	ObjectTypeDB::bind_method("_choose_file",&EditorSceneImportDialog::_choose_file);
 	ObjectTypeDB::bind_method("_choose_save_file",&EditorSceneImportDialog::_choose_save_file);
 	ObjectTypeDB::bind_method("_choose_save_file",&EditorSceneImportDialog::_choose_save_file);
 	ObjectTypeDB::bind_method("_choose_script",&EditorSceneImportDialog::_choose_script);
 	ObjectTypeDB::bind_method("_choose_script",&EditorSceneImportDialog::_choose_script);
-	ObjectTypeDB::bind_method("_import",&EditorSceneImportDialog::_import);
+	ObjectTypeDB::bind_method("_import",&EditorSceneImportDialog::_import,DEFVAL(false));
 	ObjectTypeDB::bind_method("_browse",&EditorSceneImportDialog::_browse);
 	ObjectTypeDB::bind_method("_browse",&EditorSceneImportDialog::_browse);
 	ObjectTypeDB::bind_method("_browse_target",&EditorSceneImportDialog::_browse_target);
 	ObjectTypeDB::bind_method("_browse_target",&EditorSceneImportDialog::_browse_target);
 	ObjectTypeDB::bind_method("_browse_script",&EditorSceneImportDialog::_browse_script);
 	ObjectTypeDB::bind_method("_browse_script",&EditorSceneImportDialog::_browse_script);
@@ -792,6 +1043,20 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce
 	error_dialog->get_ok()->set_text("Accept");
 	error_dialog->get_ok()->set_text("Accept");
 //	error_dialog->get_cancel()->hide();
 //	error_dialog->get_cancel()->hide();
 
 
+	this_import = memnew( OptionButton );
+	this_import->add_item("Overwrite Existing Scene");
+	this_import->add_item("Owerwrite Existing, Keep Materials");
+	this_import->add_item("Keep Existing, Merge with New");
+	this_import->add_item("Keep Existing, Ignore New");
+	vbc->add_margin_child("This Time:",this_import);
+
+	next_import = memnew( OptionButton );
+	next_import->add_item("Overwrite Existing Scene");
+	next_import->add_item("Owerwrite Existing, Keep Materials");
+	next_import->add_item("Keep Existing, Merge with New");
+	next_import->add_item("Keep Existing, Ignore New");
+	vbc->add_margin_child("Next Time:",next_import);
+
 	set_hide_on_ok(false);
 	set_hide_on_ok(false);
 
 
 	GLOBAL_DEF("import/shared_textures","res://");
 	GLOBAL_DEF("import/shared_textures","res://");
@@ -814,7 +1079,7 @@ EditorSceneImportDialog::EditorSceneImportDialog(EditorNode *p_editor, EditorSce
 	animation_options = memnew( EditorImportAnimationOptions );
 	animation_options = memnew( EditorImportAnimationOptions );
 	ovb->add_child(animation_options);
 	ovb->add_child(animation_options);
 	animation_options->set_v_size_flags(SIZE_EXPAND_FILL);
 	animation_options->set_v_size_flags(SIZE_EXPAND_FILL);
-	animation_options->set_flags(EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP|EditorSceneAnimationImportPlugin::ANIMATION_KEEP_VALUE_TRACKS|EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE|EditorSceneAnimationImportPlugin::ANIMATION_FORCE_TRACKS_IN_ALL_BONES);
+	animation_options->set_flags(EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP|EditorSceneAnimationImportPlugin::ANIMATION_KEEP_VALUE_TRACKS|EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE|EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
 
 
 
 
 	confirm_import = memnew( ConfirmationDialog );
 	confirm_import = memnew( ConfirmationDialog );
@@ -1815,6 +2080,79 @@ void EditorSceneImportPlugin::_merge_scenes(Node *p_node,Node *p_imported) {
 }
 }
 
 
 
 
+void EditorSceneImportPlugin::_scan_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials) {
+
+	if (!p_base && p_node->get_owner()!=p_base)
+		return;
+	MeshInstance *mi=p_node->cast_to<MeshInstance>();
+
+	if (mi) {
+		if (mi->get_material_override().is_valid()) {
+			String path = p_base->get_path_to(p_node);
+			override_materials[path]=mi->get_material_override();
+		}
+		Ref<Mesh> mesh = mi->get_mesh();
+		if (mesh.is_valid()) {
+
+			for(int i=0;i<mesh->get_surface_count();i++) {
+
+				String name = mesh->get_name()+":"+mesh->surface_get_name(i);
+				if (!mesh_materials.has(name)) {
+					mesh_materials[name]=mesh->surface_get_material(i);
+				}
+			}
+		}
+	}
+
+	for(int i=0;i<p_node->get_child_count();i++) {
+		_scan_materials(p_base,p_node->get_child(i),mesh_materials,override_materials);
+	}
+}
+
+
+void EditorSceneImportPlugin::_apply_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials,Set<Ref<Mesh> >& meshes_processed) {
+
+	if (!p_base && p_node->get_owner()!=p_base)
+		return;
+
+	MeshInstance *mi=p_node->cast_to<MeshInstance>();
+
+	if (mi) {
+
+		String path = p_base->get_path_to(p_node);
+		if (override_materials.has(path))
+			mi->set_material_override(override_materials[path]);
+
+		Ref<Mesh> mesh = mi->get_mesh();
+		if (mesh.is_valid() && !meshes_processed.has(mesh)) {
+			meshes_processed.insert(mesh);
+			for(int i=0;i<mesh->get_surface_count();i++) {
+
+				String name = mesh->get_name()+":"+mesh->surface_get_name(i);
+				if (mesh_materials.has(name)) {
+
+					Ref<Material> mat = mesh_materials[name];
+					mesh->surface_set_material(i,mat);
+				}
+			}
+		}
+	}
+
+	for(int i=0;i<p_node->get_child_count();i++) {
+		_apply_materials(p_base,p_node->get_child(i),mesh_materials,override_materials,meshes_processed);
+	}
+}
+
+void EditorSceneImportPlugin::_merge_materials(Node *p_node,Node *p_imported) {
+
+	Map<String,Ref<Material> > mesh_materials;
+	Map<String,Ref<Material> > override_materials;
+
+	_scan_materials(p_node,p_node,mesh_materials,override_materials);
+	Set<Ref<Mesh> > mp;
+	_apply_materials(p_imported,p_imported,mesh_materials,override_materials,mp);
+
+}
 
 
 #if 0
 #if 0
 
 
@@ -1882,14 +2220,20 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from
 
 
 	int animation_flags=p_from->get_option("animation_flags");
 	int animation_flags=p_from->get_option("animation_flags");
 	int scene_flags = from->get_option("flags");
 	int scene_flags = from->get_option("flags");
+	int fps = 24;
+	if (from->has_option("animation_bake_fps"))
+		fps=from->get_option("animation_bake_fps");
+	Array clips;
+	if (from->has_option("animation_clips"))
+		clips=from->get_option("animation_clips");
 
 
 	uint32_t import_flags=0;
 	uint32_t import_flags=0;
 	if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP)
 	if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_DETECT_LOOP)
 		import_flags|=EditorSceneImporter::IMPORT_ANIMATION_DETECT_LOOP;
 		import_flags|=EditorSceneImporter::IMPORT_ANIMATION_DETECT_LOOP;
 	if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE)
 	if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE)
 		import_flags|=EditorSceneImporter::IMPORT_ANIMATION_OPTIMIZE;
 		import_flags|=EditorSceneImporter::IMPORT_ANIMATION_OPTIMIZE;
-	if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_TRACKS_IN_ALL_BONES)
-		import_flags|=EditorSceneImporter::IMPORT_ANIMATION_FORCE_TRACKS_IN_ALL_BONES;
+	if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS)
+		import_flags|=EditorSceneImporter::IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS;
 	if (scene_flags&SCENE_FLAG_IMPORT_ANIMATIONS)
 	if (scene_flags&SCENE_FLAG_IMPORT_ANIMATIONS)
 		import_flags|=EditorSceneImporter::IMPORT_ANIMATION;
 		import_flags|=EditorSceneImporter::IMPORT_ANIMATION;
 	//if (scene_flags&SCENE_FLAG_FAIL_ON_MISSING_IMAGES)
 	//if (scene_flags&SCENE_FLAG_FAIL_ON_MISSING_IMAGES)
@@ -1902,7 +2246,7 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from
 
 
 
 
 	Error err=OK;
 	Error err=OK;
-	Node *scene = importer->import_scene(src_path,import_flags,r_missing,&err);	
+	Node *scene = importer->import_scene(src_path,import_flags,fps,r_missing,&err);
 	if (!scene || err!=OK) {
 	if (!scene || err!=OK) {
 		return err;
 		return err;
 	}
 	}
@@ -1913,19 +2257,231 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from
 	return OK;
 	return OK;
 }
 }
 
 
+
+void EditorSceneImportPlugin::_create_clips(Node *scene, const Array& p_clips,bool p_bake_all) {
+
+	if (!scene->has_node(String("AnimationPlayer")))
+		return;
+
+	Node* n = scene->get_node(String("AnimationPlayer"));
+	ERR_FAIL_COND(!n);
+	AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
+	ERR_FAIL_COND(!anim);
+
+	if (!anim->has_animation("default"))
+		return;
+
+
+	Ref<Animation> default_anim = anim->get_animation("default");
+
+	for(int i=0;i<p_clips.size();i+=4) {
+
+		String name = p_clips[i];
+		float from=p_clips[i+1];
+		float to=p_clips[i+2];
+		bool loop=p_clips[i+3];
+		if (from>=to)
+			continue;
+
+		Ref<Animation> new_anim = memnew( Animation );
+
+		for(int j=0;j<default_anim->get_track_count();j++) {
+
+
+			List<float> keys;
+			int kc = default_anim->track_get_key_count(j);
+			int dtrack=-1;
+			for(int k=0;k<kc;k++) {
+
+				float kt = default_anim->track_get_key_time(j,k);
+				if (kt>=from && kt<to) {
+
+					//found a key within range, so create track
+					if (dtrack==-1) {
+						new_anim->add_track(default_anim->track_get_type(j));
+						dtrack = new_anim->get_track_count()-1;
+						new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
+
+						if (kt>(from+0.01) && k>0) {
+
+							if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+								Quat q;
+								Vector3 p;
+								Vector3 s;
+								default_anim->transform_track_interpolate(j,from,&p,&q,&s);
+								new_anim->transform_track_insert_key(dtrack,0,p,q,s);
+							}
+						}
+
+					}
+
+					if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+						Quat q;
+						Vector3 p;
+						Vector3 s;
+						default_anim->transform_track_get_key(j,k,&p,&q,&s);
+						new_anim->transform_track_insert_key(dtrack,kt-from,p,q,s);
+					}
+
+				}
+
+				if (dtrack!=-1 && kt>=to) {
+
+					if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+						Quat q;
+						Vector3 p;
+						Vector3 s;
+						default_anim->transform_track_interpolate(j,to,&p,&q,&s);
+						new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
+					}
+				}
+
+			}
+
+			if (dtrack==-1 && p_bake_all) {
+				new_anim->add_track(default_anim->track_get_type(j));
+				dtrack = new_anim->get_track_count()-1;
+				new_anim->track_set_path(dtrack,default_anim->track_get_path(j));
+				if (default_anim->track_get_type(j)==Animation::TYPE_TRANSFORM) {
+
+
+					Quat q;
+					Vector3 p;
+					Vector3 s;
+					default_anim->transform_track_interpolate(j,from,&p,&q,&s);
+					new_anim->transform_track_insert_key(dtrack,0,p,q,s);
+					default_anim->transform_track_interpolate(j,to,&p,&q,&s);
+					new_anim->transform_track_insert_key(dtrack,to-from,p,q,s);
+				}
+
+			}
+		}
+
+
+		new_anim->set_loop(loop);
+		new_anim->set_length(to-from);
+		anim->add_animation(name,new_anim);
+	}
+
+	anim->remove_animation("default"); //remove default (no longer needed)
+}
+
+void EditorSceneImportPlugin::_filter_tracks(Node *scene, const String& p_text) {
+
+	if (!scene->has_node(String("AnimationPlayer")))
+		return;
+		Node* n = scene->get_node(String("AnimationPlayer"));
+	ERR_FAIL_COND(!n);
+	AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
+	ERR_FAIL_COND(!anim);
+
+	Vector<String> strings = p_text.split("\n");
+	for(int i=0;i<strings.size();i++) {
+
+		strings[i]=strings[i].strip_edges();
+	}
+
+	List<StringName> anim_names;
+	anim->get_animation_list(&anim_names);
+	Set<String> keep;
+	for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
+
+		String name = E->get();
+		bool valid_for_this=false;
+
+		for(int i=0;i<strings.size();i++) {
+
+
+			if (strings[i].begins_with("@")) {
+
+				valid_for_this=false;
+				keep.clear();
+
+				Vector<String> filters=strings[i].substr(1,strings[i].length()).split(",");
+				for(int j=0;j<filters.size();j++) {
+
+					String fname = filters[i].strip_edges();
+					if (fname=="")
+						continue;
+					int fc = fname[0];
+					bool plus;
+					if (fc=='+')
+						plus=true;
+					else if (fc=='-')
+						 plus=false;
+					else
+						continue;
+
+					String filter=fname.substr(1,fname.length()).strip_edges();
+
+					if (!name.matchn(filter))
+						continue;
+					valid_for_this=plus;
+				}
+			} else if (valid_for_this) {
+
+				Ref<Animation> a = anim->get_animation(name);
+				if (!a.is_valid())
+					continue;
+
+				for(int j=0;j<a->get_track_count();j++) {
+
+					String path = a->track_get_path(j);
+
+					String tname = strings[i];
+					if (tname=="")
+						continue;
+					int fc = tname[0];
+					bool plus;
+					if (fc=='+')
+						plus=true;
+					else if (fc=='-')
+						 plus=false;
+					else
+						continue;
+
+					String filter=tname.substr(1,tname.length()).strip_edges();
+
+					if (!path.matchn(filter))
+						continue;
+
+					if (plus)
+						keep.insert(path);
+					else if (!keep.has(path)) {
+						a->remove_track(j);
+						j--;
+					}
+
+				}
+
+			}
+
+		}
+
+	}
+
+
+}
+
 Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from) {
 Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from) {
 
 
 	Error err=OK;
 	Error err=OK;
 	Ref<ResourceImportMetadata> from=p_from;
 	Ref<ResourceImportMetadata> from=p_from;
 	String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
 	String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0));
 	int animation_flags=p_from->get_option("animation_flags");
 	int animation_flags=p_from->get_option("animation_flags");
+	Array animation_clips = p_from->get_option("animation_clips");
+	String animation_filter = p_from->get_option("animation_filters");
 	int scene_flags = from->get_option("flags");
 	int scene_flags = from->get_option("flags");
 
 
 	EditorProgress progress("import","Import Scene",104);
 	EditorProgress progress("import","Import Scene",104);
 	progress.step("Importing Scene..",2);
 	progress.step("Importing Scene..",2);
 
 
 
 
-	bool merge = !bool(from->get_option("reimport"));
+	bool reimport = bool(from->get_option("reimport"));
+	int this_time_action = from->get_option("import_this_time");
+	int next_time_action = from->get_option("import_next_time");
+
+	int import_action = reimport?this_time_action:next_time_action;
 
 
 	from->set_source_md5(0,FileAccess::get_md5(src_path));
 	from->set_source_md5(0,FileAccess::get_md5(src_path));
 	from->set_editor(get_name());
 	from->set_editor(get_name());
@@ -1940,6 +2496,11 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
 	Map< Ref<ImageTexture>,TextureRole > imagemap;
 	Map< Ref<ImageTexture>,TextureRole > imagemap;
 
 
 	scene=_fix_node(scene,scene,collision_map,scene_flags,imagemap);
 	scene=_fix_node(scene,scene,collision_map,scene_flags,imagemap);
+	if (animation_clips.size())
+		_create_clips(scene,animation_clips,animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
+
+	_filter_tracks(scene,animation_filter);
+
 
 
 
 
 	/// BEFORE ANYTHING, RUN SCRIPT
 	/// BEFORE ANYTHING, RUN SCRIPT
@@ -2063,7 +2624,7 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
 	/// BEFORE SAVING - MERGE
 	/// BEFORE SAVING - MERGE
 
 
 
 
-	if (merge) {
+	if (import_action!=SCENE_UPDATE_REPLACE_WITH_NEW) {
 
 
 
 
 		progress.step("Merging..",103);
 		progress.step("Merging..",103);
@@ -2082,10 +2643,30 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
 
 
 				if (existing) {
 				if (existing) {
 
 
-					_merge_scenes(existing,scene);
 
 
-					memdelete(scene);
-					scene=existing;
+					switch(import_action) {
+
+						case SCENE_UPDATE_REPLACE_WITH_NEW: break;
+						case SCENE_UPDATE_REPLACE_WITH_NEW_KEEP_MATERIALS: {
+
+							_merge_materials(existing,scene);
+							memdelete(existing);
+
+						} break;
+						case SCENE_UPDATE_KEEP_OLD_MERGE_CHANGES: {
+
+							_merge_scenes(existing,scene);
+							memdelete(scene);
+							scene=existing;
+
+						} break;
+						case SCENE_UPDATE_KEEP_OLD: {
+
+							memdelete(scene);
+							scene=existing;
+						} break;
+					}
+
 				}
 				}
 			}
 			}
 
 

+ 16 - 4
tools/editor/io_plugins/editor_scene_import_plugin.h

@@ -58,7 +58,7 @@ public:
 		IMPORT_ANIMATION=2,
 		IMPORT_ANIMATION=2,
 		IMPORT_ANIMATION_DETECT_LOOP=4,
 		IMPORT_ANIMATION_DETECT_LOOP=4,
 		IMPORT_ANIMATION_OPTIMIZE=8,
 		IMPORT_ANIMATION_OPTIMIZE=8,
-		IMPORT_ANIMATION_FORCE_TRACKS_IN_ALL_BONES=16,
+		IMPORT_ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=16,
 		IMPORT_GENERATE_TANGENT_ARRAYS=256,
 		IMPORT_GENERATE_TANGENT_ARRAYS=256,
 		IMPORT_FAIL_ON_MISSING_DEPENDENCIES=512
 		IMPORT_FAIL_ON_MISSING_DEPENDENCIES=512
 
 
@@ -66,7 +66,7 @@ public:
 
 
 	virtual uint32_t get_import_flags() const=0;
 	virtual uint32_t get_import_flags() const=0;
 	virtual void get_extensions(List<String> *r_extensions) const=0;
 	virtual void get_extensions(List<String> *r_extensions) const=0;
-	virtual Node* import_scene(const String& p_path,uint32_t p_flags,List<String> *r_missing_deps,Error* r_err=NULL)=0;
+	virtual Node* import_scene(const String& p_path,uint32_t p_flags,int p_bake_fps,List<String> *r_missing_deps,Error* r_err=NULL)=0;
 	virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags)=0;
 	virtual Ref<Animation> import_animation(const String& p_path,uint32_t p_flags)=0;
 
 
 
 
@@ -108,10 +108,16 @@ class EditorSceneImportPlugin : public EditorImportPlugin {
 
 
 	void _find_resources(const Variant& p_var,Map<Ref<ImageTexture>,TextureRole >& image_map,int p_flags);
 	void _find_resources(const Variant& p_var,Map<Ref<ImageTexture>,TextureRole >& image_map,int p_flags);
 	Node* _fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Map<Ref<ImageTexture>,TextureRole >& image_map);
 	Node* _fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Map<Ref<ImageTexture>,TextureRole >& image_map);
+	void _create_clips(Node *scene, const Array& p_clips, bool p_bake_all);
+	void _filter_tracks(Node *scene, const String& p_text);
 	void _merge_existing_node(Node *p_node,Node *p_imported_scene,Set<Ref<Resource> >& checked_resources,Set<Node*> &checked_nodes);
 	void _merge_existing_node(Node *p_node,Node *p_imported_scene,Set<Ref<Resource> >& checked_resources,Set<Node*> &checked_nodes);
+
 	void _add_new_nodes(Node *p_node,Node *p_imported,Node *p_imported_scene,Set<Node*> &checked_nodes);
 	void _add_new_nodes(Node *p_node,Node *p_imported,Node *p_imported_scene,Set<Node*> &checked_nodes);
 
 
 	void _merge_scenes(Node *p_node, Node *p_imported);
 	void _merge_scenes(Node *p_node, Node *p_imported);
+	void _scan_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials);
+	void _apply_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials,Set<Ref<Mesh> >& meshes_processed);
+	void _merge_materials(Node *p_node,Node *p_imported);
 
 
 	void _tag_import_paths(Node *p_scene,Node *p_node);
 	void _tag_import_paths(Node *p_scene,Node *p_node);
 
 
@@ -142,6 +148,13 @@ public:
 		SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY=1<<30,
 		SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY=1<<30,
 	};
 	};
 
 
+	enum SceneUpdate {
+		SCENE_UPDATE_REPLACE_WITH_NEW,
+		SCENE_UPDATE_REPLACE_WITH_NEW_KEEP_MATERIALS,
+		SCENE_UPDATE_KEEP_OLD_MERGE_CHANGES,
+		SCENE_UPDATE_KEEP_OLD,
+	};
+
 
 
 	virtual String get_name() const;
 	virtual String get_name() const;
 	virtual String get_visible_name() const;
 	virtual String get_visible_name() const;
@@ -171,7 +184,7 @@ public:
 		ANIMATION_DETECT_LOOP=1,
 		ANIMATION_DETECT_LOOP=1,
 		ANIMATION_KEEP_VALUE_TRACKS=2,
 		ANIMATION_KEEP_VALUE_TRACKS=2,
 		ANIMATION_OPTIMIZE=4,
 		ANIMATION_OPTIMIZE=4,
-		ANIMATION_FORCE_TRACKS_IN_ALL_BONES=8
+		ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS=8
 	};
 	};
 
 
 	virtual String get_name() const;
 	virtual String get_name() const;
@@ -185,5 +198,4 @@ public:
 };
 };
 
 
 
 
-
 #endif // EDITOR_SCENE_IMPORT_PLUGIN_H
 #endif // EDITOR_SCENE_IMPORT_PLUGIN_H

+ 19 - 18
tools/editor/plugins/baked_light_baker_cmpxchg.cpp

@@ -2,12 +2,11 @@
 #include "typedefs.h"
 #include "typedefs.h"
 
 
 
 
-#ifdef WINDOWS_ENABLED
-
-#include "windows.h"
+#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
 
 
 void baked_light_baker_add_64f(double *dst,double value) {
 void baked_light_baker_add_64f(double *dst,double value) {
 
 
+
 	union {
 	union {
 		int64_t i;
 		int64_t i;
 		double f;
 		double f;
@@ -19,28 +18,22 @@ void baked_light_baker_add_64f(double *dst,double value) {
 		int64_t from = swapy.i;
 		int64_t from = swapy.i;
 		swapy.f+=value;
 		swapy.f+=value;
 		int64_t to=swapy.i;
 		int64_t to=swapy.i;
-		int64_t result = InterlockedCompareExchange64((int64_t*)dst,to,from);
-		if (result==from)
+		if (__sync_bool_compare_and_swap((int64_t*)dst,from,to))
 			break;
 			break;
 	}
 	}
-
 }
 }
 
 
 void baked_light_baker_add_64i(int64_t *dst,int64_t value) {
 void baked_light_baker_add_64i(int64_t *dst,int64_t value) {
 
 
-	while(true) {
-		int64_t from = *dst;
-		int64_t to = from+value;
-		int64_t result = InterlockedCompareExchange64(dst,to,from);
-		if (result==from)
-			break;
-	}
+	while(!__sync_bool_compare_and_swap(dst,*dst,(*dst)+value)) {}
+
 }
 }
 
 
-#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
+#elif defined(WINDOWS_ENABLED)
 
 
-void baked_light_baker_add_64f(double *dst,double value) {
+#include "windows.h"
 
 
+void baked_light_baker_add_64f(double *dst,double value) {
 
 
 	union {
 	union {
 		int64_t i;
 		int64_t i;
@@ -53,17 +46,25 @@ void baked_light_baker_add_64f(double *dst,double value) {
 		int64_t from = swapy.i;
 		int64_t from = swapy.i;
 		swapy.f+=value;
 		swapy.f+=value;
 		int64_t to=swapy.i;
 		int64_t to=swapy.i;
-		if (__sync_bool_compare_and_swap((int64_t*)dst,from,to))
+		int64_t result = InterlockedCompareExchange64((int64_t*)dst,to,from);
+		if (result==from)
 			break;
 			break;
 	}
 	}
+
 }
 }
 
 
 void baked_light_baker_add_64i(int64_t *dst,int64_t value) {
 void baked_light_baker_add_64i(int64_t *dst,int64_t value) {
 
 
-	while(!__sync_bool_compare_and_swap(dst,*dst,(*dst)+value)) {}
-
+	while(true) {
+		int64_t from = *dst;
+		int64_t to = from+value;
+		int64_t result = InterlockedCompareExchange64(dst,to,from);
+		if (result==from)
+			break;
+	}
 }
 }
 
 
+
 #else
 #else
 
 
 //in goder (the god of programmers) we trust
 //in goder (the god of programmers) we trust

+ 6 - 1
tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp

@@ -13,7 +13,7 @@ void CollisionPolygon2DEditor::_notification(int p_what) {
 			button_create->set_icon( get_icon("Edit","EditorIcons"));
 			button_create->set_icon( get_icon("Edit","EditorIcons"));
 			button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
 			button_edit->set_icon( get_icon("MovePoint","EditorIcons"));
 			button_edit->set_pressed(true);
 			button_edit->set_pressed(true);
-
+			get_scene()->connect("node_removed",this,"_node_removed");
 
 
 		} break;
 		} break;
 		case NOTIFICATION_FIXED_PROCESS: {
 		case NOTIFICATION_FIXED_PROCESS: {
@@ -28,6 +28,7 @@ void CollisionPolygon2DEditor::_node_removed(Node *p_node) {
 	if(p_node==node) {
 	if(p_node==node) {
 		node=NULL;
 		node=NULL;
 		hide();
 		hide();
+		canvas_item_editor->get_viewport_control()->update();
 	}
 	}
 
 
 }
 }
@@ -83,6 +84,9 @@ void CollisionPolygon2DEditor::_wip_close() {
 bool CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) {
 bool CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) {
 
 
 
 
+	if (!node)
+		return false;
+
 	switch(p_event.type) {
 	switch(p_event.type) {
 
 
 		case InputEvent::MOUSE_BUTTON: {
 		case InputEvent::MOUSE_BUTTON: {
@@ -379,6 +383,7 @@ void CollisionPolygon2DEditor::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("_menu_option"),&CollisionPolygon2DEditor::_menu_option);
 	ObjectTypeDB::bind_method(_MD("_menu_option"),&CollisionPolygon2DEditor::_menu_option);
 	ObjectTypeDB::bind_method(_MD("_canvas_draw"),&CollisionPolygon2DEditor::_canvas_draw);
 	ObjectTypeDB::bind_method(_MD("_canvas_draw"),&CollisionPolygon2DEditor::_canvas_draw);
+	ObjectTypeDB::bind_method(_MD("_node_removed"),&CollisionPolygon2DEditor::_node_removed);
 
 
 }
 }
 
 

+ 55 - 0
tools/editor/plugins/mesh_editor_plugin.cpp

@@ -158,13 +158,54 @@ void MeshInstanceEditor::_menu_option(int p_option) {
 			ur->add_undo_method(node,"remove_child",nmi);
 			ur->add_undo_method(node,"remove_child",nmi);
 			ur->commit_action();
 			ur->commit_action();
 		} break;
 		} break;
+		case MENU_OPTION_CREATE_OUTLINE_MESH: {
+
+			outline_dialog->popup_centered(Size2(200,80));
+		} break;
 	}
 	}
 
 
 }
 }
 
 
+void MeshInstanceEditor::_create_outline_mesh() {
+
+	Ref<Mesh> mesh = node->get_mesh();
+	if (mesh.is_null()) {
+		err_dialog->set_text("MeshInstance lacks a Mesh!");
+		err_dialog->popup_centered(Size2(100,50));
+		return;
+	}
+
+	Ref<Mesh> mesho = mesh->create_outline(outline_size->get_val());
+
+	if (mesho.is_null()) {
+		err_dialog->set_text("Could not create outline!");
+		err_dialog->popup_centered(Size2(100,50));
+		return;
+	}
+
+	MeshInstance *mi = memnew( MeshInstance );
+	mi->set_mesh(mesho);
+	Node *owner=node->get_owner();
+	if (get_scene()->get_edited_scene_root()==node) {
+		owner=node;
+	}
+
+	UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+
+	ur->create_action("Create Outline");
+
+	ur->add_do_method(node,"add_child",mi);
+	ur->add_do_method(mi,"set_owner",owner);
+
+	ur->add_do_reference(mi);
+	ur->add_undo_method(node,"remove_child",mi);
+	ur->commit_action();
+}
+
 void MeshInstanceEditor::_bind_methods() {
 void MeshInstanceEditor::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method("_menu_option",&MeshInstanceEditor::_menu_option);
 	ObjectTypeDB::bind_method("_menu_option",&MeshInstanceEditor::_menu_option);
+	ObjectTypeDB::bind_method("_create_outline_mesh",&MeshInstanceEditor::_create_outline_mesh);
 }
 }
 
 
 MeshInstanceEditor::MeshInstanceEditor() {
 MeshInstanceEditor::MeshInstanceEditor() {
@@ -182,9 +223,23 @@ MeshInstanceEditor::MeshInstanceEditor() {
 	options->get_popup()->add_item("Create Convex Collision Sibling",MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE);
 	options->get_popup()->add_item("Create Convex Collision Sibling",MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE);
 	options->get_popup()->add_separator();
 	options->get_popup()->add_separator();
 	options->get_popup()->add_item("Create Navigation Mesh",MENU_OPTION_CREATE_NAVMESH);
 	options->get_popup()->add_item("Create Navigation Mesh",MENU_OPTION_CREATE_NAVMESH);
+	options->get_popup()->add_separator();
+	options->get_popup()->add_item("Create Outline Mesh..",MENU_OPTION_CREATE_OUTLINE_MESH);
 
 
 	options->get_popup()->connect("item_pressed", this,"_menu_option");
 	options->get_popup()->connect("item_pressed", this,"_menu_option");
 
 
+	outline_dialog = memnew( ConfirmationDialog );
+	outline_dialog->set_title("Outline Size: ");
+	outline_size = memnew( SpinBox );
+	outline_size->set_min(0.001);
+	outline_size->set_max(1024);
+	outline_size->set_step(0.001);
+	outline_size->set_val(0.05);
+	outline_dialog->add_child(outline_size);
+	outline_dialog->set_child_rect(outline_size);
+	add_child(outline_dialog);
+	outline_dialog->connect("confirmed",this,"_create_outline_mesh");
+
 }
 }
 
 
 
 

+ 6 - 0
tools/editor/plugins/mesh_editor_plugin.h

@@ -20,8 +20,12 @@ class MeshInstanceEditor : public Node {
 		MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE,
 		MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE,
 		MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE,
 		MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE,
 		MENU_OPTION_CREATE_NAVMESH,
 		MENU_OPTION_CREATE_NAVMESH,
+		MENU_OPTION_CREATE_OUTLINE_MESH,
 	};
 	};
 
 
+	ConfirmationDialog *outline_dialog;
+	SpinBox *outline_size;
+
 	AcceptDialog *err_dialog;
 	AcceptDialog *err_dialog;
 
 
 
 
@@ -33,6 +37,8 @@ class MeshInstanceEditor : public Node {
 
 
 
 
 	void _menu_option(int p_option);
 	void _menu_option(int p_option);
+	void _create_outline_mesh();
+
 friend class MeshInstanceEditorPlugin;
 friend class MeshInstanceEditorPlugin;
 	MenuButton * options;
 	MenuButton * options;
 
 

+ 1 - 1
tools/editor/spatial_editor_gizmos.cpp

@@ -1779,7 +1779,7 @@ void CollisionShapeSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Po
 		Ref<CapsuleShape> cs = s;
 		Ref<CapsuleShape> cs = s;
 		Vector3 ra,rb;
 		Vector3 ra,rb;
 		Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb);
 		Geometry::get_closest_points_between_segments(Vector3(),axis*4096,sg[0],sg[1],ra,rb);
-		float d = ra[p_idx];
+		float d = axis.dot(ra);
 		if (p_idx==1)
 		if (p_idx==1)
 			d-=cs->get_radius();
 			d-=cs->get_radius();
 		if (d<0.001)
 		if (d<0.001)

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