Kaynağa Gözat

Merge branch 'master' of https://github.com/godotengine/godot

Juan Linietsky 9 yıl önce
ebeveyn
işleme
e535c942f3
36 değiştirilmiş dosya ile 1293 ekleme ve 309 silme
  1. 126 0
      core/command_queue_mt.h
  2. 12 2
      core/dictionary.cpp
  3. 1 0
      core/dictionary.h
  4. 13 0
      core/dvector.h
  5. 14 0
      core/global_constants.cpp
  6. 5 1
      core/io/resource_loader.cpp
  7. 6 2
      core/variant_call.cpp
  8. 63 56
      doc/base/classes.xml
  9. 25 20
      drivers/gles2/rasterizer_gles2.cpp
  10. 1 1
      drivers/gles2/rasterizer_gles2.h
  11. 6 0
      modules/gdscript/gd_compiler.cpp
  12. 2 5
      modules/gdscript/gd_script.cpp
  13. 15 11
      platform/iphone/rasterizer_iphone.cpp
  14. 87 29
      scene/gui/control.cpp
  15. 7 0
      scene/gui/control.h
  16. 34 4
      scene/gui/patch_9_frame.cpp
  17. 4 0
      scene/gui/patch_9_frame.h
  18. 2 0
      scene/resources/bit_mask.h
  19. 19 2
      scene/resources/style_box.cpp
  20. 4 0
      scene/resources/style_box.h
  21. 61 0
      servers/server_wrap_mt_common.h
  22. 3 2
      servers/visual/rasterizer.h
  23. 1 2
      servers/visual/rasterizer_dummy.cpp
  24. 1 1
      servers/visual/rasterizer_dummy.h
  25. 2 1
      servers/visual/visual_server_raster.cpp
  26. 1 1
      servers/visual/visual_server_raster.h
  27. 1 1
      servers/visual/visual_server_wrap_mt.h
  28. 2 4
      servers/visual_server.cpp
  29. 2 2
      servers/visual_server.h
  30. 6 6
      tools/editor/editor_node.cpp
  31. 357 0
      tools/editor/io_plugins/editor_bitmask_import_plugin.cpp
  32. 41 0
      tools/editor/io_plugins/editor_bitmask_import_plugin.h
  33. 231 113
      tools/editor/plugins/texture_region_editor_plugin.cpp
  34. 35 22
      tools/editor/plugins/texture_region_editor_plugin.h
  35. 101 21
      tools/editor/project_settings.cpp
  36. 2 0
      tools/editor/project_settings.h

+ 126 - 0
core/command_queue_mt.h

@@ -152,6 +152,23 @@ class CommandQueueMT {
 		virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); }
 		virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); }
 	};
 	};
 
 
+	template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class P8>
+	struct Command8 : public CommandBase {
+
+		T*instance;
+		M method;
+		typename GetSimpleTypeT<P1>::type_t p1;
+		typename GetSimpleTypeT<P2>::type_t p2;
+		typename GetSimpleTypeT<P3>::type_t p3;
+		typename GetSimpleTypeT<P4>::type_t p4;
+		typename GetSimpleTypeT<P5>::type_t p5;
+		typename GetSimpleTypeT<P6>::type_t p6;
+		typename GetSimpleTypeT<P7>::type_t p7;
+		typename GetSimpleTypeT<P8>::type_t p8;
+
+		virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7,p8); }
+	};
+
 	/* comands that return */
 	/* comands that return */
 
 
 	template<class T,class M,class R>
 	template<class T,class M,class R>
@@ -270,6 +287,25 @@ class CommandQueueMT {
 		virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
 		virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
 	};
 	};
 
 
+	template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class P8,class R>
+	struct CommandRet8 : public CommandBase {
+
+		T*instance;
+		M method;
+		typename GetSimpleTypeT<P1>::type_t p1;
+		typename GetSimpleTypeT<P2>::type_t p2;
+		typename GetSimpleTypeT<P3>::type_t p3;
+		typename GetSimpleTypeT<P4>::type_t p4;
+		typename GetSimpleTypeT<P5>::type_t p5;
+		typename GetSimpleTypeT<P6>::type_t p6;
+		typename GetSimpleTypeT<P7>::type_t p7;
+		typename GetSimpleTypeT<P8>::type_t p8;
+		R* ret;
+		SyncSemaphore *sync;
+
+		virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6,p7,p8); sync->sem->post(); sync->in_use=false; ; }
+	};
+
 	/** commands that don't return but sync */
 	/** commands that don't return but sync */
 
 
 	/* comands that return */
 	/* comands that return */
@@ -390,6 +426,25 @@ class CommandQueueMT {
 		virtual void call() {  (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
 		virtual void call() {  (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
 	};
 	};
 
 
+	template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class P8>
+	struct CommandSync8 : public CommandBase {
+
+		T*instance;
+		M method;
+		typename GetSimpleTypeT<P1>::type_t p1;
+		typename GetSimpleTypeT<P2>::type_t p2;
+		typename GetSimpleTypeT<P3>::type_t p3;
+		typename GetSimpleTypeT<P4>::type_t p4;
+		typename GetSimpleTypeT<P5>::type_t p5;
+		typename GetSimpleTypeT<P6>::type_t p6;
+		typename GetSimpleTypeT<P7>::type_t p7;
+		typename GetSimpleTypeT<P8>::type_t p8;
+
+		SyncSemaphore *sync;
+
+		virtual void call() {  (instance->*method)(p1,p2,p3,p4,p5,p6,p7,p8); sync->sem->post(); sync->in_use=false; ; }
+	};
+
 	/***** BASE *******/
 	/***** BASE *******/
 
 
 	enum {
 	enum {
@@ -639,6 +694,27 @@ public:
 
 
 		if (sync) sync->post();
 		if (sync) sync->post();
 	}
 	}
+
+	template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7,class P8>
+	void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8 ) {
+
+		Command8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> * cmd = allocate_and_lock< Command8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> >();
+
+		cmd->instance=p_instance;
+		cmd->method=p_method;
+		cmd->p1=p1;
+		cmd->p2=p2;
+		cmd->p3=p3;
+		cmd->p4=p4;
+		cmd->p5=p5;
+		cmd->p6=p6;
+		cmd->p7=p7;
+		cmd->p8=p8;
+
+		unlock();
+
+		if (sync) sync->post();
+	}
 	/*** PUSH AND RET COMMANDS ***/
 	/*** PUSH AND RET COMMANDS ***/
 
 
 
 
@@ -806,6 +882,31 @@ public:
 		ss->sem->wait();
 		ss->sem->wait();
 	}
 	}
 
 
+	template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7,class P8,class R>
+	void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7,P8 p8, R* r_ret ) {
+
+		CommandRet8<T,M,P1,P2,P3,P4,P5,P6,P7,P8,R> * cmd = allocate_and_lock< CommandRet8<T,M,P1,P2,P3,P4,P5,P6,P7,P8,R> >();
+
+		cmd->instance=p_instance;
+		cmd->method=p_method;
+		cmd->p1=p1;
+		cmd->p2=p2;
+		cmd->p3=p3;
+		cmd->p4=p4;
+		cmd->p5=p5;
+		cmd->p6=p6;
+		cmd->p7=p7;
+		cmd->p8=p8;
+		cmd->ret=r_ret;
+		SyncSemaphore *ss=_alloc_sync_sem();
+		cmd->sync=ss;
+
+		unlock();
+
+		if (sync) sync->post();
+		ss->sem->wait();
+	}
+
 
 
 	template<class T, class M>
 	template<class T, class M>
 	void push_and_sync( T * p_instance, M p_method) {
 	void push_and_sync( T * p_instance, M p_method) {
@@ -971,6 +1072,31 @@ public:
 		ss->sem->wait();
 		ss->sem->wait();
 	}
 	}
 
 
+	template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7,class P8>
+	void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7,P8 p8) {
+
+		CommandSync8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> * cmd = allocate_and_lock< CommandSync8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> >();
+
+		cmd->instance=p_instance;
+		cmd->method=p_method;
+		cmd->p1=p1;
+		cmd->p2=p2;
+		cmd->p3=p3;
+		cmd->p4=p4;
+		cmd->p5=p5;
+		cmd->p6=p6;
+		cmd->p7=p7;
+		cmd->p8=p8;
+
+		SyncSemaphore *ss=_alloc_sync_sem();
+		cmd->sync=ss;
+
+		unlock();
+
+		if (sync) sync->post();
+		ss->sem->wait();
+	}
+
 	void wait_and_flush_one() {
 	void wait_and_flush_one() {
 		ERR_FAIL_COND(!sync);
 		ERR_FAIL_COND(!sync);
 		sync->wait();
 		sync->wait();

+ 12 - 2
core/dictionary.cpp

@@ -199,6 +199,18 @@ Array Dictionary::keys() const {
 
 
 }
 }
 
 
+Array Dictionary::values() const {
+
+	Array varr;
+	varr.resize(size());
+	const Variant *key=NULL;
+	int i=0;
+	while((key=next(key))){
+		varr[i++] = _p->variant_map[*key];
+	}
+	return varr;
+}
+
 const Variant* Dictionary::next(const Variant* p_key) const {
 const Variant* Dictionary::next(const Variant* p_key) const {
 
 
 	return _p->variant_map.next(p_key);
 	return _p->variant_map.next(p_key);
@@ -250,5 +262,3 @@ Dictionary::~Dictionary() {
 
 
 	_unref();
 	_unref();
 }
 }
-
-

+ 1 - 0
core/dictionary.h

@@ -81,6 +81,7 @@ public:
 	const Variant* next(const Variant* p_key=NULL) const;
 	const Variant* next(const Variant* p_key=NULL) const;
 
 
 	Array keys() const;
 	Array keys() const;
+	Array values() const;
 
 
 	Dictionary(const Dictionary& p_from);
 	Dictionary(const Dictionary& p_from);
 	Dictionary(bool p_shared=false);
 	Dictionary(bool p_shared=false);

+ 13 - 0
core/dvector.h

@@ -285,6 +285,7 @@ public:
 
 
 	Error resize(int p_size);
 	Error resize(int p_size);
 
 
+	void invert();
 
 
 	void operator=(const DVector& p_dvector) { reference(p_dvector); }
 	void operator=(const DVector& p_dvector) { reference(p_dvector); }
 	DVector() {}
 	DVector() {}
@@ -424,6 +425,18 @@ Error DVector<T>::resize(int p_size) {
 	return OK;
 	return OK;
 }
 }
 
 
+template<class T>
+void DVector<T>::invert() {
+	T temp;
+	Write w = write();
+	int s = size();
+	int half_s = s/2;
 
 
+	for(int i=0;i<half_s;i++) {
+		temp = w[i];
+		w[i] = w[s-i-1];
+		w[s-i-1] = temp;
+	}
+}
 
 
 #endif
 #endif

+ 14 - 0
core/global_constants.cpp

@@ -478,7 +478,21 @@ static _GlobalConstant _global_constants[]={
 	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORAGE  ),
 	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORAGE  ),
 	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_EDITOR  ),
 	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_EDITOR  ),
 	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_NETWORK  ),
 	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_NETWORK  ),
+
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_EDITOR_HELPER ),
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_CHECKABLE ),
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_CHECKED ),
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_INTERNATIONALIZED ),
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_BUNDLE ),
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_CATEGORY ),
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORE_IF_NONZERO ),
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORE_IF_NONONE ),
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_NO_INSTANCE_STATE ),
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_RESTART_IF_CHANGED ),
+
 	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_DEFAULT  ),
 	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_DEFAULT  ),
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_DEFAULT_INTL ),
+	BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_NOEDITOR ),
 
 
 	BIND_GLOBAL_CONSTANT( METHOD_FLAG_NORMAL ),
 	BIND_GLOBAL_CONSTANT( METHOD_FLAG_NORMAL ),
 	BIND_GLOBAL_CONSTANT( METHOD_FLAG_EDITOR ),
 	BIND_GLOBAL_CONSTANT( METHOD_FLAG_EDITOR ),

+ 5 - 1
core/io/resource_loader.cpp

@@ -319,7 +319,11 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
 		if (OS::get_singleton()->is_stdout_verbose())
 		if (OS::get_singleton()->is_stdout_verbose())
 			print_line("load resource: "+local_path+" (cached)");
 			print_line("load resource: "+local_path+" (cached)");
 
 
-		return RES( ResourceCache::get(local_path ) );
+		Ref<Resource> res_cached = ResourceCache::get(local_path);
+		Ref<ResourceInteractiveLoaderDefault> ril = Ref<ResourceInteractiveLoaderDefault>(memnew(ResourceInteractiveLoaderDefault));
+
+		ril->resource = res_cached;
+		return ril;
 	}
 	}
 
 
 	if (OS::get_singleton()->is_stdout_verbose())
 	if (OS::get_singleton()->is_stdout_verbose())

+ 6 - 2
core/variant_call.cpp

@@ -262,7 +262,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
 	VCALL_LOCALMEM0R(String,basename);
 	VCALL_LOCALMEM0R(String,basename);
 	VCALL_LOCALMEM1R(String,plus_file);
 	VCALL_LOCALMEM1R(String,plus_file);
 	VCALL_LOCALMEM1R(String,ord_at);
 	VCALL_LOCALMEM1R(String,ord_at);
-	//VCALL_LOCALMEM2R(String,erase);
+	VCALL_LOCALMEM2(String,erase);
 	VCALL_LOCALMEM0R(String,hash);
 	VCALL_LOCALMEM0R(String,hash);
 	VCALL_LOCALMEM0R(String,md5_text);
 	VCALL_LOCALMEM0R(String,md5_text);
 	VCALL_LOCALMEM0R(String,md5_buffer);
 	VCALL_LOCALMEM0R(String,md5_buffer);
@@ -339,6 +339,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
 	VCALL_LOCALMEM1R(Vector2,reflect);
 	VCALL_LOCALMEM1R(Vector2,reflect);
 	VCALL_LOCALMEM0R(Vector2,angle);
 	VCALL_LOCALMEM0R(Vector2,angle);
 //	VCALL_LOCALMEM1R(Vector2,cross);
 //	VCALL_LOCALMEM1R(Vector2,cross);
+	VCALL_LOCALMEM0R(Vector2,abs);
 
 
 	VCALL_LOCALMEM0R(Rect2,get_area);
 	VCALL_LOCALMEM0R(Rect2,get_area);
 	VCALL_LOCALMEM1R(Rect2,intersects);
 	VCALL_LOCALMEM1R(Rect2,intersects);
@@ -445,6 +446,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
 	VCALL_LOCALMEM1(Dictionary,erase);
 	VCALL_LOCALMEM1(Dictionary,erase);
 	VCALL_LOCALMEM0R(Dictionary,hash);
 	VCALL_LOCALMEM0R(Dictionary,hash);
 	VCALL_LOCALMEM0R(Dictionary,keys);
 	VCALL_LOCALMEM0R(Dictionary,keys);
+	VCALL_LOCALMEM0R(Dictionary,values);
 	VCALL_LOCALMEM1R(Dictionary,parse_json);
 	VCALL_LOCALMEM1R(Dictionary,parse_json);
 	VCALL_LOCALMEM0R(Dictionary,to_json);
 	VCALL_LOCALMEM0R(Dictionary,to_json);
 
 
@@ -1284,7 +1286,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
 	ADDFUNC0(STRING,STRING,String,basename,varray());
 	ADDFUNC0(STRING,STRING,String,basename,varray());
 	ADDFUNC1(STRING,STRING,String,plus_file,STRING,"file",varray());
 	ADDFUNC1(STRING,STRING,String,plus_file,STRING,"file",varray());
 	ADDFUNC1(STRING,STRING,String,ord_at,INT,"at",varray());
 	ADDFUNC1(STRING,STRING,String,ord_at,INT,"at",varray());
-//	ADDFUNC2(STRING,String,erase,INT,INT,varray());
+	ADDFUNC2(STRING,NIL,String,erase,INT,"pos",INT,"chars", varray());
 	ADDFUNC0(STRING,INT,String,hash,varray());
 	ADDFUNC0(STRING,INT,String,hash,varray());
 	ADDFUNC0(STRING,STRING,String,md5_text,varray());
 	ADDFUNC0(STRING,STRING,String,md5_text,varray());
 	ADDFUNC0(STRING,RAW_ARRAY,String,md5_buffer,varray());
 	ADDFUNC0(STRING,RAW_ARRAY,String,md5_buffer,varray());
@@ -1335,6 +1337,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
 	ADDFUNC1(VECTOR2,VECTOR2,Vector2,slide,VECTOR2,"vec",varray());
 	ADDFUNC1(VECTOR2,VECTOR2,Vector2,slide,VECTOR2,"vec",varray());
 	ADDFUNC1(VECTOR2,VECTOR2,Vector2,reflect,VECTOR2,"vec",varray());
 	ADDFUNC1(VECTOR2,VECTOR2,Vector2,reflect,VECTOR2,"vec",varray());
 	//ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray());
 	//ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray());
+	ADDFUNC0(VECTOR2,VECTOR2,Vector2,abs,varray());
 
 
 	ADDFUNC0(RECT2,REAL,Rect2,get_area,varray());
 	ADDFUNC0(RECT2,REAL,Rect2,get_area,varray());
 	ADDFUNC1(RECT2,BOOL,Rect2,intersects,RECT2,"b",varray());
 	ADDFUNC1(RECT2,BOOL,Rect2,intersects,RECT2,"b",varray());
@@ -1434,6 +1437,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
 	ADDFUNC1(DICTIONARY,NIL,Dictionary,erase,NIL,"value",varray());
 	ADDFUNC1(DICTIONARY,NIL,Dictionary,erase,NIL,"value",varray());
 	ADDFUNC0(DICTIONARY,INT,Dictionary,hash,varray());
 	ADDFUNC0(DICTIONARY,INT,Dictionary,hash,varray());
 	ADDFUNC0(DICTIONARY,ARRAY,Dictionary,keys,varray());
 	ADDFUNC0(DICTIONARY,ARRAY,Dictionary,keys,varray());
+	ADDFUNC0(DICTIONARY,ARRAY,Dictionary,values,varray());
 
 
 	ADDFUNC1(DICTIONARY,INT,Dictionary,parse_json,STRING,"json",varray());
 	ADDFUNC1(DICTIONARY,INT,Dictionary,parse_json,STRING,"json",varray());
 	ADDFUNC0(DICTIONARY,STRING,Dictionary,to_json,varray());
 	ADDFUNC0(DICTIONARY,STRING,Dictionary,to_json,varray());

+ 63 - 56
doc/base/classes.xml

@@ -9015,7 +9015,7 @@
 			</argument>
 			</argument>
 			<description>
 			<description>
 			Change the anchor (ANCHOR_BEGIN, ANCHOR_END, ANCHOR_RATIO) type for a margin (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM). Changing the anchor mode converts the current margin offset from the previous anchor mode to the new one, so margin offsets ([method set_margin]) must be done after setting anchors, or at the same time ([method set_anchor_and_margin])
 			Change the anchor (ANCHOR_BEGIN, ANCHOR_END, ANCHOR_RATIO) type for a margin (MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM). Changing the anchor mode converts the current margin offset from the previous anchor mode to the new one, so margin offsets ([method set_margin]) must be done after setting anchors, or at the same time ([method set_anchor_and_margin])
