Browse Source

-Added google play services (needed for some stuff)
-Added new screen resizing options, stretch_2d is removed, new much more flexible ones.
-Fixed bug in viewport (can create more instances in 3d-in-2d demo now)
-Can set android permissions and screen sizes manually in the export settings
-Changed export templates extension to .tpz (too many people unzipped the manually..)
-File dialog now ensures that the proper extension is used (will not allow to save without it)
-Fixed bug that made collision exceptions not work in 2D

Juan Linietsky 11 years ago
parent
commit
ec4ef2d2e7

+ 43 - 0
core/bind/core_bind.cpp

@@ -4,6 +4,7 @@
 #include "io/marshalls.h"
 #include "io/marshalls.h"
 #include "io/base64.h"
 #include "io/base64.h"
 #include "core/globals.h"
 #include "core/globals.h"
+#include "io/file_access_encrypted.h"
 
 
 _ResourceLoader *_ResourceLoader::singleton=NULL;
 _ResourceLoader *_ResourceLoader::singleton=NULL;
 
 
@@ -812,6 +813,44 @@ _Geometry::_Geometry() {
 ///////////////////////// FILE
 ///////////////////////// FILE
 
 
 
 
+
+Error _File::open_encrypted(const String& p_path, int p_mode_flags,const Vector<uint8_t>& p_key) {
+
+	Error err = open(p_path,p_mode_flags);
+	if (err)
+		return err;
+
+	FileAccessEncrypted *fae = memnew( FileAccessEncrypted );
+	err = fae->open_and_parse(f,p_key,(p_mode_flags==WRITE)?FileAccessEncrypted::MODE_WRITE_AES256:FileAccessEncrypted::MODE_READ);
+	if (err) {
+		memdelete(fae);
+		close();
+		return err;
+	}
+	f=fae;
+	return OK;
+}
+
+Error _File::open_encrypted_pass(const String& p_path, int p_mode_flags,const String& p_pass) {
+
+	Error err = open(p_path,p_mode_flags);
+	if (err)
+		return err;
+
+	FileAccessEncrypted *fae = memnew( FileAccessEncrypted );
+	err = fae->open_and_parse_password(f,p_pass,(p_mode_flags==WRITE)?FileAccessEncrypted::MODE_WRITE_AES256:FileAccessEncrypted::MODE_READ);
+	if (err) {
+		memdelete(fae);
+		close();
+		return err;
+	}
+
+	f=fae;
+	return OK;
+
+}
+
+
 Error _File::open(const String& p_path, int p_mode_flags) {
 Error _File::open(const String& p_path, int p_mode_flags) {
 
 
 	close();
 	close();
@@ -1113,6 +1152,10 @@ Variant _File::get_var() const {
 
 
 void _File::_bind_methods() {
 void _File::_bind_methods() {
 
 
+
+	ObjectTypeDB::bind_method(_MD("open_encrypted","path","mode_flags","key"),&_File::open_encrypted);
+	ObjectTypeDB::bind_method(_MD("open_encrypted_with_pass","path","mode_flags","pass"),&_File::open_encrypted_pass);
+
 	ObjectTypeDB::bind_method(_MD("open","path","flags"),&_File::open);
 	ObjectTypeDB::bind_method(_MD("open","path","flags"),&_File::open);
 	ObjectTypeDB::bind_method(_MD("close"),&_File::close);
 	ObjectTypeDB::bind_method(_MD("close"),&_File::close);
 	ObjectTypeDB::bind_method(_MD("is_open"),&_File::is_open);
 	ObjectTypeDB::bind_method(_MD("is_open"),&_File::is_open);

+ 4 - 0
core/bind/core_bind.h

@@ -243,6 +243,10 @@ public:
 		READ_WRITE=3,
 		READ_WRITE=3,
 	};
 	};
 
 
+	Error open_encrypted(const String& p_path, int p_mode_flags,const Vector<uint8_t>& p_key);
+	Error open_encrypted_pass(const String& p_path, int p_mode_flags,const String& p_pass);
+
+
 	Error open(const String& p_path, int p_mode_flags); ///< open a file
 	Error open(const String& p_path, int p_mode_flags); ///< open a file
 	void close(); ///< close a file
 	void close(); ///< close a file
 	bool is_open() const; ///< true when file is open
 	bool is_open() const; ///< true when file is open

+ 2 - 0
demos/2d/platformer/engine.cfg

@@ -10,6 +10,8 @@ name_es="Plataformero"
 width=800
 width=800
 height=480
 height=480
 stretch_2d=true
 stretch_2d=true
+stretch_mode="viewport"
+stretch_aspect="keep"
 
 
 [input]
 [input]
 
 

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


+ 6 - 0
drivers/gles1/rasterizer_gles1.cpp

@@ -4602,6 +4602,12 @@ void RasterizerGLES1::canvas_begin() {
 
 
 
 
 }
 }
+
+void RasterizerGLES1::canvas_disable_blending() {
+
+	glDisable(GL_BLEND);
+}
+
 void RasterizerGLES1::canvas_set_opacity(float p_opacity) {
 void RasterizerGLES1::canvas_set_opacity(float p_opacity) {
 
 
 	canvas_opacity = p_opacity;
 	canvas_opacity = p_opacity;

+ 1 - 0
drivers/gles1/rasterizer_gles1.h

@@ -1126,6 +1126,7 @@ public:
 	/* CANVAS API */
 	/* CANVAS API */
 
 
 	virtual void canvas_begin();
 	virtual void canvas_begin();
+	virtual void canvas_disable_blending();
 	virtual void canvas_set_opacity(float p_opacity);
 	virtual void canvas_set_opacity(float p_opacity);
 	virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode);
 	virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode);
 	virtual void canvas_begin_rect(const Matrix32& p_transform);
 	virtual void canvas_begin_rect(const Matrix32& p_transform);

+ 6 - 0
drivers/gles2/rasterizer_gles2.cpp

@@ -6302,6 +6302,12 @@ void RasterizerGLES2::canvas_begin() {
 
 
 
 
 }
 }
+
+void RasterizerGLES2::canvas_disable_blending() {
+
+	glDisable(GL_BLEND);
+}
+
 void RasterizerGLES2::canvas_set_opacity(float p_opacity) {
 void RasterizerGLES2::canvas_set_opacity(float p_opacity) {
 
 
 	canvas_opacity = p_opacity;
 	canvas_opacity = p_opacity;

+ 2 - 0
drivers/gles2/rasterizer_gles2.h

@@ -1373,6 +1373,8 @@ public:
 	/* CANVAS API */
 	/* CANVAS API */
 
 
 	virtual void canvas_begin();
 	virtual void canvas_begin();
+	virtual void canvas_disable_blending();
+
 	virtual void canvas_set_opacity(float p_opacity);
 	virtual void canvas_set_opacity(float p_opacity);
 	virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode);
 	virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode);
 	virtual void canvas_begin_rect(const Matrix32& p_transform);
 	virtual void canvas_begin_rect(const Matrix32& p_transform);

+ 77 - 91
drivers/openssl/stream_peer_ssl.cpp

@@ -1,111 +1,97 @@
 #include "stream_peer_ssl.h"
 #include "stream_peer_ssl.h"
 
 
 
 
-int StreamPeerSSL::bio_create( BIO *b ) {
-	b->init = 1;
-	b->num = 0;
-	b->ptr = NULL;
-	b->flags = 0;
-	return 1;
-}
-
-int StreamPeerSSL::bio_destroy( BIO *b ) {
-
-	if ( b == NULL ) return 0;
-	b->ptr = NULL;		/* sb_tls_remove() will free it */
-	b->init = 0;
-	b->flags = 0;
-	return 1;
-}
-
-int StreamPeerSSL::bio_read( BIO *b, char *buf, int len ) {
-
-	if ( buf == NULL || len <= 0 ) return 0;
-
-	StreamPeerSSL * sp = (StreamPeerSSL*)b->ptr;
+Error StreamPeerSSL::connect(const String &p_host,int p_port,int p_flags) {
 
 
-	if (sp->base.is_null())
-		return 0;
-
-
-
-	BIO_clear_retry_flags( b );
-
-	Error err;
-	int ret=0;
-	if (sp->block) {
-		err = sp->base->get_data((const uint8_t*)buf,len);
-		if (err==OK)
-			ret=len;
-	} else {
-
-		err = sp->base->get_partial_data((const uint8_t*)buf,len,ret);
-		if (err==OK && ret!=len) {
-			BIO_set_retry_write( b );
-		}
+	// Set up a SSL_CTX object, which will tell our BIO object how to do its work
+	ctx = SSL_CTX_new(SSLv23_client_method());
+	// Create our BIO object for SSL connections.
+	BIO* bio = BIO_new_ssl_connect(ctx);
+	// Failure?
+	if (bio == NULL) {
 
 
+		// We need to free up the SSL_CTX before we leave.
+		ERR_FAIL_COND_V(bio==NULL,ERR_CANT_CREATE);
+	}
+	// Makes ssl point to bio's SSL object.
+	BIO_get_ssl(bio, &ssl);
+	// Set the SSL to automatically retry on failure.
+	SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
+	// We're connection to google.com on port 443.
+	BIO_set_conn_hostname(bio, (p_host+":"+itos(p_port)).utf8().get_data());
+
+	// Same as before, try to connect.
+	if (BIO_do_connect(bio) <= 0) {
+
+		ERR_EXPLAIN("Failed to connect to '"+p_host+"'' port "+itos(p_port));
+		BIO_free_all(bio);
+		SSL_CTX_free(ctx);
+		ERR_FAIL_V(ERR_CANT_CONNECT);
 	}
 	}
 
 
-	return ret;
-}
-
-int StreamPeerSSL::bio_write( BIO *b, const char *buf, int len ) {
-
-	if ( buf == NULL || len <= 0 ) return 0;
-
-	StreamPeerSSL * sp = (StreamPeerSSL*)b->ptr;
-
-	if (sp->base.is_null())
-		return 0;
-
-	BIO_clear_retry_flags( b );
+	// Now we need to do the SSL handshake, so we can communicate.
+	if (BIO_do_handshake(bio) <= 0) {
+		ERR_EXPLAIN("Failed to handshake to '"+p_host+"'' port "+itos(p_port));
+		BIO_free_all(bio);
+		SSL_CTX_free(ctx);
+		ERR_FAIL_V(ERR_CANT_CONNECT);
+	}
 
 
-	Error err;
-	int wrote=0;
-	if (sp->block) {
-		err = sp->base->put_data((const uint8_t*)buf,len);
-		if (err==OK)
-			wrote=len;
-	} else {
 
 
-		err = sp->base->put_partial_data((const uint8_t*)buf,len,wrote);
-		if (err==OK && wrote!=len) {
-			BIO_set_retry_write( b );
+	// Create a buffer for grabbing information from the page.
+	char buf[1024];
+	memset(buf, 0, sizeof(buf));
+	// Create a buffer for the reqest we'll send to the server
+	char send[1024];
+	memset(send, 0, sizeof(send));
+	// Create our GET request.
+	strcat(send, "GET / HTTP/1.1\nHost:google.com\nUser Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)\nConnection: Close\n\n");
+	// BIO_puts sends a null-terminated string to the server. In this case it's our GET request.
+	BIO_puts(bio, send);
+	// Loop while there's information to be read.
+	while (1) {
+		// BIO_read() reads data from the server into a buffer. It returns the number of characters read in.
+		int x = BIO_read(bio, buf, sizeof(buf) - 1);
+		// If we haven't read in anything, assume there's nothing more to be sent since we used Connection: Close.
+		if (x == 0) {
+			break;
+		}
+		// If BIO_read() returns a negative number, there was an error
+		else if (x < 0) {
+			// BIO_should_retry lets us know if we should keep trying to read data or not.
+			if (!BIO_should_retry(bio)) {
+				printf("\nRead Failed!\n");
+				BIO_free_all(bio);
+				SSL_CTX_free(ctx);
+				return;
+			}
+		}
+		// We actually got some data, without errors!
+		else {
+			// Null-terminate our buffer, just in case
+			buf[x] = 0;
+			// Echo what the server sent to the screen
+			printf("%s", buf);
 		}
 		}
-
 	}
 	}
+	// Free up that BIO object we created.
+	BIO_free_all(bio);
+	// Remember, we also need to free up that SSL_CTX object!
+	SSL_CTX_free(ctx);
+	// Return.
 
 
-	return wrote;
 }
 }
 
 
-long StreamPeerSSL::bio_ctrl( BIO *b, int cmd, long num, void *ptr ) {
-	if ( cmd == BIO_CTRL_FLUSH ) {
-		/* The OpenSSL library needs this */
-		return 1;
-	}
-	return 0;
-}
+void StreamPeerSSL::initialize_ssl() {
 
 
-int StreamPeerSSL::bio_gets( BIO *b, char *buf, int len ) {
-	return -1;
+	CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use
+	SSL_library_init(); // Initialize OpenSSL's SSL libraries
+	SSL_load_error_strings(); // Load SSL error strings
+	ERR_load_BIO_strings(); // Load BIO error strings
+	OpenSSL_add_all_algorithms(); // Load all available encryption algorithms
 }
 }
 
 
-int StreamPeerSSL::bio_puts( BIO *b, const char *str ) {
-	return StreamPeerSSL::bio_write( b, str, strlen( str ) );
-}
+void StreamPeerSSL::finalize_ssl(){
 
 
-BIO_METHOD StreamPeerSSL::bio_methods =
-{
-	( 100 | 0x400 ),		/* it's a source/sink BIO */
-	"sockbuf glue",
-	StreamPeerSSL::bio_write,
-	StreamPeerSSL::bio_read,
-	StreamPeerSSL::bio_puts,
-	StreamPeerSSL::bio_gets,
-	StreamPeerSSL::bio_ctrl,
-	StreamPeerSSL::bio_create,
-	StreamPeerSSL::bio_destroy
-};
 
 
-StreamPeerSSL::StreamPeerSSL() {
 }
 }

+ 27 - 10
drivers/openssl/stream_peer_ssl.h

@@ -1,26 +1,43 @@
 #ifndef STREAM_PEER_SSL_H
 #ifndef STREAM_PEER_SSL_H
 #define STREAM_PEER_SSL_H
 #define STREAM_PEER_SSL_H
 
 
+#ifdef OPENSSL_ENABLED
+
 #include "io/stream_peer.h"
 #include "io/stream_peer.h"
+#include <openssl/applink.c> // To prevent crashing (see the OpenSSL FAQ)
+#include <openssl/bio.h> // BIO objects for I/O
+#include <openssl/ssl.h> // SSL and SSL_CTX for SSL connections
+#include <openssl/err.h> // Error reporting
 
 
+#include <stdio.h> // If you don't know what this is for stop reading now.
 class StreamPeerSSL : public StreamPeer {
 class StreamPeerSSL : public StreamPeer {
 
 
 	OBJ_TYPE(StreamPeerSSL,StreamPeer);
 	OBJ_TYPE(StreamPeerSSL,StreamPeer);
+public:
+
+	enum ConnectFlags {
+
+		CONNECT_FLAG_BUG_WORKAROUNDS=1,
+		CONNECT_FLAG_NO_SSLV2=2,
+		CONNECT_FLAG_NO_SSLV3=4,
+		CONNECT_FLAG_NO_TLSV1=8,
+		CONNECT_FLAG_NO_COMPRESSION=16,
+	};
 
 
-	Ref<StreamPeer> base;
-	bool block;
-	static BIO_METHOD bio_methods;
+	SSL_CTX* ctx;
+	SSL* ssl;
+	BIO* bio;
 
 
-	static int bio_create( BIO *b );
-	static int bio_destroy( BIO *b );
-	static int bio_read( BIO *b, char *buf, int len );
-	static int bio_write( BIO *b, const char *buf, int len );
-	static long bio_ctrl( BIO *b, int cmd, long num, void *ptr );
-	static int bio_gets( BIO *b, char *buf, int len );
-	static int bio_puts( BIO *b, const char *str );
 
 
 public:
 public:
+
+
+	Error connect(const String &p_host,int p_port);
+	static void initialize_ssl();
+	static void finalize_ssl();
+
 	StreamPeerSSL();
 	StreamPeerSSL();
 };
 };
 
 
+#endif
 #endif // STREAM_PEER_SSL_H
 #endif // STREAM_PEER_SSL_H

+ 23 - 6
main/main.cpp

@@ -1008,11 +1008,25 @@ bool Main::start() {
 		if (!editor) {
 		if (!editor) {
 			//standard helpers that can be changed from main config
 			//standard helpers that can be changed from main config
 
 
-			if (GLOBAL_DEF("display/stretch_2d",false).operator bool()) {
-
-				sml->get_root()->set_size_override(true,Size2(Globals::get_singleton()->get("display/width"),Globals::get_singleton()->get("display/height")));
-				sml->get_root()->set_size_override_stretch(true);
-			}
+			String stretch_mode = GLOBAL_DEF("display/stretch_mode","disabled");
+			String stretch_aspect = GLOBAL_DEF("display/stretch_aspect","ignore");
+			Size2i stretch_size = Size2(GLOBAL_DEF("display/width",0),GLOBAL_DEF("display/height",0));
+
+			SceneMainLoop::StretchMode sml_sm=SceneMainLoop::STRETCH_MODE_DISABLED;
+			if (stretch_mode=="2d")
+				sml_sm=SceneMainLoop::STRETCH_MODE_2D;
+			else if (stretch_mode=="viewport")
+				sml_sm=SceneMainLoop::STRETCH_MODE_VIEWPORT;
+
+			SceneMainLoop::StretchAspect sml_aspect=SceneMainLoop::STRETCH_ASPECT_IGNORE;
+			if (stretch_aspect=="keep")
+				sml_aspect=SceneMainLoop::STRETCH_ASPECT_KEEP;
+			else if (stretch_aspect=="keep_width")
+				sml_aspect=SceneMainLoop::STRETCH_ASPECT_KEEP_WIDTH;
+			else if (stretch_aspect=="keep_height")
+				sml_aspect=SceneMainLoop::STRETCH_ASPECT_KEEP_HEIGHT;
+
+			sml->set_screen_stretch(sml_sm,sml_aspect,stretch_size);
 
 
 			sml->set_auto_accept_quit(GLOBAL_DEF("application/auto_accept_quit",true));
 			sml->set_auto_accept_quit(GLOBAL_DEF("application/auto_accept_quit",true));
 			String appname = Globals::get_singleton()->get("application/name");
 			String appname = Globals::get_singleton()->get("application/name");
@@ -1021,7 +1035,10 @@ bool Main::start() {
 
 
 
 
 		} else {
 		} else {
-			GLOBAL_DEF("display/stretch_2d",false);
+			GLOBAL_DEF("display/stretch_mode","disabled");
+			Globals::get_singleton()->set_custom_property_info("display/stretch_mode",PropertyInfo(Variant::STRING,"display/stretch_mode",PROPERTY_HINT_ENUM,"disabled,2d,viewport"));
+			GLOBAL_DEF("display/stretch_aspect","ignore");
+			Globals::get_singleton()->set_custom_property_info("display/stretch_aspect",PropertyInfo(Variant::STRING,"display/stretch_aspect",PROPERTY_HINT_ENUM,"ignore,keep,keep_width,keep_height"));
 			sml->set_auto_accept_quit(GLOBAL_DEF("application/auto_accept_quit",true));
 			sml->set_auto_accept_quit(GLOBAL_DEF("application/auto_accept_quit",true));
 
 
 
 

+ 172 - 9
platform/android/AndroidManifest.xml.template

@@ -5,6 +5,11 @@
       android:versionName="1.0"
       android:versionName="1.0"
       android:installLocation="preferExternal"
       android:installLocation="preferExternal"
       >
       >
+<supports-screens android:smallScreens="true"
+                      android:normalScreens="true"
+                      android:largeScreens="true"
+                      android:xlargeScreens="true"/>
+
     <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon">
     <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon">
         <activity android:name="com.android.godot.Godot"
         <activity android:name="com.android.godot.Godot"
                   android:label="@string/godot_project_name_string"
                   android:label="@string/godot_project_name_string"
@@ -26,15 +31,173 @@ $$ADD_APPLICATION_CHUNKS$$
 
 
     </application>
     </application>
     <uses-feature android:glEsVersion="0x00020000"/>
     <uses-feature android:glEsVersion="0x00020000"/>
-    <uses-permission android:name="android.permission.INTERNET"></uses-permission>    
-	<uses-permission android:name="android.permission.READ_CONTACTS"/>
-	<uses-permission android:name="com.android.vending.BILLING" />
-	<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
-	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
-	<uses-permission android:name="android.permission.RECEIVE_SMS"/>
-	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 
 
-	
-    <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="15"/>
+<uses-permission android:name="godot.ACCESS_CHECKIN_PROPERTIES"/>
+<uses-permission android:name="godot.ACCESS_COARSE_LOCATION"/>
+<uses-permission android:name="godot.ACCESS_FINE_LOCATION"/>
+<uses-permission android:name="godot.ACCESS_LOCATION_EXTRA_COMMANDS"/>
+<uses-permission android:name="godot.ACCESS_MOCK_LOCATION"/>
+<uses-permission android:name="godot.ACCESS_NETWORK_STATE"/>
+<uses-permission android:name="godot.ACCESS_SURFACE_FLINGER"/>
+<uses-permission android:name="godot.ACCESS_WIFI_STATE"/>
+<uses-permission android:name="godot.ACCOUNT_MANAGER"/>
+<uses-permission android:name="godot.ADD_VOICEMAIL"/>
+<uses-permission android:name="godot.AUTHENTICATE_ACCOUNTS"/>
+<uses-permission android:name="godot.BATTERY_STATS"/>
+<uses-permission android:name="godot.BIND_ACCESSIBILITY_SERVICE"/>
+<uses-permission android:name="godot.BIND_APPWIDGET"/>
+<uses-permission android:name="godot.BIND_DEVICE_ADMIN"/>
+<uses-permission android:name="godot.BIND_INPUT_METHOD"/>
+<uses-permission android:name="godot.BIND_NFC_SERVICE"/>
+<uses-permission android:name="godot.BIND_NOTIFICATION_LISTENER_SERVICE"/>
+<uses-permission android:name="godot.BIND_PRINT_SERVICE"/>
+<uses-permission android:name="godot.BIND_REMOTEVIEWS"/>
+<uses-permission android:name="godot.BIND_TEXT_SERVICE"/>
+<uses-permission android:name="godot.BIND_VPN_SERVICE"/>
+<uses-permission android:name="godot.BIND_WALLPAPER"/>
+<uses-permission android:name="godot.BLUETOOTH"/>
+<uses-permission android:name="godot.BLUETOOTH_ADMIN"/>
+<uses-permission android:name="godot.BLUETOOTH_PRIVILEGED"/>
+<uses-permission android:name="godot.BRICK"/>
+<uses-permission android:name="godot.BROADCAST_PACKAGE_REMOVED"/>
+<uses-permission android:name="godot.BROADCAST_SMS"/>
+<uses-permission android:name="godot.BROADCAST_STICKY"/>
+<uses-permission android:name="godot.BROADCAST_WAP_PUSH"/>
+<uses-permission android:name="godot.CALL_PHONE"/>
+<uses-permission android:name="godot.CALL_PRIVILEGED"/>
+<uses-permission android:name="godot.CAMERA"/>
+<uses-permission android:name="godot.CAPTURE_AUDIO_OUTPUT"/>
+<uses-permission android:name="godot.CAPTURE_SECURE_VIDEO_OUTPUT"/>
+<uses-permission android:name="godot.CAPTURE_VIDEO_OUTPUT"/>
+<uses-permission android:name="godot.CHANGE_COMPONENT_ENABLED_STATE"/>
+<uses-permission android:name="godot.CHANGE_CONFIGURATION"/>
+<uses-permission android:name="godot.CHANGE_NETWORK_STATE"/>
+<uses-permission android:name="godot.CHANGE_WIFI_MULTICAST_STATE"/>
+<uses-permission android:name="godot.CHANGE_WIFI_STATE"/>
+<uses-permission android:name="godot.CLEAR_APP_CACHE"/>
+<uses-permission android:name="godot.CLEAR_APP_USER_DATA"/>
+<uses-permission android:name="godot.CONTROL_LOCATION_UPDATES"/>
+<uses-permission android:name="godot.DELETE_CACHE_FILES"/>
+<uses-permission android:name="godot.DELETE_PACKAGES"/>
+<uses-permission android:name="godot.DEVICE_POWER"/>
+<uses-permission android:name="godot.DIAGNOSTIC"/>
+<uses-permission android:name="godot.DISABLE_KEYGUARD"/>
+<uses-permission android:name="godot.DUMP"/>
+<uses-permission android:name="godot.EXPAND_STATUS_BAR"/>
+<uses-permission android:name="godot.FACTORY_TEST"/>
+<uses-permission android:name="godot.FLASHLIGHT"/>
+<uses-permission android:name="godot.FORCE_BACK"/>
+<uses-permission android:name="godot.GET_ACCOUNTS"/>
+<uses-permission android:name="godot.GET_PACKAGE_SIZE"/>
+<uses-permission android:name="godot.GET_TASKS"/>
+<uses-permission android:name="godot.GET_TOP_ACTIVITY_INFO"/>
+<uses-permission android:name="godot.GLOBAL_SEARCH"/>
+<uses-permission android:name="godot.HARDWARE_TEST"/>
+<uses-permission android:name="godot.INJECT_EVENTS"/>
+<uses-permission android:name="godot.INSTALL_LOCATION_PROVIDER"/>
+<uses-permission android:name="godot.INSTALL_PACKAGES"/>
+<uses-permission android:name="godot.INSTALL_SHORTCUT"/>
+<uses-permission android:name="godot.INTERNAL_SYSTEM_WINDOW"/>
+<uses-permission android:name="godot.INTERNET"/>
+<uses-permission android:name="godot.KILL_BACKGROUND_PROCESSES"/>
+<uses-permission android:name="godot.LOCATION_HARDWARE"/>
+<uses-permission android:name="godot.MANAGE_ACCOUNTS"/>
+<uses-permission android:name="godot.MANAGE_APP_TOKENS"/>
+<uses-permission android:name="godot.MANAGE_DOCUMENTS"/>
+<uses-permission android:name="godot.MASTER_CLEAR"/>
+<uses-permission android:name="godot.MEDIA_CONTENT_CONTROL"/>
+<uses-permission android:name="godot.MODIFY_AUDIO_SETTINGS"/>
+<uses-permission android:name="godot.MODIFY_PHONE_STATE"/>
+<uses-permission android:name="godot.MOUNT_FORMAT_FILESYSTEMS"/>
+<uses-permission android:name="godot.MOUNT_UNMOUNT_FILESYSTEMS"/>
+<uses-permission android:name="godot.NFC"/>
+<uses-permission android:name="godot.PERSISTENT_ACTIVITY"/>
+<uses-permission android:name="godot.PROCESS_OUTGOING_CALLS"/>
+<uses-permission android:name="godot.READ_CALENDAR"/>
+<uses-permission android:name="godot.READ_CALL_LOG"/>
+<uses-permission android:name="godot.READ_CONTACTS"/>
+<uses-permission android:name="godot.READ_EXTERNAL_STORAGE"/>
+<uses-permission android:name="godot.READ_FRAME_BUFFER"/>
+<uses-permission android:name="godot.READ_HISTORY_BOOKMARKS"/>
+<uses-permission android:name="godot.READ_INPUT_STATE"/>
+<uses-permission android:name="godot.READ_LOGS"/>
+<uses-permission android:name="godot.READ_PHONE_STATE"/>
+<uses-permission android:name="godot.READ_PROFILE"/>
+<uses-permission android:name="godot.READ_SMS"/>
+<uses-permission android:name="godot.READ_SOCIAL_STREAM"/>
+<uses-permission android:name="godot.READ_SYNC_SETTINGS"/>
+<uses-permission android:name="godot.READ_SYNC_STATS"/>
+<uses-permission android:name="godot.READ_USER_DICTIONARY"/>
+<uses-permission android:name="godot.REBOOT"/>
+<uses-permission android:name="godot.RECEIVE_BOOT_COMPLETED"/>
+<uses-permission android:name="godot.RECEIVE_MMS"/>
+<uses-permission android:name="godot.RECEIVE_SMS"/>
+<uses-permission android:name="godot.RECEIVE_WAP_PUSH"/>
+<uses-permission android:name="godot.RECORD_AUDIO"/>
+<uses-permission android:name="godot.REORDER_TASKS"/>
+<uses-permission android:name="godot.RESTART_PACKAGES"/>
+<uses-permission android:name="godot.SEND_RESPOND_VIA_MESSAGE"/>
+<uses-permission android:name="godot.SEND_SMS"/>
+<uses-permission android:name="godot.SET_ACTIVITY_WATCHER"/>
+<uses-permission android:name="godot.SET_ALARM"/>
+<uses-permission android:name="godot.SET_ALWAYS_FINISH"/>
+<uses-permission android:name="godot.SET_ANIMATION_SCALE"/>
+<uses-permission android:name="godot.SET_DEBUG_APP"/>
+<uses-permission android:name="godot.SET_ORIENTATION"/>
+<uses-permission android:name="godot.SET_POINTER_SPEED"/>
+<uses-permission android:name="godot.SET_PREFERRED_APPLICATIONS"/>
+<uses-permission android:name="godot.SET_PROCESS_LIMIT"/>
+<uses-permission android:name="godot.SET_TIME"/>
+<uses-permission android:name="godot.SET_TIME_ZONE"/>
+<uses-permission android:name="godot.SET_WALLPAPER"/>
+<uses-permission android:name="godot.SET_WALLPAPER_HINTS"/>
+<uses-permission android:name="godot.SIGNAL_PERSISTENT_PROCESSES"/>
+<uses-permission android:name="godot.STATUS_BAR"/>
+<uses-permission android:name="godot.SUBSCRIBED_FEEDS_READ"/>
+<uses-permission android:name="godot.SUBSCRIBED_FEEDS_WRITE"/>
+<uses-permission android:name="godot.SYSTEM_ALERT_WINDOW"/>
+<uses-permission android:name="godot.TRANSMIT_IR"/>
+<uses-permission android:name="godot.UNINSTALL_SHORTCUT"/>
+<uses-permission android:name="godot.UPDATE_DEVICE_STATS"/>
+<uses-permission android:name="godot.USE_CREDENTIALS"/>
+<uses-permission android:name="godot.USE_SIP"/>
+<uses-permission android:name="godot.VIBRATE"/>
+<uses-permission android:name="godot.WAKE_LOCK"/>
+<uses-permission android:name="godot.WRITE_APN_SETTINGS"/>
+<uses-permission android:name="godot.WRITE_CALENDAR"/>
+<uses-permission android:name="godot.WRITE_CALL_LOG"/>
+<uses-permission android:name="godot.WRITE_CONTACTS"/>
+<uses-permission android:name="godot.WRITE_EXTERNAL_STORAGE"/>
+<uses-permission android:name="godot.WRITE_GSERVICES"/>
+<uses-permission android:name="godot.WRITE_HISTORY_BOOKMARKS"/>
+<uses-permission android:name="godot.WRITE_PROFILE"/>
+<uses-permission android:name="godot.WRITE_SECURE_SETTINGS"/>
+<uses-permission android:name="godot.WRITE_SETTINGS"/>
+<uses-permission android:name="godot.WRITE_SMS"/>
+<uses-permission android:name="godot.WRITE_SOCIAL_STREAM"/>
+<uses-permission android:name="godot.WRITE_SYNC_SETTINGS"/>
+<uses-permission android:name="godot.WRITE_USER_DICTIONARY"/>
+<uses-permission android:name="godot.custom.0"/>
+<uses-permission android:name="godot.custom.1"/>
+<uses-permission android:name="godot.custom.2"/>
+<uses-permission android:name="godot.custom.3"/>
+<uses-permission android:name="godot.custom.4"/>
+<uses-permission android:name="godot.custom.5"/>
+<uses-permission android:name="godot.custom.6"/>
+<uses-permission android:name="godot.custom.7"/>
+<uses-permission android:name="godot.custom.8"/>
+<uses-permission android:name="godot.custom.9"/>
+<uses-permission android:name="godot.custom.0"/>
+<uses-permission android:name="godot.custom.11"/>
+<uses-permission android:name="godot.custom.12"/>
+<uses-permission android:name="godot.custom.13"/>
+<uses-permission android:name="godot.custom.14"/>
+<uses-permission android:name="godot.custom.15"/>
+<uses-permission android:name="godot.custom.16"/>
+<uses-permission android:name="godot.custom.17"/>
+<uses-permission android:name="godot.custom.18"/>
+<uses-permission android:name="godot.custom.19"/>
+
+<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="15"/>
          
          
 </manifest> 
 </manifest> 

+ 1 - 0
platform/android/detect.py

@@ -57,6 +57,7 @@ def configure(env):
 		env['SPAWN'] = methods.win32_spawn
 		env['SPAWN'] = methods.win32_spawn
 
 
 	env.android_source_modules.append("../libs/apk_expansion")	
 	env.android_source_modules.append("../libs/apk_expansion")	
+	env.android_source_modules.append("../libs/google_play_services")	
 	ndk_platform=""
 	ndk_platform=""
 
 
 	ndk_platform="android-15"
 	ndk_platform="android-15"

+ 271 - 2
platform/android/export/export.cpp

@@ -10,10 +10,169 @@
 #include "os/os.h"
 #include "os/os.h"
 #include "platform/android/logo.h"
 #include "platform/android/logo.h"
 
 
+
+static const char* android_perms[]={
+"ACCESS_CHECKIN_PROPERTIES",
+"ACCESS_COARSE_LOCATION",
+"ACCESS_FINE_LOCATION",
+"ACCESS_LOCATION_EXTRA_COMMANDS",
+"ACCESS_MOCK_LOCATION",
+"ACCESS_NETWORK_STATE",
+"ACCESS_SURFACE_FLINGER",
+"ACCESS_WIFI_STATE",
+"ACCOUNT_MANAGER",
+"ADD_VOICEMAIL",
+"AUTHENTICATE_ACCOUNTS",
+"BATTERY_STATS",
+"BIND_ACCESSIBILITY_SERVICE",
+"BIND_APPWIDGET",
+"BIND_DEVICE_ADMIN",
+"BIND_INPUT_METHOD",
+"BIND_NFC_SERVICE",
+"BIND_NOTIFICATION_LISTENER_SERVICE",
+"BIND_PRINT_SERVICE",
+"BIND_REMOTEVIEWS",
+"BIND_TEXT_SERVICE",
+"BIND_VPN_SERVICE",
+"BIND_WALLPAPER",
+"BLUETOOTH",
+"BLUETOOTH_ADMIN",
+"BLUETOOTH_PRIVILEGED",
+"BRICK",
+"BROADCAST_PACKAGE_REMOVED",
+"BROADCAST_SMS",
+"BROADCAST_STICKY",
+"BROADCAST_WAP_PUSH",
+"CALL_PHONE",
+"CALL_PRIVILEGED",
+"CAMERA",
+"CAPTURE_AUDIO_OUTPUT",
+"CAPTURE_SECURE_VIDEO_OUTPUT",
+"CAPTURE_VIDEO_OUTPUT",
+"CHANGE_COMPONENT_ENABLED_STATE",
+"CHANGE_CONFIGURATION",
+"CHANGE_NETWORK_STATE",
+"CHANGE_WIFI_MULTICAST_STATE",
+"CHANGE_WIFI_STATE",
+"CLEAR_APP_CACHE",
+"CLEAR_APP_USER_DATA",
+"CONTROL_LOCATION_UPDATES",
+"DELETE_CACHE_FILES",
+"DELETE_PACKAGES",
+"DEVICE_POWER",
+"DIAGNOSTIC",
+"DISABLE_KEYGUARD",
+"DUMP",
+"EXPAND_STATUS_BAR",
+"FACTORY_TEST",
+"FLASHLIGHT",
+"FORCE_BACK",
+"GET_ACCOUNTS",
+"GET_PACKAGE_SIZE",
+"GET_TASKS",
+"GET_TOP_ACTIVITY_INFO",
+"GLOBAL_SEARCH",
+"HARDWARE_TEST",
+"INJECT_EVENTS",
+"INSTALL_LOCATION_PROVIDER",
+"INSTALL_PACKAGES",
+"INSTALL_SHORTCUT",
+"INTERNAL_SYSTEM_WINDOW",
+"INTERNET",
+"KILL_BACKGROUND_PROCESSES",
+"LOCATION_HARDWARE",
+"MANAGE_ACCOUNTS",
+"MANAGE_APP_TOKENS",
+"MANAGE_DOCUMENTS",
+"MASTER_CLEAR",
+"MEDIA_CONTENT_CONTROL",
+"MODIFY_AUDIO_SETTINGS",
+"MODIFY_PHONE_STATE",
+"MOUNT_FORMAT_FILESYSTEMS",
+"MOUNT_UNMOUNT_FILESYSTEMS",
+"NFC",
+"PERSISTENT_ACTIVITY",
+"PROCESS_OUTGOING_CALLS",
+"READ_CALENDAR",
+"READ_CALL_LOG",
+"READ_CONTACTS",
+"READ_EXTERNAL_STORAGE",
+"READ_FRAME_BUFFER",
+"READ_HISTORY_BOOKMARKS",
+"READ_INPUT_STATE",
+"READ_LOGS",
+"READ_PHONE_STATE",
+"READ_PROFILE",
+"READ_SMS",
+"READ_SOCIAL_STREAM",
+"READ_SYNC_SETTINGS",
+"READ_SYNC_STATS",
+"READ_USER_DICTIONARY",
+"REBOOT",
+"RECEIVE_BOOT_COMPLETED",
+"RECEIVE_MMS",
+"RECEIVE_SMS",
+"RECEIVE_WAP_PUSH",
+"RECORD_AUDIO",
+"REORDER_TASKS",
+"RESTART_PACKAGES",
+"SEND_RESPOND_VIA_MESSAGE",
+"SEND_SMS",
+"SET_ACTIVITY_WATCHER",
+"SET_ALARM",
+"SET_ALWAYS_FINISH",
+"SET_ANIMATION_SCALE",
+"SET_DEBUG_APP",
+"SET_ORIENTATION",
+"SET_POINTER_SPEED",
+"SET_PREFERRED_APPLICATIONS",
+"SET_PROCESS_LIMIT",
+"SET_TIME",
+"SET_TIME_ZONE",
+"SET_WALLPAPER",
+"SET_WALLPAPER_HINTS",
+"SIGNAL_PERSISTENT_PROCESSES",
+"STATUS_BAR",
+"SUBSCRIBED_FEEDS_READ",
+"SUBSCRIBED_FEEDS_WRITE",
+"SYSTEM_ALERT_WINDOW",
+"TRANSMIT_IR",
+"UNINSTALL_SHORTCUT",
+"UPDATE_DEVICE_STATS",
+"USE_CREDENTIALS",
+"USE_SIP",
+"VIBRATE",
+"WAKE_LOCK",
+"WRITE_APN_SETTINGS",
+"WRITE_CALENDAR",
+"WRITE_CALL_LOG",
+"WRITE_CONTACTS",
+"WRITE_EXTERNAL_STORAGE",
+"WRITE_GSERVICES",
+"WRITE_HISTORY_BOOKMARKS",
+"WRITE_PROFILE",
+"WRITE_SECURE_SETTINGS",
+"WRITE_SETTINGS",
+"WRITE_SMS",
+"WRITE_SOCIAL_STREAM",
+"WRITE_SYNC_SETTINGS",
+"WRITE_USER_DICTIONARY",
+NULL};
+
 class EditorExportPlatformAndroid : public EditorExportPlatform {
 class EditorExportPlatformAndroid : public EditorExportPlatform {
 
 
 	OBJ_TYPE( EditorExportPlatformAndroid,EditorExportPlatform );
 	OBJ_TYPE( EditorExportPlatformAndroid,EditorExportPlatform );
 
 
+
+	enum {
+		MAX_USER_PERMISSIONS=20,
+		SCREEN_SMALL=0,
+		SCREEN_NORMAL=1,
+		SCREEN_LARGE=2,
+		SCREEN_XLARGE=3,
+		SCREEN_MAX=4
+	};
+
 	String custom_release_package;
 	String custom_release_package;
 	String custom_debug_package;
 	String custom_debug_package;
 
 
@@ -47,6 +206,10 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
 	Thread *device_thread;
 	Thread *device_thread;
 	Ref<ImageTexture> logo;
 	Ref<ImageTexture> logo;
 
 
+	Set<String> perms;
+	String user_perms[MAX_USER_PERMISSIONS];
+	bool screen_support[SCREEN_MAX];
+
 	volatile bool quit_request;
 	volatile bool quit_request;
 
 
 
 
@@ -104,11 +267,33 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant&
 		_signed=p_value;
 		_signed=p_value;
 	else if (n=="screen/orientation")
 	else if (n=="screen/orientation")
 		orientation=p_value;
 		orientation=p_value;
+	else if (n=="screen/support_small")
+		screen_support[SCREEN_SMALL]=p_value;
+	else if (n=="screen/support_normal")
+		screen_support[SCREEN_NORMAL]=p_value;
+	else if (n=="screen/support_large")
+		screen_support[SCREEN_LARGE]=p_value;
+	else if (n=="screen/support_xlarge")
+		screen_support[SCREEN_XLARGE]=p_value;
 	else if (n=="keystore/release")
 	else if (n=="keystore/release")
 		release_keystore=p_value;
 		release_keystore=p_value;
 	else if (n=="keystore/release_user")
 	else if (n=="keystore/release_user")
 		release_username=p_value;
 		release_username=p_value;
-	else
+	else if (n.begins_with("permissions/")) {
+
+		String what = n.get_slice("/",1).to_upper();
+		bool state = p_value;
+		if (state)
+			perms.insert(what);
+		else
+			perms.erase(what);
+	} else if (n.begins_with("user_permissions/")) {
+
+		int which = n.get_slice("/",1).to_int();
+		ERR_FAIL_INDEX_V(which,MAX_USER_PERMISSIONS,false);
+		user_perms[which]=p_value;
+
+	} else
 		return false;
 		return false;
 
 
 	return true;
 	return true;
@@ -132,15 +317,33 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret)
 		r_ret=_signed;
 		r_ret=_signed;
 	else if (n=="screen/orientation")
 	else if (n=="screen/orientation")
 		r_ret=orientation;
 		r_ret=orientation;
+	else if (n=="screen/support_small")
+		r_ret=screen_support[SCREEN_SMALL];
+	else if (n=="screen/support_normal")
+		r_ret=screen_support[SCREEN_NORMAL];
+	else if (n=="screen/support_large")
+		r_ret=screen_support[SCREEN_LARGE];
+	else if (n=="screen/support_xlarge")
+		r_ret=screen_support[SCREEN_XLARGE];
 	else if (n=="keystore/release")
 	else if (n=="keystore/release")
 		r_ret=release_keystore;
 		r_ret=release_keystore;
 	else if (n=="keystore/release_user")
 	else if (n=="keystore/release_user")
 		r_ret=release_username;
 		r_ret=release_username;
-	else
+	else if (n.begins_with("permissions/")) {
+
+		String what = n.get_slice("/",1).to_upper();
+		r_ret = perms.has(what);
+	} else if (n.begins_with("user_permissions/")) {
+
+		int which = n.get_slice("/",1).to_int();
+		ERR_FAIL_INDEX_V(which,MAX_USER_PERMISSIONS,false);
+		r_ret=user_perms[which];
+	} else
 		return false;
 		return false;
 
 
 	return true;
 	return true;
 }
 }
+
 void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list) const{
 void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list) const{
 
 
 	p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_FILE,"apk"));
 	p_list->push_back( PropertyInfo( Variant::STRING, "custom_package/debug", PROPERTY_HINT_FILE,"apk"));
@@ -152,9 +355,25 @@ void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list
 	p_list->push_back( PropertyInfo( Variant::STRING, "package/icon",PROPERTY_HINT_FILE,"png") );
 	p_list->push_back( PropertyInfo( Variant::STRING, "package/icon",PROPERTY_HINT_FILE,"png") );
 	p_list->push_back( PropertyInfo( Variant::BOOL, "package/signed") );
 	p_list->push_back( PropertyInfo( Variant::BOOL, "package/signed") );
 	p_list->push_back( PropertyInfo( Variant::INT, "screen/orientation",PROPERTY_HINT_ENUM,"Landscape,Portrait") );
 	p_list->push_back( PropertyInfo( Variant::INT, "screen/orientation",PROPERTY_HINT_ENUM,"Landscape,Portrait") );
+	p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_small") );
+	p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_normal") );
+	p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_large") );
+	p_list->push_back( PropertyInfo( Variant::BOOL, "screen/support_xlarge") );
 	p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release",PROPERTY_HINT_FILE,"keystore") );
 	p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release",PROPERTY_HINT_FILE,"keystore") );
 	p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release_user" ) );
 	p_list->push_back( PropertyInfo( Variant::STRING, "keystore/release_user" ) );
 
 
+	const char **perms = android_perms;
+	while(*perms) {
+
+		p_list->push_back( PropertyInfo( Variant::BOOL, "permissions/"+String(*perms).to_lower()));
+		perms++;
+	}
+
+	for(int i=0;i<MAX_USER_PERMISSIONS;i++) {
+
+		p_list->push_back( PropertyInfo( Variant::STRING, "user_permissions/"+itos(i)));
+	}
+
 	//p_list->push_back( PropertyInfo( Variant::INT, "resources/pack_mode", PROPERTY_HINT_ENUM,"Copy,Single Exec.,Pack (.pck),Bundles (Optical)"));
 	//p_list->push_back( PropertyInfo( Variant::INT, "resources/pack_mode", PROPERTY_HINT_ENUM,"Copy,Single Exec.,Pack (.pck),Bundles (Optical)"));
 
 
 }
 }
@@ -536,6 +755,53 @@ void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest) {
 						}
 						}
 					}
 					}
 
 
