-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
This commit is contained in:
Juan Linietsky 2014-04-14 22:43:44 -03:00
parent 162d2ebe4f
commit ec4ef2d2e7
33 changed files with 1594 additions and 262 deletions

View file

@ -4,6 +4,7 @@
#include "io/marshalls.h"
#include "io/base64.h"
#include "core/globals.h"
#include "io/file_access_encrypted.h"
_ResourceLoader *_ResourceLoader::singleton=NULL;
@ -812,6 +813,44 @@ _Geometry::_Geometry() {
///////////////////////// 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) {
close();
@ -1113,6 +1152,10 @@ Variant _File::get_var() const {
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("close"),&_File::close);
ObjectTypeDB::bind_method(_MD("is_open"),&_File::is_open);

View file

@ -243,6 +243,10 @@ public:
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
void close(); ///< close a file
bool is_open() const; ///< true when file is open

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

@ -1,111 +1,97 @@
#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;
}
Error StreamPeerSSL::connect(const String &p_host,int p_port,int p_flags) {
int StreamPeerSSL::bio_destroy( BIO *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) {
if ( b == NULL ) return 0;
b->ptr = NULL; /* sb_tls_remove() will free it */
b->init = 0;
b->flags = 0;
return 1;
}
// 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());
int StreamPeerSSL::bio_read( BIO *b, char *buf, int len ) {
// Same as before, try to connect.
if (BIO_do_connect(bio) <= 0) {
if ( buf == NULL || len <= 0 ) return 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);
}
StreamPeerSSL * sp = (StreamPeerSSL*)b->ptr;
if (sp->base.is_null())
return 0;
// 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);
}
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 );
// 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;
}
}
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 );
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 );
// 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() {
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_gets( BIO *b, char *buf, int len ) {
return -1;
}
void StreamPeerSSL::finalize_ssl(){
int StreamPeerSSL::bio_puts( BIO *b, const char *str ) {
return StreamPeerSSL::bio_write( b, str, strlen( str ) );
}
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() {
}

View file

@ -1,26 +1,43 @@
#ifndef STREAM_PEER_SSL_H
#define STREAM_PEER_SSL_H
#include "io/stream_peer.h"
#ifdef OPENSSL_ENABLED
#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 {
OBJ_TYPE(StreamPeerSSL,StreamPeer);
public:
Ref<StreamPeer> base;
bool block;
static BIO_METHOD bio_methods;
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,
};
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:
Error connect(const String &p_host,int p_port);
static void initialize_ssl();
static void finalize_ssl();
StreamPeerSSL();
};
#endif
#endif // STREAM_PEER_SSL_H

View file

@ -1008,11 +1008,25 @@ bool Main::start() {
if (!editor) {
//standard helpers that can be changed from main config
if (GLOBAL_DEF("display/stretch_2d",false).operator bool()) {
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));
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);
}
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));
String appname = Globals::get_singleton()->get("application/name");
@ -1021,7 +1035,10 @@ bool Main::start() {
} 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));

View file

@ -5,6 +5,11 @@
android:versionName="1.0"
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">
<activity android:name="com.android.godot.Godot"
android:label="@string/godot_project_name_string"
@ -26,15 +31,173 @@ $$ADD_APPLICATION_CHUNKS$$
</application>
<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-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"/>
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="15"/>
</manifest>

View file

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

View file