-			
+
 			Additionally, [code]keep_margin[/code] controls whether margins should be left the same, or changed to keep the same position and size on-screen.
 			Additionally, [code]keep_margin[/code] controls whether margins should be left the same, or changed to keep the same position and size on-screen.
 			</description>
 			</description>
 		</method>
 		</method>
@@ -10312,7 +10312,7 @@ This approximation makes straight segments between each point, then subdivides t
 			<return type="Array">
 			<return type="Array">
 			</return>
 			</return>
 			<description>
 			<description>
-			Return the list of keys in the dictionary.
+			Return the list of keys in the [Dictionary].
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="parse_json">
 		<method name="parse_json">
@@ -10338,6 +10338,13 @@ This approximation makes straight segments between each point, then subdivides t
 			Return the dictionary as json text.
 			Return the dictionary as json text.
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="values">
+			<return type="Array">
+			</return>
+			<description>
+			Return the list of values in the [Dictionary].
+			</description>
+		</method>
 	</methods>
 	</methods>
 	<constants>
 	<constants>
 	</constants>
 	</constants>
@@ -10671,14 +10678,14 @@ This approximation makes straight segments between each point, then subdivides t
 			This function is called for each file exported and
 			This function is called for each file exported and
 			depending from the return value one of many things
 			depending from the return value one of many things
 			might happen.
 			might happen.
-			
+
 			1) If returned value is null, the file is exported
 			1) If returned value is null, the file is exported
 			as is.
 			as is.
-			
+
 			2) If the returned value is a RawAray (array of
 			2) If the returned value is a RawAray (array of
 			bytes), the content of that array becomes the new
 			bytes), the content of that array becomes the new
 			file being exported.
 			file being exported.
-			
+
 			3) If the file must also change it's name when
 			3) If the file must also change it's name when
 			exported, then a [Dictionary] must be returned with
 			exported, then a [Dictionary] must be returned with
 			two fields: 'name' with the new filename and 'data'
 			two fields: 'name' with the new filename and 'data'
@@ -10848,8 +10855,8 @@ This approximation makes straight segments between each point, then subdivides t
 	</brief_description>
 	</brief_description>
 	<description>
 	<description>
 	Import plugins make it easy to handle importing of external assets
 	Import plugins make it easy to handle importing of external assets
-	into a project. 
-	
+	into a project.
+
 	They way they work is not that obvious though, so please make sure
 	They way they work is not that obvious though, so please make sure
 	to read the documentation, tutorials and examples.
 	to read the documentation, tutorials and examples.
 	</description>
 	</description>
@@ -10872,7 +10879,7 @@ This approximation makes straight segments between each point, then subdivides t
 			when exported. The only exception is in some cases
 			when exported. The only exception is in some cases
 			when the file must be re-imported for different
 			when the file must be re-imported for different
 			platforms (ie. texture compression).
 			platforms (ie. texture compression).
-			
+
 			If you want to customize the export process, it's
 			If you want to customize the export process, it's
 			recommended to use [EditorExportPlugin.custom_export]
 			recommended to use [EditorExportPlugin.custom_export]
 			instead.
 			instead.
@@ -10884,7 +10891,7 @@ This approximation makes straight segments between each point, then subdivides t
 			<description>
 			<description>
 			Get the name of the import plugin, which will be
 			Get the name of the import plugin, which will be
 			used to identify content imported by this plugin.
 			used to identify content imported by this plugin.
-			
+
 			Try to use lowecase and underscores if possible.
 			Try to use lowecase and underscores if possible.
 			</description>
 			</description>
 		</method>
 		</method>
@@ -10909,23 +10916,23 @@ This approximation makes straight segments between each point, then subdivides t
 			(from the dialog) or re-import
 			(from the dialog) or re-import
 			(manual or automatic when external source files
 			(manual or automatic when external source files
 			changed).
 			changed).
-			
+
 			An import process generally works like this:
 			An import process generally works like this:
-			
+
 			1) Check the metadata for source files and options.
 			1) Check the metadata for source files and options.
 			Metadata is either generated in the import dialog or
 			Metadata is either generated in the import dialog or
 			taken from an existing resource upon reimport.
 			taken from an existing resource upon reimport.
-			
+
 			2) Perform the import process into a new resource.
 			2) Perform the import process into a new resource.
 			Some times the resource being re-imported may be already loaded
 			Some times the resource being re-imported may be already loaded
 			and in use, so checking for this by using
 			and in use, so checking for this by using
 			[ResourceLoader.has] is recommended. Otherwise
 			[ResourceLoader.has] is recommended. Otherwise
 			create a new resource.
 			create a new resource.
-			
+
 			3) Set the metadata from the argument into the existing or new
 			3) Set the metadata from the argument into the existing or new
 			resource being created using
 			resource being created using
 			[Resource.set_import_metadata].
 			[Resource.set_import_metadata].
-			
+
 			4) Save the resource into 'path' (function argument)
 			4) Save the resource into 'path' (function argument)
 			</description>
 			</description>
 		</method>
 		</method>
@@ -10938,12 +10945,12 @@ This approximation makes straight segments between each point, then subdivides t
 			when the user chooses to re-import the resource
 			when the user chooses to re-import the resource
 			(from filesystem). In the later case, the path for
 			(from filesystem). In the later case, the path for
 			the existing file is supplied in the argument.
 			the existing file is supplied in the argument.
-			
+
 			If the path is supplied, it is recommended to read
 			If the path is supplied, it is recommended to read
 			the import metadata with
 			the import metadata with
 			[ResourceLoader.load_import_metadata] and fill in
 			[ResourceLoader.load_import_metadata] and fill in
 			the fields with the values contained there.
 			the fields with the values contained there.
-			
+
 			The dialog can be shown in any way (just use a
 			The dialog can be shown in any way (just use a
 			ConfirmationDialog and pop it up). Upon
 			ConfirmationDialog and pop it up). Upon
 			confirmation, fill up a ResourceImportMetadata and
 			confirmation, fill up a ResourceImportMetadata and
@@ -11000,8 +11007,8 @@ This approximation makes straight segments between each point, then subdivides t
 			This method is called when the editor is about to
 			This method is called when the editor is about to
 			save the project, switch to another tab, etc. It
 			save the project, switch to another tab, etc. It
 			asks the plugin to apply any pending state changes
 			asks the plugin to apply any pending state changes
-			to ensure consistency. 
-			
+			to ensure consistency.
+
 			This is used, for example, in shader editors to let
 			This is used, for example, in shader editors to let
 			the plugin know that it must apply the shader code
 			the plugin know that it must apply the shader code
 			being written by the user to the object.
 			being written by the user to the object.
@@ -11045,7 +11052,7 @@ This approximation makes straight segments between each point, then subdivides t
 			object type derived from CanvasItem to capture the input in the 2D editor
 			object type derived from CanvasItem to capture the input in the 2D editor
 			viewport. The function is only being called if your
 			viewport. The function is only being called if your
 			object is being edited.
 			object is being edited.
-			
+
 			Return true if you want to capture the input,
 			Return true if you want to capture the input,
 			otherwise false.
 			otherwise false.
 			</description>
 			</description>
@@ -11062,11 +11069,11 @@ This approximation makes straight segments between each point, then subdivides t
 			given objet type derived from Spatial to capture the
 			given objet type derived from Spatial to capture the
 			input of the viewport. The function is only being
 			input of the viewport. The function is only being
 			called if your object is being edited.
 			called if your object is being edited.
-			
+
 			By using the [InputEvent] and the [Camera] arguments
 			By using the [InputEvent] and the [Camera] arguments
 			it's pretty easy to do raycasts into space using
 			it's pretty easy to do raycasts into space using
 			Camera functions.
 			Camera functions.
-			
+
 			Return true if you want to capture the input,
 			Return true if you want to capture the input,
 			otherwise false.
 			otherwise false.
 			</description>
 			</description>
@@ -11128,7 +11135,7 @@ This approximation makes straight segments between each point, then subdivides t
 			This function will be called when the editor is
 			This function will be called when the editor is
 			requested to become visible. It is used for plugins
 			requested to become visible. It is used for plugins
 			that edit a specific object type.
 			that edit a specific object type.
-			
+
 			Remember that you have to manage the visibility of
 			Remember that you have to manage the visibility of
 			all your editor controls manually.
 			all your editor controls manually.
 			</description>
 			</description>
@@ -11149,11 +11156,11 @@ This approximation makes straight segments between each point, then subdivides t
 			Add a custom control to a container (see
 			Add a custom control to a container (see
 			CONTAINER_* enum). There are many locations where
 			CONTAINER_* enum). There are many locations where
 			custom controls can be added in the editor UI.
 			custom controls can be added in the editor UI.
-			
+
 			Please remember that you have to manage the
 			Please remember that you have to manage the
 			visibility of your custom controls yourself (and likely
 			visibility of your custom controls yourself (and likely
 			hide it after adding it).
 			hide it after adding it).
-			
+
 			If your plugin is being removed, also make sure to
 			If your plugin is being removed, also make sure to
 			remove your custom controls too.
 			remove your custom controls too.
 			</description>
 			</description>
@@ -11166,7 +11173,7 @@ This approximation makes straight segments between each point, then subdivides t
 			<description>
 			<description>
 			Add a control to the bottom panel (together with
 			Add a control to the bottom panel (together with
 			Output, Debug, Animation, etc).
 			Output, Debug, Animation, etc).
-			
+
 			If your plugin is being removed, also make sure to
 			If your plugin is being removed, also make sure to
 			remove your control by calling [method
 			remove your control by calling [method
 			remove_control_from_bottom_panel].
 			remove_control_from_bottom_panel].
@@ -11179,12 +11186,12 @@ This approximation makes straight segments between each point, then subdivides t
 			</argument>
 			</argument>
 			<description>
 			<description>
 			Add the control to a specific dock slot (see DOCK_*
 			Add the control to a specific dock slot (see DOCK_*
-			enum for options). 
-			
+			enum for options).
+
 			If the dock is repositioned and as long as the
 			If the dock is repositioned and as long as the
 			plugin is active, the editor will save the dock
 			plugin is active, the editor will save the dock
 			position on further sessions.
 			position on further sessions.
-			
+
 			If your plugin is being removed, also make sure to
 			If your plugin is being removed, also make sure to
 			remove your control by calling [method
 			remove your control by calling [method
 			remove_control_from_docks].
 			remove_control_from_docks].
@@ -11221,16 +11228,16 @@ This approximation makes straight segments between each point, then subdivides t
 			Add a custom type, which will appear in the list of
 			Add a custom type, which will appear in the list of
 			nodes or resources. An icon can be optionally
 			nodes or resources. An icon can be optionally
 			passed.
 			passed.
-			
+
 			When given node or resource is selected, the base
 			When given node or resource is selected, the base
 			type will be instanced (ie, "Spatial", "Control",
 			type will be instanced (ie, "Spatial", "Control",
 			"Resource"), then the script will be loaded and set
 			"Resource"), then the script will be loaded and set
 			to this object.
 			to this object.
-			
+
 			You can use the [EditorPlugin.handles] to check if
 			You can use the [EditorPlugin.handles] to check if
 			your custom object is being edited by checking the
 			your custom object is being edited by checking the
-			script or using 'extends' keyword.			
-			
+			script or using 'extends' keyword.
+
 			During run-time, this will be a simple object with a
 			During run-time, this will be a simple object with a
 			script so this function does not need to be called
 			script so this function does not need to be called
 			then.
 			then.
@@ -11251,7 +11258,7 @@ This approximation makes straight segments between each point, then subdivides t
 			Add an import plugin. These plugins manage importing
 			Add an import plugin. These plugins manage importing
 			external content (from outside the project) into
 			external content (from outside the project) into
 			formats the engine can understand.
 			formats the engine can understand.
-			
+
 			On exit, don't forget to remove the plugin by
 			On exit, don't forget to remove the plugin by
 			calling [method remove_import_plugin]
 			calling [method remove_import_plugin]
 			</description>
 			</description>
@@ -11367,7 +11374,7 @@ This approximation makes straight segments between each point, then subdivides t
 			<description>
 			<description>
 			This function is called upon import with the
 			This function is called upon import with the
 			imported scene.
 			imported scene.
-			
+
 			Just do any changes desired to the scene and return
 			Just do any changes desired to the scene and return
 			it. If null is returned, import will fail and throw
 			it. If null is returned, import will fail and throw
 			an error to the user.
 			an error to the user.
@@ -11457,14 +11464,14 @@ This approximation makes straight segments between each point, then subdivides t
 	<description>
 	<description>
 	Object that holds the project-independent editor settings. These
 	Object that holds the project-independent editor settings. These
 	settings are generally visible in the Editor Settings menu.
 	settings are generally visible in the Editor Settings menu.
-	
+
 	Accessing the settings is done by using the regular [Object] API,
 	Accessing the settings is done by using the regular [Object] API,
 	such as.
 	such as.
-	
+
 	settings.set(prop,value)
 	settings.set(prop,value)
-	
+
 	settings.get(prop)
 	settings.get(prop)
-	
+
 	list_of_settings = settings.get_property_list()
 	list_of_settings = settings.get_property_list()
 	</description>
 	</description>
 	<methods>
 	<methods>
@@ -11481,9 +11488,9 @@ This approximation makes straight segments between each point, then subdivides t
 			<description>
 			<description>
 			Get the global settings path for the engine. Inside
 			Get the global settings path for the engine. Inside
 			this path you can find some standard paths such as:
 			this path you can find some standard paths such as:
-			
+
 			settings/tmp - used for temporary storage of files
 			settings/tmp - used for temporary storage of files
-			
+
 			settings/templates - where export templates are
 			settings/templates - where export templates are
 			located
 			located
 			</description>
 			</description>
@@ -11559,7 +11566,7 @@ This approximation makes straight segments between each point, then subdivides t
 			<description>
 			<description>
 			Commit a handle being edited (handles must have been
 			Commit a handle being edited (handles must have been
 			prevously added by [method add_handles]).
 			prevously added by [method add_handles]).
-			
+
 			If the cancel parameter is true, an option to
 			If the cancel parameter is true, an option to
 			restore the edited value to the original is
 			restore the edited value to the original is
 			provided.
 			provided.
@@ -11573,7 +11580,7 @@ This approximation makes straight segments between each point, then subdivides t
 			<description>
 			<description>
 			Get the name of an edited handle (handles must have
 			Get the name of an edited handle (handles must have
 			been previously added by [method add_handles]).
 			been previously added by [method add_handles]).
-			
+
 			Handles can be named for reference to the user when editing.
 			Handles can be named for reference to the user when editing.
 			</description>
 			</description>
 		</method>
 		</method>
@@ -11605,8 +11612,8 @@ This approximation makes straight segments between each point, then subdivides t
 			<description>
 			<description>
 			This function is used when the user drags a gizmo
 			This function is used when the user drags a gizmo
 			handle (previously added with [method add_handles])
 			handle (previously added with [method add_handles])
-			in screen coordinates. 
-			
+			in screen coordinates.
+
 			The [Camera] is also provided
 			The [Camera] is also provided
 			so screen coordinates can be converted to raycasts.
 			so screen coordinates can be converted to raycasts.
 			</description>
 			</description>
@@ -11622,7 +11629,7 @@ This approximation makes straight segments between each point, then subdivides t
 			Add lines to the gizmo (as sets of 2 points), with a
 			Add lines to the gizmo (as sets of 2 points), with a
 			given material. The lines are used for visualizing
 			given material. The lines are used for visualizing
 			the gizmo.
 			the gizmo.
-			
+
 			Call this function during [method redraw].
 			Call this function during [method redraw].
 			</description>
 			</description>
 		</method>
 		</method>
@@ -11636,7 +11643,7 @@ This approximation makes straight segments between each point, then subdivides t
 			<description>
 			<description>
 			Add a mesh to the gizmo, this is used for
 			Add a mesh to the gizmo, this is used for
 			visualization.
 			visualization.
-			
+
 			Call this function during [method redraw].
 			Call this function during [method redraw].
 			</description>
 			</description>
 		</method>
 		</method>
@@ -11653,7 +11660,7 @@ This approximation makes straight segments between each point, then subdivides t
 			Add collision triangles to the gizmo for picking. A
 			Add collision triangles to the gizmo for picking. A
 			[TriangleMesh] can be generated from a regular
 			[TriangleMesh] can be generated from a regular
 			[Mesh] too.
 			[Mesh] too.
-			
+
 			Call this function during [method redraw].
 			Call this function during [method redraw].
 			</description>
 			</description>
 		</method>
 		</method>
@@ -11664,7 +11671,7 @@ This approximation makes straight segments between each point, then subdivides t
 			</argument>
 			</argument>
 			<description>
 			<description>
 			Add an unscaled billboard for visualization.
 			Add an unscaled billboard for visualization.
-			
+
 			Call this function during [method redraw].
 			Call this function during [method redraw].
 			</description>
 			</description>
 		</method>
 		</method>
@@ -11678,10 +11685,10 @@ This approximation makes straight segments between each point, then subdivides t
 			<description>
 			<description>
 			Add a list of handles (points) which can be used to
 			Add a list of handles (points) which can be used to
 			deform the object being edited.
 			deform the object being edited.
-			
+
 			There are virtual functions which will be called
 			There are virtual functions which will be called
 			upon editing of these handles.
 			upon editing of these handles.
-			
+
 			Call this function during [method redraw].
 			Call this function during [method redraw].
 			</description>
 			</description>
 		</method>
 		</method>
@@ -11691,7 +11698,7 @@ This approximation makes straight segments between each point, then subdivides t
 			<description>
 			<description>
 			Call this function once and upon creation of the
 			Call this function once and upon creation of the
 			gizmo, otherwise no other function will work.
 			gizmo, otherwise no other function will work.
-			
+
 			The argument is the node being edited by the gizmo.
 			The argument is the node being edited by the gizmo.
 			</description>
 			</description>
 		</method>
 		</method>
@@ -14449,7 +14456,7 @@ This approximation makes straight segments between each point, then subdivides t
 	Hyper-text transfer protocol client.
 	Hyper-text transfer protocol client.
 	</brief_description>
 	</brief_description>
 	<description>
 	<description>
-	Hyper-text transfer protocol client. Supports SSL and SSL server certificate verification. 
+	Hyper-text transfer protocol client. Supports SSL and SSL server certificate verification.
 	Can be reused to connect to different hosts and make many requests.
 	Can be reused to connect to different hosts and make many requests.
 	</description>
 	</description>
 	<methods>
 	<methods>
@@ -14792,7 +14799,7 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
 	A Node with the ability to send HTTP requests.
 	A Node with the ability to send HTTP requests.
 	</brief_description>
 	</brief_description>
 	<description>
 	<description>
-	A Node with the ability to send HTTP requests. Uses a [HTTPClient] internally, supports HTTPS. 
+	A Node with the ability to send HTTP requests. Uses a [HTTPClient] internally, supports HTTPS.
 	Can be used to make HTTP requests or download files via HTTP.
 	Can be used to make HTTP requests or download files via HTTP.
 	</description>
 	</description>
 	<methods>
 	<methods>
@@ -41413,7 +41420,7 @@ This method controls whether the position between two cached points is interpola
 	<description>
 	<description>
 	Helper to maange UndoRedo in the editor or custom tools. It works by
 	Helper to maange UndoRedo in the editor or custom tools. It works by
 	storing calls to functions in both 'do' an 'undo' lists.
 	storing calls to functions in both 'do' an 'undo' lists.