+					if (tname=="uses-permission" && /*nspace=="android" &&*/ attrname=="name") {
+
+						if (value.begins_with("godot.custom")) {
+
+							int which = value.get_slice(".",2).to_int();
+							if (which>=0 && which<MAX_USER_PERMISSIONS && user_perms[which].strip_edges()!="") {
+
+								string_table[attr_value]=user_perms[which].strip_edges();
+							}
+
+						} else if (value.begins_with("godot.")) {
+							String perm = value.get_slice(".",1);
+							if (perms.has(perm)) {
+								string_table[attr_value]="android.permission."+perm;
+							}
+
+						}
+					}
+
+					if (tname=="supports-screens" ) {
+
+						if (attr_value==0xFFFFFFFF) {
+							WARN_PRINT("Screen res name in a resource, should be plaintext")
+						} else if (attrname=="smallScreens") {
+
+							print_line("SMALLSCREEN");
+							string_table[attr_value]=screen_support[SCREEN_SMALL]?"true":"false";
+
+						} else if (attrname=="mediumScreens") {
+
+							print_line("MEDSCREEN");
+							string_table[attr_value]=screen_support[SCREEN_NORMAL]?"true":"false";
+
+						} else if (attrname=="largeScreens") {
+
+							print_line("LARGECREEN");
+							string_table[attr_value]=screen_support[SCREEN_LARGE]?"true":"false";
+
+						} else if (attrname=="xlargeScreens") {
+
+							print_line("XLARGECREEN");
+							string_table[attr_value]=screen_support[SCREEN_XLARGE]?"true":"false";
+
+						}
+					}
+
+
 					iofs+=20;
 					iofs+=20;
 				}
 				}
 
 
