summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/SCsub3
-rw-r--r--platform/android/android_native_app_glue.c437
-rw-r--r--platform/android/android_native_app_glue.h351
-rw-r--r--platform/android/audio_driver_jandroid.cpp4
-rw-r--r--platform/android/audio_driver_jandroid.h3
-rw-r--r--platform/android/dir_access_android.cpp190
-rw-r--r--platform/android/dir_access_android.h80
-rw-r--r--platform/android/dir_access_jandroid.cpp3
-rw-r--r--platform/android/dir_access_jandroid.h3
-rw-r--r--platform/android/export/export.cpp22
-rw-r--r--platform/android/file_access_jandroid.cpp4
-rw-r--r--platform/android/file_access_jandroid.h4
-rw-r--r--platform/android/godot_android.cpp937
-rw-r--r--platform/android/java_glue.cpp3
-rw-r--r--platform/android/java_glue.h3
-rw-r--r--platform/android/os_android.cpp19
-rw-r--r--platform/android/os_android.h6
-rwxr-xr-xplatform/android/sign.sh9
-rw-r--r--platform/iphone/export/export.cpp88
-rw-r--r--platform/iphone/gl_view.mm3
-rw-r--r--platform/javascript/audio_driver_javascript.cpp104
-rw-r--r--platform/javascript/audio_driver_javascript.h7
-rw-r--r--platform/javascript/detect.py1
-rw-r--r--platform/osx/export/export.cpp166
-rw-r--r--platform/uwp/export/export.cpp2
-rw-r--r--platform/windows/detect.py4
-rw-r--r--platform/windows/os_windows.cpp38
-rw-r--r--platform/windows/os_windows.h1
-rw-r--r--platform/x11/os_x11.cpp10
29 files changed, 384 insertions, 2121 deletions
diff --git a/platform/android/SCsub b/platform/android/SCsub
index da2219b9e4..6d5af99bc5 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -10,9 +10,7 @@ from detect import get_ndk_version
android_files = [
'os_android.cpp',
- 'godot_android.cpp',
'file_access_android.cpp',
- 'dir_access_android.cpp',
'audio_driver_opensl.cpp',
'file_access_jandroid.cpp',
'dir_access_jandroid.cpp',
@@ -25,7 +23,6 @@ android_files = [
thirdparty_files = [
'ifaddrs_android.cpp',
- 'android_native_app_glue.c',
'cpu-features.c',
]
diff --git a/platform/android/android_native_app_glue.c b/platform/android/android_native_app_glue.c
deleted file mode 100644
index 965f6284cd..0000000000
--- a/platform/android/android_native_app_glue.c
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifdef ANDROID_NATIVE_ACTIVITY
-
-#include <jni.h>
-
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/resource.h>
-
-#include "android_native_app_glue.h"
-#include <android/log.h>
-
-#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
-
-static void free_saved_state(struct android_app* android_app) {
- pthread_mutex_lock(&android_app->mutex);
- if (android_app->savedState != NULL) {
- free(android_app->savedState);
- android_app->savedState = NULL;
- android_app->savedStateSize = 0;
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-int8_t android_app_read_cmd(struct android_app* android_app) {
- int8_t cmd;
- if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
- switch (cmd) {
- case APP_CMD_SAVE_STATE:
- free_saved_state(android_app);
- break;
- }
- return cmd;
- } else {
- LOGI("No data on command pipe!");
- }
- return -1;
-}
-
-static void print_cur_config(struct android_app* android_app) {
- char lang[2], country[2];
- AConfiguration_getLanguage(android_app->config, lang);
- AConfiguration_getCountry(android_app->config, country);
-
- LOGI("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
- "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
- "modetype=%d modenight=%d",
- AConfiguration_getMcc(android_app->config),
- AConfiguration_getMnc(android_app->config),
- lang[0], lang[1], country[0], country[1],
- AConfiguration_getOrientation(android_app->config),
- AConfiguration_getTouchscreen(android_app->config),
- AConfiguration_getDensity(android_app->config),
- AConfiguration_getKeyboard(android_app->config),
- AConfiguration_getNavigation(android_app->config),
- AConfiguration_getKeysHidden(android_app->config),
- AConfiguration_getNavHidden(android_app->config),
- AConfiguration_getSdkVersion(android_app->config),
- AConfiguration_getScreenSize(android_app->config),
- AConfiguration_getScreenLong(android_app->config),
- AConfiguration_getUiModeType(android_app->config),
- AConfiguration_getUiModeNight(android_app->config));
-}
-
-void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
- switch (cmd) {
- case APP_CMD_INPUT_CHANGED:
- LOGI("APP_CMD_INPUT_CHANGED\n");
- pthread_mutex_lock(&android_app->mutex);
- if (android_app->inputQueue != NULL) {
- AInputQueue_detachLooper(android_app->inputQueue);
- }
- android_app->inputQueue = android_app->pendingInputQueue;
- if (android_app->inputQueue != NULL) {
- LOGI("Attaching input queue to looper");
- AInputQueue_attachLooper(android_app->inputQueue,
- android_app->looper, LOOPER_ID_INPUT, NULL,
- &android_app->inputPollSource);
- }
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_INIT_WINDOW:
- LOGI("APP_CMD_INIT_WINDOW\n");
- pthread_mutex_lock(&android_app->mutex);
- android_app->window = android_app->pendingWindow;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_TERM_WINDOW:
- LOGI("APP_CMD_TERM_WINDOW\n");
- pthread_cond_broadcast(&android_app->cond);
- break;
-
- case APP_CMD_RESUME:
- case APP_CMD_START:
- case APP_CMD_PAUSE:
- case APP_CMD_STOP:
- LOGI("activityState=%d\n", cmd);
- pthread_mutex_lock(&android_app->mutex);
- android_app->activityState = cmd;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_CONFIG_CHANGED:
- LOGI("APP_CMD_CONFIG_CHANGED\n");
- AConfiguration_fromAssetManager(android_app->config,
- android_app->activity->assetManager);
- print_cur_config(android_app);
- break;
-
- case APP_CMD_DESTROY:
- LOGI("APP_CMD_DESTROY\n");
- android_app->destroyRequested = 1;
- break;
- }
-}
-
-void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
- switch (cmd) {
- case APP_CMD_TERM_WINDOW:
- LOGI("APP_CMD_TERM_WINDOW\n");
- pthread_mutex_lock(&android_app->mutex);
- android_app->window = NULL;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_SAVE_STATE:
- LOGI("APP_CMD_SAVE_STATE\n");
- pthread_mutex_lock(&android_app->mutex);
- android_app->stateSaved = 1;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_RESUME:
- free_saved_state(android_app);
- break;
- }
-}
-
-void app_dummy() {
-
-}
-
-static void android_app_destroy(struct android_app* android_app) {
- LOGI("android_app_destroy!");
- free_saved_state(android_app);
- pthread_mutex_lock(&android_app->mutex);
- if (android_app->inputQueue != NULL) {
- AInputQueue_detachLooper(android_app->inputQueue);
- }
- AConfiguration_delete(android_app->config);
- android_app->destroyed = 1;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- // Can't touch android_app object after this.
-}
-
-static void process_input(struct android_app* app, struct android_poll_source* source) {
- AInputEvent* event = NULL;
- if (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
- LOGI("New input event: type=%d\n", AInputEvent_getType(event));
- if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
- return;
- }
- int32_t handled = 0;
- if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
- AInputQueue_finishEvent(app->inputQueue, event, handled);
- } else {
- LOGI("Failure reading next input event: %s\n", strerror(errno));
- }
-}
-
-static void process_cmd(struct android_app* app, struct android_poll_source* source) {
- int8_t cmd = android_app_read_cmd(app);
- android_app_pre_exec_cmd(app, cmd);
- if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
- android_app_post_exec_cmd(app, cmd);
-}
-
-static void* android_app_entry(void* param) {
- struct android_app* android_app = (struct android_app*)param;
-
- android_app->config = AConfiguration_new();
- AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
-
- print_cur_config(android_app);
-
- android_app->cmdPollSource.id = LOOPER_ID_MAIN;
- android_app->cmdPollSource.app = android_app;
- android_app->cmdPollSource.process = process_cmd;
- android_app->inputPollSource.id = LOOPER_ID_INPUT;
- android_app->inputPollSource.app = android_app;
- android_app->inputPollSource.process = process_input;
-
- ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
- ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
- &android_app->cmdPollSource);
- android_app->looper = looper;
-
- pthread_mutex_lock(&android_app->mutex);
- android_app->running = 1;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
-
- android_main(android_app);
-
- android_app_destroy(android_app);
- return NULL;
-}
-
-// --------------------------------------------------------------------
-// Native activity interaction (called from main thread)
-// --------------------------------------------------------------------
-
-static struct android_app* android_app_create(ANativeActivity* activity,
- void* savedState, size_t savedStateSize) {
- struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
- memset(android_app, 0, sizeof(struct android_app));
- android_app->activity = activity;
-
- pthread_mutex_init(&android_app->mutex, NULL);
- pthread_cond_init(&android_app->cond, NULL);
-
- if (savedState != NULL) {
- android_app->savedState = malloc(savedStateSize);
- android_app->savedStateSize = savedStateSize;
- memcpy(android_app->savedState, savedState, savedStateSize);
- }
-
- int msgpipe[2];
- if (pipe(msgpipe)) {
- LOGI("could not create pipe: %s", strerror(errno));
- }
- android_app->msgread = msgpipe[0];
- android_app->msgwrite = msgpipe[1];
-
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
-
- // Wait for thread to start.
- pthread_mutex_lock(&android_app->mutex);
- while (!android_app->running) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-
- return android_app;
-}
-
-static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
- if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
- LOGI("Failure writing android_app cmd: %s\n", strerror(errno));
- }
-}
-
-static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
- pthread_mutex_lock(&android_app->mutex);
- android_app->pendingInputQueue = inputQueue;
- android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
- while (android_app->inputQueue != android_app->pendingInputQueue) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
- pthread_mutex_lock(&android_app->mutex);
- if (android_app->pendingWindow != NULL) {
- android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
- }
- android_app->pendingWindow = window;
- if (window != NULL) {
- android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
- }
- while (android_app->window != android_app->pendingWindow) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
- pthread_mutex_lock(&android_app->mutex);
- android_app_write_cmd(android_app, cmd);
- while (android_app->activityState != cmd) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-static void android_app_free(struct android_app* android_app) {
- pthread_mutex_lock(&android_app->mutex);
- android_app_write_cmd(android_app, APP_CMD_DESTROY);
- while (!android_app->destroyed) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-
- close(android_app->msgread);
- close(android_app->msgwrite);
- pthread_cond_destroy(&android_app->cond);
- pthread_mutex_destroy(&android_app->mutex);
- free(android_app);
-}
-
-static void onDestroy(ANativeActivity* activity) {
- LOGI("Destroy: %p\n", activity);
- android_app_free((struct android_app*)activity->instance);
-}
-
-static void onStart(ANativeActivity* activity) {
- LOGI("Start: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
-}
-
-static void onResume(ANativeActivity* activity) {
- LOGI("Resume: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
-}
-
-static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
- struct android_app* android_app = (struct android_app*)activity->instance;
- void* savedState = NULL;
-
- LOGI("SaveInstanceState: %p\n", activity);
- pthread_mutex_lock(&android_app->mutex);
- android_app->stateSaved = 0;
- android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
- while (!android_app->stateSaved) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
-
- if (android_app->savedState != NULL) {
- savedState = android_app->savedState;
- *outLen = android_app->savedStateSize;
- android_app->savedState = NULL;
- android_app->savedStateSize = 0;
- }
-
- pthread_mutex_unlock(&android_app->mutex);
-
- return savedState;
-}
-
-static void onPause(ANativeActivity* activity) {
- LOGI("Pause: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
-}
-
-static void onStop(ANativeActivity* activity) {
- LOGI("Stop: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
-}
-
-static void onConfigurationChanged(ANativeActivity* activity) {
- struct android_app* android_app = (struct android_app*)activity->instance;
- LOGI("ConfigurationChanged: %p\n", activity);
- android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
-}
-
-static void onLowMemory(ANativeActivity* activity) {
- struct android_app* android_app = (struct android_app*)activity->instance;
- LOGI("LowMemory: %p\n", activity);
- android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);
-}
-
-static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
- LOGI("WindowFocusChanged: %p -- %d\n", activity, focused);
- android_app_write_cmd((struct android_app*)activity->instance,
- focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
-}
-
-static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
- LOGI("NativeWindowCreated: %p -- %p\n", activity, window);
- android_app_set_window((struct android_app*)activity->instance, window);
-}
-
-static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
- LOGI("NativeWindowDestroyed: %p -- %p\n", activity, window);
- android_app_set_window((struct android_app*)activity->instance, NULL);
-}
-
-static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
- LOGI("InputQueueCreated: %p -- %p\n", activity, queue);
- android_app_set_input((struct android_app*)activity->instance, queue);
-}
-
-static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
- LOGI("InputQueueDestroyed: %p -- %p\n", activity, queue);
- android_app_set_input((struct android_app*)activity->instance, NULL);
-}
-
-void ANativeActivity_onCreate(ANativeActivity* activity,
- void* savedState, size_t savedStateSize) {
- LOGI("Creating: %p\n", activity);
- activity->callbacks->onDestroy = onDestroy;
- activity->callbacks->onStart = onStart;
- activity->callbacks->onResume = onResume;
- activity->callbacks->onSaveInstanceState = onSaveInstanceState;
- activity->callbacks->onPause = onPause;
- activity->callbacks->onStop = onStop;
- activity->callbacks->onConfigurationChanged = onConfigurationChanged;
- activity->callbacks->onLowMemory = onLowMemory;
- activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
- activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
- activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
- activity->callbacks->onInputQueueCreated = onInputQueueCreated;
- activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
-
- activity->instance = android_app_create(activity, savedState, savedStateSize);
-}
-#endif
diff --git a/platform/android/android_native_app_glue.h b/platform/android/android_native_app_glue.h
deleted file mode 100644
index 36278d4c66..0000000000
--- a/platform/android/android_native_app_glue.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef _ANDROID_NATIVE_APP_GLUE_H
-#define _ANDROID_NATIVE_APP_GLUE_H
-#ifdef ANDROID_NATIVE_ACTIVITY
-
-#include <poll.h>
-#include <pthread.h>
-#include <sched.h>
-
-#include <android/configuration.h>
-#include <android/looper.h>
-#include <android/native_activity.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * The native activity interface provided by <android/native_activity.h>
- * is based on a set of application-provided callbacks that will be called
- * by the Activity's main thread when certain events occur.
- *
- * This means that each one of this callbacks _should_ _not_ block, or they
- * risk having the system force-close the application. This programming
- * model is direct, lightweight, but constraining.
- *
- * The 'threaded_native_app' static library is used to provide a different
- * execution model where the application can implement its own main event
- * loop in a different thread instead. Here's how it works:
- *
- * 1/ The application must provide a function named "android_main()" that
- * will be called when the activity is created, in a new thread that is
- * distinct from the activity's main thread.
- *
- * 2/ android_main() receives a pointer to a valid "android_app" structure
- * that contains references to other important objects, e.g. the
- * ANativeActivity obejct instance the application is running in.
- *
- * 3/ the "android_app" object holds an ALooper instance that already
- * listens to two important things:
- *
- * - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
- * declarations below.
- *
- * - input events coming from the AInputQueue attached to the activity.
- *
- * Each of these correspond to an ALooper identifier returned by
- * ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
- * respectively.
- *
- * Your application can use the same ALooper to listen to additional
- * file-descriptors. They can either be callback based, or with return
- * identifiers starting with LOOPER_ID_USER.
- *
- * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
- * the returned data will point to an android_poll_source structure. You
- * can call the process() function on it, and fill in android_app->onAppCmd
- * and android_app->onInputEvent to be called for your own processing
- * of the event.
- *
- * Alternatively, you can call the low-level functions to read and process
- * the data directly... look at the process_cmd() and process_input()
- * implementations in the glue to see how to do this.
- *
- * See the sample named "native-activity" that comes with the NDK with a
- * full usage example. Also look at the JavaDoc of NativeActivity.
- */
-
-struct android_app;
-
-/**
- * Data associated with an ALooper fd that will be returned as the "outData"
- * when that source has data ready.
- */
-struct android_poll_source {
- // The identifier of this source. May be LOOPER_ID_MAIN or
- // LOOPER_ID_INPUT.
- int32_t id;
-
- // The android_app this ident is associated with.
- struct android_app* app;
-
- // Function to call to perform the standard processing of data from
- // this source.
- void (*process)(struct android_app* app, struct android_poll_source* source);
-};
-
-/**
- * This is the interface for the standard glue code of a threaded
- * application. In this model, the application's code is running
- * in its own thread separate from the main thread of the process.
- * It is not required that this thread be associated with the Java
- * VM, although it will need to be in order to make JNI calls any
- * Java objects.
- */
-struct android_app {
- // The application can place a pointer to its own state object
- // here if it likes.
- void* userData;
-
- // Fill this in with the function to process main app commands (APP_CMD_*)
- void (*onAppCmd)(struct android_app* app, int32_t cmd);
-
- // Fill this in with the function to process input events. At this point
- // the event has already been pre-dispatched, and it will be finished upon
- // return. Return 1 if you have handled the event, 0 for any default
- // dispatching.
- int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
-
- // The ANativeActivity object instance that this app is running in.
- ANativeActivity* activity;
-
- // The current configuration the app is running in.
- AConfiguration* config;
-
- // This is the last instance's saved state, as provided at creation time.
- // It is NULL if there was no state. You can use this as you need; the
- // memory will remain around until you call android_app_exec_cmd() for
- // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
- // These variables should only be changed when processing a APP_CMD_SAVE_STATE,
- // at which point they will be initialized to NULL and you can malloc your
- // state and place the information here. In that case the memory will be
- // freed for you later.
- void* savedState;
- size_t savedStateSize;
-
- // The ALooper associated with the app's thread.
- ALooper* looper;
-
- // When non-NULL, this is the input queue from which the app will
- // receive user input events.
- AInputQueue* inputQueue;
-
- // When non-NULL, this is the window surface that the app can draw in.
- ANativeWindow* window;
-
- // Current content rectangle of the window; this is the area where the
- // window's content should be placed to be seen by the user.
- ARect contentRect;
-
- // Current state of the app's activity. May be either APP_CMD_START,
- // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
- int activityState;
-
- // This is non-zero when the application's NativeActivity is being
- // destroyed and waiting for the app thread to complete.
- int destroyRequested;
-
- // -------------------------------------------------
- // Below are "private" implementation of the glue code.
-
- pthread_mutex_t mutex;
- pthread_cond_t cond;
-
- int msgread;
- int msgwrite;
-
- pthread_t thread;
-
- struct android_poll_source cmdPollSource;
- struct android_poll_source inputPollSource;
-
- int running;
- int stateSaved;
- int destroyed;
- int redrawNeeded;
- AInputQueue* pendingInputQueue;
- ANativeWindow* pendingWindow;
- ARect pendingContentRect;
-};
-
-enum {
- /**
- * Looper data ID of commands coming from the app's main thread, which
- * is returned as an identifier from ALooper_pollOnce(). The data for this
- * identifier is a pointer to an android_poll_source structure.
- * These can be retrieved and processed with android_app_read_cmd()
- * and android_app_exec_cmd().
- */
- LOOPER_ID_MAIN = 1,
-
- /**
- * Looper data ID of events coming from the AInputQueue of the
- * application's window, which is returned as an identifier from
- * ALooper_pollOnce(). The data for this identifier is a pointer to an
- * android_poll_source structure. These can be read via the inputQueue
- * object of android_app.
- */
- LOOPER_ID_INPUT = 2,
-
- /**
- * Start of user-defined ALooper identifiers.
- */
- LOOPER_ID_USER = 3,
-};
-
-enum {
- /**
- * Command from main thread: the AInputQueue has changed. Upon processing
- * this command, android_app->inputQueue will be updated to the new queue
- * (or NULL).
- */
- APP_CMD_INPUT_CHANGED,
-
- /**
- * Command from main thread: a new ANativeWindow is ready for use. Upon
- * receiving this command, android_app->window will contain the new window
- * surface.
- */
- APP_CMD_INIT_WINDOW,
-
- /**
- * Command from main thread: the existing ANativeWindow needs to be
- * terminated. Upon receiving this command, android_app->window still
- * contains the existing window; after calling android_app_exec_cmd
- * it will be set to NULL.
- */
- APP_CMD_TERM_WINDOW,
-
- /**
- * Command from main thread: the current ANativeWindow has been resized.
- * Please redraw with its new size.
- */
- APP_CMD_WINDOW_RESIZED,
-
- /**
- * Command from main thread: the system needs that the current ANativeWindow
- * be redrawn. You should redraw the window before handing this to
- * android_app_exec_cmd() in order to avoid transient drawing glitches.
- */
- APP_CMD_WINDOW_REDRAW_NEEDED,
-
- /**
- * Command from main thread: the content area of the window has changed,
- * such as from the soft input window being shown or hidden. You can
- * find the new content rect in android_app::contentRect.
- */
- APP_CMD_CONTENT_RECT_CHANGED,
-
- /**
- * Command from main thread: the app's activity window has gained
- * input focus.
- */
- APP_CMD_GAINED_FOCUS,
-
- /**
- * Command from main thread: the app's activity window has lost
- * input focus.
- */
- APP_CMD_LOST_FOCUS,
-
- /**
- * Command from main thread: the current device configuration has changed.
- */
- APP_CMD_CONFIG_CHANGED,
-
- /**
- * Command from main thread: the system is running low on memory.
- * Try to reduce your memory use.
- */
- APP_CMD_LOW_MEMORY,
-
- /**
- * Command from main thread: the app's activity has been started.
- */
- APP_CMD_START,
-
- /**
- * Command from main thread: the app's activity has been resumed.
- */
- APP_CMD_RESUME,
-
- /**
- * Command from main thread: the app should generate a new saved state
- * for itself, to restore from later if needed. If you have saved state,
- * allocate it with malloc and place it in android_app.savedState with
- * the size in android_app.savedStateSize. The will be freed for you
- * later.
- */
- APP_CMD_SAVE_STATE,
-
- /**
- * Command from main thread: the app's activity has been paused.
- */
- APP_CMD_PAUSE,
-
- /**
- * Command from main thread: the app's activity has been stopped.
- */
- APP_CMD_STOP,
-
- /**
- * Command from main thread: the app's activity is being destroyed,
- * and waiting for the app thread to clean up and exit before proceeding.
- */
- APP_CMD_DESTROY,
-};
-
-/**
- * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
- * app command message.
- */
-int8_t android_app_read_cmd(struct android_app* android_app);
-
-/**
- * Call with the command returned by android_app_read_cmd() to do the
- * initial pre-processing of the given command. You can perform your own
- * actions for the command after calling this function.
- */
-void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
-
-/**
- * Call with the command returned by android_app_read_cmd() to do the
- * final post-processing of the given command. You must have done your own
- * actions for the command before calling this function.
- */
-void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
-
-/**
- * Dummy function you can call to ensure glue code isn't stripped.
- */
-void app_dummy();
-
-/**
- * This is the function that application code must implement, representing
- * the main entry to the app.
- */
-extern void android_main(struct android_app* app);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ANDROID_NATIVE_APP_GLUE_H */
-#endif
diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp
index 4fab40d534..b75a4a3869 100644
--- a/platform/android/audio_driver_jandroid.cpp
+++ b/platform/android/audio_driver_jandroid.cpp
@@ -34,8 +34,6 @@
#include "core/project_settings.h"
#include "thread_jandroid.h"
-#ifndef ANDROID_NATIVE_ACTIVITY
-
AudioDriverAndroid *AudioDriverAndroid::s_ad = NULL;
jobject AudioDriverAndroid::io;
@@ -204,5 +202,3 @@ AudioDriverAndroid::AudioDriverAndroid() {
s_ad = this;
active = false;
}
-
-#endif
diff --git a/platform/android/audio_driver_jandroid.h b/platform/android/audio_driver_jandroid.h
index 763f0e9b5a..3c51ed746d 100644
--- a/platform/android/audio_driver_jandroid.h
+++ b/platform/android/audio_driver_jandroid.h
@@ -33,8 +33,6 @@
#include "servers/audio_server.h"
-#ifndef ANDROID_NATIVE_ACTIVITY
-
#include "java_glue.h"
class AudioDriverAndroid : public AudioDriver {
@@ -78,5 +76,4 @@ public:
AudioDriverAndroid();
};
-#endif
#endif // AUDIO_DRIVER_ANDROID_H
diff --git a/platform/android/dir_access_android.cpp b/platform/android/dir_access_android.cpp
deleted file mode 100644
index 402da4527e..0000000000
--- a/platform/android/dir_access_android.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/*************************************************************************/
-/* dir_access_android.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifdef ANDROID_NATIVE_ACTIVITY
-#include "dir_access_android.h"
-#include "file_access_android.h"
-
-DirAccess *DirAccessAndroid::create_fs() {
-
- return memnew(DirAccessAndroid);
-}
-
-Error DirAccessAndroid::list_dir_begin() {
-
- list_dir_end();
-
- AAssetDir *aad = AAssetManager_openDir(FileAccessAndroid::asset_manager, current_dir.utf8().get_data());
- if (!aad)
- return ERR_CANT_OPEN; //nothing
-
- return OK;
-}
-
-String DirAccessAndroid::get_next() {
-
- const char *fn = AAssetDir_getNextFileName(aad);
- if (!fn)
- return "";
- String s;
- s.parse_utf8(fn);
- current = s;
- return s;
-}
-
-bool DirAccessAndroid::current_is_dir() const {
-
- String sd;
- if (current_dir == "")
- sd = current;
- else
- sd = current_dir + "/" + current;
-
- AAssetDir *aad2 = AAssetManager_openDir(FileAccessAndroid::asset_manager, sd.utf8().get_data());
- if (aad2) {
-
- AAssetDir_close(aad2);
- return true;
- }
-
- return false;
-}
-
-bool DirAccessAndroid::current_is_hidden() const {
- return current != "." && current != ".." && current.begins_with(".");
-}
-
-void DirAccessAndroid::list_dir_end() {
-
- if (aad == NULL)
- return;
-
- AAssetDir_close(aad);
- aad = NULL;
-}
-
-int DirAccessAndroid::get_drive_count() {
-
- return 0;
-}
-
-String DirAccessAndroid::get_drive(int p_drive) {
-
- return "";
-}
-
-Error DirAccessAndroid::change_dir(String p_dir) {
-
- p_dir = p_dir.simplify_path();
-
- if (p_dir == "" || p_dir == "." || (p_dir == ".." && current_dir == ""))
- return OK;
-
- String new_dir;
-
- if (p_dir.begins_with("/"))
- new_dir = p_dir.substr(1, p_dir.length());
- else if (p_dir.begins_with("res://"))
- new_dir = p_dir.substr(6, p_dir.length());
- else //relative
- new_dir = new_dir + "/" + p_dir;
-
- //test if newdir exists
- new_dir = new_dir.simplify_path();
-
- AAssetDir *aad = AAssetManager_openDir(FileAccessAndroid::asset_manager, new_dir.utf8().get_data());
- if (aad) {
-
- current_dir = new_dir;
- AAssetDir_close(aad);
- return OK;
- }
-
- return ERR_INVALID_PARAMETER;
-}
-
-String DirAccessAndroid::get_current_dir() {
-
- return "/" + current_dir;
-}
-
-bool DirAccessAndroid::file_exists(String p_file) {
-
- String sd;
- if (current_dir == "")
- sd = p_file;
- else
- sd = current_dir + "/" + p_file;
-
- AAsset *a = AAssetManager_open(FileAccessAndroid::asset_manager, sd.utf8().get_data(), AASSET_MODE_STREAMING);
- if (a) {
- AAsset_close(a);
- return true;
- }
-
- return false;
-}
-
-Error DirAccessAndroid::make_dir(String p_dir) {
-
- ERR_FAIL_V(ERR_UNAVAILABLE);
-}
-
-Error DirAccessAndroid::rename(String p_from, String p_to) {
-
- ERR_FAIL_V(ERR_UNAVAILABLE);
-}
-
-Error DirAccessAndroid::remove(String p_name) {
-
- ERR_FAIL_V(ERR_UNAVAILABLE);
-}
-
-//FileType get_file_type() const;
-size_t DirAccessAndroid::get_space_left() {
-
- return 0;
-}
-
-void DirAccessAndroid::make_default() {
-
- instance_func = create_fs;
-}
-
-DirAccessAndroid::DirAccessAndroid() {
-
- aad = NULL;
-}
-
-DirAccessAndroid::~DirAccessAndroid() {
-
- list_dir_end();
-}
-#endif
diff --git a/platform/android/dir_access_android.h b/platform/android/dir_access_android.h
deleted file mode 100644
index 3ac0bd6332..0000000000
--- a/platform/android/dir_access_android.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*************************************************************************/
-/* dir_access_android.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef DIR_ACCESS_ANDROID_H
-#define DIR_ACCESS_ANDROID_H
-
-#ifdef ANDROID_NATIVE_ACTIVITY
-
-#include "core/os/dir_access.h"
-#include <android/asset_manager.h>
-#include <android/log.h>
-#include <android_native_app_glue.h>
-#include <stdio.h>
-
-class DirAccessAndroid : public DirAccess {
-
- AAssetDir *aad;
- String current_dir;
- String current;
-
- static DirAccess *create_fs();
-
-public:
- virtual Error list_dir_begin(); ///< This starts dir listing
- virtual String get_next();
- virtual bool current_is_dir() const;
- virtual bool current_is_hidden() const;
- virtual void list_dir_end(); ///<
-
- virtual int get_drive_count();
- virtual String get_drive(int p_drive);
-
- virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
- virtual String get_current_dir(); ///< return current dir location
-
- virtual bool file_exists(String p_file);
-
- virtual Error make_dir(String p_dir);
-
- virtual Error rename(String p_from, String p_to);
- virtual Error remove(String p_name);
-
- //virtual FileType get_file_type() const;
- size_t get_space_left();
-
- static void make_default();
-
- DirAccessAndroid();
- ~DirAccessAndroid();
-};
-
-#endif
-#endif // DIR_ACCESS_ANDROID_H
diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index 6a95277585..679a13217f 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef ANDROID_NATIVE_ACTIVITY
-
#include "dir_access_jandroid.h"
#include "core/print_string.h"
#include "file_access_jandroid.h"
@@ -245,4 +243,3 @@ DirAccessJAndroid::~DirAccessJAndroid() {
list_dir_end();
}
-#endif
diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h
index 1653fb0aa5..ea1e11a4f1 100644
--- a/platform/android/dir_access_jandroid.h
+++ b/platform/android/dir_access_jandroid.h
@@ -31,8 +31,6 @@
#ifndef DIR_ACCESS_JANDROID_H
#define DIR_ACCESS_JANDROID_H
-#ifndef ANDROID_NATIVE_ACTIVITY
-
#include "core/os/dir_access.h"
#include "java_glue.h"
#include <stdio.h>
@@ -87,4 +85,3 @@ public:
};
#endif // DIR_ACCESS_JANDROID_H
-#endif
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 3766f732e4..a3b5b6dd58 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -672,10 +672,13 @@ class EditorExportAndroid : public EditorExportPlatform {
aperms++;
}
- for (int i = 0; i < MAX_USER_PERMISSIONS; i++) {
- String user_perm = p_preset->get("user_permissions/" + itos(i));
- if (user_perm.strip_edges() != "" && user_perm.strip_edges() != "False")
- perms.push_back(user_perm.strip_edges());
+ PoolStringArray user_perms = p_preset->get("permissions/custom_permissions");
+
+ for (int i = 0; i < user_perms.size(); i++) {
+ String user_perm = user_perms[i].strip_edges();
+ if (!user_perm.empty()) {
+ perms.push_back(user_perm);
+ }
}
if (p_give_internet) {
@@ -1104,10 +1107,6 @@ class EditorExportAndroid : public EditorExportPlatform {
}
public:
- enum {
- MAX_USER_PERMISSIONS = 20
- };
-
typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total);
public:
@@ -1169,17 +1168,14 @@ public:
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "architectures/" + abi), is_default));
}
+ r_options->push_back(ExportOption(PropertyInfo(Variant::POOL_STRING_ARRAY, "permissions/custom_permissions"), PoolStringArray()));
+
const char **perms = android_perms;
while (*perms) {
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "permissions/" + String(*perms).to_lower()), false));
perms++;
}
-
- for (int i = 0; i < MAX_USER_PERMISSIONS; i++) {
-
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "user_permissions/" + itos(i)), false));
- }
}
virtual String get_name() const {
diff --git a/platform/android/file_access_jandroid.cpp b/platform/android/file_access_jandroid.cpp
index 573200bcf9..bba45ffc1d 100644
--- a/platform/android/file_access_jandroid.cpp
+++ b/platform/android/file_access_jandroid.cpp
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef ANDROID_NATIVE_ACTIVITY
-
#include "file_access_jandroid.h"
#include "core/os/os.h"
#include "thread_jandroid.h"
@@ -212,5 +210,3 @@ FileAccessJAndroid::~FileAccessJAndroid() {
if (is_open())
close();
}
-
-#endif
diff --git a/platform/android/file_access_jandroid.h b/platform/android/file_access_jandroid.h
index 39c201ba85..98486702ab 100644
--- a/platform/android/file_access_jandroid.h
+++ b/platform/android/file_access_jandroid.h
@@ -31,8 +31,6 @@
#ifndef FILE_ACCESS_JANDROID_H
#define FILE_ACCESS_JANDROID_H
-#ifndef ANDROID_NATIVE_ACTIVITY
-
#include "core/os/file_access.h"
#include "java_glue.h"
class FileAccessJAndroid : public FileAccess {
@@ -81,6 +79,4 @@ public:
~FileAccessJAndroid();
};
-#endif
-
#endif // FILE_ACCESS_JANDROID_H
diff --git a/platform/android/godot_android.cpp b/platform/android/godot_android.cpp
deleted file mode 100644
index c46c6f7804..0000000000
--- a/platform/android/godot_android.cpp
+++ /dev/null
@@ -1,937 +0,0 @@
-/*************************************************************************/
-/* godot_android.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifdef ANDROID_NATIVE_ACTIVITY
-
-#include "core/engine.h"
-#include "core/project_settings.h"
-#include "file_access_android.h"
-#include "main/main.h"
-#include "os_android.h"
-
-#include <EGL/egl.h>
-#include <android/log.h>
-#include <android/sensor.h>
-#include <android/window.h>
-#include <android_native_app_glue.h>
-#include <errno.h>
-#include <jni.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "godot", __VA_ARGS__))
-#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "godot", __VA_ARGS__))
-
-extern "C" {
-JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerSingleton(JNIEnv *env, jobject obj, jstring name, jobject p_object);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerMethod(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args);
-JNIEXPORT jstring JNICALL Java_org_godotengine_godot_Godot_getGlobal(JNIEnv *env, jobject obj, jstring path);
-};
-
-class JNISingleton : public Object {
-
- GDCLASS(JNISingleton, Object);
-
- struct MethodData {
-
- jmethodID method;
- Variant::Type ret_type;
- Vector<Variant::Type> argtypes;
- };
-
- jobject instance;
- Map<StringName, MethodData> method_map;
- JNIEnv *env;
-
-public:
- void update_env(JNIEnv *p_env) { env = p_env; }
-
- virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
-
- r_error.error = Variant::CallError::CALL_OK;
-
- Map<StringName, MethodData>::Element *E = method_map.find(p_method);
- if (!E) {
-
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
- return Variant();
- }
-
- int ac = E->get().argtypes.size();
- if (ac < p_argcount) {
-
- r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = ac;
- return Variant();
- }
-
- if (ac > p_argcount) {
-
- r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
- r_error.argument = ac;
- return Variant();
- }
-
- for (int i = 0; i < p_argcount; i++) {
-
- if (!Variant::can_convert(p_args[i]->get_type(), E->get().argtypes[i])) {
-
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = i;
- r_error.expected = E->get().argtypes[i];
- }
- }
-
- jvalue *v = NULL;
-
- if (p_argcount) {
-
- v = (jvalue *)alloca(sizeof(jvalue) * p_argcount);
- }
-
- for (int i = 0; i < p_argcount; i++) {
-
- switch (E->get().argtypes[i]) {
-
- case Variant::BOOL: {
-
- v[i].z = *p_args[i];
- } break;
- case Variant::INT: {
-
- v[i].i = *p_args[i];
- } break;
- case Variant::REAL: {
-
- v[i].f = *p_args[i];
- } break;
- case Variant::STRING: {
-
- String s = *p_args[i];
- jstring jStr = env->NewStringUTF(s.utf8().get_data());
- v[i].l = jStr;
- } break;
- case Variant::STRING_ARRAY: {
-
- PoolVector<String> sarray = *p_args[i];
- jobjectArray arr = env->NewObjectArray(sarray.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
-
- for (int j = 0; j < sarray.size(); j++) {
-
- env->SetObjectArrayElement(arr, j, env->NewStringUTF(sarray[i].utf8().get_data()));
- }
- v[i].l = arr;
-
- } break;
- case Variant::INT_ARRAY: {
-
- PoolVector<int> array = *p_args[i];
- jintArray arr = env->NewIntArray(array.size());
- PoolVector<int>::Read r = array.read();
- env->SetIntArrayRegion(arr, 0, array.size(), r.ptr());
- v[i].l = arr;
-
- } break;
- case Variant::REAL_ARRAY: {
-
- PoolVector<float> array = *p_args[i];
- jfloatArray arr = env->NewFloatArray(array.size());
- PoolVector<float>::Read r = array.read();
- env->SetFloatArrayRegion(arr, 0, array.size(), r.ptr());
- v[i].l = arr;
-
- } break;
- default: {
-
- ERR_FAIL_V(Variant());
- } break;
- }
- }
-
- Variant ret;
-
- switch (E->get().ret_type) {
-
- case Variant::NIL: {
-
- env->CallVoidMethodA(instance, E->get().method, v);
- } break;
- case Variant::BOOL: {
-
- ret = env->CallBooleanMethodA(instance, E->get().method, v);
- } break;
- case Variant::INT: {
-
- ret = env->CallIntMethodA(instance, E->get().method, v);
- } break;
- case Variant::REAL: {
-
- ret = env->CallFloatMethodA(instance, E->get().method, v);
- } break;
- case Variant::STRING: {
-
- jobject o = env->CallObjectMethodA(instance, E->get().method, v);
- String singname = env->GetStringUTFChars((jstring)o, NULL);
- } break;
- case Variant::STRING_ARRAY: {
-
- jobjectArray arr = (jobjectArray)env->CallObjectMethodA(instance, E->get().method, v);
-
- int stringCount = env->GetArrayLength(arr);
- PoolVector<String> sarr;
-
- for (int i = 0; i < stringCount; i++) {
- jstring string = (jstring)env->GetObjectArrayElement(arr, i);
- const char *rawString = env->GetStringUTFChars(string, 0);
- sarr.push_back(String(rawString));
- }
-
- ret = sarr;
-
- } break;
- case Variant::INT_ARRAY: {
-
- jintArray arr = (jintArray)env->CallObjectMethodA(instance, E->get().method, v);
-
- int fCount = env->GetArrayLength(arr);
- PoolVector<int> sarr;
- sarr.resize(fCount);
-
- PoolVector<int>::Write w = sarr.write();
- env->GetIntArrayRegion(arr, 0, fCount, w.ptr());
- w = PoolVector<int>::Write();
- ret = sarr;
- } break;
- case Variant::REAL_ARRAY: {
-
- jfloatArray arr = (jfloatArray)env->CallObjectMethodA(instance, E->get().method, v);
-
- int fCount = env->GetArrayLength(arr);
- PoolVector<float> sarr;
- sarr.resize(fCount);
-
- PoolVector<float>::Write w = sarr.write();
- env->GetFloatArrayRegion(arr, 0, fCount, w.ptr());
- w = PoolVector<float>::Write();
- ret = sarr;
- } break;
- default: {
-
- ERR_FAIL_V(Variant());
- } break;
- }
-
- return ret;
- }
-
- jobject get_instance() const {
-
- return instance;
- }
- void set_instance(jobject p_instance) {
-
- instance = p_instance;
- }
-
- void add_method(const StringName &p_name, jmethodID p_method, const Vector<Variant::Type> &p_args, Variant::Type p_ret_type) {
-
- MethodData md;
- md.method = p_method;
- md.argtypes = p_args;
- md.ret_type = p_ret_type;
- method_map[p_name] = md;
- }
-
- JNISingleton() {}
-};
-
-//JNIEnv *JNISingleton::env=NULL;
-
-static HashMap<String, JNISingleton *> jni_singletons;
-
-struct engine {
- struct android_app *app;
- OS_Android *os;
- JNIEnv *jni;
-
- ASensorManager *sensorManager;
- const ASensor *accelerometerSensor;
- const ASensor *magnetometerSensor;
- const ASensor *gyroscopeSensor;
- ASensorEventQueue *sensorEventQueue;
-
- bool display_active;
- bool requested_quit;
- int animating;
- EGLDisplay display;
- EGLSurface surface;
- EGLContext context;
- int32_t width;
- int32_t height;
-};
-
-/**
- * Initialize an EGL context for the current display.
- */
-static int engine_init_display(struct engine *engine, bool p_gl2) {
- // initialize OpenGL ES and EGL
-
- /*
- * Here specify the attributes of the desired configuration.
- * Below, we select an EGLConfig with at least 8 bits per color
- * component compatible with on-screen windows
- */
- const EGLint gl2_attribs[] = {
- // EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_BLUE_SIZE, 4,
- EGL_GREEN_SIZE, 4,
- EGL_RED_SIZE, 4,
- EGL_ALPHA_SIZE, 0,
- EGL_DEPTH_SIZE, 16,
- EGL_STENCIL_SIZE, EGL_DONT_CARE,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_NONE
- };
-
- const EGLint gl1_attribs[] = {
- // EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_BLUE_SIZE, 4,
- EGL_GREEN_SIZE, 4,
- EGL_RED_SIZE, 4,
- EGL_ALPHA_SIZE, 0,
- EGL_DEPTH_SIZE, 16,
- EGL_STENCIL_SIZE, EGL_DONT_CARE,
- EGL_NONE
- };
-
- const EGLint *attribs = p_gl2 ? gl2_attribs : gl1_attribs;
-
- EGLint w, h, dummy, format;
- EGLint numConfigs;
- EGLConfig config;
- EGLSurface surface;
- EGLContext context;
-
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-
- eglInitialize(display, 0, 0);
-
- /* Here, the application chooses the configuration it desires. In this
- * sample, we have a very simplified selection process, where we pick
- * the first EGLConfig that matches our criteria */
-
- eglChooseConfig(display, attribs, &config, 1, &numConfigs);
-
- LOGI("Num configs: %i\n", numConfigs);
-
- /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
- * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
- * As soon as we picked a EGLConfig, we can safely reconfigure the
- * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
- eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
-
- ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
- //ANativeWindow_setFlags(engine->app->window, 0, 0, format|);
-
- surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
-
- const EGLint context_attribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
- context = eglCreateContext(display, config, EGL_NO_CONTEXT, p_gl2 ? context_attribs : NULL);
-
- if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
- LOGW("Unable to eglMakeCurrent");
- return -1;
- }
-
- eglQuerySurface(display, surface, EGL_WIDTH, &w);
- eglQuerySurface(display, surface, EGL_HEIGHT, &h);
-
- //engine->os->set_egl_extensions(eglQueryString(display,EGL_EXTENSIONS));
- engine->os->init_video_mode(w, h);
-
- engine->display = display;
- engine->context = context;
- engine->surface = surface;
- engine->width = w;
- engine->height = h;
- engine->display_active = true;
-
- //engine->state.angle = 0;
-
- // Initialize GL state.
- //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
- glEnable(GL_CULL_FACE);
- // glShadeModel(GL_SMOOTH);
- glDisable(GL_DEPTH_TEST);
- LOGI("GL Version: %s - %s %s\n", glGetString(GL_VERSION), glGetString(GL_VENDOR), glGetString(GL_RENDERER));
-
- return 0;
-}
-
-static void engine_draw_frame(struct engine *engine) {
- if (engine->display == NULL) {
- // No display.
- return;
- }
-
- // Just fill the screen with a color.
- //glClearColor(0,1,0,1);
- //glClear(GL_COLOR_BUFFER_BIT);
- if (engine->os && engine->os->main_loop_iterate()) {
-
- engine->requested_quit = true;
- return; //should exit instead
- }
-
- eglSwapBuffers(engine->display, engine->surface);
-}
-
-static void engine_term_display(struct engine *engine) {
- if (engine->display != EGL_NO_DISPLAY) {
- eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if (engine->context != EGL_NO_CONTEXT) {
- eglDestroyContext(engine->display, engine->context);
- }
- if (engine->surface != EGL_NO_SURFACE) {
- eglDestroySurface(engine->display, engine->surface);
- }
- eglTerminate(engine->display);
- }
-
- engine->animating = 0;
- engine->display = EGL_NO_DISPLAY;
- engine->context = EGL_NO_CONTEXT;
- engine->surface = EGL_NO_SURFACE;
- engine->display_active = false;
-}
-
-/**
- * Process the next input event.
- */
-static int32_t engine_handle_input(struct android_app *app, AInputEvent *event) {
- struct engine *engine = (struct engine *)app->userData;
-
- if (!engine->os)
- return 0;
-
- switch (AInputEvent_getType(event)) {
-
- case AINPUT_EVENT_TYPE_KEY: {
-
- int ac = AKeyEvent_getAction(event);
- switch (ac) {
-
- case AKEY_EVENT_ACTION_DOWN: {
-
- int32_t code = AKeyEvent_getKeyCode(event);
- if (code == AKEYCODE_BACK) {
-
- //AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled);
- if (engine->os)
- engine->os->main_loop_request_quit();
- return 1;
- }
-
- } break;
- case AKEY_EVENT_ACTION_UP: {
-
- } break;
- }
-
- } break;
- case AINPUT_EVENT_TYPE_MOTION: {
-
- Vector<OS_Android::TouchPos> touchvec;
-
- int pc = AMotionEvent_getPointerCount(event);
-
- touchvec.resize(pc);
-
- for (int i = 0; i < pc; i++) {
-
- touchvec[i].pos.x = AMotionEvent_getX(event, i);
- touchvec[i].pos.y = AMotionEvent_getY(event, i);
- touchvec[i].id = AMotionEvent_getPointerId(event, i);
- }
-
- //System.out.printf("gaction: %d\n",event.getAction());
- int pidx = (AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> 8;
- switch (AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK) {
-
- case AMOTION_EVENT_ACTION_DOWN: {
- engine->os->process_touch(0, 0, touchvec);
-
- //System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
- } break;
- case AMOTION_EVENT_ACTION_MOVE: {
- engine->os->process_touch(1, 0, touchvec);
- /*
- for(int i=0;i<event.getPointerCount();i++) {
- System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i));
- }
- */
- } break;
- case AMOTION_EVENT_ACTION_POINTER_UP: {
-
- engine->os->process_touch(4, pidx, touchvec);
- //System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
- } break;
- case AMOTION_EVENT_ACTION_POINTER_DOWN: {
- engine->os->process_touch(3, pidx, touchvec);
- //System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
- } break;
- case AMOTION_EVENT_ACTION_CANCEL:
- case AMOTION_EVENT_ACTION_UP: {
- engine->os->process_touch(2, 0, touchvec);
- /*
- for(int i=0;i<event.getPointerCount();i++) {
- System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i));
- }
- */
- } break;
- }
-
- return 1;
- } break;
- }
-
- return 0;
-}
-
-/**
- * Process the next main command.
- */
-
-static void _gfx_init(void *ud, bool p_gl2) {
-
- struct engine *engine = (struct engine *)ud;
- engine_init_display(engine, p_gl2);
-}
-
-static void engine_handle_cmd(struct android_app *app, int32_t cmd) {
- struct engine *engine = (struct engine *)app->userData;
- // LOGI("**** CMD %i\n",cmd);
- switch (cmd) {
- case APP_CMD_SAVE_STATE:
- // The system has asked us to save our current state. Do so.
- //engine->app->savedState = malloc(sizeof(struct saved_state));
- //*((struct saved_state*)engine->app->savedState) = engine->state;
- //engine->app->savedStateSize = sizeof(struct saved_state);
- break;
- case APP_CMD_CONFIG_CHANGED:
- case APP_CMD_WINDOW_RESIZED: {
-
- if (engine->display_active) {
-
- EGLint w, h;
- eglQuerySurface(engine->display, engine->surface, EGL_WIDTH, &w);
- eglQuerySurface(engine->display, engine->surface, EGL_HEIGHT, &h);
- // if (w==engine->os->get_video_mode().width && h==engine->os->get_video_mode().height)
- // break;
-
- engine_term_display(engine);
- }
-
- engine->os->reload_gfx();
- engine_draw_frame(engine);
- engine->animating = 1;
-
- } break;
- case APP_CMD_INIT_WINDOW:
- //The window is being shown, get it ready.
- //LOGI("INIT WINDOW");
- if (engine->app->window != NULL) {
-
- if (engine->os == NULL) {
-
- //do initialization here, when there's OpenGL! hackish but the only way
- engine->os = new OS_Android(_gfx_init, engine);
-
- __android_log_print(ANDROID_LOG_INFO, "godot", "pre asdasd setup...");
-
- Error err = Main::setup("apk", 0, NULL);
-
- String modules = ProjectSettings::get_singleton()->get("android/modules");
- Vector<String> mods = modules.split(",", false);
- mods.push_back("GodotOS");
- __android_log_print(ANDROID_LOG_INFO, "godot", "mod count: %i", mods.size());
-
- if (mods.size()) {
-
- jclass activityClass = engine->jni->FindClass("android/app/NativeActivity");
-
- jmethodID getClassLoader = engine->jni->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
-
- jobject cls = engine->jni->CallObjectMethod(app->activity->clazz, getClassLoader);
-
- jclass classLoader = engine->jni->FindClass("java/lang/ClassLoader");
-
- jmethodID findClass = engine->jni->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
-
- static JNINativeMethod methods[] = {
- { "registerSingleton", "(Ljava/lang/String;Ljava/lang/Object;)V", (void *)&Java_org_godotengine_godot_Godot_registerSingleton },
- { "registerMethod", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V", (void *)&Java_org_godotengine_godot_Godot_registerMethod },
- { "getGlobal", "(Ljava/lang/String;)Ljava/lang/String;", (void *)&Java_org_godotengine_godot_Godot_getGlobal },
- };
-
- jstring gstrClassName = engine->jni->NewStringUTF("org/godotengine/godot/Godot");
- jclass GodotClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, gstrClassName);
-
- __android_log_print(ANDROID_LOG_INFO, "godot", "godot ****^*^*?^*^*class data %x", GodotClass);
-
- engine->jni->RegisterNatives(GodotClass, methods, sizeof(methods) / sizeof(methods[0]));
-
- for (int i = 0; i < mods.size(); i++) {
-
- String m = mods[i];
- //jclass singletonClass = engine->jni->FindClass(m.utf8().get_data());
-
- jstring strClassName = engine->jni->NewStringUTF(m.utf8().get_data());
- jclass singletonClass = (jclass)engine->jni->CallObjectMethod(cls, findClass, strClassName);
-
- __android_log_print(ANDROID_LOG_INFO, "godot", "****^*^*?^*^*class data %x", singletonClass);
- jmethodID initialize = engine->jni->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lorg/godotengine/godot/Godot$SingletonBase;");
-
- jobject obj = engine->jni->CallStaticObjectMethod(singletonClass, initialize, app->activity->clazz);
- __android_log_print(ANDROID_LOG_INFO, "godot", "****^*^*?^*^*class instance %x", obj);
- jobject gob = engine->jni->NewGlobalRef(obj);
- }
- }
-
- if (!Main::start())
- return; //should exit instead and print the error
-
- engine->os->main_loop_begin();
- } else {
- //i guess recreate resources?
- engine->os->reload_gfx();
- }
-
- engine->animating = 1;
- engine_draw_frame(engine);
- }
- break;
- case APP_CMD_TERM_WINDOW:
- // The window is being hidden or closed, clean it up.
- //LOGI("TERM WINDOW");
- engine_term_display(engine);
- break;
- case APP_CMD_GAINED_FOCUS:
- // When our app gains focus, we start monitoring the accelerometer.
- if (engine->accelerometerSensor != NULL) {
- ASensorEventQueue_enableSensor(engine->sensorEventQueue,
- engine->accelerometerSensor);
- // We'd like to get 60 events per second (in us).
- ASensorEventQueue_setEventRate(engine->sensorEventQueue,
- engine->accelerometerSensor, (1000L / 60) * 1000);
- }
- // start monitoring gravity
- if (engine->gravitySensor != NULL) {
- ASensorEventQueue_enableSensor(engine->sensorEventQueue,
- engine->gravitySensor);
- // We'd like to get 60 events per second (in us).
- ASensorEventQueue_setEventRate(engine->sensorEventQueue,
- engine->gravitySensor, (1000L / 60) * 1000);
- }
- // Also start monitoring the magnetometer.
- if (engine->magnetometerSensor != NULL) {
- ASensorEventQueue_enableSensor(engine->sensorEventQueue,
- engine->magnetometerSensor);
- // We'd like to get 60 events per second (in us).
- ASensorEventQueue_setEventRate(engine->sensorEventQueue,
- engine->magnetometerSensor, (1000L / 60) * 1000);
- }
- // And the gyroscope.
- if (engine->gyroscopeSensor != NULL) {
- ASensorEventQueue_enableSensor(engine->sensorEventQueue,
- engine->gyroscopeSensor);
- // We'd like to get 60 events per second (in us).
- ASensorEventQueue_setEventRate(engine->sensorEventQueue,
- engine->gyroscopeSensor, (1000L / 60) * 1000);
- }
- engine->animating = 1;
- break;
- case APP_CMD_LOST_FOCUS:
- // When our app loses focus, we stop monitoring the sensors.
- // This is to avoid consuming battery while not being used.
- if (engine->accelerometerSensor != NULL) {
- ASensorEventQueue_disableSensor(engine->sensorEventQueue,
- engine->accelerometerSensor);
- }
- if (engine->gravitySensor != NULL) {
- ASensorEventQueue_disableSensor(engine->sensorEventQueue,
- engine->gravitySensor);
- }
- if (engine->magnetometerSensor != NULL) {
- ASensorEventQueue_disableSensor(engine->sensorEventQueue,
- engine->magnetometerSensor);
- }
- if (engine->gyroscopeSensor != NULL) {
- ASensorEventQueue_disableSensor(engine->sensorEventQueue,
- engine->gyroscopeSensor);
- }
- // Also stop animating.
- engine->animating = 0;
- engine_draw_frame(engine);
- break;
- }
-}
-
-void android_main(struct android_app *app) {
- struct engine engine;
- // Make sure glue isn't stripped.
- app_dummy();
-
- memset(&engine, 0, sizeof(engine));
- app->userData = &engine;
- app->onAppCmd = engine_handle_cmd;
- app->onInputEvent = engine_handle_input;
- engine.app = app;
- engine.requested_quit = false;
- engine.os = NULL;
- engine.display_active = false;
-
- FileAccessAndroid::asset_manager = app->activity->assetManager;
-
- // Prepare to monitor sensors
- engine.sensorManager = ASensorManager_getInstance();
- engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
- ASENSOR_TYPE_ACCELEROMETER);
- engine.gravitySensor = ASensorManager_getDefaultSensor(engine.sensorManager,
- ASENSOR_TYPE_GRAVITY);
- engine.magnetometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
- ASENSOR_TYPE_MAGNETIC_FIELD);
- engine.gyroscopeSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
- ASENSOR_TYPE_GYROSCOPE);
- engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
- app->looper, LOOPER_ID_USER, NULL, NULL);
-
- ANativeActivity_setWindowFlags(app->activity, AWINDOW_FLAG_FULLSCREEN | AWINDOW_FLAG_KEEP_SCREEN_ON, 0);
-
- app->activity->vm->AttachCurrentThread(&engine.jni, NULL);
-
- // loop waiting for stuff to do.
-
- while (1) {
- // Read all pending events.
- int ident;
- int events;
- struct android_poll_source *source;
-
- // If not animating, we will block forever waiting for events.
- // If animating, we loop until all events are read, then continue
- // to draw the next frame of animation.
-
- int nullmax = 50;
- while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
- (void **)&source)) >= 0) {
-
- // Process this event.
-
- if (source != NULL) {
- // LOGI("process\n");
- source->process(app, source);
- } else {
- nullmax--;
- if (nullmax < 0)
- break;
- }
-
- // If a sensor has data, process it now.
- // LOGI("events\n");
- if (ident == LOOPER_ID_USER) {
- if (engine.accelerometerSensor != NULL || engine.magnetometerSensor != NULL || engine.gyroscopeSensor != NULL) {
- ASensorEvent event;
- while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
- &event, 1) > 0) {
-
- if (engine.os) {
- if (event.acceleration != NULL) {
- engine.os->process_accelerometer(Vector3(event.acceleration.x, event.acceleration.y,
- event.acceleration.z));
- }
- if (event.magnetic != NULL) {
- engine.os->process_magnetometer(Vector3(event.magnetic.x, event.magnetic.y,
- event.magnetic.z));
- }
- if (event.vector != NULL) {
- engine.os->process_gyroscope(Vector3(event.vector.x, event.vector.y,
- event.vector.z));
- }
- }
- }
- }
- }
-
- // Check if we are exiting.
- if (app->destroyRequested != 0) {
- if (engine.os) {
- engine.os->main_loop_request_quit();
- }
- app->destroyRequested = 0;
- }
-
- if (engine.requested_quit) {
- engine_term_display(&engine);
- exit(0);
- }
-
- // LOGI("end\n");
- }
-
- // LOGI("engine animating? %i\n",engine.animating);
-
- if (engine.animating) {
- //do os render
-
- engine_draw_frame(&engine);
- //LOGI("TERM WINDOW");
- }
- }
-}
-
-JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerSingleton(JNIEnv *env, jobject obj, jstring name, jobject p_object) {
-
- String singname = env->GetStringUTFChars(name, NULL);
- JNISingleton *s = memnew(JNISingleton);
- s->update_env(env);
- s->set_instance(env->NewGlobalRef(p_object));
- jni_singletons[singname] = s;
-
- Engine::get_singleton()->add_singleton(Engine::Singleton(singname, s));
-}
-
-static Variant::Type get_jni_type(const String &p_type) {
-
- static struct {
- const char *name;
- Variant::Type type;
- } _type_to_vtype[] = {
- { "void", Variant::NIL },
- { "boolean", Variant::BOOL },
- { "int", Variant::INT },
- { "float", Variant::REAL },
- { "java.lang.String", Variant::STRING },
- { "[I", Variant::INT_ARRAY },
- { "[F", Variant::REAL_ARRAY },
- { "[Ljava.lang.String;", Variant::STRING_ARRAY },
- { NULL, Variant::NIL }
- };
-
- int idx = 0;
-
- while (_type_to_vtype[idx].name) {
-
- if (p_type == _type_to_vtype[idx].name)
- return _type_to_vtype[idx].type;
-
- idx++;
- }
-
- return Variant::NIL;
-}
-
-static const char *get_jni_sig(const String &p_type) {
-
- static struct {
- const char *name;
- const char *sig;
- } _type_to_vtype[] = {
- { "void", "V" },
- { "boolean", "Z" },
- { "int", "I" },
- { "float", "F" },
- { "java.lang.String", "Ljava/lang/String;" },
- { "[I", "[I" },
- { "[F", "[F" },
- { "[Ljava.lang.String;", "[Ljava/lang/String;" },
- { NULL, "V" }
- };
-
- int idx = 0;
-
- while (_type_to_vtype[idx].name) {
-
- if (p_type == _type_to_vtype[idx].name)
- return _type_to_vtype[idx].sig;
-
- idx++;
- }
-
- return "";
-}
-
-JNIEXPORT jstring JNICALL Java_org_godotengine_godot_Godot_getGlobal(JNIEnv *env, jobject obj, jstring path) {
-
- String js = env->GetStringUTFChars(path, NULL);
-
- return env->NewStringUTF(ProjectSettings::get_singleton()->get(js).operator String().utf8().get_data());
-}
-
-JNIEXPORT void JNICALL Java_org_godotengine_godot_Godot_registerMethod(JNIEnv *env, jobject obj, jstring sname, jstring name, jstring ret, jobjectArray args) {
-
- String singname = env->GetStringUTFChars(sname, NULL);
-
- ERR_FAIL_COND(!jni_singletons.has(singname));
-
- JNISingleton *s = jni_singletons.get(singname);
-
- String mname = env->GetStringUTFChars(name, NULL);
- String retval = env->GetStringUTFChars(ret, NULL);
- Vector<Variant::Type> types;
- String cs = "(";
-
- int stringCount = env->GetArrayLength(args);
-
- for (int i = 0; i < stringCount; i++) {
-
- jstring string = (jstring)env->GetObjectArrayElement(args, i);
- const char *rawString = env->GetStringUTFChars(string, 0);
- types.push_back(get_jni_type(String(rawString)));
- cs += get_jni_sig(String(rawString));
- }
-
- cs += ")";
- cs += get_jni_sig(retval);
- jclass cls = env->GetObjectClass(s->get_instance());
- jmethodID mid = env->GetMethodID(cls, mname.ascii().get_data(), cs.ascii().get_data());
- if (!mid) {
-
- print_line("RegisterMethod: Failed getting method ID: " + mname);
- }
-
- s->add_method(mname, mid, types, get_jni_type(retval));
-}
-
-#endif
diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp
index 43bd841baf..fb9c0f08ad 100644
--- a/platform/android/java_glue.cpp
+++ b/platform/android/java_glue.cpp
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef ANDROID_NATIVE_ACTIVITY
-
#include "java_glue.h"
#include "android/asset_manager_jni.h"
#include "audio_driver_jandroid.h"
@@ -1566,4 +1564,3 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *
//Main::cleanup();
//return os.get_exit_code();
-#endif
diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h
index d433b5f0d8..dc5b9cca49 100644
--- a/platform/android/java_glue.h
+++ b/platform/android/java_glue.h
@@ -28,8 +28,6 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef ANDROID_NATIVE_ACTIVITY
-
#ifndef JAVA_GLUE_H
#define JAVA_GLUE_H
@@ -64,5 +62,4 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jobject obj, jint p_height);
}
-#endif
#endif // JAVA_GLUE_H
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 96ff226402..afdd108987 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -41,13 +41,8 @@
#include "servers/visual/visual_server_raster.h"
#include "servers/visual/visual_server_wrap_mt.h"
-#ifdef ANDROID_NATIVE_ACTIVITY
-#include "dir_access_android.h"
-#include "file_access_android.h"
-#else
#include "dir_access_jandroid.h"
#include "file_access_jandroid.h"
-#endif
#include <dlfcn.h>
@@ -90,18 +85,6 @@ void OS_Android::initialize_core() {
OS_Unix::initialize_core();
-#ifdef ANDROID_NATIVE_ACTIVITY
-
- FileAccess::make_default<FileAccessAndroid>(FileAccess::ACCESS_RESOURCES);
- FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
- FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
- //FileAccessBufferedFA<FileAccessUnix>::make_default();
- DirAccess::make_default<DirAccessAndroid>(DirAccess::ACCESS_RESOURCES);
- DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
- DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
-
-#else
-
if (use_apk_expansion)
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
else {
@@ -121,8 +104,6 @@ void OS_Android::initialize_core() {
DirAccess::make_default<DirAccessJAndroid>(DirAccess::ACCESS_RESOURCES);
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
-
-#endif
}
void OS_Android::set_opengl_extensions(const char *p_gl_extensions) {
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index e89a380e4c..ad6fe1976a 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -41,12 +41,6 @@
#include "servers/audio_server.h"
#include "servers/visual/rasterizer.h"
-#ifdef ANDROID_NATIVE_ACTIVITY
-#include <android/log.h>
-#include <android/sensor.h>
-#include <android_native_app_glue.h>
-#endif
-
typedef void (*GFXInitFunc)(void *ud, bool gl2);
typedef int (*OpenURIFunc)(const String &);
typedef String (*GetUserDataDirFunc)();
diff --git a/platform/android/sign.sh b/platform/android/sign.sh
deleted file mode 100755
index 830da05a37..0000000000
--- a/platform/android/sign.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-jarsigner -digestalg SHA1 -sigalg MD5withRSA -verbose -keystore my-release-key.keystore "$1" reduz
-
-echo ""
-echo ""
-echo "Checking if APK is verified..."
-jarsigner -verify "$1" -verbose -certs
-
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 1fc497456c..8a9b254cdc 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -99,6 +99,70 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
Error _export_additional_assets(const String &p_out_dir, const Vector<String> &p_assets, bool p_is_framework, Vector<IOSExportAsset> &r_exported_assets);
Error _export_additional_assets(const String &p_out_dir, const Vector<SharedObject> &p_libraries, Vector<IOSExportAsset> &r_exported_assets);
+ bool is_package_name_valid(const String &p_package, String *r_error = NULL) const {
+
+ String pname = p_package;
+
+ if (pname.length() == 0) {
+ if (r_error) {
+ *r_error = "Identifier is missing.";
+ }
+ return false;
+ }
+
+ int segments = 0;
+ bool first = true;
+ for (int i = 0; i < pname.length(); i++) {
+ CharType c = pname[i];
+ if (first && c == '.') {
+ if (r_error) {
+ *r_error = "Identifier segments must be of non-zero length.";
+ }
+ return false;
+ }
+ if (c == '.') {
+ segments++;
+ first = true;
+ continue;
+ }
+ if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_')) {
+ if (r_error) {
+ *r_error = "The character '" + String::chr(c) + "' is not allowed in Identifier.";
+ }
+ return false;
+ }
+ if (first && (c >= '0' && c <= '9')) {
+ if (r_error) {
+ *r_error = "A digit cannot be the first character in a Identifier segment.";
+ }
+ return false;
+ }
+ if (first && c == '_') {
+ if (r_error) {
+ *r_error = "The character '" + String::chr(c) + "' cannot be the first character in a Identifier segment.";
+ }
+ return false;
+ }
+ first = false;
+ }
+
+ if (segments == 0) {
+ if (r_error) {
+ *r_error = "The Identifier must have at least one '.' separator.";
+ }
+ return false;
+ }
+
+ if (first) {
+ if (r_error) {
+ *r_error = "Identifier segments must be of non-zero length.";
+ }
+ return false;
+ }
+
+ return true;
+ }
+
protected:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);
virtual void get_export_options(List<ExportOption> *r_options);
@@ -982,11 +1046,33 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset
err += "Custom release package not found.\n";
}
+ String team_id = p_preset->get("application/app_store_team_id");
+ if (team_id.length() == 0) {
+ err += "App Store Team ID not specified - cannot configure the project.\n";
+ }
+
+ String identifier = p_preset->get("application/identifier");
+ String pn_err;
+ if (!is_package_name_valid(identifier, &pn_err)) {
+ err += "Invalid Identifier - " + pn_err + "\n";
+ }
+
+ for (unsigned int i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
+ IconInfo info = icon_infos[i];
+ String icon_path = p_preset->get(info.preset_key);
+ if (icon_path.length() == 0) {
+ if (info.is_required) {
+ err += "Required icon is not specified in the preset.\n";
+ }
+ break;
+ }
+ }
+
if (!err.empty())
r_error = err;
r_missing_templates = !valid;
- return valid;
+ return err.empty();
}
EditorExportPlatformIOS::EditorExportPlatformIOS() {
diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm
index 2925b46007..5b4d1f8226 100644
--- a/platform/iphone/gl_view.mm
+++ b/platform/iphone/gl_view.mm
@@ -84,7 +84,8 @@ Rect2 _get_ios_window_safe_area(float p_window_width, float p_window_height) {
}
ERR_FAIL_COND_V(insets.left < 0 || insets.top < 0 || insets.right < 0 || insets.bottom < 0,
Rect2(0, 0, p_window_width, p_window_height));
- return Rect2(insets.left, insets.top, p_window_width - insets.right - insets.left, p_window_height - insets.bottom - insets.top);
+ UIEdgeInsets window_insets = UIEdgeInsetsMake(_points_to_pixels(insets.top), _points_to_pixels(insets.left), _points_to_pixels(insets.bottom), _points_to_pixels(insets.right));
+ return Rect2(window_insets.left, window_insets.top, p_window_width - window_insets.right - window_insets.left, p_window_height - window_insets.bottom - window_insets.top);
}
bool _play_video(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) {
diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp
index 7a6613bb32..a5b627b8dc 100644
--- a/platform/javascript/audio_driver_javascript.cpp
+++ b/platform/javascript/audio_driver_javascript.cpp
@@ -44,6 +44,11 @@ extern "C" EMSCRIPTEN_KEEPALIVE void audio_driver_js_mix() {
AudioDriverJavaScript::singleton->mix_to_js();
}
+extern "C" EMSCRIPTEN_KEEPALIVE void audio_driver_process_capture(float sample) {
+
+ AudioDriverJavaScript::singleton->process_capture(sample);
+}
+
void AudioDriverJavaScript::mix_to_js() {
int channel_count = get_total_channels_by_speaker_mode(get_speaker_mode());
@@ -51,31 +56,39 @@ void AudioDriverJavaScript::mix_to_js() {
int32_t *stream_buffer = reinterpret_cast<int32_t *>(internal_buffer);
audio_server_process(sample_count, stream_buffer);
for (int i = 0; i < sample_count * channel_count; i++) {
- internal_buffer[i] = float(stream_buffer[i] >> 16) / 32768.0;
+ internal_buffer[i] = float(stream_buffer[i] >> 16) / 32768.f;
}
}
+void AudioDriverJavaScript::process_capture(float sample) {
+
+ int32_t sample32 = int32_t(sample * 32768.f) * (1U << 16);
+ input_buffer_write(sample32);
+}
+
Error AudioDriverJavaScript::init() {
/* clang-format off */
EM_ASM({
_audioDriver_audioContext = new (window.AudioContext || window.webkitAudioContext);
+ _audioDriver_audioInput = null;
+ _audioDriver_inputStream = null;
_audioDriver_scriptNode = null;
});
/* clang-format on */
int channel_count = get_total_channels_by_speaker_mode(get_speaker_mode());
/* clang-format off */
- int buffer_length = EM_ASM_INT({
+ buffer_length = EM_ASM_INT({
var CHANNEL_COUNT = $0;
var channelCount = _audioDriver_audioContext.destination.channelCount;
try {
// Try letting the browser recommend a buffer length.
- _audioDriver_scriptNode = _audioDriver_audioContext.createScriptProcessor(0, 0, channelCount);
+ _audioDriver_scriptNode = _audioDriver_audioContext.createScriptProcessor(0, 2, channelCount);
} catch (e) {
// ...otherwise, default to 4096.
- _audioDriver_scriptNode = _audioDriver_audioContext.createScriptProcessor(4096, 0, channelCount);
+ _audioDriver_scriptNode = _audioDriver_audioContext.createScriptProcessor(4096, 2, channelCount);
}
_audioDriver_scriptNode.connect(_audioDriver_audioContext.destination);
@@ -91,6 +104,7 @@ Error AudioDriverJavaScript::init() {
memdelete_arr(internal_buffer);
internal_buffer = memnew_arr(float, buffer_length *channel_count);
}
+
return internal_buffer ? OK : ERR_OUT_OF_MEMORY;
}
@@ -101,11 +115,13 @@ void AudioDriverJavaScript::start() {
var INTERNAL_BUFFER_PTR = $0;
var audioDriverMixFunction = cwrap('audio_driver_js_mix');
+ var audioDriverProcessCapture = cwrap('audio_driver_process_capture', null, ['number']);
_audioDriver_scriptNode.onaudioprocess = function(audioProcessingEvent) {
audioDriverMixFunction();
- // The output buffer contains the samples that will be modified and played.
+
+ var input = audioProcessingEvent.inputBuffer;
var output = audioProcessingEvent.outputBuffer;
- var input = HEAPF32.subarray(
+ var internalBuffer = HEAPF32.subarray(
INTERNAL_BUFFER_PTR / HEAPF32.BYTES_PER_ELEMENT,
INTERNAL_BUFFER_PTR / HEAPF32.BYTES_PER_ELEMENT + output.length * output.numberOfChannels);
@@ -113,8 +129,16 @@ void AudioDriverJavaScript::start() {
var outputData = output.getChannelData(channel);
// Loop through samples.
for (var sample = 0; sample < outputData.length; sample++) {
- // Set output equal to input.
- outputData[sample] = input[sample * output.numberOfChannels + channel];
+ outputData[sample] = internalBuffer[sample * output.numberOfChannels + channel];
+ }
+ }
+
+ if (_audioDriver_audioInput) {
+ var inputDataL = input.getChannelData(0);
+ var inputDataR = input.getChannelData(1);
+ for (var i = 0; i < inputDataL.length; i++) {
+ audioDriverProcessCapture(inputDataL[i]);
+ audioDriverProcessCapture(inputDataR[i]);
}
}
};
@@ -152,14 +176,74 @@ void AudioDriverJavaScript::finish() {
/* clang-format off */
EM_ASM({
_audioDriver_audioContext = null;
+ _audioDriver_audioInput = null;
_audioDriver_scriptNode = null;
});
/* clang-format on */
- memdelete_arr(internal_buffer);
- internal_buffer = NULL;
+
+ if (internal_buffer) {
+ memdelete_arr(internal_buffer);
+ internal_buffer = NULL;
+ }
+}
+
+Error AudioDriverJavaScript::capture_start() {
+
+ input_buffer_init(buffer_length);
+
+ /* clang-format off */
+ EM_ASM({
+ function gotMediaInput(stream) {
+ _audioDriver_inputStream = stream;
+ _audioDriver_audioInput = _audioDriver_audioContext.createMediaStreamSource(stream);
+ _audioDriver_audioInput.connect(_audioDriver_scriptNode);
+ }
+
+ function gotMediaInputError(e) {
+ console.log(e);
+ }
+
+ if (navigator.mediaDevices.getUserMedia) {
+ navigator.mediaDevices.getUserMedia({"audio": true}).then(gotMediaInput, gotMediaInputError);
+ } else {
+ if (!navigator.getUserMedia)
+ navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
+ navigator.getUserMedia({"audio": true}, gotMediaInput, gotMediaInputError);
+ }
+ });
+ /* clang-format on */
+
+ return OK;
+}
+
+Error AudioDriverJavaScript::capture_stop() {
+
+ /* clang-format off */
+ EM_ASM({
+ if (_audioDriver_inputStream) {
+ const tracks = _audioDriver_inputStream.getTracks();
+ for (var i = 0; i < tracks.length; i++) {
+ tracks[i].stop();
+ }
+ _audioDriver_inputStream = null;
+ }
+
+ if (_audioDriver_audioInput) {
+ _audioDriver_audioInput.disconnect();
+ _audioDriver_audioInput = null;
+ }
+
+ });
+ /* clang-format on */
+
+ input_buffer.clear();
+
+ return OK;
}
AudioDriverJavaScript::AudioDriverJavaScript() {
+ internal_buffer = NULL;
+
singleton = this;
}
diff --git a/platform/javascript/audio_driver_javascript.h b/platform/javascript/audio_driver_javascript.h
index a65a8ec29f..c8aeb0b446 100644
--- a/platform/javascript/audio_driver_javascript.h
+++ b/platform/javascript/audio_driver_javascript.h
@@ -37,8 +37,12 @@ class AudioDriverJavaScript : public AudioDriver {
float *internal_buffer;
+ int buffer_length;
+
public:
void mix_to_js();
+ void process_capture(float sample);
+
static AudioDriverJavaScript *singleton;
virtual const char *get_name() const;
@@ -51,6 +55,9 @@ public:
virtual void unlock();
virtual void finish();
+ virtual Error capture_start();
+ virtual Error capture_stop();
+
AudioDriverJavaScript();
};
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index cf85c3df7f..22b5f1f87a 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -122,6 +122,7 @@ def configure(env):
## Link flags
env.Append(LINKFLAGS=['-s', 'BINARYEN=1'])
+ env.Append(LINKFLAGS=['-s', 'BINARYEN_TRAP_MODE=\'clamp\''])
# Allow increasing memory buffer size during runtime. This is efficient
# when using WebAssembly (in comparison to asm.js) and works well for
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index f27c042637..12a0193521 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -139,10 +139,76 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), false));
}
+void _rgba8_to_packbits_encode(int p_ch, int p_size, PoolVector<uint8_t> &p_source, Vector<uint8_t> &p_dest) {
+
+ int src_len = p_size * p_size;
+
+ Vector<uint8_t> result;
+ result.resize(src_len * 1.25); //temp vector for rle encoded data, make it 25% larger for worst case scenario
+ int res_size = 0;
+
+ uint8_t buf[128];
+ int buf_size = 0;
+
+ int i = 0;
+ while (i < src_len) {
+ uint8_t cur = p_source.read()[i * 4 + p_ch];
+
+ if (i < src_len - 2) {
+
+ if ((p_source.read()[(i + 1) * 4 + p_ch] == cur) && (p_source.read()[(i + 2) * 4 + p_ch] == cur)) {
+ if (buf_size > 0) {
+ result.write[res_size++] = (uint8_t)(buf_size - 1);
+ copymem(&result.write[res_size], &buf, buf_size);
+ res_size += buf_size;
+ buf_size = 0;
+ }
+
+ uint8_t lim = i + 130 >= src_len ? src_len - i - 1 : 130;
+ bool hit_lim = true;
+
+ for (int j = 3; j <= lim; j++) {
+ if (p_source.read()[(i + j) * 4 + p_ch] != cur) {
+ hit_lim = false;
+ i = i + j - 1;
+ result.write[res_size++] = (uint8_t)(j - 3 + 0x80);
+ result.write[res_size++] = cur;
+ break;
+ }
+ }
+ if (hit_lim) {
+ result.write[res_size++] = (uint8_t)(lim - 3 + 0x80);
+ result.write[res_size++] = cur;
+ i = i + lim;
+ }
+ } else {
+ buf[buf_size++] = cur;
+ if (buf_size == 128) {
+ result.write[res_size++] = (uint8_t)(buf_size - 1);
+ copymem(&result.write[res_size], &buf, buf_size);
+ res_size += buf_size;
+ buf_size = 0;
+ }
+ }
+ } else {
+ buf[buf_size++] = cur;
+ result.write[res_size++] = (uint8_t)(buf_size - 1);
+ copymem(&result.write[res_size], &buf, buf_size);
+ res_size += buf_size;
+ buf_size = 0;
+ }
+
+ i++;
+ }
+
+ int ofs = p_dest.size();
+ p_dest.resize(p_dest.size() + res_size);
+ copymem(&p_dest.write[ofs], result.ptr(), res_size);
+}
+
void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) {
Ref<ImageTexture> it = memnew(ImageTexture);
- int size = 512;
Vector<uint8_t> data;
@@ -152,32 +218,82 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
data.write[2] = 'n';
data.write[3] = 's';
- const char *name[] = { "ic09", "ic08", "ic07", "icp6", "icp5", "icp4" };
- int index = 0;
-
- while (size >= 16) {
-
+ struct MacOSIconInfo {
+ const char *name;
+ const char *mask_name;
+ bool is_png;
+ int size;
+ };
+
+ static const MacOSIconInfo icon_infos[] = {
+ { "ic10", "", true, 1024 }, //1024x1024 32-bit PNG and 512x512@2x 32-bit "retina" PNG
+ { "ic09", "", true, 512 }, //512×512 32-bit PNG
+ { "ic14", "", true, 512 }, //256x256@2x 32-bit "retina" PNG
+ { "ic08", "", true, 256 }, //256×256 32-bit PNG
+ { "ic13", "", true, 256 }, //128x128@2x 32-bit "retina" PNG
+ { "ic07", "", true, 128 }, //128x128 32-bit PNG
+ { "ic12", "", true, 64 }, //32x32@2x 32-bit "retina" PNG
+ { "ic11", "", true, 32 }, //16x16@2x 32-bit "retina" PNG
+ { "il32", "l8mk", false, 32 }, //32x32 24-bit RLE + 8-bit uncompressed mask
+ { "is32", "s8mk", false, 16 } //16x16 24-bit RLE + 8-bit uncompressed mask
+ };
+
+ for (unsigned int i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
Ref<Image> copy = p_icon; // does this make sense? doesn't this just increase the reference count instead of making a copy? Do we even need a copy?
copy->convert(Image::FORMAT_RGBA8);
- copy->resize(size, size);
- it->create_from_image(copy);
- String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("icon.png");
- ResourceSaver::save(path, it);
-
- FileAccess *f = FileAccess::open(path, FileAccess::READ);
- ERR_FAIL_COND(!f);
-
- int ofs = data.size();
- uint32_t len = f->get_len();
- data.resize(data.size() + len + 8);
- f->get_buffer(&data.write[ofs + 8], len);
- memdelete(f);
- len += 8;
- len = BSWAP32(len);
- copymem(&data.write[ofs], name[index], 4);
- encode_uint32(len, &data.write[ofs + 4]);
- index++;
- size /= 2;
+ copy->resize(icon_infos[i].size, icon_infos[i].size);
+
+ if (icon_infos[i].is_png) {
+ //encode png icon
+ it->create_from_image(copy);
+ String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("icon.png");
+ ResourceSaver::save(path, it);
+
+ FileAccess *f = FileAccess::open(path, FileAccess::READ);
+ ERR_FAIL_COND(!f);
+
+ int ofs = data.size();
+ uint32_t len = f->get_len();
+ data.resize(data.size() + len + 8);
+ f->get_buffer(&data.write[ofs + 8], len);
+ memdelete(f);
+ len += 8;
+ len = BSWAP32(len);
+ copymem(&data.write[ofs], icon_infos[i].name, 4);
+ encode_uint32(len, &data.write[ofs + 4]);
+ } else {
+ PoolVector<uint8_t> src_data = copy->get_data();
+
+ //encode 24bit RGB RLE icon
+ {
+ int ofs = data.size();
+ data.resize(data.size() + 8);
+
+ _rgba8_to_packbits_encode(0, icon_infos[i].size, src_data, data); // encode R
+ _rgba8_to_packbits_encode(1, icon_infos[i].size, src_data, data); // encode G
+ _rgba8_to_packbits_encode(2, icon_infos[i].size, src_data, data); // encode B
+
+ int len = data.size() - ofs;
+ len = BSWAP32(len);
+ copymem(&data.write[ofs], icon_infos[i].name, 4);
+ encode_uint32(len, &data.write[ofs + 4]);
+ }
+
+ //encode 8bit mask uncompressed icon
+ {
+ int ofs = data.size();
+ int len = copy->get_width() * copy->get_height();
+ data.resize(data.size() + len + 8);
+
+ for (int j = 0; j < len; j++) {
+ data.write[ofs + 8 + j] = src_data.read()[j * 4 + 3];
+ }
+ len += 8;
+ len = BSWAP32(len);
+ copymem(&data.write[ofs], icon_infos[i].mask_name, 4);
+ encode_uint32(len, &data.write[ofs + 4]);
+ }
+ }
}
uint32_t total_len = data.size();
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index 41e59a5352..c0ea13e7fb 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -1134,7 +1134,7 @@ public:
} break;
}
- if (!exists_export_template("uwp_" + platform_infix + "_debug.zip", &err) || !exists_export_template("uwp_" + platform_infix + "_debug.zip", &err)) {
+ if (!exists_export_template("uwp_" + platform_infix + "_debug.zip", &err) || !exists_export_template("uwp_" + platform_infix + "_release.zip", &err)) {
valid = false;
r_missing_templates = true;
}
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index dd0042668f..e14db9a201 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -147,9 +147,9 @@ def setup_msvc_auto(env):
# Note: actual compiler version can be found in env['MSVC_VERSION'], e.g. "14.1" for VS2015
# Get actual target arch into bits (it may be "default" at this point):
if env['TARGET_ARCH'] in ('amd64', 'x86_64'):
- env['bits'] = 64
+ env['bits'] = '64'
else:
- env['bits'] = 32
+ env['bits'] = '32'
print(" Found MSVC version %s, arch %s, bits=%s" % (env['MSVC_VERSION'], env['TARGET_ARCH'], env['bits']))
if env['TARGET_ARCH'] in ('amd64', 'x86_64'):
env["x86_libtheora_opt_vc"] = False
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index bdf459fd83..55d2bb2153 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -727,16 +727,28 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
} break;
+ case WM_MOVE: {
+ if (!IsIconic(hWnd)) {
+ int x = LOWORD(lParam);
+ int y = HIWORD(lParam);
+ last_pos = Point2(x, y);
+ }
+ } break;
+
case WM_SIZE: {
- int window_w = LOWORD(lParam);
- int window_h = HIWORD(lParam);
- if (window_w > 0 && window_h > 0 && !preserve_window_size) {
- video_mode.width = window_w;
- video_mode.height = window_h;
- } else {
- preserve_window_size = false;
- set_window_size(Size2(video_mode.width, video_mode.height));
+ // Ignore size when a SIZE_MINIMIZED event is triggered
+ if (wParam != SIZE_MINIMIZED) {
+ int window_w = LOWORD(lParam);
+ int window_h = HIWORD(lParam);
+ if (window_w > 0 && window_h > 0 && !preserve_window_size) {
+ video_mode.width = window_w;
+ video_mode.height = window_h;
+ } else {
+ preserve_window_size = false;
+ set_window_size(Size2(video_mode.width, video_mode.height));
+ }
}
+
if (wParam == SIZE_MAXIMIZED) {
maximized = true;
minimized = false;
@@ -1685,6 +1697,10 @@ int OS_Windows::get_screen_dpi(int p_screen) const {
Point2 OS_Windows::get_window_position() const {
+ if (minimized) {
+ return last_pos;
+ }
+
RECT r;
GetWindowRect(hWnd, &r);
return Point2(r.left, r.top);
@@ -1705,9 +1721,15 @@ void OS_Windows::set_window_position(const Point2 &p_position) {
ClientToScreen(hWnd, (POINT *)&rect.right);
ClipCursor(&rect);
}
+
+ last_pos = p_position;
}
Size2 OS_Windows::get_window_size() const {
+ if (minimized) {
+ return Size2(video_mode.width, video_mode.height);
+ }
+
RECT r;
if (GetClientRect(hWnd, &r)) { // Only area inside of window border
return Size2(r.right - r.left, r.bottom - r.top);
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 6aadd6994c..d09ade4daa 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -93,6 +93,7 @@ class OS_Windows : public OS {
HDC hDC; // Private GDI Device Context
HINSTANCE hInstance; // Holds The Instance Of The Application
HWND hWnd;
+ Point2 last_pos;
HBITMAP hBitmap; //DIB section for layered window
uint8_t *dib_data;
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 04854e93b6..0c02e47b5e 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -2853,11 +2853,19 @@ void OS_X11::set_context(int p_context) {
XClassHint *classHint = XAllocClassHint();
if (classHint) {
+ char *wm_class = (char *)"Godot";
if (p_context == CONTEXT_EDITOR)
classHint->res_name = (char *)"Godot_Editor";
if (p_context == CONTEXT_PROJECTMAN)
classHint->res_name = (char *)"Godot_ProjectList";
- classHint->res_class = (char *)"Godot";
+
+ if (p_context == CONTEXT_ENGINE) {
+ classHint->res_name = (char *)"Godot_Engine";
+ wm_class = (char *)((String)GLOBAL_GET("application/config/name")).utf8().ptrw();
+ }
+
+ classHint->res_class = wm_class;
+
XSetClassHint(x11_display, x11_window, classHint);
XFree(classHint);
}