-	
+
 	Common behavior is to create an action, then add do/undo calls to
 	Common behavior is to create an action, then add do/undo calls to
 	functions or property changes, then commiting the action.
 	functions or property changes, then commiting the action.
 	</description>
 	</description>
@@ -41537,8 +41544,8 @@ This method controls whether the position between two cached points is interpola
 			<description>
 			<description>
 			Get the version, each time a new action is commited,
 			Get the version, each time a new action is commited,
 			the version number of the UndoRedo is increased
 			the version number of the UndoRedo is increased
-			automatically. 
-			
+			automatically.
+
 			This is useful mostly to check if something changed
 			This is useful mostly to check if something changed
 			from a saved version.
 			from a saved version.
 			</description>
 			</description>

+ 25 - 20
drivers/gles2/rasterizer_gles2.cpp

@@ -6497,7 +6497,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
 			if (!*e->additive_ptr) {
 			if (!*e->additive_ptr) {
 
 
 				additive=false;
 				additive=false;
-				*e->additive_ptr=true;				
+				*e->additive_ptr=true;
 			} else {
 			} else {
 				additive=true;
 				additive=true;
 			}
 			}
@@ -6684,7 +6684,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
 			}
 			}
 			rebind=true;
 			rebind=true;
 		}
 		}
-		
+
 		if  (use_hw_skeleton_xform && (skeleton!=prev_skeleton||morph_values!=prev_morph_values)) {
 		if  (use_hw_skeleton_xform && (skeleton!=prev_skeleton||morph_values!=prev_morph_values)) {
 			if (!prev_skeleton || !skeleton)
 			if (!prev_skeleton || !skeleton)
 				rebind=true; //went from skeleton <-> no skeleton, needs rebind
 				rebind=true; //went from skeleton <-> no skeleton, needs rebind
@@ -6718,7 +6718,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
 			DEBUG_TEST_ERROR("Setup geometry");
 			DEBUG_TEST_ERROR("Setup geometry");
 		};
 		};
 
 
-		if (i==0 || light!=prev_light || rebind) {			
+		if (i==0 || light!=prev_light || rebind) {
 			if (e->light!=0xFFFF) {
 			if (e->light!=0xFFFF) {
 				_setup_light(e->light);
 				_setup_light(e->light);
 
 
@@ -6958,7 +6958,7 @@ void RasterizerGLES2::_process_glow_bloom() {
 	_copy_screen_quad();
 	_copy_screen_quad();
 
 
 	copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_COPY,false);
 	copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_COPY,false);
-	copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false);	
+	copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false);
 	int passes = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES];
 	int passes = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES];
 	Vector2 psize(1.0/framebuffer.blur_size,1.0/framebuffer.blur_size);
 	Vector2 psize(1.0/framebuffer.blur_size,1.0/framebuffer.blur_size);
 	float pscale = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_SCALE];
 	float pscale = current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_SCALE];
@@ -7427,7 +7427,7 @@ void RasterizerGLES2::end_scene() {
 			_process_hdr();
 			_process_hdr();
 		}
 		}
 		if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) {
 		if (current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]) {
-			_process_glow_bloom();			
+			_process_glow_bloom();
 			int glow_transfer_mode=current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE];
 			int glow_transfer_mode=current_env->fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE];
 			if (glow_transfer_mode==1)
 			if (glow_transfer_mode==1)
 				copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,true);
 				copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,true);
@@ -8438,7 +8438,7 @@ void RasterizerGLES2::canvas_draw_rect(const Rect2& p_rect, int p_flags, const R
 
 
 }
 }
 
 
-void RasterizerGLES2::canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) {
+void RasterizerGLES2::canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) {
 
 
 	Color m = p_modulate;
 	Color m = p_modulate;
 	m.a*=canvas_opacity;
 	m.a*=canvas_opacity;
@@ -8446,52 +8446,57 @@ void RasterizerGLES2::canvas_draw_style_box(const Rect2& p_rect, RID p_texture,c
 
 
 	Texture* texture=_bind_canvas_texture(p_texture);
 	Texture* texture=_bind_canvas_texture(p_texture);
 	ERR_FAIL_COND(!texture);
 	ERR_FAIL_COND(!texture);
-	/* CORNERS */
 
 
+	Rect2 region = p_src_region;
+	if (region.size.width <= 0 )
+	    region.size.width = texture->width;
+	if (region.size.height <= 0)
+	    region.size.height = texture->height;
+	/* CORNERS */
 	_draw_textured_quad( // top left
 	_draw_textured_quad( // top left
 		Rect2( p_rect.pos, Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])),
 		Rect2( p_rect.pos, Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])),
-		Rect2( Point2(), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])),
+		Rect2( region.pos, Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	_draw_textured_quad( // top right
 	_draw_textured_quad( // top right
 		Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])),
 		Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])),
-		Rect2( Point2(texture->width-p_margin[MARGIN_RIGHT],0), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])),
+		Rect2( Point2(region.pos.x+region.size.width-p_margin[MARGIN_RIGHT], region.pos.y), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 
 
 	_draw_textured_quad( // bottom left
 	_draw_textured_quad( // bottom left
 		Rect2( Point2(p_rect.pos.x,p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])),
 		Rect2( Point2(p_rect.pos.x,p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])),
-		Rect2( Point2(0,texture->height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])),
+		Rect2( Point2(region.pos.x, region.pos.y+region.size.height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	_draw_textured_quad( // bottom right
 	_draw_textured_quad( // bottom right
 		Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])),
 		Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])),
-		Rect2( Point2(texture->width-p_margin[MARGIN_RIGHT],texture->height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])),
+		Rect2( Point2(region.pos.x+region.size.width-p_margin[MARGIN_RIGHT], region.pos.y+region.size.height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	Rect2 rect_center( p_rect.pos+Point2( p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP]), Size2( p_rect.size.width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], p_rect.size.height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] ));
 	Rect2 rect_center( p_rect.pos+Point2( p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP]), Size2( p_rect.size.width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], p_rect.size.height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] ));
 
 
-	Rect2 src_center( Point2( p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP]), Size2( texture->width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], texture->height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] ));
+	Rect2 src_center( Point2(region.pos.x+p_margin[MARGIN_LEFT], region.pos.y+p_margin[MARGIN_TOP]), Size2(region.size.width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], region.size.height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] ));
 
 
 
 
 	_draw_textured_quad( // top
 	_draw_textured_quad( // top
 		Rect2( Point2(rect_center.pos.x,p_rect.pos.y),Size2(rect_center.size.width,p_margin[MARGIN_TOP])),
 		Rect2( Point2(rect_center.pos.x,p_rect.pos.y),Size2(rect_center.size.width,p_margin[MARGIN_TOP])),
-		Rect2( Point2(p_margin[MARGIN_LEFT],0), Size2(src_center.size.width,p_margin[MARGIN_TOP])),
+		Rect2( Point2(src_center.pos.x,region.pos.y), Size2(src_center.size.width,p_margin[MARGIN_TOP])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	_draw_textured_quad( // bottom
 	_draw_textured_quad( // bottom
 		Rect2( Point2(rect_center.pos.x,rect_center.pos.y+rect_center.size.height),Size2(rect_center.size.width,p_margin[MARGIN_BOTTOM])),
 		Rect2( Point2(rect_center.pos.x,rect_center.pos.y+rect_center.size.height),Size2(rect_center.size.width,p_margin[MARGIN_BOTTOM])),
-		Rect2( Point2(p_margin[MARGIN_LEFT],src_center.pos.y+src_center.size.height), Size2(src_center.size.width,p_margin[MARGIN_BOTTOM])),
+		Rect2( Point2(src_center.pos.x,src_center.pos.y+src_center.size.height), Size2(src_center.size.width,p_margin[MARGIN_BOTTOM])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	_draw_textured_quad( // left
 	_draw_textured_quad( // left
 		Rect2( Point2(p_rect.pos.x,rect_center.pos.y),Size2(p_margin[MARGIN_LEFT],rect_center.size.height)),
 		Rect2( Point2(p_rect.pos.x,rect_center.pos.y),Size2(p_margin[MARGIN_LEFT],rect_center.size.height)),
-		Rect2( Point2(0,p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_LEFT],src_center.size.height)),
+		Rect2( Point2(region.pos.x,region.pos.y+p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_LEFT],src_center.size.height)),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	_draw_textured_quad( // right
 	_draw_textured_quad( // right
 		Rect2( Point2(rect_center.pos.x+rect_center.size.width,rect_center.pos.y),Size2(p_margin[MARGIN_RIGHT],rect_center.size.height)),
 		Rect2( Point2(rect_center.pos.x+rect_center.size.width,rect_center.pos.y),Size2(p_margin[MARGIN_RIGHT],rect_center.size.height)),
-		Rect2( Point2(src_center.pos.x+src_center.size.width,p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_RIGHT],src_center.size.height)),
+		Rect2( Point2(src_center.pos.x+src_center.size.width,region.pos.y+p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_RIGHT],src_center.size.height)),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	if (p_draw_center) {
 	if (p_draw_center) {
@@ -8569,7 +8574,7 @@ void RasterizerGLES2::canvas_draw_polygon(int p_vertex_count, const int* p_indic
 
 
 
 
 #else //WebGL specific impl.
 #else //WebGL specific impl.
-	glBindBuffer(GL_ARRAY_BUFFER, gui_quad_buffer);    
+	glBindBuffer(GL_ARRAY_BUFFER, gui_quad_buffer);
     float *b = GlobalVertexBuffer;
     float *b = GlobalVertexBuffer;
     int ofs = 0;
     int ofs = 0;
     if(p_vertex_count > MAX_POLYGON_VERTICES){
     if(p_vertex_count > MAX_POLYGON_VERTICES){
@@ -9184,7 +9189,7 @@ void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item,CanvasItem
 				CanvasItem::CommandStyle* style = static_cast<CanvasItem::CommandStyle*>(c);
 				CanvasItem::CommandStyle* style = static_cast<CanvasItem::CommandStyle*>(c);
 				if (use_normalmap)
 				if (use_normalmap)
 					_canvas_normal_set_flip(Vector2(1,1));
 					_canvas_normal_set_flip(Vector2(1,1));
-				canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color);
+				canvas_draw_style_box(style->rect,style->source,style->texture,style->margin,style->draw_center,style->color);
 
 
 			} break;
 			} break;
 			case CanvasItem::Command::TYPE_PRIMITIVE: {
 			case CanvasItem::Command::TYPE_PRIMITIVE: {
@@ -9430,7 +9435,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
 				draw_viewport_func(ci->vp_render->owner,ci->vp_render->udata,ci->vp_render->rect);
 				draw_viewport_func(ci->vp_render->owner,ci->vp_render->udata,ci->vp_render->rect);
 			}
 			}
 			memdelete(ci->vp_render);
 			memdelete(ci->vp_render);
-			ci->vp_render=NULL;			
+			ci->vp_render=NULL;
 			canvas_last_material=NULL;
 			canvas_last_material=NULL;
 			canvas_use_modulate=p_modulate!=Color(1,1,1,1);
 			canvas_use_modulate=p_modulate!=Color(1,1,1,1);
 			canvas_modulate=p_modulate;
 			canvas_modulate=p_modulate;
@@ -11424,7 +11429,7 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo
 void RasterizerGLES2::restore_framebuffer() {
 void RasterizerGLES2::restore_framebuffer() {
 
 
 	glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer);
 	glBindFramebuffer(GL_FRAMEBUFFER, base_framebuffer);
-	
+
 }
 }
 
 
 RasterizerGLES2::~RasterizerGLES2() {
 RasterizerGLES2::~RasterizerGLES2() {

+ 1 - 1
drivers/gles2/rasterizer_gles2.h

@@ -1635,7 +1635,7 @@ public:
 	virtual void canvas_end_rect();
 	virtual void canvas_end_rect();
 	virtual void canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width);
 	virtual void canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width);
 	virtual void canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate);
 	virtual void canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate);
-	virtual void canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margins, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1));
+	virtual void canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margins, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1));
 	virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width);
 	virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width);
 	virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor);
 	virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor);
 	virtual void canvas_set_transform(const Matrix32& p_transform);
 	virtual void canvas_set_transform(const Matrix32& p_transform);

+ 6 - 0
modules/gdscript/gd_compiler.cpp

@@ -1588,6 +1588,12 @@ Error GDCompiler::_parse_class(GDScript *p_script, GDScript *p_owner, const GDPa
 		}
 		}
 
 
 
 
+	} else {
+		// without extends, implicitly extend Reference
+		int native_idx = GDScriptLanguage::get_singleton()->get_global_map()["Reference"];
+		native = GDScriptLanguage::get_singleton()->get_global_array()[native_idx];
+		ERR_FAIL_COND_V(native.is_null(), ERR_BUG);
+		p_script->native=native;
 	}
 	}
 
 
 
 

+ 2 - 5
modules/gdscript/gd_script.cpp

@@ -145,11 +145,8 @@ Variant GDScript::_new(const Variant** p_args,int p_argcount,Variant::CallError&
 		_baseptr=_baseptr->_base;
 		_baseptr=_baseptr->_base;
 	}
 	}
 
 
-	if (_baseptr->native.ptr()) {
-		owner=_baseptr->native->instance();
-	} else {
-		owner=memnew( Reference ); //by default, no base means use reference
-	}
+	ERR_FAIL_COND_V(_baseptr->native.is_null(), Variant());
+	owner=_baseptr->native->instance();
 
 
 	Reference *r=owner->cast_to<Reference>();
 	Reference *r=owner->cast_to<Reference>();
 	if (r) {
 	if (r) {

+ 15 - 11
platform/iphone/rasterizer_iphone.cpp

@@ -2446,7 +2446,7 @@ void RasterizerIPhone::canvas_draw_rect(const Rect2& p_rect, bool p_region, cons
 
 
 
 
 }
 }
-void RasterizerIPhone::canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margin, bool p_draw_center) {
+void RasterizerIPhone::canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margin, bool p_draw_center) {
 
 
 	glColor4f(1, 1, 1, 1);
 	glColor4f(1, 1, 1, 1);
 
 
@@ -2458,52 +2458,56 @@ void RasterizerIPhone::canvas_draw_style_box(const Rect2& p_rect, RID p_texture,
 	glBindTexture( GL_TEXTURE_2D,texture->tex_id );
 	glBindTexture( GL_TEXTURE_2D,texture->tex_id );
 
 
 
 
+	Rect2 region = p_src_region;
+	if (region.size.width <= 0 )
+	    region.size.width = texture->width;
+	if (region.size.height <= 0)
+	    region.size.height = texture->height;
 	/* CORNERS */
 	/* CORNERS */
-
 	_draw_textured_quad( // top left
 	_draw_textured_quad( // top left
 		Rect2( p_rect.pos, Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])),
 		Rect2( p_rect.pos, Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])),
-		Rect2( Point2(), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])),
+		Rect2( region.pos, Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_TOP])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	_draw_textured_quad( // top right
 	_draw_textured_quad( // top right
 		Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])),
 		Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])),
-		Rect2( Point2(texture->width-p_margin[MARGIN_RIGHT],0), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])),
+		Rect2( Point2(region.pos.x+region.size.width-p_margin[MARGIN_RIGHT], region.pos.y), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_TOP])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 
 
 	_draw_textured_quad( // bottom left
 	_draw_textured_quad( // bottom left
 		Rect2( Point2(p_rect.pos.x,p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])),
 		Rect2( Point2(p_rect.pos.x,p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])),
-		Rect2( Point2(0,texture->height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])),
+		Rect2( Point2(region.pos.x, region.pos.y+region.size.height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_LEFT],p_margin[MARGIN_BOTTOM])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	_draw_textured_quad( // bottom right
 	_draw_textured_quad( // bottom right
 		Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])),
 		Rect2( Point2( p_rect.pos.x + p_rect.size.width - p_margin[MARGIN_RIGHT], p_rect.pos.y + p_rect.size.height - p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])),
-		Rect2( Point2(texture->width-p_margin[MARGIN_RIGHT],texture->height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])),
+		Rect2( Point2(region.pos.x+region.size.width-p_margin[MARGIN_RIGHT], region.pos.y+region.size.height-p_margin[MARGIN_BOTTOM]), Size2(p_margin[MARGIN_RIGHT],p_margin[MARGIN_BOTTOM])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	Rect2 rect_center( p_rect.pos+Point2( p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP]), Size2( p_rect.size.width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], p_rect.size.height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] ));
 	Rect2 rect_center( p_rect.pos+Point2( p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP]), Size2( p_rect.size.width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], p_rect.size.height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] ));
 
 