@@ -1144,6 +1410,9 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
 	Image img( _android_logo );
 	Image img( _android_logo );
 	logo = Ref<ImageTexture>( memnew( ImageTexture ));
 	logo = Ref<ImageTexture>( memnew( ImageTexture ));
 	logo->create_from_image(img);
 	logo->create_from_image(img);
+
+	for(int i=0;i<4;i++)
+		screen_support[i]=true;
 }
 }
 
 
 bool EditorExportPlatformAndroid::can_export(String *r_error) const {
 bool EditorExportPlatformAndroid::can_export(String *r_error) const {

+ 7 - 3
platform/android/java/src/com/android/godot/GodotPaymentV3.java

@@ -24,8 +24,12 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
 			}
 			}
 		});
 		});
 	};
 	};
+	
+/*	public string requestPurchasedTicket(){
+	    activity.getPaymentsManager()
+	}
 
 
-
+*/
     static public Godot.SingletonBase initialize(Activity p_activity) {
     static public Godot.SingletonBase initialize(Activity p_activity) {
 
 
         return new GodotPaymentV3(p_activity);
         return new GodotPaymentV3(p_activity);
@@ -40,8 +44,8 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
 
 
 
 
 	
 	
-	public void callbackSuccess(){
-        GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{});
+	public void callbackSuccess(String ticket){
+        GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket});
 	}
 	}
 	
 	
 	public void callbackFail(){
 	public void callbackFail(){

+ 2 - 2
platform/android/java/src/com/android/godot/payments/HandlePurchaseTask.java

@@ -61,7 +61,7 @@ abstract public class HandlePurchaseTask {
 				pc.setConsumableFlag("block", productId, true);
 				pc.setConsumableFlag("block", productId, true);
 				pc.setConsumableValue("token", productId, purchaseToken);
 				pc.setConsumableValue("token", productId, purchaseToken);
 				
 				
-				success(purchaseToken, productId);
+				success(purchaseData);
 				return;
 				return;
 			}	catch (JSONException e) {
 			}	catch (JSONException e) {
 				error(e.getMessage());
 				error(e.getMessage());
@@ -71,7 +71,7 @@ abstract public class HandlePurchaseTask {
 		}
 		}
 	}
 	}
 
 