@ -10,10 +10,169 @@
#include "os/os.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 {
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_debug_package;
@ -47,6 +206,10 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
Thread *device_thread;
Ref<ImageTexture> logo;
Set<String> perms;
String user_perms[MAX_USER_PERMISSIONS];
bool screen_support[SCREEN_MAX];
volatile bool quit_request;
@ -104,11 +267,33 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant&
_signed=p_value;
else if (n=="screen/orientation")
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")
release_keystore=p_value;
else if (n=="keystore/release_user")
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 true;
@ -132,15 +317,33 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret)
r_ret=_signed;
else if (n=="screen/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")
r_ret=release_keystore;
else if (n=="keystore/release_user")
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 true;
}
void EditorExportPlatformAndroid::_get_property_list( List<PropertyInfo> *p_list) const{
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::BOOL, "package/signed") );
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_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)"));
}
@ -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;
}
@ -1144,6 +1410,9 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
Image img( _android_logo );
logo = Ref<ImageTexture>( memnew( ImageTexture ));
logo->create_from_image(img);
for(int i=0;i<4;i++)
screen_support[i]=true;
}
bool EditorExportPlatformAndroid::can_export(String *r_error) const {

View file

@ -25,7 +25,11 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
});
};
/* public string requestPurchasedTicket(){
activity.getPaymentsManager()
}
*/
static public Godot.SingletonBase initialize(Activity 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(){

View file

@ -61,7 +61,7 @@ abstract public class HandlePurchaseTask {
pc.setConsumableFlag("block", productId, true);
pc.setConsumableValue("token", productId, purchaseToken);
success(purchaseToken, productId);
success(purchaseData);
return;
} catch (JSONException e) {
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 canceled();

View file

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

View file

@ -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 {
ERR_FAIL_COND_V(!is_inside_scene(),Matrix32());

View file

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

View file

@ -955,7 +955,7 @@ void Control::_window_input_event(InputEvent p_event) {
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) {
@ -1102,7 +1102,7 @@ void Control::_window_input_event(InputEvent p_event) {
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();
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));

View file

@ -516,7 +516,8 @@ bool SceneMainLoop::idle(float p_time){
last_screen_size=win_size;
root->set_rect(Rect2(Point2(),last_screen_size));
_update_root_rect();
emit_signal("screen_resized");
@ -849,6 +850,120 @@ int SceneMainLoop::get_node_count() const {
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() {
@ -874,6 +989,9 @@ void SceneMainLoop::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_frame"),&SceneMainLoop::get_frame);
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);
@ -899,6 +1017,14 @@ void SceneMainLoop::_bind_methods() {
BIND_CONSTANT( GROUP_CALL_REALTIME );
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() {
@ -927,6 +1053,9 @@ SceneMainLoop::SceneMainLoop() {
root->set_as_audio_listener(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 );
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);
}
}

View file

@ -50,6 +50,25 @@ class SceneMainLoop : public MainLoop {
_THREAD_SAFE_CLASS_
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 {
@ -95,6 +114,12 @@ class SceneMainLoop : public MainLoop {
Set<Node*> call_skip; //skip erased nodes
StretchMode stretch_mode;
StretchAspect stretch_aspect;
Size2i stretch_min;
void _update_root_rect();
List<ObjectID> delete_queue;
Map<UGCall,Vector<Variant> > unique_group_calls;
@ -152,7 +177,6 @@ public:
GROUP_CALL_MULIILEVEL=8,
};
_FORCE_INLINE_ Viewport *get_root() const { return root; }
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 set_screen_stretch(StretchMode p_mode,StretchAspect p_aspect,const Size2 p_minsize);
SceneMainLoop();
~SceneMainLoop();
};
VARIANT_ENUM_CAST( SceneMainLoop::StretchMode );
VARIANT_ENUM_CAST( SceneMainLoop::StretchAspect );
#endif

View file

@ -86,8 +86,9 @@ void Viewport::_update_stretch_transform() {
if (size_override_stretch && size_override) {
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 {
@ -629,7 +630,9 @@ Ref<World> Viewport::get_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;
else if (parent)
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() {
@ -918,15 +975,20 @@ void Viewport::_bind_methods() {
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("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("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::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_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") );
@ -969,6 +1031,7 @@ Viewport::Viewport() {
render_target_update_mode=RENDER_TARGET_UPDATE_WHEN_VISIBLE;
render_target_texture = Ref<RenderTargetTexture>( memnew( RenderTargetTexture(this) ) );
String id=itos(get_instance_ID());
input_group = "_vp_input"+id;
gui_input_group = "_vp_gui_input"+id;

View file

@ -101,6 +101,7 @@ friend class RenderTargetTexture;
Matrix32 stretch_transform;
Rect2 rect;
Rect2 to_screen_rect;
bool size_override;
@ -120,6 +121,7 @@ friend class RenderTargetTexture;
Ref<World2D> world_2d;
Ref<World> world;
Ref<World> own_world;
StringName input_group;
StringName gui_input_group;
@ -213,9 +215,15 @@ public:
void queue_screen_capture();
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 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();

View file

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

View file

@ -494,6 +494,7 @@ public:
};
virtual void canvas_begin()=0;
virtual void canvas_disable_blending()=0;
virtual void canvas_set_opacity(float p_opacity)=0;
virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode)=0;
virtual void canvas_begin_rect(const Matrix32& p_transform)=0;;

View file

@ -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) {

View file

@ -627,7 +627,7 @@ public:
virtual void begin_frame();
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 capture_viewport(Image* r_capture);
@ -652,6 +652,7 @@ public:
/* CANVAS API */
virtual void canvas_begin();
virtual void canvas_disable_blending();
virtual void canvas_set_opacity(float p_opacity);
virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode);
virtual void canvas_begin_rect(const Matrix32& p_transform);

View file

@ -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{
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() {
//draw viewports for render targets
List<Viewport*> to_blit;
List<Viewport*> to_disable;
for(SelfList<Viewport> *E=viewport_update_list.first();E;E=E->next()) {
@ -5472,6 +5483,9 @@ void VisualServerRaster::_draw_viewports() {
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);
_draw_viewport(vp,0,0,vp->rect.width,vp->rect.height);
@ -5491,6 +5505,38 @@ void VisualServerRaster::_draw_viewports() {
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
for(Map<RID,int>::Element *E=screen_viewports.front();E;E=E->next()) {

View file

@ -481,6 +481,8 @@ class VisualServerRaster : public VisualServer {
RID render_target;
RID render_target_texture;
Rect2 rt_to_screen_rect;
bool hide_scenario;
bool hide_canvas;
bool transparent_bg;
@ -913,6 +915,7 @@ public:
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 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 Image viewport_get_screen_capture(RID p_viewport) const;

View file

@ -891,6 +891,7 @@ public:
FUNC2(viewport_set_render_target_vflip,RID,bool);
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);
FUNC1RC(Image,viewport_get_screen_capture,RID);

View file

@ -592,6 +592,7 @@ public:
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_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect)=0;
enum RenderTargetUpdateMode {
RENDER_TARGET_UPDATE_DISABLED,
@ -611,6 +612,8 @@ public:
virtual void viewport_queue_screen_capture(RID p_viewport)=0;
virtual Image viewport_get_screen_capture(RID p_viewport) const=0;
struct ViewportRect {
int x,y,width,height;

View file

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