-	Rect2 src_center( Point2( p_margin[MARGIN_LEFT], p_margin[MARGIN_TOP]), Size2( texture->width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], texture->height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] ));
+	Rect2 src_center( Point2(region.pos.x+p_margin[MARGIN_LEFT], region.pos.y+p_margin[MARGIN_TOP]), Size2(region.size.width - p_margin[MARGIN_LEFT] - p_margin[MARGIN_RIGHT], region.size.height - p_margin[MARGIN_TOP] - p_margin[MARGIN_BOTTOM] ));
 
 
 
 
 	_draw_textured_quad( // top
 	_draw_textured_quad( // top
 		Rect2( Point2(rect_center.pos.x,p_rect.pos.y),Size2(rect_center.size.width,p_margin[MARGIN_TOP])),
 		Rect2( Point2(rect_center.pos.x,p_rect.pos.y),Size2(rect_center.size.width,p_margin[MARGIN_TOP])),
-		Rect2( Point2(p_margin[MARGIN_LEFT],0), Size2(src_center.size.width,p_margin[MARGIN_TOP])),
+		Rect2( Point2(src_center.pos.x,region.pos.y), Size2(src_center.size.width,p_margin[MARGIN_TOP])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	_draw_textured_quad( // bottom
 	_draw_textured_quad( // bottom
 		Rect2( Point2(rect_center.pos.x,rect_center.pos.y+rect_center.size.height),Size2(rect_center.size.width,p_margin[MARGIN_BOTTOM])),
 		Rect2( Point2(rect_center.pos.x,rect_center.pos.y+rect_center.size.height),Size2(rect_center.size.width,p_margin[MARGIN_BOTTOM])),
-		Rect2( Point2(p_margin[MARGIN_LEFT],src_center.pos.y+src_center.size.height), Size2(src_center.size.width,p_margin[MARGIN_BOTTOM])),
+		Rect2( Point2(src_center.pos.x,src_center.pos.y+src_center.size.height), Size2(src_center.size.width,p_margin[MARGIN_BOTTOM])),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	_draw_textured_quad( // left
 	_draw_textured_quad( // left
 		Rect2( Point2(p_rect.pos.x,rect_center.pos.y),Size2(p_margin[MARGIN_LEFT],rect_center.size.height)),
 		Rect2( Point2(p_rect.pos.x,rect_center.pos.y),Size2(p_margin[MARGIN_LEFT],rect_center.size.height)),
-		Rect2( Point2(0,p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_LEFT],src_center.size.height)),
+		Rect2( Point2(region.pos.x,region.pos.y+p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_LEFT],src_center.size.height)),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	_draw_textured_quad( // right
 	_draw_textured_quad( // right
 		Rect2( Point2(rect_center.pos.x+rect_center.size.width,rect_center.pos.y),Size2(p_margin[MARGIN_RIGHT],rect_center.size.height)),
 		Rect2( Point2(rect_center.pos.x+rect_center.size.width,rect_center.pos.y),Size2(p_margin[MARGIN_RIGHT],rect_center.size.height)),
-		Rect2( Point2(src_center.pos.x+src_center.size.width,p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_RIGHT],src_center.size.height)),
+		Rect2( Point2(src_center.pos.x+src_center.size.width,region.pos.y+p_margin[MARGIN_TOP]), Size2(p_margin[MARGIN_RIGHT],src_center.size.height)),
 		Size2( texture->width, texture->height ) );
 		Size2( texture->width, texture->height ) );
 
 
 	if (p_draw_center) {
 	if (p_draw_center) {

+ 87 - 29
scene/gui/control.cpp

@@ -770,7 +770,7 @@ Size2 Control::get_minimum_size() const {
 
 
 Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type) const {
 Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type) const {
 
 
-	if (p_type==StringName()) {
+	if (p_type==StringName() || p_type=="") {
 
 
 		const Ref<Texture>* tex = data.icon_override.getptr(p_name);
 		const Ref<Texture>* tex = data.icon_override.getptr(p_name);
 		if (tex)
 		if (tex)
@@ -800,7 +800,7 @@ Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type
 }
 }
 
 
 Ref<Shader> Control::get_shader(const StringName& p_name,const StringName& p_type) const {
 Ref<Shader> Control::get_shader(const StringName& p_name,const StringName& p_type) const {
-	if (p_type==StringName()) {
+	if (p_type==StringName() || p_type=="") {
 
 
 		const Ref<Shader>* sdr = data.shader_override.getptr(p_name);
 		const Ref<Shader>* sdr = data.shader_override.getptr(p_name);
 		if (sdr)
 		if (sdr)
@@ -830,7 +830,7 @@ Ref<Shader> Control::get_shader(const StringName& p_name,const StringName& p_typ
 
 
 Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p_type) const {
 Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p_type) const {
 
 
-	if (p_type==StringName()) {
+	if (p_type==StringName() || p_type=="") {
 		const Ref<StyleBox>* style = data.style_override.getptr(p_name);
 		const Ref<StyleBox>* style = data.style_override.getptr(p_name);
 		if (style)
 		if (style)
 			return *style;
 			return *style;
@@ -858,7 +858,7 @@ Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p
 }
 }
 Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) const {
 Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) const {
 
 
-	if (p_type==StringName()) {
+	if (p_type==StringName() || p_type=="") {
 		const Ref<Font>* font = data.font_override.getptr(p_name);
 		const Ref<Font>* font = data.font_override.getptr(p_name);
 		if (font)
 		if (font)
 			return *font;
 			return *font;
@@ -889,7 +889,7 @@ Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) c
 }
 }
 Color Control::get_color(const StringName& p_name,const StringName& p_type) const {
 Color Control::get_color(const StringName& p_name,const StringName& p_type) const {
 
 
-	if (p_type==StringName()) {
+	if (p_type==StringName() || p_type=="") {
 		const Color* color = data.color_override.getptr(p_name);
 		const Color* color = data.color_override.getptr(p_name);
 		if (color)
 		if (color)
 			return *color;
 			return *color;
@@ -918,7 +918,7 @@ Color Control::get_color(const StringName& p_name,const StringName& p_type) cons
 
 
 int Control::get_constant(const StringName& p_name,const StringName& p_type) const {
 int Control::get_constant(const StringName& p_name,const StringName& p_type) const {
 
 
-	if (p_type==StringName()) {
+	if (p_type==StringName() || p_type=="") {
 		const int* constant = data.constant_override.getptr(p_name);
 		const int* constant = data.constant_override.getptr(p_name);
 		if (constant)
 		if (constant)
 			return *constant;
 			return *constant;
@@ -946,12 +946,64 @@ int Control::get_constant(const StringName& p_name,const StringName& p_type) con
 
 
 }
 }
 
 
+bool Control::has_icon_override(const StringName& p_name) const {
+
+	const Ref<Texture>* tex = data.icon_override.getptr(p_name);
+	if (tex)
+		return true;
+	else
+		return false;
+}
+
+bool Control::has_shader_override(const StringName &p_name) const {
+
+	const Ref<Shader>* sdr = data.shader_override.getptr(p_name);
+	if (sdr)
+		return true;
+	else
+		return false;
+}
+
+bool Control::has_stylebox_override(const StringName& p_name) const {
+
+	const Ref<StyleBox>* style = data.style_override.getptr(p_name);
+	if (style)
+		return true;
+	else
+		return false;
+}
+
+bool Control::has_font_override(const StringName& p_name) const {
+
+	const Ref<Font>* font = data.font_override.getptr(p_name);
+	if (font)
+		return true;
+	else
+		return false;
+}
+
+bool Control::has_color_override(const StringName& p_name) const {
+
+	const Color* color = data.color_override.getptr(p_name);
+	if (color)
+		return true;
+	else
+		return false;
+}
+
+bool Control::has_constant_override(const StringName& p_name) const {
+
+	const int* constant = data.constant_override.getptr(p_name);
+	if (constant)
+		return true;
+	else
+		return false;
+}
 
 
 bool Control::has_icon(const StringName& p_name,const StringName& p_type) const {
 bool Control::has_icon(const StringName& p_name,const StringName& p_type) const {
 
 
-	if (p_type==StringName()) {
-		const Ref<Texture>* tex = data.icon_override.getptr(p_name);
-		if (tex)
+	if (p_type==StringName() || p_type=="") {
+		if (has_icon_override(p_name) == true)
 			return true;
 			return true;
 	}
 	}
 
 
@@ -977,11 +1029,10 @@ bool Control::has_icon(const StringName& p_name,const StringName& p_type) const
 
 
 }
 }
 
 
-bool Control::has_shader(const StringName &p_name, const StringName &p_type) const
-{
-	if (p_type==StringName()) {
-		const Ref<Shader>* sdr = data.shader_override.getptr(p_name);
-		if (sdr)
+bool Control::has_shader(const StringName &p_name, const StringName &p_type) const {
+
+	if (p_type==StringName() || p_type=="") {
+		if (has_shader_override(p_name)==true)
 			return true;
 			return true;
 	}
 	}
 
 
@@ -1008,10 +1059,8 @@ bool Control::has_shader(const StringName &p_name, const StringName &p_type) con
 }
 }
 bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) const {
 bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) const {
 
 
-	if (p_type==StringName()) {
-		const Ref<StyleBox>* style = data.style_override.getptr(p_name);
-
-		if (style)
+	if (p_type==StringName() || p_type=="") {
+		if (has_stylebox_override(p_name)==true)
 			return true;
 			return true;
 	}
 	}
 
 
@@ -1038,9 +1087,8 @@ bool Control::has_stylebox(const StringName& p_name,const StringName& p_type) co
 }
 }
 bool Control::has_font(const StringName& p_name,const StringName& p_type) const {
 bool Control::has_font(const StringName& p_name,const StringName& p_type) const {
 
 
-	if (p_type==StringName()) {
-		const Ref<Font>* font = data.font_override.getptr(p_name);
-		if (font)
+	if (p_type==StringName() || p_type=="") {
+		if (has_font_override(p_name)==true)
 			return true;
 			return true;
 	}
 	}
 
 
@@ -1066,11 +1114,11 @@ bool Control::has_font(const StringName& p_name,const StringName& p_type) const
 	return Theme::get_default()->has_font( p_name, type );
 	return Theme::get_default()->has_font( p_name, type );
 
 
 }
 }
-bool Control::has_color(const StringName& p_name,const StringName& p_type) const {
 
 
-	if (p_type==StringName()) {
-		const Color* color = data.color_override.getptr(p_name);
-		if (color)
+bool Control::has_color(const StringName& p_name, const StringName& p_type) const {
+
+	if (p_type==StringName() || p_type=="") {
+		if (has_color_override(p_name)==true)
 			return true;
 			return true;
 	}
 	}
 
 
@@ -1098,10 +1146,8 @@ bool Control::has_color(const StringName& p_name,const StringName& p_type) const
 
 
 bool Control::has_constant(const StringName& p_name,const StringName& p_type) const {
 bool Control::has_constant(const StringName& p_name,const StringName& p_type) const {
 
 
-	if (p_type==StringName()) {
-
-		const int* constant = data.constant_override.getptr(p_name);
-		if (constant)
+	if (p_type==StringName() || p_type=="") {
+		if (has_constant_override(p_name) == true)
 			return true;
 			return true;
 	}
 	}
 
 
@@ -2297,6 +2343,17 @@ void Control::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_color","name","type"),&Control::get_color,DEFVAL(""));
 	ObjectTypeDB::bind_method(_MD("get_color","name","type"),&Control::get_color,DEFVAL(""));
 	ObjectTypeDB::bind_method(_MD("get_constant","name","type"),&Control::get_constant,DEFVAL(""));
 	ObjectTypeDB::bind_method(_MD("get_constant","name","type"),&Control::get_constant,DEFVAL(""));
 
 
+	ObjectTypeDB::bind_method(_MD("has_icon_override", "name"), &Control::has_icon_override);
+	ObjectTypeDB::bind_method(_MD("has_stylebox_override", "name"), &Control::has_stylebox_override);
+	ObjectTypeDB::bind_method(_MD("has_font_override", "name"), &Control::has_font_override);
+	ObjectTypeDB::bind_method(_MD("has_color_override", "name"), &Control::has_color_override);
+	ObjectTypeDB::bind_method(_MD("has_constant_override", "name"), &Control::has_constant_override);
+
+	ObjectTypeDB::bind_method(_MD("has_icon", "name", "type"), &Control::has_icon, DEFVAL(""));
+	ObjectTypeDB::bind_method(_MD("has_stylebox", "name", "type"), &Control::has_stylebox, DEFVAL(""));
+	ObjectTypeDB::bind_method(_MD("has_font", "name", "type"), &Control::has_font, DEFVAL(""));
+	ObjectTypeDB::bind_method(_MD("has_color", "name", "type"), &Control::has_color, DEFVAL(""));
+	ObjectTypeDB::bind_method(_MD("has_constant", "name", "type"), &Control::has_constant, DEFVAL(""));
 
 
 	ObjectTypeDB::bind_method(_MD("get_parent_control:Control"),&Control::get_parent_control);
 	ObjectTypeDB::bind_method(_MD("get_parent_control:Control"),&Control::get_parent_control);
 
 
@@ -2326,6 +2383,7 @@ void Control::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"),&Control::warp_mouse);
 	ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"),&Control::warp_mouse);
 
 
+	ObjectTypeDB::bind_method(_MD("minimum_size_changed"), &Control::minimum_size_changed);
 
 
 	BIND_VMETHOD(MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event")));
 	BIND_VMETHOD(MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event")));
 	BIND_VMETHOD(MethodInfo(Variant::VECTOR2,"get_minimum_size"));
 	BIND_VMETHOD(MethodInfo(Variant::VECTOR2,"get_minimum_size"));

+ 7 - 0
scene/gui/control.h

@@ -341,6 +341,13 @@ public:
 	Color get_color(const StringName& p_name,const StringName& p_type=StringName()) const;
 	Color get_color(const StringName& p_name,const StringName& p_type=StringName()) const;
 	int get_constant(const StringName& p_name,const StringName& p_type=StringName()) const;
 	int get_constant(const StringName& p_name,const StringName& p_type=StringName()) const;
 
 
+	bool has_icon_override(const StringName& p_name) const;
+	bool has_shader_override(const StringName& p_name) const;
+	bool has_stylebox_override(const StringName& p_name) const;
+	bool has_font_override(const StringName& p_name) const;
+	bool has_color_override(const StringName& p_name) const;
+	bool has_constant_override(const StringName& p_name) const;
+
 	bool has_icon(const StringName& p_name,const StringName& p_type=StringName()) const;
 	bool has_icon(const StringName& p_name,const StringName& p_type=StringName()) const;
 	bool has_shader(const StringName& p_name,const StringName& p_type=StringName()) const;
 	bool has_shader(const StringName& p_name,const StringName& p_type=StringName()) const;
 	bool has_stylebox(const StringName& p_name,const StringName& p_type=StringName()) const;
 	bool has_stylebox(const StringName& p_name,const StringName& p_type=StringName()) const;

+ 34 - 4
scene/gui/patch_9_frame.cpp

@@ -9,10 +9,9 @@ void Patch9Frame::_notification(int p_what) {
 		if (texture.is_null())
 		if (texture.is_null())
 			return;
 			return;
 
 
-
 		Size2 s=get_size();
 		Size2 s=get_size();
 		RID ci = get_canvas_item();
 		RID ci = get_canvas_item();
-		VS::get_singleton()->canvas_item_add_style_box(ci,Rect2(Point2(),s),texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate);
+		VS::get_singleton()->canvas_item_add_style_box(ci,Rect2(Point2(),s),region_rect,texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center,modulate);
 //		draw_texture_rect(texture,Rect2(Point2(),s),false,modulate);
 //		draw_texture_rect(texture,Rect2(Point2(),s),false,modulate);
 
 
 /*
 /*
@@ -47,12 +46,15 @@ void Patch9Frame::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_modulate"), & Patch9Frame::get_modulate );
 	ObjectTypeDB::bind_method(_MD("get_modulate"), & Patch9Frame::get_modulate );
 	ObjectTypeDB::bind_method(_MD("set_patch_margin","margin","value"), & Patch9Frame::set_patch_margin );
 	ObjectTypeDB::bind_method(_MD("set_patch_margin","margin","value"), & Patch9Frame::set_patch_margin );
 	ObjectTypeDB::bind_method(_MD("get_patch_margin","margin"), & Patch9Frame::get_patch_margin );
 	ObjectTypeDB::bind_method(_MD("get_patch_margin","margin"), & Patch9Frame::get_patch_margin );
+	ObjectTypeDB::bind_method(_MD("set_region_rect","rect"),&Patch9Frame::set_region_rect);
+	ObjectTypeDB::bind_method(_MD("get_region_rect"),&Patch9Frame::get_region_rect);
 	ObjectTypeDB::bind_method(_MD("set_draw_center","draw_center"), & Patch9Frame::set_draw_center );
 	ObjectTypeDB::bind_method(_MD("set_draw_center","draw_center"), & Patch9Frame::set_draw_center );
 	ObjectTypeDB::bind_method(_MD("get_draw_center"), & Patch9Frame::get_draw_center );
 	ObjectTypeDB::bind_method(_MD("get_draw_center"), & Patch9Frame::get_draw_center );
 
 
 	ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") );
 	ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") );
 	ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") );
 	ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") );
 	ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "draw_center"), _SCS("set_draw_center"),_SCS("get_draw_center") );
 	ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "draw_center"), _SCS("set_draw_center"),_SCS("get_draw_center") );
+	ADD_PROPERTYNZ( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect"));
 	ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/left",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_LEFT );
 	ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/left",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_LEFT );
 	ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/top",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_TOP );
 	ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/top",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_TOP );
 	ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/right",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_RIGHT );
 	ADD_PROPERTYINZ( PropertyInfo( Variant::INT, "patch_margin/right",PROPERTY_HINT_RANGE,"0,16384,1"), _SCS("set_patch_margin"),_SCS("get_patch_margin"),MARGIN_RIGHT );
@@ -93,6 +95,20 @@ void Patch9Frame::set_patch_margin(Margin p_margin,int p_size) {
 	margin[p_margin]=p_size;
 	margin[p_margin]=p_size;
 	update();
 	update();
 	minimum_size_changed();
 	minimum_size_changed();
+	switch (p_margin) {
+		case MARGIN_LEFT:
+			_change_notify("patch_margin/left");
+			break;
+		case MARGIN_TOP:
+			_change_notify("patch_margin/top");
+			break;
+		case MARGIN_RIGHT:
+			_change_notify("patch_margin/right");
+			break;
+		case MARGIN_BOTTOM:
+			_change_notify("patch_margin/bottom");
+			break;
+	}
 }
 }
 
 
 int Patch9Frame::get_patch_margin(Margin p_margin) const{
 int Patch9Frame::get_patch_margin(Margin p_margin) const{
@@ -101,6 +117,22 @@ int Patch9Frame::get_patch_margin(Margin p_margin) const{
 	return margin[p_margin];
 	return margin[p_margin];
 }
 }
 
 
+void Patch9Frame::set_region_rect(const Rect2& p_region_rect) {
+
+	if (region_rect==p_region_rect)
+		return;
+
+	region_rect=p_region_rect;
+
+	item_rect_changed();
+	_change_notify("region_rect");
+}
+
+Rect2 Patch9Frame::get_region_rect() const {
+
+	return region_rect;
+}
+
 void Patch9Frame::set_draw_center(bool p_draw) {
 void Patch9Frame::set_draw_center(bool p_draw) {
 
 
 	draw_center=p_draw;
 	draw_center=p_draw;
@@ -128,5 +160,3 @@ Patch9Frame::Patch9Frame() {
 Patch9Frame::~Patch9Frame()
 Patch9Frame::~Patch9Frame()
 {
 {
 }
 }
-
-

+ 4 - 0
scene/gui/patch_9_frame.h

@@ -11,6 +11,7 @@ class Patch9Frame : public Control {
 
 
 	bool draw_center;
 	bool draw_center;
 	int margin[4];
 	int margin[4];
+	Rect2 region_rect;
 	Color modulate;
 	Color modulate;
 	Ref<Texture> texture;
 	Ref<Texture> texture;
 protected:
 protected:
@@ -30,6 +31,9 @@ public:
 	void set_patch_margin(Margin p_margin,int p_size);
 	void set_patch_margin(Margin p_margin,int p_size);
 	int get_patch_margin(Margin p_margin) const;
 	int get_patch_margin(Margin p_margin) const;
 
 
+	void set_region_rect(const Rect2& p_region_rect);
+	Rect2 get_region_rect() const;
+
 	void set_draw_center(bool p_enable);
 	void set_draw_center(bool p_enable);
 	bool get_draw_center() const;
 	bool get_draw_center() const;
 
 

+ 2 - 0
scene/resources/bit_mask.h

@@ -36,6 +36,8 @@
 class BitMap : public Resource {
 class BitMap : public Resource {
 
 
 	OBJ_TYPE(BitMap,Resource);
 	OBJ_TYPE(BitMap,Resource);
+	OBJ_SAVE_TYPE(BitMap);
+	RES_BASE_EXTENSION("pbm");
 
 
 	Vector<uint8_t> bitmask;
 	Vector<uint8_t> bitmask;
 	int width;
 	int width;

+ 19 - 2
scene/resources/style_box.cpp

@@ -138,7 +138,7 @@ void StyleBoxTexture::draw(RID p_canvas_item,const Rect2& p_rect) const {
 	r.pos.y-=expand_margin[MARGIN_TOP];
 	r.pos.y-=expand_margin[MARGIN_TOP];
 	r.size.x+=expand_margin[MARGIN_LEFT]+expand_margin[MARGIN_RIGHT];
 	r.size.x+=expand_margin[MARGIN_LEFT]+expand_margin[MARGIN_RIGHT];
 	r.size.y+=expand_margin[MARGIN_TOP]+expand_margin[MARGIN_BOTTOM];
 	r.size.y+=expand_margin[MARGIN_TOP]+expand_margin[MARGIN_BOTTOM];
-	VisualServer::get_singleton()->canvas_item_add_style_box( p_canvas_item,r,texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center);
+	VisualServer::get_singleton()->canvas_item_add_style_box( p_canvas_item,r,region_rect,texture->get_rid(),Vector2(margin[MARGIN_LEFT],margin[MARGIN_TOP]),Vector2(margin[MARGIN_RIGHT],margin[MARGIN_BOTTOM]),draw_center);
 }
 }
 
 
 void StyleBoxTexture::set_draw_center(bool p_draw) {
 void StyleBoxTexture::set_draw_center(bool p_draw) {
@@ -175,6 +175,20 @@ float StyleBoxTexture::get_expand_margin_size(Margin p_expand_margin) const {
 	return expand_margin[p_expand_margin];
 	return expand_margin[p_expand_margin];
 }
 }
 
 
+void StyleBoxTexture::set_region_rect(const Rect2& p_region_rect) {
+
+	if (region_rect==p_region_rect)
+		return;
+
+	region_rect=p_region_rect;
+	emit_changed();
+}
+
+Rect2 StyleBoxTexture::get_region_rect() const {
+
+	return region_rect;
+}
+
 
 
 void StyleBoxTexture::_bind_methods() {
 void StyleBoxTexture::_bind_methods() {
 
 
@@ -187,10 +201,14 @@ void StyleBoxTexture::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_expand_margin_size","margin","size"),&StyleBoxTexture::set_expand_margin_size);
 	ObjectTypeDB::bind_method(_MD("set_expand_margin_size","margin","size"),&StyleBoxTexture::set_expand_margin_size);
 	ObjectTypeDB::bind_method(_MD("get_expand_margin_size","margin"),&StyleBoxTexture::get_expand_margin_size);
 	ObjectTypeDB::bind_method(_MD("get_expand_margin_size","margin"),&StyleBoxTexture::get_expand_margin_size);
 
 
+	ObjectTypeDB::bind_method(_MD("set_region_rect","region"),&StyleBoxTexture::set_region_rect);
+	ObjectTypeDB::bind_method(_MD("get_region_rect"),&StyleBoxTexture::get_region_rect);
+
 	ObjectTypeDB::bind_method(_MD("set_draw_center","enable"),&StyleBoxTexture::set_draw_center);
 	ObjectTypeDB::bind_method(_MD("set_draw_center","enable"),&StyleBoxTexture::set_draw_center);
 	ObjectTypeDB::bind_method(_MD("get_draw_center"),&StyleBoxTexture::get_draw_center);
 	ObjectTypeDB::bind_method(_MD("get_draw_center"),&StyleBoxTexture::get_draw_center);
 
 
 	ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), _SCS("set_texture"),_SCS("get_texture") );
 	ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), _SCS("set_texture"),_SCS("get_texture") );
+	ADD_PROPERTYNZ( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect"));
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin/left", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_margin_size"),_SCS("get_margin_size"), MARGIN_LEFT );
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin/left", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_margin_size"),_SCS("get_margin_size"), MARGIN_LEFT );
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin/right", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_margin_size"),_SCS("get_margin_size"), MARGIN_RIGHT );
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin/right", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_margin_size"),_SCS("get_margin_size"), MARGIN_RIGHT );
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin/top", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_margin_size"),_SCS("get_margin_size"), MARGIN_TOP);
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "margin/top", PROPERTY_HINT_RANGE,"0,2048,1" ), _SCS("set_margin_size"),_SCS("get_margin_size"), MARGIN_TOP);
@@ -505,4 +523,3 @@ StyleBoxImageMask::StyleBoxImageMask() {
 	}
 	}
 	expand=true;
 	expand=true;
 }
 }
-

+ 4 - 0
scene/resources/style_box.h

@@ -81,6 +81,7 @@ class StyleBoxTexture : public StyleBox {
 
 
 	float expand_margin[4];
 	float expand_margin[4];
 	float margin[4];
 	float margin[4];
+	Rect2 region_rect;
 	Ref<Texture> texture;
 	Ref<Texture> texture;
 	bool draw_center;
 	bool draw_center;
 
 
@@ -98,6 +99,9 @@ public:
 	void set_margin_size(Margin p_margin,float p_size);
 	void set_margin_size(Margin p_margin,float p_size);
 	float get_margin_size(Margin p_margin) const;
 	float get_margin_size(Margin p_margin) const;
 
 
+	void set_region_rect(const Rect2& p_region_rect);
+	Rect2 get_region_rect() const;
+
 	void set_texture(RES p_texture);
 	void set_texture(RES p_texture);
 	RES get_texture() const;
 	RES get_texture() const;
 
 

+ 61 - 0
servers/server_wrap_mt_common.h

@@ -698,3 +698,64 @@
 		}\
 		}\
 	}
 	}
 
 
+#define FUNC8R(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)\
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) { \
+		if (Thread::get_caller_ID()!=server_thread) {\
+			m_r ret;\
+			command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7, p8, &ret);\
+			SYNC_DEBUG\
+			return ret;\
+		} else {\
+			return server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);\
+		}\
+	}
+
+#define FUNC8RC(m_r,m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)\
+	virtual m_r m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const { \
+		if (Thread::get_caller_ID()!=server_thread) {\
+			m_r ret;\
+			command_queue.push_and_ret( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7, p8, &ret);\
+			SYNC_DEBUG\
+			return ret;\
+		} else {\
+			return server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);\
+		}\
+	}
+
+
+#define FUNC8S(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)\
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) { \
+		if (Thread::get_caller_ID()!=server_thread) {\
+			command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7, p8);\
+		} else {\
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);\
+		}\
+	}
+
+#define FUNC8SC(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)\
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const { \
+		if (Thread::get_caller_ID()!=server_thread) {\
+			command_queue.push_and_sync( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7, p8);\
+		} else {\
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);\
+		}\
+	}
+
+
+#define FUNC8(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)\
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) { \
+		if (Thread::get_caller_ID()!=server_thread) {\
+			command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7, p8);\
+		} else {\
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);\
+		}\
+	}
+
+#define FUNC8C(m_type,m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8)\
+	virtual void m_type(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5, m_arg6 p6, m_arg7 p7, m_arg8 p8) const { \
+		if (Thread::get_caller_ID()!=server_thread) {\
+			command_queue.push( server_name, &ServerName::m_type,p1, p2, p3, p4, p5, p6, p7, p8);\
+		} else {\
+			server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8);\
+		}\
+	}

+ 3 - 2
servers/visual/rasterizer.h

@@ -702,6 +702,7 @@ public:
 		struct CommandStyle : public Command {
 		struct CommandStyle : public Command {
 
 
 			Rect2 rect;
 			Rect2 rect;
+			Rect2 source;
 			RID texture;
 			RID texture;
 			float margin[4];
 			float margin[4];
 			bool draw_center;
 			bool draw_center;
@@ -944,12 +945,12 @@ public:
 	virtual void canvas_disable_blending()=0;
 	virtual void canvas_disable_blending()=0;
 	virtual void canvas_set_opacity(float p_opacity)=0;
 	virtual void canvas_set_opacity(float p_opacity)=0;
 	virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode)=0;
 	virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode)=0;
-	virtual void canvas_begin_rect(const Matrix32& p_transform)=0;;
+	virtual void canvas_begin_rect(const Matrix32& p_transform)=0;
 	virtual void canvas_set_clip(bool p_clip, const Rect2& p_rect)=0;
 	virtual void canvas_set_clip(bool p_clip, const Rect2& p_rect)=0;
 	virtual void canvas_end_rect()=0;
 	virtual void canvas_end_rect()=0;
 	virtual void canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width)=0;
 	virtual void canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width)=0;
 	virtual void canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate)=0;
 	virtual void canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate)=0;
-	virtual void canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margins, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1))=0;
+	virtual void canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margins, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1))=0;
 	virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width)=0;
 	virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width)=0;
 	virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor)=0;
 	virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor)=0;
 	virtual void canvas_set_transform(const Matrix32& p_transform)=0;
 	virtual void canvas_set_transform(const Matrix32& p_transform)=0;

+ 1 - 2
servers/visual/rasterizer_dummy.cpp

@@ -1627,7 +1627,7 @@ void RasterizerDummy::canvas_draw_rect(const Rect2& p_rect, int p_flags, const R
 
 
 
 
 }
 }
-void RasterizerDummy::canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) {
+void RasterizerDummy::canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) {
 
 
 
 
 }
 }
@@ -1959,4 +1959,3 @@ RasterizerDummy::RasterizerDummy() {
 RasterizerDummy::~RasterizerDummy() {
 RasterizerDummy::~RasterizerDummy() {
 
 
 };
 };
-

+ 1 - 1
servers/visual/rasterizer_dummy.h

@@ -708,7 +708,7 @@ public:
 	virtual void canvas_end_rect();
 	virtual void canvas_end_rect();
 	virtual void canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width);
 	virtual void canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width);
 	virtual void canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate);
 	virtual void canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate);
-	virtual void canvas_draw_style_box(const Rect2& p_rect, RID p_texture,const float *p_margins, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1));
+	virtual void canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margins, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1));
 	virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width);
 	virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width);
 	virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor);
 	virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor);
 	virtual void canvas_set_transform(const Matrix32& p_transform);
 	virtual void canvas_set_transform(const Matrix32& p_transform);

+ 2 - 1
servers/visual/visual_server_raster.cpp

@@ -3745,7 +3745,7 @@ void VisualServerRaster::canvas_item_add_texture_rect_region(RID p_item, const R
 
 
 }
 }
 
 
-void VisualServerRaster::canvas_item_add_style_box(RID p_item, const Rect2& p_rect, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center,const Color& p_modulate) {
+void VisualServerRaster::canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture, const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center,const Color& p_modulate) {
 
 
 	VS_CHANGED;
 	VS_CHANGED;
 	CanvasItem *canvas_item = canvas_item_owner.get( p_item );
 	CanvasItem *canvas_item = canvas_item_owner.get( p_item );
@@ -3755,6 +3755,7 @@ void VisualServerRaster::canvas_item_add_style_box(RID p_item, const Rect2& p_re
 	ERR_FAIL_COND(!style);
 	ERR_FAIL_COND(!style);
 	style->texture=p_texture;
 	style->texture=p_texture;
 	style->rect=p_rect;
 	style->rect=p_rect;
+	style->source=p_source;
 	style->draw_center=p_draw_center;
 	style->draw_center=p_draw_center;
 	style->color=p_modulate;
 	style->color=p_modulate;
 	style->margin[MARGIN_LEFT]=p_topleft.x;
 	style->margin[MARGIN_LEFT]=p_topleft.x;

+ 1 - 1
servers/visual/visual_server_raster.h

@@ -1171,7 +1171,7 @@ public:
 	virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color);
 	virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color);
 	virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false);
 	virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false);
 	virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false);
 	virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false);
-	virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1));
+	virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1));
 	virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0);
 	virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0);
 	virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID());
 	virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID());
 	virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID(), int p_count=-1);
 	virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID(), int p_count=-1);

+ 1 - 1
servers/visual/visual_server_wrap_mt.h

@@ -607,7 +607,7 @@ public:
 	FUNC4(canvas_item_add_circle,RID, const Point2& , float ,const Color& );
 	FUNC4(canvas_item_add_circle,RID, const Point2& , float ,const Color& );
 	FUNC6(canvas_item_add_texture_rect,RID, const Rect2& , RID ,bool ,const Color&,bool );
 	FUNC6(canvas_item_add_texture_rect,RID, const Rect2& , RID ,bool ,const Color&,bool );
 	FUNC6(canvas_item_add_texture_rect_region,RID, const Rect2& , RID ,const Rect2& ,const Color&,bool );
 	FUNC6(canvas_item_add_texture_rect_region,RID, const Rect2& , RID ,const Rect2& ,const Color&,bool );
-	FUNC7(canvas_item_add_style_box,RID, const Rect2& , RID ,const Vector2& ,const Vector2&, bool ,const Color& );
+	FUNC8(canvas_item_add_style_box,RID, const Rect2& , const Rect2&, RID ,const Vector2& ,const Vector2&, bool ,const Color& );
 	FUNC6(canvas_item_add_primitive,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ,float );
 	FUNC6(canvas_item_add_primitive,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ,float );
 	FUNC5(canvas_item_add_polygon,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID );
 	FUNC5(canvas_item_add_polygon,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID );
 	FUNC7(canvas_item_add_triangle_array,RID, const Vector<int>& , const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID , int );
 	FUNC7(canvas_item_add_triangle_array,RID, const Vector<int>& , const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID , int );

+ 2 - 4
servers/visual_server.cpp

@@ -705,10 +705,10 @@ void VisualServer::_bind_methods() {
 
 
 }
 }
 
 
-void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2& p_rect, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate) {
+void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate) {
 
 
 	ERR_FAIL_COND(p_margins.size()!=4);
 	ERR_FAIL_COND(p_margins.size()!=4);
-	canvas_item_add_style_box(p_item, p_rect, p_texture,Vector2(p_margins[0],p_margins[1]),Vector2(p_margins[2],p_margins[3]),true,p_modulate);
+	canvas_item_add_style_box(p_item,p_rect,p_source,p_texture,Vector2(p_margins[0],p_margins[1]),Vector2(p_margins[2],p_margins[3]),true,p_modulate);
 }
 }
 
 
 void VisualServer::_camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far) {
 void VisualServer::_camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far) {
@@ -822,5 +822,3 @@ VisualServer::~VisualServer() {
 
 
 	singleton=NULL;
 	singleton=NULL;
 }
 }
-
-

+ 2 - 2
servers/visual_server.h

@@ -52,7 +52,7 @@ class VisualServer : public Object {
 	void _camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far);
 	void _camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far);
 	void _viewport_set_rect(RID p_viewport,const Rect2& p_rect);
 	void _viewport_set_rect(RID p_viewport,const Rect2& p_rect);
 	Rect2 _viewport_get_rect(RID p_viewport) const;
 	Rect2 _viewport_get_rect(RID p_viewport) const;
-	void _canvas_item_add_style_box(RID p_item, const Rect2& p_rect, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate=Color(1,1,1));
+	void _canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate=Color(1,1,1));
 protected:
 protected:
 	RID _make_test_cube();
 	RID _make_test_cube();
 	void _free_internal_rids();
 	void _free_internal_rids();
@@ -1025,7 +1025,7 @@ public:
 	virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color)=0;
 	virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color)=0;
 	virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0;
 	virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0;
 	virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0;
 	virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0;
-	virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1))=0;
+	virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1))=0;
 	virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0)=0;
 	virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0)=0;
 	virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID())=0;
 	virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID())=0;
 	virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID(), int p_count=-1)=0;
 	virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID(), int p_count=-1)=0;

+ 6 - 6
tools/editor/editor_node.cpp

@@ -59,7 +59,7 @@
 
 
 // plugins
 // plugins
 #include "plugins/sprite_frames_editor_plugin.h"
 #include "plugins/sprite_frames_editor_plugin.h"
-#include "plugins/sprite_region_editor_plugin.h"
+#include "plugins/texture_region_editor_plugin.h"
 #include "plugins/canvas_item_editor_plugin.h"
 #include "plugins/canvas_item_editor_plugin.h"
 #include "addon_editor_plugin.h"
 #include "addon_editor_plugin.h"
 #include "plugins/spatial_editor_plugin.h"
 #include "plugins/spatial_editor_plugin.h"
@@ -106,6 +106,7 @@
 #include "tools/editor/io_plugins/editor_font_import_plugin.h"
 #include "tools/editor/io_plugins/editor_font_import_plugin.h"
 #include "tools/editor/io_plugins/editor_sample_import_plugin.h"
 #include "tools/editor/io_plugins/editor_sample_import_plugin.h"
 #include "tools/editor/io_plugins/editor_translation_import_plugin.h"
 #include "tools/editor/io_plugins/editor_translation_import_plugin.h"
+#include "tools/editor/io_plugins/editor_bitmask_import_plugin.h"
 #include "tools/editor/io_plugins/editor_mesh_import_plugin.h"
 #include "tools/editor/io_plugins/editor_mesh_import_plugin.h"
 #include "tools/editor/io_plugins/editor_export_scene.h"
 #include "tools/editor/io_plugins/editor_export_scene.h"
 
 
@@ -5215,7 +5216,7 @@ void EditorNode::_bind_methods() {
 	ADD_SIGNAL( MethodInfo("play_pressed") );
 	ADD_SIGNAL( MethodInfo("play_pressed") );
 	ADD_SIGNAL( MethodInfo("pause_pressed") );
 	ADD_SIGNAL( MethodInfo("pause_pressed") );
 	ADD_SIGNAL( MethodInfo("stop_pressed") );
 	ADD_SIGNAL( MethodInfo("stop_pressed") );
-	ADD_SIGNAL( MethodInfo("request_help") );	
+	ADD_SIGNAL( MethodInfo("request_help") );
 	ADD_SIGNAL( MethodInfo("script_add_function_request",PropertyInfo(Variant::OBJECT,"obj"),PropertyInfo(Variant::STRING,"function"),PropertyInfo(Variant::STRING_ARRAY,"args")) );
 	ADD_SIGNAL( MethodInfo("script_add_function_request",PropertyInfo(Variant::OBJECT,"obj"),PropertyInfo(Variant::STRING,"function"),PropertyInfo(Variant::STRING_ARRAY,"args")) );
 	ADD_SIGNAL( MethodInfo("resource_saved",PropertyInfo(Variant::OBJECT,"obj")) );
 	ADD_SIGNAL( MethodInfo("resource_saved",PropertyInfo(Variant::OBJECT,"obj")) );
 
 
@@ -6365,6 +6366,8 @@ EditorNode::EditorNode() {
 	editor_import_export->add_import_plugin( Ref<EditorFontImportPlugin>( memnew(EditorFontImportPlugin(this))));
 	editor_import_export->add_import_plugin( Ref<EditorFontImportPlugin>( memnew(EditorFontImportPlugin(this))));
 	editor_import_export->add_import_plugin( Ref<EditorSampleImportPlugin>( memnew(EditorSampleImportPlugin(this))));
 	editor_import_export->add_import_plugin( Ref<EditorSampleImportPlugin>( memnew(EditorSampleImportPlugin(this))));
 	editor_import_export->add_import_plugin( Ref<EditorTranslationImportPlugin>( memnew(EditorTranslationImportPlugin(this))));
 	editor_import_export->add_import_plugin( Ref<EditorTranslationImportPlugin>( memnew(EditorTranslationImportPlugin(this))));
+	editor_import_export->add_import_plugin( Ref<EditorBitMaskImportPlugin>( memnew(EditorBitMaskImportPlugin(this))));
+
 
 
 	editor_import_export->add_export_plugin( Ref<EditorTextureExportPlugin>( memnew(EditorTextureExportPlugin)));
 	editor_import_export->add_export_plugin( Ref<EditorTextureExportPlugin>( memnew(EditorTextureExportPlugin)));
 	editor_import_export->add_export_plugin( Ref<EditorSampleExportPlugin>( memnew(EditorSampleExportPlugin)));
 	editor_import_export->add_export_plugin( Ref<EditorSampleExportPlugin>( memnew(EditorSampleExportPlugin)));
@@ -6404,7 +6407,7 @@ EditorNode::EditorNode() {
 	add_editor_plugin( memnew( TileSetEditorPlugin(this) ) );
 	add_editor_plugin( memnew( TileSetEditorPlugin(this) ) );
 	add_editor_plugin( memnew( TileMapEditorPlugin(this) ) );
 	add_editor_plugin( memnew( TileMapEditorPlugin(this) ) );
 	add_editor_plugin( memnew( SpriteFramesEditorPlugin(this) ) );
 	add_editor_plugin( memnew( SpriteFramesEditorPlugin(this) ) );
-	add_editor_plugin( memnew( SpriteRegionEditorPlugin(this) ) );
+	add_editor_plugin( memnew( TextureRegionEditorPlugin(this) ) );
 	add_editor_plugin( memnew( Particles2DEditorPlugin(this) ) );
 	add_editor_plugin( memnew( Particles2DEditorPlugin(this) ) );
 	add_editor_plugin( memnew( Path2DEditorPlugin(this) ) );
 	add_editor_plugin( memnew( Path2DEditorPlugin(this) ) );
 	add_editor_plugin( memnew( PathEditorPlugin(this) ) );
 	add_editor_plugin( memnew( PathEditorPlugin(this) ) );
@@ -6636,6 +6639,3 @@ EditorPluginList::EditorPluginList() {
 
 
 EditorPluginList::~EditorPluginList() {
 EditorPluginList::~EditorPluginList() {
 }
 }
-
-
-

+ 357 - 0
tools/editor/io_plugins/editor_bitmask_import_plugin.cpp

@@ -0,0 +1,357 @@
+#include "editor_bitmask_import_plugin.h"
+#include "io/image_loader.h"
+#include "tools/editor/editor_file_dialog.h"
+#include "tools/editor/editor_dir_dialog.h"
+#include "tools/editor/editor_node.h"
+#include "tools/editor/property_editor.h"
+#include "io/resource_saver.h"
+#include "os/file_access.h"
+#include "io/marshalls.h"
+#include "tools/editor/editor_settings.h"
+
+class _EditorBitMaskImportOptions : public Object {
+
+	OBJ_TYPE(_EditorBitMaskImportOptions, Object);
+public:
+
+	bool _set(const StringName& p_name, const Variant& p_value) {
+
+		return false;
+	}
+
+	bool _get(const StringName& p_name, Variant &r_ret) const{
+
+		return false;
+	}
+
+	void _get_property_list(List<PropertyInfo> *p_list) const{
+
+	}
+
+	static void _bind_methods() {
+
+		ADD_SIGNAL(MethodInfo("changed"));
+	}
+
+
+	_EditorBitMaskImportOptions() {
+
+	}
+
+};
+
+class EditorBitMaskImportDialog : public ConfirmationDialog {
+
+	OBJ_TYPE(EditorBitMaskImportDialog, ConfirmationDialog);
+
+	EditorBitMaskImportPlugin *plugin;
+
+	LineEdit *import_path;
+	LineEdit *save_path;
+	EditorFileDialog *file_select;
+	EditorDirDialog *save_select;
+	ConfirmationDialog *error_dialog;
+	PropertyEditor *option_editor;
+
+public:
+
+	void _choose_files(const Vector<String>& p_path) {
+
+		String files;
+		for (int i = 0; i<p_path.size(); i++) {
+
+			if (i>0)
+				files += ",";
+			files += p_path[i];
+		}
+
+		import_path->set_text(files);
+
+	}
+	void _choose_save_dir(const String& p_path) {
+
+		save_path->set_text(p_path);
+	}
+
+	void _browse() {
+
+		file_select->popup_centered_ratio();
+	}
+
+	void _browse_target() {
+
+		save_select->popup_centered_ratio();
+
+	}
+
+
+	void popup_import(const String& p_path) {
+
+		popup_centered(Size2(400, 100)*EDSCALE);
+		if (p_path != "") {
+
+			Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path);
+			ERR_FAIL_COND(!rimd.is_valid());
+
+			save_path->set_text(p_path.get_base_dir());
+
+			String src = "";
+			for (int i = 0; i<rimd->get_source_count(); i++) {
+				if (i>0)
+					src += ",";
+				src += EditorImportPlugin::expand_source_path(rimd->get_source_path(i));
+			}
+			import_path->set_text(src);
+		}
+	}
+
+
+	void _import() {
+
+		Vector<String> bitmasks = import_path->get_text().split(",");
+
+		if (bitmasks.size() == 0) {
+			error_dialog->set_text(TTR("No bit masks to import!"));
+			error_dialog->popup_centered(Size2(200, 100)*EDSCALE);
+		}
+
+		if (save_path->get_text().strip_edges() == "") {
+			error_dialog->set_text(TTR("Target path is empty."));
+			error_dialog->popup_centered_minsize();
+			return;
+		}
+
+		if (!save_path->get_text().begins_with("res://")) {
+			error_dialog->set_text(TTR("Target path must be a complete resource path."));
+			error_dialog->popup_centered_minsize();
+			return;
+		}
+
+		if (!DirAccess::exists(save_path->get_text())) {
+			error_dialog->set_text(TTR("Target path must exist."));
+			error_dialog->popup_centered_minsize();
+			return;
+		}
+
+		for (int i = 0; i<bitmasks.size(); i++) {
+
+			Ref<ResourceImportMetadata> imd = memnew(ResourceImportMetadata);
+
+			imd->add_source(EditorImportPlugin::validate_source_path(bitmasks[i]));
+
+			String dst = save_path->get_text();
+			if (dst == "") {
+				error_dialog->set_text(TTR("Save path is empty!"));
+				error_dialog->popup_centered(Size2(200, 100)*EDSCALE);
+			}
+
+			dst = dst.plus_file(bitmasks[i].get_file().basename() + ".pbm");
+
+			Error err = plugin->import(dst, imd);
+		}
+
+		hide();
+
+	}
+
+
+	void _notification(int p_what) {
+
+	}
+
+	static void _bind_methods() {
+
+
+		ObjectTypeDB::bind_method("_choose_files", &EditorBitMaskImportDialog::_choose_files);
+		ObjectTypeDB::bind_method("_choose_save_dir", &EditorBitMaskImportDialog::_choose_save_dir);
+		ObjectTypeDB::bind_method("_import", &EditorBitMaskImportDialog::_import);
+		ObjectTypeDB::bind_method("_browse", &EditorBitMaskImportDialog::_browse);
+		ObjectTypeDB::bind_method("_browse_target", &EditorBitMaskImportDialog::_browse_target);
+		//	ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) );
+	}
+
+	EditorBitMaskImportDialog(EditorBitMaskImportPlugin *p_plugin) {
+
+		plugin = p_plugin;
+
+
+		set_title(TTR("Import BitMasks"));
+
+		VBoxContainer *vbc = memnew(VBoxContainer);
+		add_child(vbc);
+		set_child_rect(vbc);
+
+
+		HBoxContainer *hbc = memnew(HBoxContainer);
+		vbc->add_margin_child(TTR("Source Texture(s):"), hbc);
+
+		import_path = memnew(LineEdit);
+		import_path->set_h_size_flags(SIZE_EXPAND_FILL);
+		hbc->add_child(import_path);
+
+		Button * import_choose = memnew(Button);
+		import_choose->set_text(" .. ");
+		hbc->add_child(import_choose);
+
+		import_choose->connect("pressed", this, "_browse");
+
+		hbc = memnew(HBoxContainer);
+		vbc->add_margin_child(TTR("Target Path:"), hbc);
+
+		save_path = memnew(LineEdit);
+		save_path->set_h_size_flags(SIZE_EXPAND_FILL);
+		hbc->add_child(save_path);
+
+		Button * save_choose = memnew(Button);
+		save_choose->set_text(" .. ");
+		hbc->add_child(save_choose);
+
+		save_choose->connect("pressed", this, "_browse_target");
+
+		file_select = memnew(EditorFileDialog);
+		file_select->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+		add_child(file_select);
+		file_select->set_mode(EditorFileDialog::MODE_OPEN_FILES);
+		file_select->connect("files_selected", this, "_choose_files");
+
+		List<String> extensions;
+		ImageLoader::get_recognized_extensions(&extensions);
+		file_select->clear_filters();
+		for (int i = 0; i<extensions.size(); i++) {
+
+			file_select->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+		}
+
+		save_select = memnew(EditorDirDialog);
+		add_child(save_select);
+
+		//	save_select->set_mode(EditorFileDialog::MODE_OPEN_DIR);
+		save_select->connect("dir_selected", this, "_choose_save_dir");
+
+		get_ok()->connect("pressed", this, "_import");
+		get_ok()->set_text(TTR("Import"));
+
+
+		error_dialog = memnew(ConfirmationDialog);
+		add_child(error_dialog);
+		error_dialog->get_ok()->set_text(TTR("Accept"));
+		//	error_dialog->get_cancel()->hide();
+
+		set_hide_on_ok(false);
+	}
+
+	~EditorBitMaskImportDialog() {
+	}
+
+};
+
+
+String EditorBitMaskImportPlugin::get_name() const {
+
+	return "bitmask";
+}
+String EditorBitMaskImportPlugin::get_visible_name() const{
+
+	return TTR("Bit Mask");
+}
+void EditorBitMaskImportPlugin::import_dialog(const String& p_from){
+
+	dialog->popup_import(p_from);
+}
+Error EditorBitMaskImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){
+
+	ERR_FAIL_COND_V(p_from->get_source_count() != 1, ERR_INVALID_PARAMETER);
+
+	Ref<ResourceImportMetadata> from = p_from;
+
+	String src_path = EditorImportPlugin::expand_source_path(from->get_source_path(0));
+	Ref<ImageTexture> it = ResourceLoader::load(src_path);
+	ERR_FAIL_COND_V(it.is_null(), ERR_CANT_OPEN);
+
+	Ref<BitMap> target = memnew(BitMap);
+	target->create_from_image_alpha(it.ptr()->get_data());
+
+	from->set_source_md5(0, FileAccess::get_md5(src_path));
+	from->set_editor(get_name());
+	target->set_import_metadata(from);
+
+
+	Error err = ResourceSaver::save(p_path, target);
+
+	return err;
+
+}
+
+
+EditorBitMaskImportPlugin* EditorBitMaskImportPlugin::singleton = NULL;
+
+
+void EditorBitMaskImportPlugin::import_from_drop(const Vector<String>& p_drop, const String &p_dest_path) {
+
+	Vector<String> files;
+
+	List<String> valid_extensions;
+	ImageLoader::get_recognized_extensions(&valid_extensions);
+	for(int i=0;i<p_drop.size();i++) {
+
+		String extension=p_drop[i].extension().to_lower();
+
+		for (List<String>::Element *E=valid_extensions.front();E;E=E->next()) {
+
+			if (E->get()==extension) {
+				files.push_back(p_drop[i]);
+				break;
+			}
+		}
+	}
+
+	if (files.size()) {
+		import_dialog();
+		dialog->_choose_files(files);
+		dialog->_choose_save_dir(p_dest_path);
+	}
+}
+
+void EditorBitMaskImportPlugin::reimport_multiple_files(const Vector<String>& p_list) {
+
+	if (p_list.size() == 0)
+		return;
+
+	Vector<String> sources;
+	for (int i = 0; i<p_list.size(); i++) {
+		int idx;
+		EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->find_file(p_list[i], &idx);
+		if (efsd) {
+			for (int j = 0; j<efsd->get_source_count(idx); j++) {
+				String file = expand_source_path(efsd->get_source_file(idx, j));
+				if (sources.find(file) == -1) {
+					sources.push_back(file);
+				}
+
+			}
+		}
+	}
+
+	if (sources.size()) {
+
+		dialog->popup_import(p_list[0]);
+		dialog->_choose_files(sources);
+		dialog->_choose_save_dir(p_list[0].get_base_dir());
+	}
+}
+
+bool EditorBitMaskImportPlugin::can_reimport_multiple_files() const {
+
+	return true;
+}
+
+EditorBitMaskImportPlugin::EditorBitMaskImportPlugin(EditorNode* p_editor) {
+
+	singleton = this;
+	dialog = memnew(EditorBitMaskImportDialog(this));
+	p_editor->get_gui_base()->add_child(dialog);
+}
+
+EditorBitMaskExportPlugin::EditorBitMaskExportPlugin() {
+
+}

+ 41 - 0
tools/editor/io_plugins/editor_bitmask_import_plugin.h

@@ -0,0 +1,41 @@
+#ifndef EDITOR_BITMASK_IMPORT_PLUGIN_H
+#define EDITOR_BITMASK_IMPORT_PLUGIN_H
+
+#include "tools/editor/editor_import_export.h"
+#include "scene/resources/font.h"
+
+class EditorNode;
+class EditorBitMaskImportDialog;
+
+class EditorBitMaskImportPlugin : public EditorImportPlugin {
+
+	OBJ_TYPE(EditorBitMaskImportPlugin, EditorImportPlugin);
+
+	EditorBitMaskImportDialog *dialog;
+public:
+
+	static EditorBitMaskImportPlugin *singleton;
+
+	virtual String get_name() const;
+	virtual String get_visible_name() const;
+	virtual void import_dialog(const String& p_from = "");
+	virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from);
+	void import_from_drop(const Vector<String>& p_drop, const String &p_dest_path);
+	virtual void reimport_multiple_files(const Vector<String>& p_list);
+	virtual bool can_reimport_multiple_files() const;
+
+
+	EditorBitMaskImportPlugin(EditorNode* p_editor);
+};
+
+class EditorBitMaskExportPlugin : public EditorExportPlugin {
+
+	OBJ_TYPE(EditorBitMaskExportPlugin, EditorExportPlugin);
+
+
+public:
+
+	EditorBitMaskExportPlugin();
+};
+
+#endif // EDITOR_SAMPLE_IMPORT_PLUGIN_H

+ 231 - 113
tools/editor/plugins/sprite_region_editor_plugin.cpp → tools/editor/plugins/texture_region_editor_plugin.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
 /*************************************************************************/
-/*  sprite_region_editor_plugin.cpp                                      */
+/*  texture_region_editor_plugin.cpp                                      */
 /*************************************************************************/
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
 /*                           GODOT ENGINE                                */
@@ -29,14 +29,20 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 /*************************************************************************/
 
 
-#include "sprite_region_editor_plugin.h"
+#include "texture_region_editor_plugin.h"
 #include "scene/gui/check_box.h"
 #include "scene/gui/check_box.h"
 #include "os/input.h"
 #include "os/input.h"
 #include "os/keyboard.h"
 #include "os/keyboard.h"
 
 
-void SpriteRegionEditor::_region_draw()
+void TextureRegionEditor::_region_draw()
 {
 {
-	Ref<Texture> base_tex = node->get_texture();
+	Ref<Texture> base_tex = NULL;
+	if(node_type == "Sprite" && node_sprite)
+		base_tex = node_sprite->get_texture();
+	else if(node_type == "Patch9Frame" && node_patch9)
+		base_tex = node_patch9->get_texture();
+	else if(node_type == "StyleBoxTexture" && obj_styleBox)
+		base_tex = obj_styleBox->get_texture();
 	if (base_tex.is_null())
 	if (base_tex.is_null())
 		return;
 		return;
 
 
@@ -87,7 +93,9 @@ void SpriteRegionEditor::_region_draw()
 		mtx.basis_xform(rect.pos+rect.size),
 		mtx.basis_xform(rect.pos+rect.size),
 		mtx.basis_xform(rect.pos+Vector2(0,rect.size.y))
 		mtx.basis_xform(rect.pos+Vector2(0,rect.size.y))
 	};
 	};
-
+	Color color(0.9,0.5,0.5);
+	if(this->editing_region == REGION_PATCH_MARGIN)
+		color = Color(0.21, 0.79, 0.31);
 	for(int i=0;i<4;i++) {
 	for(int i=0;i<4;i++) {
 
 
 		int prev = (i+3)%4;
 		int prev = (i+3)%4;
@@ -96,7 +104,7 @@ void SpriteRegionEditor::_region_draw()
 		Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
 		Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
 		ofs*=1.4144*(select_handle->get_size().width/2);
 		ofs*=1.4144*(select_handle->get_size().width/2);
 
 
-		edit_draw->draw_line(endpoints[i]-draw_ofs, endpoints[next]-draw_ofs, Color(0.9,0.5,0.5), 2);
+		edit_draw->draw_line(endpoints[i]-draw_ofs, endpoints[next]-draw_ofs, color , 2);
 
 
 		edit_draw->draw_texture(select_handle,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor()-draw_ofs);
 		edit_draw->draw_texture(select_handle,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor()-draw_ofs);
 
 
@@ -124,7 +132,7 @@ void SpriteRegionEditor::_region_draw()
 	updating_scroll=false;
 	updating_scroll=false;
 }
 }
 
 
-void SpriteRegionEditor::_region_input(const InputEvent& p_input)
+void TextureRegionEditor::_region_input(const InputEvent& p_input)
 {
 {
 	Matrix32 mtx;
 	Matrix32 mtx;
 	mtx.elements[2]=-draw_ofs;
 	mtx.elements[2]=-draw_ofs;
@@ -154,7 +162,12 @@ void SpriteRegionEditor::_region_input(const InputEvent& p_input)
 				drag_from=mtx.affine_inverse().xform(Vector2(mb.x,mb.y));
 				drag_from=mtx.affine_inverse().xform(Vector2(mb.x,mb.y));
 				drag_from=snap_point(drag_from);
 				drag_from=snap_point(drag_from);
 				drag=true;
 				drag=true;
-				rect_prev=node->get_region_rect();
+				if(node_type == "Sprite" && node_sprite )
+					rect_prev=node_sprite->get_region_rect();
+				else if(node_type == "Patch9Frame" && node_patch9)
+					rect_prev=node_patch9->get_region_rect();
+				else if(node_type == "StyleBoxTexture" && obj_styleBox)
+					rect_prev=obj_styleBox->get_region_rect();
 
 
 				drag_index=-1;
 				drag_index=-1;
 				for(int i=0;i<8;i++) {
 				for(int i=0;i<8;i++) {
@@ -172,14 +185,20 @@ void SpriteRegionEditor::_region_input(const InputEvent& p_input)
 				}
 				}
 
 
 			} else if (drag) {
 			} else if (drag) {
-
-				undo_redo->create_action(TTR("Set region_rect"));
-				undo_redo->add_do_method(node,"set_region_rect",node->get_region_rect());
-				undo_redo->add_undo_method(node,"set_region_rect",rect_prev);
-				undo_redo->add_do_method(edit_draw,"update");
-				undo_redo->add_undo_method(edit_draw,"update");
-				undo_redo->commit_action();
-
+				if(editing_region == REGION_TEXTURE_REGION) {
+					undo_redo->create_action("Set region_rect");
+					if(node_type == "Sprite" && node_sprite ){
+						undo_redo->add_do_method(node_sprite ,"set_region_rect",node_sprite->get_region_rect());
+						undo_redo->add_undo_method(node_sprite,"set_region_rect",rect_prev);
+					}
+					else if(node_type == "Patch9Frame" && node_patch9){
+						undo_redo->add_do_method(node_patch9 ,"set_region_rect",node_patch9->get_region_rect());
+						undo_redo->add_undo_method(node_patch9,"set_region_rect",rect_prev);
+					}
+					undo_redo->add_do_method(edit_draw,"update");
+					undo_redo->add_undo_method(edit_draw,"update");
+					undo_redo->commit_action();
+				}
 				drag=false;
 				drag=false;
 			}
 			}
 
 
@@ -187,7 +206,7 @@ void SpriteRegionEditor::_region_input(const InputEvent& p_input)
 
 
 			if (drag) {
 			if (drag) {
 				drag=false;
 				drag=false;
-				node->set_region_rect(rect_prev);
+				apply_rect(rect_prev);
 				rect=rect_prev;
 				rect=rect_prev;
 				edit_draw->update();
 				edit_draw->update();
 			}
 			}
@@ -218,60 +237,60 @@ void SpriteRegionEditor::_region_input(const InputEvent& p_input)
 			if (creating) {
 			if (creating) {
 				rect = Rect2(drag_from,Size2());
 				rect = Rect2(drag_from,Size2());
 				rect.expand_to(new_pos);
 				rect.expand_to(new_pos);
-				node->set_region_rect(rect);
+				apply_rect(rect);
 				edit_draw->update();
 				edit_draw->update();
 				return;
 				return;
 			}
 			}
 
 
 			switch(drag_index) {
 			switch(drag_index) {
 			case 0: {
 			case 0: {
-				Vector2 p=rect_prev.pos+rect_prev.size;
-				rect = Rect2(p,Size2());
-				rect.expand_to(new_pos);
-				node->set_region_rect(rect);
-			} break;
+					Vector2 p=rect_prev.pos+rect_prev.size;
+					rect = Rect2(p,Size2());
+					rect.expand_to(new_pos);
+					apply_rect(rect);
+				} break;
 			case 1: {
 			case 1: {
-				Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y);
-				rect = Rect2(p,Size2(rect_prev.size.x,0));
-				rect.expand_to(new_pos);
-				node->set_region_rect(rect);
-			} break;
+					Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y);
+					rect = Rect2(p,Size2(rect_prev.size.x,0));
+					rect.expand_to(new_pos);
+					apply_rect(rect);
+				} break;
 			case 2: {
 			case 2: {
-				Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y);
-				rect = Rect2(p,Size2());
-				rect.expand_to(new_pos);
-				node->set_region_rect(rect);
-			} break;
+					Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y);
+					rect = Rect2(p,Size2());
+					rect.expand_to(new_pos);
+					apply_rect(rect);
+				} break;
 			case 3: {
 			case 3: {
-				Vector2 p=rect_prev.pos;
-				rect = Rect2(p,Size2(0,rect_prev.size.y));
-				rect.expand_to(new_pos);
-				node->set_region_rect(rect);
-			} break;
+					Vector2 p=rect_prev.pos;
+					rect = Rect2(p,Size2(0,rect_prev.size.y));
+					rect.expand_to(new_pos);
+					apply_rect(rect);
+				} break;
 			case 4: {
 			case 4: {
-				Vector2 p=rect_prev.pos;
-				rect = Rect2(p,Size2());
-				rect.expand_to(new_pos);
-				node->set_region_rect(rect);
-			} break;
+					Vector2 p=rect_prev.pos;
+					rect = Rect2(p,Size2());
+					rect.expand_to(new_pos);
+					apply_rect(rect);
+				} break;
 			case 5: {
 			case 5: {
-				Vector2 p=rect_prev.pos;
-				rect = Rect2(p,Size2(rect_prev.size.x,0));
-				rect.expand_to(new_pos);
-				node->set_region_rect(rect);
-			} break;
+					Vector2 p=rect_prev.pos;
+					rect = Rect2(p,Size2(rect_prev.size.x,0));
+					rect.expand_to(new_pos);
+					apply_rect(rect);
+				} break;
 			case 6: {
 			case 6: {
-				Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0);
-				rect = Rect2(p,Size2());
-				rect.expand_to(new_pos);
-				node->set_region_rect(rect);
-			} break;
+					Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0);
+					rect = Rect2(p,Size2());
+					rect.expand_to(new_pos);
+					apply_rect(rect);
+				} break;
 			case 7: {
 			case 7: {
-				Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0);
-				rect = Rect2(p,Size2(0,rect_prev.size.y));
-				rect.expand_to(new_pos);
-				node->set_region_rect(rect);
-			} break;
+					Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0);
+					rect = Rect2(p,Size2(0,rect_prev.size.y));
+					rect.expand_to(new_pos);
+					apply_rect(rect);
+				} break;
 
 
 			}
 			}
 			edit_draw->update();
 			edit_draw->update();
@@ -280,7 +299,7 @@ void SpriteRegionEditor::_region_input(const InputEvent& p_input)
 	}
 	}
 }
 }
 
 
-void SpriteRegionEditor::_scroll_changed(float)
+void TextureRegionEditor::_scroll_changed(float)
 {
 {
 	if (updating_scroll)
 	if (updating_scroll)
 		return;
 		return;
@@ -292,47 +311,73 @@ void SpriteRegionEditor::_scroll_changed(float)
 	edit_draw->update();
 	edit_draw->update();
 }
 }
 
 
-void SpriteRegionEditor::_set_use_snap(bool p_use)
+void TextureRegionEditor::_set_use_snap(bool p_use)
 {
 {
 	use_snap=p_use;
 	use_snap=p_use;
 }
 }
 
 
-void SpriteRegionEditor::_set_show_grid(bool p_show)
+void TextureRegionEditor::_set_show_grid(bool p_show)
 {
 {
 	snap_show_grid=p_show;
 	snap_show_grid=p_show;
 	edit_draw->update();
 	edit_draw->update();
 }
 }
 
 
-void SpriteRegionEditor::_set_snap_off_x(float p_val)
+void TextureRegionEditor::_set_snap_off_x(float p_val)
 {
 {
 	snap_offset.x=p_val;
 	snap_offset.x=p_val;
 	edit_draw->update();
 	edit_draw->update();
 }
 }
 
 
-void SpriteRegionEditor::_set_snap_off_y(float p_val)
+void TextureRegionEditor::_set_snap_off_y(float p_val)
 {
 {
 	snap_offset.y=p_val;
 	snap_offset.y=p_val;
 	edit_draw->update();
 	edit_draw->update();
 }
 }
 
 
-void SpriteRegionEditor::_set_snap_step_x(float p_val)
+void TextureRegionEditor::_set_snap_step_x(float p_val)
 {
 {
 	snap_step.x=p_val;
 	snap_step.x=p_val;
 	edit_draw->update();
 	edit_draw->update();
 }
 }
 
 
-void SpriteRegionEditor::_set_snap_step_y(float p_val)
+void TextureRegionEditor::_set_snap_step_y(float p_val)
 {
 {
 	snap_step.y=p_val;
 	snap_step.y=p_val;
 	edit_draw->update();
 	edit_draw->update();
 }
 }
 
 
-void SpriteRegionEditor::_notification(int p_what)
+void TextureRegionEditor::apply_rect(const Rect2& rect){
+
+	if(this->editing_region == REGION_TEXTURE_REGION) {
+		if(node_sprite)
+			node_sprite->set_region_rect(rect);
+		else if(node_patch9)
+			node_patch9->set_region_rect(rect);
+		else if(obj_styleBox)
+			obj_styleBox->set_region_rect(rect);
+	}
+	else if(this->editing_region == REGION_PATCH_MARGIN) {
+		if(node_patch9) {
+			node_patch9->set_patch_margin(MARGIN_LEFT, rect.pos.x - tex_region.pos.x);
+			node_patch9->set_patch_margin(MARGIN_RIGHT, tex_region.pos.x+tex_region.size.width-(rect.pos.x+rect.size.width));
+			node_patch9->set_patch_margin(MARGIN_TOP, rect.pos.y - tex_region.pos.y);
+			node_patch9->set_patch_margin(MARGIN_BOTTOM, tex_region.pos.y+tex_region.size.height-(rect.pos.y+rect.size.height));
+		}
+		else if(obj_styleBox) {
+			obj_styleBox->set_margin_size(MARGIN_LEFT, rect.pos.x - tex_region.pos.x);
+			obj_styleBox->set_margin_size(MARGIN_RIGHT, tex_region.pos.x+tex_region.size.width-(rect.pos.x+rect.size.width));
+			obj_styleBox->set_margin_size(MARGIN_TOP, rect.pos.y - tex_region.pos.y);
+			obj_styleBox->set_margin_size(MARGIN_BOTTOM, tex_region.pos.y+tex_region.size.height-(rect.pos.y+rect.size.height));
+		}
+	}
+}
+
+void TextureRegionEditor::_notification(int p_what)
 {
 {
 	switch(p_what) {
 	switch(p_what) {
-
-		case NOTIFICATION_READY: {
-			edit_node->set_icon( get_icon("RegionEdit","EditorIcons"));
+	case NOTIFICATION_READY: {
+			region_button->set_icon( get_icon("RegionEdit","EditorIcons"));
+			margin_button->set_icon( get_icon("Patch9Frame", "EditorIcons"));
 			b_snap_grid->set_icon( get_icon("Grid", "EditorIcons"));
 			b_snap_grid->set_icon( get_icon("Grid", "EditorIcons"));
 			b_snap_enable->set_icon( get_icon("Snap", "EditorIcons"));
 			b_snap_enable->set_icon( get_icon("Snap", "EditorIcons"));
 			icon_zoom->set_texture( get_icon("Zoom", "EditorIcons"));
 			icon_zoom->set_texture( get_icon("Zoom", "EditorIcons"));
@@ -340,60 +385,129 @@ void SpriteRegionEditor::_notification(int p_what)
 	}
 	}
 }
 }
 
 
-void SpriteRegionEditor::_node_removed(Node *p_node)
+void TextureRegionEditor::_node_removed(Object *p_obj)
 {
 {
-	if(p_node==node) {
-		node=NULL;
+	if(p_obj == node_sprite || p_obj == node_patch9 || p_obj == obj_styleBox) {
+		node_patch9 = NULL;
+		node_sprite = NULL;
+		obj_styleBox = NULL;
 		hide();
 		hide();
 	}
 	}
 }
 }
 
 
-void SpriteRegionEditor::_bind_methods()
+void TextureRegionEditor::_bind_methods()
 {
 {
-	ObjectTypeDB::bind_method(_MD("_edit_node"),&SpriteRegionEditor::_edit_node);
-	ObjectTypeDB::bind_method(_MD("_region_draw"),&SpriteRegionEditor::_region_draw);
-	ObjectTypeDB::bind_method(_MD("_region_input"),&SpriteRegionEditor::_region_input);
-	ObjectTypeDB::bind_method(_MD("_scroll_changed"),&SpriteRegionEditor::_scroll_changed);
-	ObjectTypeDB::bind_method(_MD("_node_removed"),&SpriteRegionEditor::_node_removed);
-	ObjectTypeDB::bind_method(_MD("_set_use_snap"),&SpriteRegionEditor::_set_use_snap);
-	ObjectTypeDB::bind_method(_MD("_set_show_grid"),&SpriteRegionEditor::_set_show_grid);
-	ObjectTypeDB::bind_method(_MD("_set_snap_off_x"),&SpriteRegionEditor::_set_snap_off_x);
-	ObjectTypeDB::bind_method(_MD("_set_snap_off_y"),&SpriteRegionEditor::_set_snap_off_y);
-	ObjectTypeDB::bind_method(_MD("_set_snap_step_x"),&SpriteRegionEditor::_set_snap_step_x);
-	ObjectTypeDB::bind_method(_MD("_set_snap_step_y"),&SpriteRegionEditor::_set_snap_step_y);
+	ObjectTypeDB::bind_method(_MD("_edit_node"),&TextureRegionEditor::_edit_node);
+	ObjectTypeDB::bind_method(_MD("_edit_region"),&TextureRegionEditor::_edit_region);
+	ObjectTypeDB::bind_method(_MD("_edit_margin"),&TextureRegionEditor::_edit_margin);
+	ObjectTypeDB::bind_method(_MD("_region_draw"),&TextureRegionEditor::_region_draw);
+	ObjectTypeDB::bind_method(_MD("_region_input"),&TextureRegionEditor::_region_input);
+	ObjectTypeDB::bind_method(_MD("_scroll_changed"),&TextureRegionEditor::_scroll_changed);
+	ObjectTypeDB::bind_method(_MD("_node_removed"),&TextureRegionEditor::_node_removed);
+	ObjectTypeDB::bind_method(_MD("_set_use_snap"),&TextureRegionEditor::_set_use_snap);
+	ObjectTypeDB::bind_method(_MD("_set_show_grid"),&TextureRegionEditor::_set_show_grid);
+	ObjectTypeDB::bind_method(_MD("_set_snap_off_x"),&TextureRegionEditor::_set_snap_off_x);
+	ObjectTypeDB::bind_method(_MD("_set_snap_off_y"),&TextureRegionEditor::_set_snap_off_y);
+	ObjectTypeDB::bind_method(_MD("_set_snap_step_x"),&TextureRegionEditor::_set_snap_step_x);
+	ObjectTypeDB::bind_method(_MD("_set_snap_step_y"),&TextureRegionEditor::_set_snap_step_y);
 }
 }
 
 
-void SpriteRegionEditor::edit(Node *p_sprite)
+void TextureRegionEditor::edit(Object *p_obj)
 {
 {
-	if (p_sprite) {
-		node=p_sprite->cast_to<Sprite>();
-		node->connect("exit_tree",this,"_node_removed",varray(p_sprite),CONNECT_ONESHOT);
+	if (p_obj) {
+		margin_button->hide();
+		node_type = p_obj->get_type();
+		if(node_type == "Sprite"){
+			node_sprite = p_obj->cast_to<Sprite>();
+			node_patch9 = NULL;
+			obj_styleBox = NULL;
+		}
+		else if(node_type == "Patch9Frame") {
+			node_patch9 = p_obj->cast_to<Patch9Frame>();
+			node_sprite = NULL;
+			obj_styleBox = NULL;
+			margin_button->show();
+		}
+		else if(node_type == "StyleBoxTexture") {
+			obj_styleBox = p_obj->cast_to<StyleBoxTexture>();
+			node_sprite = NULL;
+			node_patch9 = NULL;
+			margin_button->show();
+		}
+		p_obj->connect("exit_tree",this,"_node_removed",varray(p_obj),CONNECT_ONESHOT);
 	} else {
 	} else {
-		if (node)
-			node->disconnect("exit_tree",this,"_node_removed");
-		node=NULL;
+		if(node_sprite)
+			node_sprite->disconnect("exit_tree",this,"_node_removed");
+		else if(node_patch9)
+			node_patch9->disconnect("exit_tree",this,"_node_removed");
+		else if(obj_styleBox)
+			obj_styleBox->disconnect("exit_tree",this,"_node_removed");
+		node_sprite = NULL;
+		node_patch9 = NULL;
+		obj_styleBox = NULL;
 	}
 	}
+}
 
 
+void TextureRegionEditor::_edit_region()
+{
+	this->_edit_node(REGION_TEXTURE_REGION);
+	dlg_editor->set_title(TTR("Texture Region Editor"));
 }
 }
-void SpriteRegionEditor::_edit_node()
+
+void TextureRegionEditor::_edit_margin()
 {
 {
-	if (node->get_texture().is_null()) {
+	this->_edit_node(REGION_PATCH_MARGIN);
+	dlg_editor->set_title(TTR("Scale Region Editor"));
+}
 
 
-		error->set_text("No texture in this sprite.\nSet a texture to be able to edit Region.");
+void TextureRegionEditor::_edit_node(int region)
+{
+	Ref<Texture> texture = NULL;
+	if(node_type == "Sprite" && node_sprite )
+		texture = node_sprite->get_texture();
+	else if(node_type == "Patch9Frame" && node_patch9 )
+		texture = node_patch9->get_texture();
+	else if(node_type == "StyleBoxTexture" && obj_styleBox)
+		texture = obj_styleBox->get_texture();
+
+	if (texture.is_null()) {
+		error->set_text(TTR("No texture in this node.\nSet a texture to be able to edit region."));
 		error->popup_centered_minsize();
 		error->popup_centered_minsize();
 		return;
 		return;
 	}
 	}
 
 
-	rect=node->get_region_rect();
+	if(node_type == "Sprite" && node_sprite )
+		tex_region = node_sprite->get_region_rect();
+	else if(node_type == "Patch9Frame" && node_patch9 )
+		tex_region = node_patch9->get_region_rect();
+	else if(node_type == "StyleBoxTexture" && obj_styleBox)
+		tex_region = obj_styleBox->get_region_rect();
+	rect = tex_region;
+
+	if(region == REGION_PATCH_MARGIN) {
+		if(node_patch9){
+			Patch9Frame *node = node_patch9;
+			rect.pos += Point2(node->get_patch_margin(MARGIN_LEFT),node->get_patch_margin(MARGIN_TOP));
+			rect.size -= Size2(node->get_patch_margin(MARGIN_RIGHT)+node->get_patch_margin(MARGIN_LEFT), node->get_patch_margin(MARGIN_BOTTOM)+node->get_patch_margin(MARGIN_TOP));
+		}
+		else if(obj_styleBox) {
+			StyleBoxTexture * node = obj_styleBox;
+			rect.pos += Point2(node->get_margin_size(MARGIN_LEFT),node->get_margin_size(MARGIN_TOP));
+			rect.size -= Size2(node->get_margin_size(MARGIN_RIGHT)+node->get_margin_size(MARGIN_LEFT), node->get_margin_size(MARGIN_BOTTOM)+node->get_margin_size(MARGIN_TOP));
+		}
+	}
+
 	dlg_editor->popup_centered_ratio(0.85);
 	dlg_editor->popup_centered_ratio(0.85);
 	dlg_editor->get_ok()->release_focus();
 	dlg_editor->get_ok()->release_focus();
+
+	editing_region = region;
 }
 }
 
 
 inline float _snap_scalar(float p_offset, float p_step, float p_target) {
 inline float _snap_scalar(float p_offset, float p_step, float p_target) {
 	return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target;
 	return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target;
 }
 }
 
 
-Vector2 SpriteRegionEditor::snap_point(Vector2 p_target) const {
+Vector2 TextureRegionEditor::snap_point(Vector2 p_target) const {
 	if (use_snap) {
 	if (use_snap) {
 		p_target.x = _snap_scalar(snap_offset.x, snap_step.x, p_target.x);
 		p_target.x = _snap_scalar(snap_offset.x, snap_step.x, p_target.x);
 		p_target.y = _snap_scalar(snap_offset.y, snap_step.y, p_target.y);
 		p_target.y = _snap_scalar(snap_offset.y, snap_step.y, p_target.y);
@@ -403,9 +517,10 @@ Vector2 SpriteRegionEditor::snap_point(Vector2 p_target) const {
 	return p_target;
 	return p_target;
 }
 }
 
 
-SpriteRegionEditor::SpriteRegionEditor(EditorNode* p_editor)
+TextureRegionEditor::TextureRegionEditor(EditorNode* p_editor)
 {
 {
-	node=NULL;
+	node_sprite = NULL;
+	node_patch9 = NULL;
 	editor=p_editor;
 	editor=p_editor;
 	undo_redo = editor->get_undo_redo();
 	undo_redo = editor->get_undo_redo();
 
 
@@ -415,14 +530,18 @@ SpriteRegionEditor::SpriteRegionEditor(EditorNode* p_editor)
 	drag=false;
 	drag=false;
 
 
 	add_child( memnew( VSeparator ));
 	add_child( memnew( VSeparator ));
-	edit_node = memnew( ToolButton );
-	add_child(edit_node);
-	edit_node->set_tooltip(TTR("Sprite Region Editor"));
-	edit_node->connect("pressed",this,"_edit_node");
+	region_button = memnew( ToolButton );
+	add_child(region_button);
+	region_button->set_tooltip(TTR("Texture Region Editor"));
+	region_button->connect("pressed",this,"_edit_region");
+
+	margin_button = memnew( ToolButton );
+	add_child(margin_button);
+	margin_button->set_tooltip(TTR("Scale Region Editor"));
+	margin_button->connect("pressed",this,"_edit_margin");
 
 
 	dlg_editor = memnew( AcceptDialog );
 	dlg_editor = memnew( AcceptDialog );
 	add_child(dlg_editor);
 	add_child(dlg_editor);
-	dlg_editor->set_title(TTR("Sprite Region Editor"));
 	dlg_editor->set_self_opacity(0.9);
 	dlg_editor->set_self_opacity(0.9);
 
 
 	VBoxContainer *main_vb = memnew( VBoxContainer );
 	VBoxContainer *main_vb = memnew( VBoxContainer );
@@ -535,17 +654,17 @@ SpriteRegionEditor::SpriteRegionEditor(EditorNode* p_editor)
 
 
 }
 }
 
 
-void SpriteRegionEditorPlugin::edit(Object *p_node)
+void TextureRegionEditorPlugin::edit(Object *p_node)
 {
 {
-	region_editor->edit(p_node->cast_to<Node>());
+	region_editor->edit(p_node);
 }
 }
 
 
-bool SpriteRegionEditorPlugin::handles(Object *p_node) const
+bool TextureRegionEditorPlugin::handles(Object *p_obj) const
 {
 {
-	return p_node->is_type("Sprite");
+	return p_obj->is_type("Sprite") || p_obj->is_type("Patch9Frame") || p_obj->is_type("StyleBoxTexture");
 }
 }
 
 
-void SpriteRegionEditorPlugin::make_visible(bool p_visible)
+void TextureRegionEditorPlugin::make_visible(bool p_visible)
 {
 {
 	if (p_visible) {
 	if (p_visible) {
 		region_editor->show();
 		region_editor->show();
@@ -556,7 +675,7 @@ void SpriteRegionEditorPlugin::make_visible(bool p_visible)
 }
 }
 
 
 
 
-Dictionary SpriteRegionEditorPlugin::get_state() const {
+Dictionary TextureRegionEditorPlugin::get_state() const {
 
 
 	Dictionary state;
 	Dictionary state;
 	state["zoom"]=region_editor->zoom->get_val();
 	state["zoom"]=region_editor->zoom->get_val();
@@ -567,7 +686,7 @@ Dictionary SpriteRegionEditorPlugin::get_state() const {
 	return state;
 	return state;
 }
 }
 
 
-void SpriteRegionEditorPlugin::set_state(const Dictionary& p_state){
+void TextureRegionEditorPlugin::set_state(const Dictionary& p_state){
 
 
 	Dictionary state=p_state;
 	Dictionary state=p_state;
 	if (state.has("zoom")) {
 	if (state.has("zoom")) {
@@ -599,12 +718,11 @@ void SpriteRegionEditorPlugin::set_state(const Dictionary& p_state){
 	}
 	}
 }
 }
 
 
-SpriteRegionEditorPlugin::SpriteRegionEditorPlugin(EditorNode *p_node)
+TextureRegionEditorPlugin::TextureRegionEditorPlugin(EditorNode *p_node)
 {
 {
 	editor = p_node;
 	editor = p_node;
-	region_editor= memnew ( SpriteRegionEditor(p_node) );
+	region_editor= memnew ( TextureRegionEditor(p_node) );
 	CanvasItemEditor::get_singleton()->add_control_to_menu_panel(region_editor);
 	CanvasItemEditor::get_singleton()->add_control_to_menu_panel(region_editor);
 
 
 	region_editor->hide();
 	region_editor->hide();
 }
 }
-

+ 35 - 22
tools/editor/plugins/sprite_region_editor_plugin.h → tools/editor/plugins/texture_region_editor_plugin.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
 /*************************************************************************/
-/*  sprite_region_editor_plugin.h                                        */
+/*  texture_region_editor_plugin.h                                        */
 /*************************************************************************/
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
 /*                           GODOT ENGINE                                */
@@ -29,22 +29,27 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 /*************************************************************************/
 
 
-#ifndef SPRITE_REGION_EDITOR_PLUGIN_H
-#define SPRITE_REGION_EDITOR_PLUGIN_H
+#ifndef TEXTURE_REGION_EDITOR_PLUGIN_H
+#define TEXTURE_REGION_EDITOR_PLUGIN_H
 
 
 #include "canvas_item_editor_plugin.h"
 #include "canvas_item_editor_plugin.h"
 #include "tools/editor/editor_plugin.h"
 #include "tools/editor/editor_plugin.h"
 #include "tools/editor/editor_node.h"
 #include "tools/editor/editor_node.h"
 #include "scene/2d/sprite.h"
 #include "scene/2d/sprite.h"
+#include "scene/gui/patch_9_frame.h"
+#include "scene/resources/style_box.h"
 
 
-class SpriteRegionEditor : public HBoxContainer {
+class TextureRegionEditor : public HBoxContainer {
 
 
-	OBJ_TYPE(SpriteRegionEditor, HBoxContainer );
+	OBJ_TYPE(TextureRegionEditor, HBoxContainer );
+	enum RegionType {
+		REGION_TEXTURE_REGION,
+		REGION_PATCH_MARGIN
+	};
 
 
-	friend class SpriteRegionEditorPlugin;
-
-	ToolButton *edit_node;
-//	Button *use_region;
+	friend class TextureRegionEditorPlugin;
+	ToolButton *region_button;
+	ToolButton *margin_button;
 	ToolButton *b_snap_enable;
 	ToolButton *b_snap_enable;
 	ToolButton *b_snap_grid;
 	ToolButton *b_snap_grid;
 	TextureFrame *icon_zoom;
 	TextureFrame *icon_zoom;
@@ -59,7 +64,6 @@ class SpriteRegionEditor : public HBoxContainer {
 	VScrollBar *vscroll;
 	VScrollBar *vscroll;
 	HScrollBar *hscroll;
 	HScrollBar *hscroll;
 
 
-	Sprite *node;
 	EditorNode *editor;
 	EditorNode *editor;
 	AcceptDialog *dlg_editor;
 	AcceptDialog *dlg_editor;
 	UndoRedo* undo_redo;
 	UndoRedo* undo_redo;
@@ -73,8 +77,17 @@ class SpriteRegionEditor : public HBoxContainer {
 	Vector2 snap_offset;
 	Vector2 snap_offset;
 	Vector2 snap_step;
 	Vector2 snap_step;
 
 
+
+	String node_type;
+	Patch9Frame *node_patch9;
+	Sprite *node_sprite;
+	StyleBoxTexture *obj_styleBox;
+
+	int editing_region;
 	Rect2 rect;
 	Rect2 rect;
 	Rect2 rect_prev;
 	Rect2 rect_prev;
+	Rect2 tex_region;
+
 	bool drag;
 	bool drag;
 	bool creating;
 	bool creating;
 	Vector2 drag_from;
 	Vector2 drag_from;
@@ -88,34 +101,34 @@ class SpriteRegionEditor : public HBoxContainer {
 	void _set_snap_off_y(float p_val);
 	void _set_snap_off_y(float p_val);
 	void _set_snap_step_x(float p_val);
 	void _set_snap_step_x(float p_val);
 	void _set_snap_step_y(float p_val);
 	void _set_snap_step_y(float p_val);
-
+	void apply_rect(const Rect2& rect);
 protected:
 protected:
 
 
 	void _notification(int p_what);
 	void _notification(int p_what);
-	void _node_removed(Node *p_node);
+	void _node_removed(Object *p_obj);
 	static void _bind_methods();
 	static void _bind_methods();
 
 
 	Vector2 snap_point(Vector2 p_target) const;
 	Vector2 snap_point(Vector2 p_target) const;
 
 
 public:
 public:
 
 
-	void edit();
-	void _edit_node();
+	void _edit_node(int tex_region);
+	void _edit_region();
+	void _edit_margin();
 	void _region_draw();
 	void _region_draw();
 	void _region_input(const InputEvent &p_input);
 	void _region_input(const InputEvent &p_input);
 	void _scroll_changed(float);
 	void _scroll_changed(float);
 
 
-	void edit(Node *p_sprite);
-	SpriteRegionEditor(EditorNode* p_editor);
+	void edit(Object *p_obj);
+	TextureRegionEditor(EditorNode* p_editor);
 
 
 };
 };
 
 
-class SpriteRegionEditorPlugin : public EditorPlugin
+class TextureRegionEditorPlugin : public EditorPlugin
 {
 {
+	OBJ_TYPE( TextureRegionEditorPlugin, EditorPlugin );
 
 
-	OBJ_TYPE( SpriteRegionEditorPlugin, EditorPlugin );
-
-	SpriteRegionEditor *region_editor;
+	TextureRegionEditor *region_editor;
 	EditorNode *editor;
 	EditorNode *editor;
 public:
 public:
 
 
@@ -127,7 +140,7 @@ public:
 	void set_state(const Dictionary &p_state);
 	void set_state(const Dictionary &p_state);
 	Dictionary get_state() const;
 	Dictionary get_state() const;
 
 
-	SpriteRegionEditorPlugin(EditorNode *p_node);
+	TextureRegionEditorPlugin(EditorNode *p_node);
 };
 };
 
 
-#endif // SPRITE_REGION_EDITOR_PLUGIN_H
+#endif // TEXTURE_REGION_EDITOR_PLUGIN_H

+ 101 - 21
tools/editor/project_settings.cpp

@@ -834,35 +834,104 @@ void ProjectSettings::_autoload_edited() {
 		return;
 		return;
 
 
 	TreeItem *ti = autoload_list->get_edited();
 	TreeItem *ti = autoload_list->get_edited();
-	if (!ti || autoload_list->get_edited_column()!=2)
+	int column = autoload_list->get_edited_column();
+
+	if (!ti || (column != 0 && column != 2))
 		return;
 		return;
 
 
-	updating_autoload=true;
-	bool checked=ti->is_checked(2);
+	if (column == 0) {
+		String name = ti->get_text(0);
+		String old_name = selected_autoload.substr(selected_autoload.find("/")+1,selected_autoload.length());
 
 
-	String base="autoload/"+ti->get_text(0);
+		if (!name.is_valid_identifier()) {
+			ti->set_text(0,old_name);
+			message->set_text(TTR("Invalid name.")+"\n"+TTR("Valid characters:")+" a-z, A-Z, 0-9 or _");
+			message->popup_centered(Size2(300,100));
+			return;
+		}
 
 
-	String path = Globals::get_singleton()->get(base);
-	int order = Globals::get_singleton()->get_order(base);
+		if (ObjectTypeDB::type_exists(name)) {
+			ti->set_text(0,old_name);
+			message->set_text(TTR("Invalid name. Must not collide with an existing engine class name."));
+			message->popup_centered(Size2(400,100));
+			return;
+		}
 
 
-	if (path.begins_with("*"))
-		path=path.substr(1,path.length());
+		for(int i=0;i<Variant::VARIANT_MAX;i++) {
+			if (Variant::get_type_name(Variant::Type(i))==name) {
+				ti->set_text(0,old_name);
+				message->set_text(TTR("Invalid name. Must not collide with an existing buit-in type name."));
+				message->popup_centered(Size2(400,100));
+				return;
+			}
+		}
 
 
-	if (checked)
-		path="*"+path;
+		for(int i=0;i<GlobalConstants::get_global_constant_count();i++) {
+			if (GlobalConstants::get_global_constant_name(i)==name) {
+				ti->set_text(0,old_name);
+				message->set_text(TTR("Invalid name. Must not collide with an existing global constant name."));
+				message->popup_centered(Size2(400,100));
+				return;
+			}
+		}
 
 
-	undo_redo->create_action(TTR("Toggle AutoLoad Globals"));
-	undo_redo->add_do_property(Globals::get_singleton(),base,path);
-	undo_redo->add_undo_property(Globals::get_singleton(),base,Globals::get_singleton()->get(base));
-	undo_redo->add_do_method(Globals::get_singleton(),"set_order",base,order); // keep order, as config order matters for these
-	undo_redo->add_undo_method(Globals::get_singleton(),"set_order",base,order);
-	undo_redo->add_do_method(this,"_update_autoload");
-	undo_redo->add_undo_method(this,"_update_autoload");
-	undo_redo->add_do_method(this,"_settings_changed");
-	undo_redo->add_undo_method(this,"_settings_changed");
-	undo_redo->commit_action();
-	updating_autoload=false;
+		if (Globals::get_singleton()->has("autoload/"+name)) {
+			ti->set_text(0,old_name);
+			message->set_text(vformat(TTR("Autoload '%s' already exists!"),name));
+			message->popup_centered(Size2(300,100));
+			return;
+		}
+
+		updating_autoload = true;
+
+		name = "autoload/"+name;
+		String path = Globals::get_singleton()->get(selected_autoload);
+		bool is_persisting = Globals::get_singleton()->is_persisting(selected_autoload);
+		int order = Globals::get_singleton()->get_order(selected_autoload);
+
+		undo_redo->create_action(TTR("Rename Autoload"));
+		undo_redo->add_do_property(Globals::get_singleton(),name,path);
+		undo_redo->add_do_method(Globals::get_singleton(),"set_persisting",name,is_persisting);
+		undo_redo->add_do_method(Globals::get_singleton(),"set_order",name,order);
+		undo_redo->add_do_method(Globals::get_singleton(),"clear",selected_autoload);
+		undo_redo->add_undo_property(Globals::get_singleton(),selected_autoload,path);
+		undo_redo->add_undo_method(Globals::get_singleton(),"set_persisting",selected_autoload,is_persisting);
+		undo_redo->add_undo_method(Globals::get_singleton(),"set_order",selected_autoload,order);
+		undo_redo->add_undo_method(Globals::get_singleton(),"clear",name);
+		undo_redo->add_do_method(this,"_update_autoload");
+		undo_redo->add_undo_method(this,"_update_autoload");
+		undo_redo->add_do_method(this,"_settings_changed");
+		undo_redo->add_undo_method(this,"_settings_changed");
+		undo_redo->commit_action();
+
+		selected_autoload = name;
+	} else if (column == 2) {
+		updating_autoload = true;
 
 
+		bool checked = ti->is_checked(2);
+		String base = "autoload/"+ti->get_text(0);
+		String path = Globals::get_singleton()->get(base);
+		int order = Globals::get_singleton()->get_order(base);
+
+		if (path.begins_with("*"))
+			path = path.substr(1,path.length());
+
+		if (checked)
+			path = "*" + path;
+
+		undo_redo->create_action(TTR("Toggle AutoLoad Globals"));
+		undo_redo->add_do_property(Globals::get_singleton(),base,path);
+		undo_redo->add_undo_property(Globals::get_singleton(),base,Globals::get_singleton()->get(base));
+		undo_redo->add_do_method(Globals::get_singleton(),"set_order",base,order); // keep order, as config order matters for these
+		undo_redo->add_undo_method(Globals::get_singleton(),"set_order",base,order);
+		undo_redo->add_do_method(this,"_update_autoload");
+		undo_redo->add_undo_method(this,"_update_autoload");
+		undo_redo->add_do_method(this,"_settings_changed");
+		undo_redo->add_undo_method(this,"_settings_changed");
+		undo_redo->commit_action();
+	}
+
+	updating_autoload = false;
 }
 }
 
 
 void ProjectSettings::_autoload_add() {
 void ProjectSettings::_autoload_add() {
@@ -990,6 +1059,14 @@ void ProjectSettings::_autoload_delete(Object *p_item,int p_column, int p_button
 
 
 }
 }
 
 
+void ProjectSettings::_autoload_selected() {
+	TreeItem *ti = autoload_list->get_selected();
+
+	if (!ti)
+		return;
+
+	selected_autoload = "autoload/"+ti->get_text(0);
+}
 
 
 void ProjectSettings::_translation_delete(Object *p_item,int p_column, int p_button) {
 void ProjectSettings::_translation_delete(Object *p_item,int p_column, int p_button) {
 
 
@@ -1348,6 +1425,7 @@ void ProjectSettings::_update_autoload() {
 		}
 		}
 		TreeItem *t = autoload_list->create_item(root);
 		TreeItem *t = autoload_list->create_item(root);
 		t->set_text(0,name);
 		t->set_text(0,name);
+		t->set_editable(0,true);
 		t->set_text(1,path);
 		t->set_text(1,path);
 		t->set_cell_mode(2,TreeItem::CELL_MODE_CHECK);
 		t->set_cell_mode(2,TreeItem::CELL_MODE_CHECK);
 		t->set_editable(2,true);
 		t->set_editable(2,true);
@@ -1436,6 +1514,7 @@ void ProjectSettings::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("_update_autoload"),&ProjectSettings::_update_autoload);
 	ObjectTypeDB::bind_method(_MD("_update_autoload"),&ProjectSettings::_update_autoload);
 	ObjectTypeDB::bind_method(_MD("_autoload_delete"),&ProjectSettings::_autoload_delete);
 	ObjectTypeDB::bind_method(_MD("_autoload_delete"),&ProjectSettings::_autoload_delete);
 	ObjectTypeDB::bind_method(_MD("_autoload_edited"),&ProjectSettings::_autoload_edited);
 	ObjectTypeDB::bind_method(_MD("_autoload_edited"),&ProjectSettings::_autoload_edited);
+	ObjectTypeDB::bind_method(_MD("_autoload_selected"),&ProjectSettings::_autoload_selected);
 
 
 	ObjectTypeDB::bind_method(_MD("_clear_search_box"),&ProjectSettings::_clear_search_box);
 	ObjectTypeDB::bind_method(_MD("_clear_search_box"),&ProjectSettings::_clear_search_box);
 	ObjectTypeDB::bind_method(_MD("_toggle_search_bar"),&ProjectSettings::_toggle_search_bar);
 	ObjectTypeDB::bind_method(_MD("_toggle_search_bar"),&ProjectSettings::_toggle_search_bar);
@@ -1838,6 +1917,7 @@ ProjectSettings::ProjectSettings(EditorData *p_data) {
 
 
 		autoload_list->connect("button_pressed",this,"_autoload_delete");
 		autoload_list->connect("button_pressed",this,"_autoload_delete");
 		autoload_list->connect("item_edited",this,"_autoload_edited");
 		autoload_list->connect("item_edited",this,"_autoload_edited");
+		autoload_list->connect("cell_selected", this, "_autoload_selected");
 
 
 		updating_autoload=false;
 		updating_autoload=false;
 
 

+ 2 - 0
tools/editor/project_settings.h

@@ -91,6 +91,7 @@ class ProjectSettings : public AcceptDialog {
 
 
 
 
 	Tree *autoload_list;
 	Tree *autoload_list;
+	String selected_autoload;
 	EditorFileDialog *autoload_file_open;
 	EditorFileDialog *autoload_file_open;
 	LineEdit *autoload_add_name;
 	LineEdit *autoload_add_name;
 	LineEdit *autoload_add_path;
 	LineEdit *autoload_add_path;
@@ -104,6 +105,7 @@ class ProjectSettings : public AcceptDialog {
 	void _autoload_edited();
 	void _autoload_edited();
 	void _autoload_file_open();
 	void _autoload_file_open();
 	void _autoload_delete(Object *p_item,int p_column, int p_button);
 	void _autoload_delete(Object *p_item,int p_column, int p_button);
+	void _autoload_selected();
 	bool updating_autoload;
 	bool updating_autoload;