-	abstract protected void success(String purchaseToken, String sku);
+	abstract protected void success(String ticket);
 	abstract protected void error(String message);
 	abstract protected void error(String message);
 	abstract protected void canceled();
 	abstract protected void canceled();
 
 

+ 4 - 5
platform/android/java/src/com/android/godot/payments/PaymentsManager.java

@@ -84,8 +84,9 @@ public class PaymentsManager {
 		new HandlePurchaseTask(activity){
 		new HandlePurchaseTask(activity){
 
 
 			@Override
 			@Override
-			protected void success(String purchaseToken, String sku) {
-				validatePurchase(purchaseToken, sku);
+			protected void success(String ticket) {
+			    godotPaymentV3.callbackSuccess(ticket);
+			    //validatePurchase(purchaseToken, sku);
 			}
 			}
 
 
 			@Override
 			@Override
@@ -112,7 +113,7 @@ public class PaymentsManager {
 					
 					
 					@Override
 					@Override
 					protected void success() {
 					protected void success() {
-						godotPaymentV3.callbackSuccess();
+						godotPaymentV3.callbackSuccess("");
 						
 						
 					}
 					}
 					
 					
@@ -145,7 +146,5 @@ public class PaymentsManager {
 		this.godotPaymentV3 = godotPaymentV3;
 		this.godotPaymentV3 = godotPaymentV3;
 		
 		
 	}
 	}
-
-
 }
 }
 
 

+ 11 - 0
scene/2d/canvas_item.cpp

@@ -821,6 +821,17 @@ void CanvasItem::_bind_methods() {
 
 
 }
 }
 
 
+Matrix32 CanvasItem::get_canvas_transform() const {
+
+	ERR_FAIL_COND_V(!is_inside_scene(),Matrix32());
+
+	if (canvas_layer)
+		return canvas_layer->get_transform();
+	else
+		return get_viewport()->get_canvas_transform();
+
+}
+
 Matrix32 CanvasItem::get_viewport_transform() const {
 Matrix32 CanvasItem::get_viewport_transform() const {
 
 
 	ERR_FAIL_COND_V(!is_inside_scene(),Matrix32());
 	ERR_FAIL_COND_V(!is_inside_scene(),Matrix32());

+ 2 - 0
scene/2d/canvas_item.h

@@ -195,6 +195,8 @@ public:
 	void set_block_transform_notify(bool p_enable);
 	void set_block_transform_notify(bool p_enable);
 	bool is_block_transform_notify_enabled() const;
 	bool is_block_transform_notify_enabled() const;
 
 
+
+	Matrix32 get_canvas_transform() const;
 	Matrix32 get_viewport_transform() const;
 	Matrix32 get_viewport_transform() const;
 	Rect2 get_viewport_rect() const;
 	Rect2 get_viewport_rect() const;
 	RID get_viewport_rid() const;
 	RID get_viewport_rid() const;

+ 2 - 2
scene/gui/control.cpp

@@ -955,7 +955,7 @@ void Control::_window_input_event(InputEvent p_event) {
 
 
 		window->key_event_accepted=false;
 		window->key_event_accepted=false;
 
 
-		Point2 mpos =(get_viewport_transform()).affine_inverse().xform(Point2(p_event.mouse_button.x,p_event.mouse_button.y));
+		Point2 mpos =(get_canvas_transform()).affine_inverse().xform(Point2(p_event.mouse_button.x,p_event.mouse_button.y));
 
 
 		if (p_event.mouse_button.pressed) {
 		if (p_event.mouse_button.pressed) {
 
 
@@ -1102,7 +1102,7 @@ void Control::_window_input_event(InputEvent p_event) {
 
 
 			window->key_event_accepted=false;
 			window->key_event_accepted=false;
 
 
-			Matrix32 localizer = (get_viewport_transform()).affine_inverse();
+			Matrix32 localizer = (get_canvas_transform()).affine_inverse();
 			Size2 pos = localizer.xform(Size2(p_event.mouse_motion.x,p_event.mouse_motion.y)) - _window_get_pos();
 			Size2 pos = localizer.xform(Size2(p_event.mouse_motion.x,p_event.mouse_motion.y)) - _window_get_pos();
 			Vector2 speed = localizer.basis_xform(Point2(p_event.mouse_motion.speed_x,p_event.mouse_motion.speed_y));
 			Vector2 speed = localizer.basis_xform(Point2(p_event.mouse_motion.speed_x,p_event.mouse_motion.speed_y));
 			Vector2 rel = localizer.basis_xform(Point2(p_event.mouse_motion.relative_x,p_event.mouse_motion.relative_y));
 			Vector2 rel = localizer.basis_xform(Point2(p_event.mouse_motion.relative_x,p_event.mouse_motion.relative_y));

+ 130 - 2
scene/main/scene_main_loop.cpp

@@ -516,7 +516,8 @@ bool SceneMainLoop::idle(float p_time){
 
 
 
 
 		last_screen_size=win_size;
 		last_screen_size=win_size;
-		root->set_rect(Rect2(Point2(),last_screen_size));
+		_update_root_rect();
+
 
 
 		emit_signal("screen_resized");
 		emit_signal("screen_resized");
 
 
@@ -849,6 +850,120 @@ int SceneMainLoop::get_node_count() const {
 	return node_count;
 	return node_count;
 }
 }
 
 
+
+void SceneMainLoop::_update_root_rect() {
+
+
+	if (stretch_mode==STRETCH_MODE_DISABLED) {
+		root->set_rect(Rect2(Point2(),last_screen_size));
+		return; //user will take care
+	}
+
+	//actual screen video mode
+	Size2 video_mode = Size2(OS::get_singleton()->get_video_mode().width,OS::get_singleton()->get_video_mode().height);
+	Size2 desired_res = stretch_min;
+
+	Size2 viewport_size;
+	Size2 screen_size;
+
+	float viewport_aspect = desired_res.get_aspect();
+	float video_mode_aspect = video_mode.get_aspect();
+
+	if (stretch_aspect==STRETCH_ASPECT_IGNORE || ABS(viewport_aspect - video_mode_aspect)<CMP_EPSILON) {
+		//same aspect or ignore aspect
+		viewport_size=desired_res;
+		screen_size=video_mode;
+	} else if (viewport_aspect < video_mode_aspect) {
+		// screen ratio is smaller vertically
+
+		if (stretch_aspect==STRETCH_ASPECT_KEEP_HEIGHT) {
+
+			//will stretch horizontally
+			viewport_size.x=desired_res.y*video_mode_aspect;
+			viewport_size.y=desired_res.y;
+			screen_size=video_mode;
+
+		} else {
+			//will need black bars
+			viewport_size=desired_res;
+			screen_size.x = video_mode.y * viewport_aspect;
+			screen_size.y=video_mode.y;
+		}
+	} else {
+		//screen ratio is smaller horizontally
+		if (stretch_aspect==STRETCH_ASPECT_KEEP_WIDTH) {
+
+			//will stretch horizontally
+			viewport_size.x=desired_res.x;
+			viewport_size.y=desired_res.x / video_mode_aspect;
+			screen_size=video_mode;
+
+		} else {
+			//will need black bars
+			viewport_size=desired_res;
+			screen_size.x=video_mode.x;
+			screen_size.y = video_mode.x / viewport_aspect;
+		}
+
+	}
+
+	screen_size = screen_size.floor();
+	viewport_size = viewport_size.floor();
+
+	Size2 margin;
+	Size2 offset;
+	//black bars and margin
+	if (screen_size.x < video_mode.x) {
+		margin.x = Math::round((video_mode.x - screen_size.x)/2.0);
+		VisualServer::get_singleton()->black_bars_set_margins(margin.x,0,margin.x,0);
+		offset.x = Math::round(margin.x * viewport_size.y / screen_size.y);
+	} else if (screen_size.y < video_mode.y) {
+
+		margin.y = Math::round((video_mode.y - screen_size.y)/2.0);
+		VisualServer::get_singleton()->black_bars_set_margins(0,margin.y,0,margin.y);
+		offset.y = Math::round(margin.y * viewport_size.x / screen_size.x);
+	} else {
+		VisualServer::get_singleton()->black_bars_set_margins(0,0,0,0);
+	}
+
+//	print_line("VP SIZE: "+viewport_size+" OFFSET: "+offset+" = "+(offset*2+viewport_size));
+//	print_line("SS: "+video_mode);
+	switch (stretch_mode) {
+		case STRETCH_MODE_2D: {
+
+//			root->set_rect(Rect2(Point2(),video_mode));
+			root->set_as_render_target(false);
+			root->set_rect(Rect2(margin,screen_size));
+			root->set_size_override_stretch(true);
+			root->set_size_override(true,viewport_size);
+
+		} break;
+		case STRETCH_MODE_VIEWPORT: {
+
+			print_line("VP SIZE: "+viewport_size);
+			root->set_rect(Rect2(Point2(),viewport_size));
+			root->set_size_override_stretch(false);
+			root->set_size_override(false,Size2());
+			root->set_as_render_target(true);
+			root->set_render_target_update_mode(Viewport::RENDER_TARGET_UPDATE_ALWAYS);
+			root->set_render_target_to_screen_rect(Rect2(margin,screen_size));
+
+		} break;
+
+
+	}
+
+}
+
+void SceneMainLoop::set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 p_minsize) {
+
+	stretch_mode=p_mode;
+	stretch_aspect=p_aspect;
+	stretch_min=p_minsize;
+	_update_root_rect();
+}
+
+
 void SceneMainLoop::_bind_methods() {
 void SceneMainLoop::_bind_methods() {
 
 
 
 
@@ -874,6 +989,9 @@ void SceneMainLoop::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_frame"),&SceneMainLoop::get_frame);
 	ObjectTypeDB::bind_method(_MD("get_frame"),&SceneMainLoop::get_frame);
 	ObjectTypeDB::bind_method(_MD("quit"),&SceneMainLoop::quit);
 	ObjectTypeDB::bind_method(_MD("quit"),&SceneMainLoop::quit);
 
 
+	ObjectTypeDB::bind_method(_MD("set_screen_stretch","mode","aspect","minsize"),&SceneMainLoop::set_screen_stretch);
+
+
 	ObjectTypeDB::bind_method(_MD("queue_delete","obj"),&SceneMainLoop::queue_delete);
 	ObjectTypeDB::bind_method(_MD("queue_delete","obj"),&SceneMainLoop::queue_delete);
 
 
 
 
@@ -899,6 +1017,14 @@ void SceneMainLoop::_bind_methods() {
 	BIND_CONSTANT( GROUP_CALL_REALTIME );
 	BIND_CONSTANT( GROUP_CALL_REALTIME );
 	BIND_CONSTANT( GROUP_CALL_UNIQUE );
 	BIND_CONSTANT( GROUP_CALL_UNIQUE );
 
 
+	BIND_CONSTANT( STRETCH_MODE_DISABLED );
+	BIND_CONSTANT( STRETCH_MODE_2D );
+	BIND_CONSTANT( STRETCH_MODE_VIEWPORT );
+	BIND_CONSTANT( STRETCH_ASPECT_IGNORE );
+	BIND_CONSTANT( STRETCH_ASPECT_KEEP );
+	BIND_CONSTANT( STRETCH_ASPECT_KEEP_WIDTH );
+	BIND_CONSTANT( STRETCH_ASPECT_KEEP_HEIGHT );
+
 }
 }
 
 
 SceneMainLoop::SceneMainLoop() {
 SceneMainLoop::SceneMainLoop() {
@@ -927,6 +1053,9 @@ SceneMainLoop::SceneMainLoop() {
 	root->set_as_audio_listener(true);
 	root->set_as_audio_listener(true);
 	root->set_as_audio_listener_2d(true);
 	root->set_as_audio_listener_2d(true);
 
 
+	stretch_mode=STRETCH_MODE_DISABLED;
+	stretch_aspect=STRETCH_ASPECT_IGNORE;
+
 	last_screen_size=Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height );
 	last_screen_size=Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height );
 	root->set_rect(Rect2(Point2(),last_screen_size));
 	root->set_rect(Rect2(Point2(),last_screen_size));
 
 
@@ -934,7 +1063,6 @@ SceneMainLoop::SceneMainLoop() {
 		ScriptDebugger::get_singleton()->set_request_scene_tree_message_func(_debugger_request_tree,this);
 		ScriptDebugger::get_singleton()->set_request_scene_tree_message_func(_debugger_request_tree,this);
 	}
 	}
 
 
-
 }
 }
 
 
 
 

+ 33 - 1
scene/main/scene_main_loop.h

@@ -50,6 +50,25 @@ class SceneMainLoop : public MainLoop {
 	_THREAD_SAFE_CLASS_
 	_THREAD_SAFE_CLASS_
 
 
 	OBJ_TYPE( SceneMainLoop, MainLoop );	
 	OBJ_TYPE( SceneMainLoop, MainLoop );	
+public:
+
+
+	enum StretchMode {
+
+		STRETCH_MODE_DISABLED,
+		STRETCH_MODE_2D,
+		STRETCH_MODE_VIEWPORT,
+	};
+
+	enum StretchAspect {
+
+		STRETCH_ASPECT_IGNORE,
+		STRETCH_ASPECT_KEEP,
+		STRETCH_ASPECT_KEEP_WIDTH,
+		STRETCH_ASPECT_KEEP_HEIGHT,
+	};
+private:
+
 
 
 	struct Group {
 	struct Group {
 
 
@@ -95,6 +114,12 @@ class SceneMainLoop : public MainLoop {
 	Set<Node*> call_skip; //skip erased nodes
 	Set<Node*> call_skip; //skip erased nodes
 
 
 
 
+	StretchMode stretch_mode;
+	StretchAspect stretch_aspect;
+	Size2i stretch_min;
+
+	void _update_root_rect();
+
 	List<ObjectID> delete_queue;
 	List<ObjectID> delete_queue;
 
 
 	Map<UGCall,Vector<Variant> > unique_group_calls;
 	Map<UGCall,Vector<Variant> > unique_group_calls;
@@ -152,7 +177,6 @@ public:
 		GROUP_CALL_MULIILEVEL=8,
 		GROUP_CALL_MULIILEVEL=8,
 	};
 	};
 
 
-
 	_FORCE_INLINE_ Viewport *get_root() const { return root; }
 	_FORCE_INLINE_ Viewport *get_root() const { return root; }
 
 
 	uint32_t get_last_event_id() const;
 	uint32_t get_last_event_id() const;
@@ -196,10 +220,18 @@ public:
 
 
 	void get_nodes_in_group(const StringName& p_group,List<Node*> *p_list);
 	void get_nodes_in_group(const StringName& p_group,List<Node*> *p_list);
 
 
+	void set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 p_minsize);
+
+
 	SceneMainLoop();
 	SceneMainLoop();
 	~SceneMainLoop();
 	~SceneMainLoop();
 
 
 };
 };
 
 
 
 
+VARIANT_ENUM_CAST( SceneMainLoop::StretchMode );
+VARIANT_ENUM_CAST( SceneMainLoop::StretchAspect );
+
+
+
 #endif
 #endif

+ 66 - 3
scene/main/viewport.cpp

@@ -86,8 +86,9 @@ void Viewport::_update_stretch_transform() {
 	if (size_override_stretch && size_override) {
 	if (size_override_stretch && size_override) {
 
 
 		stretch_transform=Matrix32();
 		stretch_transform=Matrix32();
-		stretch_transform.scale(rect.size/(size_override_size+size_override_margin*2));
-		stretch_transform.elements[2]=size_override_margin;
+		Size2 scale = rect.size/(size_override_size+size_override_margin*2);
+		stretch_transform.scale(scale);
+		stretch_transform.elements[2]=size_override_margin*scale;
 
 
 	} else {
 	} else {
 
 
@@ -629,7 +630,9 @@ Ref<World> Viewport::get_world() const{
 
 
 Ref<World> Viewport::find_world() const{
 Ref<World> Viewport::find_world() const{
 
 
-	if (world.is_valid())
+	if (own_world.is_valid())
+		return own_world;
+	else if (world.is_valid())
 		return world;
 		return world;
 	else if (parent)
 	else if (parent)
 		return parent->find_world();
 		return parent->find_world();
@@ -863,6 +866,60 @@ void Viewport::unhandled_input(const InputEvent& p_event) {
 	}
 	}
 }
 }
 
 
+void Viewport::set_use_own_world(bool p_world) {
+
+	if (p_world==own_world.is_valid())
+		return;
+
+
+	if (is_inside_scene())
+		_propagate_exit_world(this);
+
+#ifndef _3D_DISABLED
+	if (find_world().is_valid() && camera)
+		camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
+#endif
+
+	if (!p_world)
+		own_world=Ref<World>();
+	else
+		own_world=Ref<World>( memnew( World ));
+
+	if (is_inside_scene())
+		_propagate_enter_world(this);
+
+#ifndef _3D_DISABLED
+	if (find_world().is_valid() && camera)
+		camera->notification(Camera::NOTIFICATION_BECAME_CURRENT);
+#endif
+
+	//propagate exit
+
+	if (is_inside_scene()) {
+		VisualServer::get_singleton()->viewport_set_scenario(viewport,find_world()->get_scenario());
+	}
+
+	_update_listener();
+
+
+}
+
+bool Viewport::is_using_own_world() const {
+
+	return own_world.is_valid();
+}
+
+void Viewport::set_render_target_to_screen_rect(const Rect2& p_rect) {
+
+	to_screen_rect=p_rect;
+	VisualServer::get_singleton()->viewport_set_render_target_to_screen_rect(viewport,to_screen_rect);
+}
+
+Rect2 Viewport::get_render_target_to_screen_rect() const{
+
+	return to_screen_rect;
+}
+
 
 
 void Viewport::_bind_methods() {
 void Viewport::_bind_methods() {
 
 
@@ -918,15 +975,20 @@ void Viewport::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("update_worlds"), &Viewport::update_worlds);
 	ObjectTypeDB::bind_method(_MD("update_worlds"), &Viewport::update_worlds);
 
 
+	ObjectTypeDB::bind_method(_MD("set_use_own_world","enable"), &Viewport::set_use_own_world);
+	ObjectTypeDB::bind_method(_MD("is_using_own_world"), &Viewport::is_using_own_world);
+
 
 
 	ObjectTypeDB::bind_method(_MD("set_as_audio_listener","enable"), &Viewport::set_as_audio_listener);
 	ObjectTypeDB::bind_method(_MD("set_as_audio_listener","enable"), &Viewport::set_as_audio_listener);
 	ObjectTypeDB::bind_method(_MD("is_audio_listener","enable"), &Viewport::is_audio_listener);
 	ObjectTypeDB::bind_method(_MD("is_audio_listener","enable"), &Viewport::is_audio_listener);
 
 
 	ObjectTypeDB::bind_method(_MD("set_as_audio_listener_2d","enable"), &Viewport::set_as_audio_listener_2d);
 	ObjectTypeDB::bind_method(_MD("set_as_audio_listener_2d","enable"), &Viewport::set_as_audio_listener_2d);
 	ObjectTypeDB::bind_method(_MD("is_audio_listener_2d","enable"), &Viewport::is_audio_listener_2d);
 	ObjectTypeDB::bind_method(_MD("is_audio_listener_2d","enable"), &Viewport::is_audio_listener_2d);
+	ObjectTypeDB::bind_method(_MD("set_render_target_to_screen_rect"), &Viewport::set_render_target_to_screen_rect);
 
 
 
 
 	ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"), _SCS("set_rect"), _SCS("get_rect") );
 	ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"), _SCS("set_rect"), _SCS("get_rect") );
+	ADD_PROPERTY( PropertyInfo(Variant::BOOL,"own_world"), _SCS("set_use_own_world"), _SCS("is_using_own_world") );
 	ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world",PROPERTY_HINT_RESOURCE_TYPE,"World"), _SCS("set_world"), _SCS("get_world") );
 	ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world",PROPERTY_HINT_RESOURCE_TYPE,"World"), _SCS("set_world"), _SCS("get_world") );
 //	ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world_2d",PROPERTY_HINT_RESOURCE_TYPE,"World2D"), _SCS("set_world_2d"), _SCS("get_world_2d") );
 //	ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world_2d",PROPERTY_HINT_RESOURCE_TYPE,"World2D"), _SCS("set_world_2d"), _SCS("get_world_2d") );
 	ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transparent_bg"), _SCS("set_transparent_background"), _SCS("has_transparent_background") );
 	ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transparent_bg"), _SCS("set_transparent_background"), _SCS("has_transparent_background") );
@@ -969,6 +1031,7 @@ Viewport::Viewport() {
 	render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE;
 	render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE;
 	render_target_texture = Ref<RenderTargetTexture>( memnew( RenderTargetTexture(this) ) );
 	render_target_texture = Ref<RenderTargetTexture>( memnew( RenderTargetTexture(this) ) );
 
 
+
 	String id=itos(get_instance_ID());
 	String id=itos(get_instance_ID());
 	input_group = "_vp_input"+id;
 	input_group = "_vp_input"+id;
 	gui_input_group = "_vp_gui_input"+id;
 	gui_input_group = "_vp_gui_input"+id;

+ 8 - 0
scene/main/viewport.h

@@ -101,6 +101,7 @@ friend class RenderTargetTexture;
 	Matrix32 stretch_transform;
 	Matrix32 stretch_transform;
 
 
 	Rect2 rect;
 	Rect2 rect;
+	Rect2 to_screen_rect;
 
 
 
 
 	bool size_override;
 	bool size_override;
@@ -120,6 +121,7 @@ friend class RenderTargetTexture;
 
 
 	Ref<World2D> world_2d;
 	Ref<World2D> world_2d;
 	Ref<World> world;
 	Ref<World> world;
+	Ref<World> own_world;
 
 
 	StringName input_group;
 	StringName input_group;
 	StringName gui_input_group;
 	StringName gui_input_group;
@@ -213,9 +215,15 @@ public:
 	void queue_screen_capture();
 	void queue_screen_capture();
 	Image get_screen_capture() const;
 	Image get_screen_capture() const;
 
 
+	void set_use_own_world(bool p_world);
+	bool is_using_own_world() const;
+
 	void input(const InputEvent& p_event);
 	void input(const InputEvent& p_event);
 	void unhandled_input(const InputEvent& p_event);
 	void unhandled_input(const InputEvent& p_event);
 
 
+	void set_render_target_to_screen_rect(const Rect2& p_rect);
+	Rect2 get_render_target_to_screen_rect() const;
+
 	Viewport();	
 	Viewport();	
 	~Viewport();
 	~Viewport();
 
 

+ 1 - 1
servers/physics_2d/physics_2d_server_sw.cpp

@@ -770,7 +770,7 @@ void Physics2DServerSW::body_remove_collision_exception(RID p_body, RID p_body_b
 	Body2DSW *body = body_owner.get(p_body);
 	Body2DSW *body = body_owner.get(p_body);
 	ERR_FAIL_COND(!body);
 	ERR_FAIL_COND(!body);
 
 
-	body->remove_exception(p_body);
+	body->remove_exception(p_body_b);
 
 
 };
 };
 
 

+ 1 - 0
servers/visual/rasterizer.h

@@ -494,6 +494,7 @@ public:
 	};
 	};
 		
 		
 	virtual void canvas_begin()=0;
 	virtual void canvas_begin()=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;;

+ 7 - 1
servers/visual/rasterizer_dummy.cpp

@@ -1384,7 +1384,7 @@ void RasterizerDummy::set_viewport(const VS::ViewportRect& p_viewport) {
 
 
 }
 }
 
 
-void RasterizerDummy::set_render_target(RID p_render_target,bool p_transparent_bg) {
+void RasterizerDummy::set_render_target(RID p_render_target, bool p_transparent_bg, bool p_vflip) {
 
 
 
 
 }
 }
@@ -1455,6 +1455,12 @@ void RasterizerDummy::canvas_begin() {
 
 
 
 
 }
 }
+void RasterizerDummy::canvas_disable_blending() {
+
+
+
+}
+
 void RasterizerDummy::canvas_set_opacity(float p_opacity) {
 void RasterizerDummy::canvas_set_opacity(float p_opacity) {
 
 
 
 

+ 2 - 1
servers/visual/rasterizer_dummy.h

@@ -627,7 +627,7 @@ public:
 	virtual void begin_frame();
 	virtual void begin_frame();
 
 
 	virtual void set_viewport(const VS::ViewportRect& p_viewport);
 	virtual void set_viewport(const VS::ViewportRect& p_viewport);
-	virtual void set_render_target(RID p_render_target,bool p_transparent_bg=false);
+	virtual void set_render_target(RID p_render_target,bool p_transparent_bg=false,bool p_vflip=false);
 	virtual void clear_viewport(const Color& p_color);
 	virtual void clear_viewport(const Color& p_color);
 	virtual void capture_viewport(Image* r_capture);
 	virtual void capture_viewport(Image* r_capture);
 
 
@@ -652,6 +652,7 @@ public:
 	/* CANVAS API */
 	/* CANVAS API */
 
 
 	virtual void canvas_begin();
 	virtual void canvas_begin();
+	virtual void canvas_disable_blending();
 	virtual void canvas_set_opacity(float p_opacity);
 	virtual void canvas_set_opacity(float p_opacity);
 	virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode);
 	virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode);
 	virtual void canvas_begin_rect(const Matrix32& p_transform);
 	virtual void canvas_begin_rect(const Matrix32& p_transform);

+ 46 - 0
servers/visual/visual_server_raster.cpp

@@ -1145,6 +1145,15 @@ void VisualServerRaster::viewport_set_render_target_vflip(RID p_viewport,bool p_
 
 
 }
 }
 
 
+void VisualServerRaster::viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect) {
+
+	Viewport *viewport = viewport_owner.get( p_viewport );
+	ERR_FAIL_COND(!viewport);
+
+	viewport->rt_to_screen_rect=p_rect;
+
+}
+
 bool VisualServerRaster::viewport_get_render_target_vflip(RID p_viewport) const{
 bool VisualServerRaster::viewport_get_render_target_vflip(RID p_viewport) const{
 
 
 	const Viewport *viewport = viewport_owner.get( p_viewport );
 	const Viewport *viewport = viewport_owner.get( p_viewport );
@@ -5458,6 +5467,8 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
 void VisualServerRaster::_draw_viewports() {
 void VisualServerRaster::_draw_viewports() {
 
 
 	//draw viewports for render targets
 	//draw viewports for render targets
+
+	List<Viewport*> to_blit;
 	List<Viewport*> to_disable;
 	List<Viewport*> to_disable;
 	for(SelfList<Viewport> *E=viewport_update_list.first();E;E=E->next()) {
 	for(SelfList<Viewport> *E=viewport_update_list.first();E;E=E->next()) {
 
 
@@ -5472,6 +5483,9 @@ void VisualServerRaster::_draw_viewports() {
 			continue;
 			continue;
 		}
 		}
 
 
+		if (vp->rt_to_screen_rect!=Rect2())
+			to_blit.push_back(vp);
+
 		rasterizer->set_render_target(vp->render_target,vp->transparent_bg,vp->render_target_vflip);
 		rasterizer->set_render_target(vp->render_target,vp->transparent_bg,vp->render_target_vflip);
 		_draw_viewport(vp,0,0,vp->rect.width,vp->rect.height);
 		_draw_viewport(vp,0,0,vp->rect.width,vp->rect.height);
 
 
@@ -5491,6 +5505,38 @@ void VisualServerRaster::_draw_viewports() {
 		to_disable.pop_front();
 		to_disable.pop_front();
 	}
 	}
 
 
+
+	//draw RTs directly to screen when requested
+
+	for (List<Viewport*>::Element *E=to_blit.front();E;E=E->next()) {
+
+		int window_w = OS::get_singleton()->get_video_mode().width;
+		int window_h = OS::get_singleton()->get_video_mode().height;
+
+		ViewportRect desired_rect;
+		desired_rect.x = desired_rect.y = 0;
+		desired_rect.width = window_w;
+		desired_rect.height = window_h;
+
+		if ( viewport_rect.x != desired_rect.x ||
+			viewport_rect.y != desired_rect.y ||
+			viewport_rect.width != desired_rect.width ||
+			viewport_rect.height != desired_rect.height ) {
+
+			viewport_rect=desired_rect;
+
+			rasterizer->set_viewport(viewport_rect);
+		}
+
+		rasterizer->canvas_begin();
+		rasterizer->canvas_disable_blending();
+		rasterizer->canvas_begin_rect(Matrix32());
+		rasterizer->canvas_draw_rect(E->get()->rt_to_screen_rect,0,Rect2(Point2(),E->get()->rt_to_screen_rect.size),E->get()->render_target_texture,Color(1,1,1));
+
+	}
+
+
+
 	//draw viewports attached to screen
 	//draw viewports attached to screen
 
 
 	for(Map<RID,int>::Element *E=screen_viewports.front();E;E=E->next()) {
 	for(Map<RID,int>::Element *E=screen_viewports.front();E;E=E->next()) {

+ 3 - 0
servers/visual/visual_server_raster.h

@@ -481,6 +481,8 @@ class VisualServerRaster : public VisualServer {
 		RID render_target;
 		RID render_target;
 		RID render_target_texture;
 		RID render_target_texture;
 
 
+		Rect2 rt_to_screen_rect;
+
 		bool hide_scenario;
 		bool hide_scenario;
 		bool hide_canvas;
 		bool hide_canvas;
 		bool transparent_bg;
 		bool transparent_bg;
@@ -913,6 +915,7 @@ public:
 	virtual RID viewport_get_render_target_texture(RID p_viewport) const;
 	virtual RID viewport_get_render_target_texture(RID p_viewport) const;
 	virtual void viewport_set_render_target_vflip(RID p_viewport,bool p_enable);
 	virtual void viewport_set_render_target_vflip(RID p_viewport,bool p_enable);
 	virtual bool viewport_get_render_target_vflip(RID p_viewport) const;
 	virtual bool viewport_get_render_target_vflip(RID p_viewport) const;
+	virtual void viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect);
 
 
 	virtual void viewport_queue_screen_capture(RID p_viewport);
 	virtual void viewport_queue_screen_capture(RID p_viewport);
 	virtual Image viewport_get_screen_capture(RID p_viewport) const;
 	virtual Image viewport_get_screen_capture(RID p_viewport) const;

+ 1 - 0
servers/visual/visual_server_wrap_mt.h

@@ -891,6 +891,7 @@ public:
 
 
 	FUNC2(viewport_set_render_target_vflip,RID,bool);
 	FUNC2(viewport_set_render_target_vflip,RID,bool);
 	FUNC1RC(bool,viewport_get_render_target_vflip,RID);
 	FUNC1RC(bool,viewport_get_render_target_vflip,RID);
+	FUNC2(viewport_set_render_target_to_screen_rect,RID,const Rect2&);
 
 
 	FUNC1(viewport_queue_screen_capture,RID);
 	FUNC1(viewport_queue_screen_capture,RID);
 	FUNC1RC(Image,viewport_get_screen_capture,RID);
 	FUNC1RC(Image,viewport_get_screen_capture,RID);

+ 3 - 0
servers/visual_server.h

@@ -592,6 +592,7 @@ public:
 
 
 	virtual void viewport_attach_to_screen(RID p_viewport,int p_screen=0)=0;
 	virtual void viewport_attach_to_screen(RID p_viewport,int p_screen=0)=0;
 	virtual void viewport_detach(RID p_viewport)=0;
 	virtual void viewport_detach(RID p_viewport)=0;
+	virtual void viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect)=0;
 
 
 	enum RenderTargetUpdateMode {
 	enum RenderTargetUpdateMode {
 		RENDER_TARGET_UPDATE_DISABLED,
 		RENDER_TARGET_UPDATE_DISABLED,
@@ -611,6 +612,8 @@ public:
 	virtual void viewport_queue_screen_capture(RID p_viewport)=0;
 	virtual void viewport_queue_screen_capture(RID p_viewport)=0;
 	virtual Image viewport_get_screen_capture(RID p_viewport) const=0;
 	virtual Image viewport_get_screen_capture(RID p_viewport) const=0;
 
 
+
+
 	struct ViewportRect {
 	struct ViewportRect {
 	
 	
 		int x,y,width,height;
 		int x,y,width,height;

+ 1 - 1
tools/editor/editor_node.cpp

@@ -3927,7 +3927,7 @@ EditorNode::EditorNode() {
 	file_templates->set_mode(FileDialog::MODE_OPEN_FILE);
 	file_templates->set_mode(FileDialog::MODE_OPEN_FILE);
 	file_templates->set_access(FileDialog::ACCESS_FILESYSTEM);
 	file_templates->set_access(FileDialog::ACCESS_FILESYSTEM);
 	file_templates->clear_filters();
 	file_templates->clear_filters();
-	file_templates->add_filter("*.zip ; Zip Template Package");
+	file_templates->add_filter("*.tpz ; Template Package");
 
 
 
 
 	file = memnew( FileDialog );
 	file = memnew( FileDialog );

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