From 11daeb47469c011ee9e1e9cbf37e7000cb571690 Mon Sep 17 00:00:00 2001 From: Relintai Date: Sat, 16 Dec 2023 16:30:34 +0100 Subject: [PATCH] Removed the non-desktop platforms. --- platform/android/README.md | 14 - platform/android/SCsub | 70 - platform/android/android_input_handler.cpp | 419 --- platform/android/android_input_handler.h | 110 - platform/android/android_keys_utils.cpp | 79 - platform/android/android_keys_utils.h | 177 - platform/android/api/api.cpp | 88 - platform/android/api/api.h | 36 - platform/android/api/java_class_wrapper.h | 254 -- platform/android/api/jni_singleton.h | 221 -- platform/android/audio_driver_opensl.cpp | 345 -- platform/android/audio_driver_opensl.h | 108 - platform/android/detect.py | 197 - platform/android/dir_access_jandroid.cpp | 356 -- platform/android/dir_access_jandroid.h | 106 - platform/android/export/export.cpp | 57 - platform/android/export/export.h | 36 - platform/android/export/export_plugin.cpp | 3338 ----------------- platform/android/export/export_plugin.h | 261 -- .../android/export/gradle_export_util.cpp | 250 -- platform/android/export/gradle_export_util.h | 88 - .../export/pandemonium_plugin_config.cpp | 229 -- .../export/pandemonium_plugin_config.h | 106 - platform/android/file_access_android.cpp | 180 - platform/android/file_access_android.h | 87 - .../file_access_filesystem_jandroid.cpp | 343 -- .../android/file_access_filesystem_jandroid.h | 100 - platform/android/java/app/AndroidManifest.xml | 68 - .../app/assetPacks/installTime/build.gradle | 8 - platform/android/java/app/assets/.gitignore | 2 - platform/android/java/app/build.gradle | 288 -- platform/android/java/app/config.gradle | 315 -- platform/android/java/app/gradle.properties | 25 - .../java/app/res/drawable-nodpi/splash.png | Bin 31538 -> 0 bytes .../res/drawable-nodpi/splash_bg_color.png | Bin 5948 -> 0 bytes .../java/app/res/drawable/splash_drawable.xml | 12 - .../pandemonium_project_name_string.xml | 5 - .../pandemonium_project_name_string.xml | 5 - .../pandemonium_project_name_string.xml | 5 - .../android/java/app/res/values/themes.xml | 10 - platform/android/java/app/settings.gradle | 15 - .../com/pandemonium/game/PandemoniumApp.java | 47 - platform/android/java/build.gradle | 330 -- platform/android/java/editor/build.gradle | 81 - platform/android/java/editor/src/.gitignore | 1 - .../java/editor/src/main/AndroidManifest.xml | 79 - .../editor/PandemoniumEditor.kt | 396 -- .../editor/PandemoniumGame.kt | 62 - .../editor/PandemoniumProjectManager.kt | 50 - .../editor/src/main/res/values/dimens.xml | 5 - .../editor/src/main/res/values/strings.xml | 5 - platform/android/java/gradle.properties | 28 - .../java/gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 - platform/android/java/gradlew | 185 - platform/android/java/gradlew.bat | 89 - platform/android/java/lib/AndroidManifest.xml | 35 - platform/android/java/lib/THIRDPARTY.md | 39 - .../licensing/ILicenseResultListener.aidl | 21 - .../vending/licensing/ILicensingService.aidl | 23 - platform/android/java/lib/build.gradle | 165 - ...android.vending.expansion.downloader.patch | 300 -- ...com.google.android.vending.licensing.patch | 42 - .../lib/res/layout/downloading_expansion.xml | 165 - .../lib/res/layout/pandemonium_app_layout.xml | 5 - .../status_bar_ongoing_event_progress_bar.xml | 108 - .../java/lib/res/mipmap-anydpi-v26/icon.xml | 5 - .../android/java/lib/res/mipmap-hdpi/icon.png | Bin 3521 -> 0 bytes .../lib/res/mipmap-hdpi/icon_background.png | Bin 4964 -> 0 bytes .../lib/res/mipmap-hdpi/icon_foreground.png | Bin 4555 -> 0 bytes .../android/java/lib/res/mipmap-mdpi/icon.png | Bin 2320 -> 0 bytes .../lib/res/mipmap-mdpi/icon_background.png | Bin 4829 -> 0 bytes .../lib/res/mipmap-mdpi/icon_foreground.png | Bin 2914 -> 0 bytes .../java/lib/res/mipmap-xhdpi/icon.png | Bin 4571 -> 0 bytes .../lib/res/mipmap-xhdpi/icon_background.png | Bin 5105 -> 0 bytes .../lib/res/mipmap-xhdpi/icon_foreground.png | Bin 5971 -> 0 bytes .../java/lib/res/mipmap-xxhdpi/icon.png | Bin 6901 -> 0 bytes .../lib/res/mipmap-xxhdpi/icon_background.png | Bin 5492 -> 0 bytes .../lib/res/mipmap-xxhdpi/icon_foreground.png | Bin 9022 -> 0 bytes .../java/lib/res/mipmap-xxxhdpi/icon.png | Bin 9162 -> 0 bytes .../res/mipmap-xxxhdpi/icon_background.png | Bin 5948 -> 0 bytes .../res/mipmap-xxxhdpi/icon_foreground.png | Bin 12301 -> 0 bytes platform/android/java/lib/res/mipmap/icon.png | Bin 9162 -> 0 bytes .../java/lib/res/mipmap/icon_background.png | Bin 4829 -> 0 bytes .../java/lib/res/mipmap/icon_foreground.png | Bin 2914 -> 0 bytes .../android/java/lib/res/values/dimens.xml | 4 - .../android/java/lib/res/values/strings.xml | 57 - .../android/java/lib/res/values/styles.xml | 25 - .../res/xml/pandemonium_provider_paths.xml | 11 - .../expansion/downloader/Constants.java | 236 -- .../downloader/DownloadProgressInfo.java | 80 - .../DownloaderClientMarshaller.java | 297 -- .../DownloaderServiceMarshaller.java | 201 - .../vending/expansion/downloader/Helpers.java | 367 -- .../downloader/IDownloaderClient.java | 126 - .../downloader/IDownloaderService.java | 83 - .../vending/expansion/downloader/IStub.java | 41 - .../expansion/downloader/SystemFacade.java | 129 - .../downloader/impl/CustomIntentService.java | 112 - .../downloader/impl/DownloadInfo.java | 92 - .../downloader/impl/DownloadNotification.java | 229 -- .../downloader/impl/DownloadThread.java | 852 ----- .../downloader/impl/DownloaderService.java | 1346 ------- .../downloader/impl/DownloadsDB.java | 510 --- .../downloader/impl/HttpDateTime.java | 200 - .../vending/licensing/AESObfuscator.java | 110 - .../vending/licensing/APKExpansionPolicy.java | 414 -- .../vending/licensing/DeviceLimiter.java | 47 - .../vending/licensing/LicenseChecker.java | 389 -- .../licensing/LicenseCheckerCallback.java | 67 - .../vending/licensing/LicenseValidator.java | 231 -- .../vending/licensing/NullDeviceLimiter.java | 32 - .../android/vending/licensing/Obfuscator.java | 48 - .../android/vending/licensing/Policy.java | 65 - .../licensing/PreferenceObfuscator.java | 80 - .../vending/licensing/ResponseData.java | 81 - .../licensing/ServerManagedPolicy.java | 300 -- .../vending/licensing/StrictPolicy.java | 100 - .../licensing/ValidationException.java | 33 - .../vending/licensing/util/Base64.java | 578 --- .../util/Base64DecoderException.java | 32 - .../licensing/util/URIQueryDecoder.java | 60 - .../pandemonium/Dictionary.java | 75 - .../pandemonium/FullScreenPandemoniumApp.java | 186 - .../pandemonium/Pandemonium.java | 1307 ------- .../PandemoniumDownloaderAlarmReceiver.java | 59 - .../PandemoniumDownloaderService.java | 85 - .../pandemonium/PandemoniumHost.java | 95 - .../pandemonium/PandemoniumIO.java | 361 -- .../pandemonium/PandemoniumLib.java | 222 -- .../pandemonium/PandemoniumRenderer.java | 94 - .../pandemonium/PandemoniumView.java | 308 -- .../config/RegularConfigChooser.java | 149 - .../config/RegularContextFactory.java | 83 - .../config/RegularFallbackConfigChooser.java | 61 - .../pandemonium/gl/EGLLogWrapper.java | 564 --- .../gl/PandemoniumGLSurfaceView.java | 1840 --------- .../pandemonium/input/Joystick.java | 52 - .../input/PandemoniumEditText.java | 307 -- .../input/PandemoniumGestureHandler.kt | 271 -- .../input/PandemoniumInputHandler.java | 566 --- .../input/PandemoniumTextInputWrapper.java | 156 - .../pandemonium/io/StorageScope.kt | 124 - .../io/directory/AssetsDirectoryAccess.kt | 179 - .../io/directory/DirectoryAccessHandler.kt | 227 -- .../io/directory/FilesystemDirectoryAccess.kt | 231 -- .../pandemonium/io/file/DataAccess.kt | 183 - .../pandemonium/io/file/FileAccessFlags.kt | 87 - .../pandemonium/io/file/FileAccessHandler.kt | 213 -- .../pandemonium/io/file/FileData.kt | 93 - .../pandemonium/io/file/MediaStoreData.kt | 284 -- .../pandemonium/plugin/PandemoniumPlugin.java | 426 --- .../plugin/PandemoniumPluginInfoProvider.java | 72 - .../plugin/PandemoniumPluginRegistry.java | 172 - .../pandemonium/plugin/SignalInfo.java | 99 - .../pandemonium/plugin/UsedByPandemonium.java | 45 - .../pandemonium/utils/BenchmarkUtils.kt | 123 - .../pandemonium/utils/Crypt.java | 68 - .../pandemonium/utils/GLUtils.java | 156 - .../utils/PandemoniumNetUtils.java | 82 - .../pandemonium/utils/PermissionsUtil.java | 275 -- .../pandemonium/utils/ProcessPhoenix.java | 148 - .../nativeSrcsConfigs/AndroidManifest.xml | 2 - .../java/nativeSrcsConfigs/CMakeLists.txt | 21 - .../android/java/nativeSrcsConfigs/README.md | 4 - .../java/nativeSrcsConfigs/build.gradle | 59 - .../java/scripts/publish-module.gradle | 58 - .../android/java/scripts/publish-root.gradle | 39 - platform/android/java/settings.gradle | 25 - platform/android/java_class_wrapper.cpp | 1202 ------ .../android/java_pandemonium_io_wrapper.cpp | 273 -- .../android/java_pandemonium_io_wrapper.h | 91 - platform/android/java_pandemonium_lib_jni.cpp | 548 --- platform/android/java_pandemonium_lib_jni.h | 72 - .../android/java_pandemonium_view_wrapper.cpp | 114 - .../android/java_pandemonium_view_wrapper.h | 69 - platform/android/java_pandemonium_wrapper.cpp | 477 --- platform/android/java_pandemonium_wrapper.h | 131 - platform/android/jni_utils.cpp | 398 -- platform/android/jni_utils.h | 54 - platform/android/logo.png | Bin 968 -> 0 bytes platform/android/net_socket_android.cpp | 135 - platform/android/net_socket_android.h | 76 - platform/android/os_android.cpp | 754 ---- platform/android/os_android.h | 235 -- platform/android/platform_config.h | 32 - .../android/plugin/pandemonium_plugin_jni.cpp | 158 - .../android/plugin/pandemonium_plugin_jni.h | 44 - platform/android/power_android.cpp | 255 -- platform/android/power_android.h | 74 - platform/android/run_icon.png | Bin 324 -> 0 bytes platform/android/string_android.h | 58 - platform/android/thread_jandroid.cpp | 83 - platform/android/thread_jandroid.h | 40 - platform/frt/.clang-format | 100 - platform/frt/.gitignore | 8 - platform/frt/.travis.yml | 20 - platform/frt/CREDITS.txt | 21 - platform/frt/LICENSE.txt | 21 - platform/frt/LICENSE_GODOT.txt | 28 - platform/frt/Local.mk | 11 - platform/frt/Makefile | 16 - platform/frt/README.md | 72 - platform/frt/SCsub | 28 - platform/frt/bits/egl_base_context.h | 116 - platform/frt/bits/frt_app_impl.h | 114 - platform/frt/bits/frt_load_gles.h | 51 - platform/frt/bits/linux_input.h | 169 - platform/frt/bits/mouse_virtual.h | 110 - platform/frt/bits/x11.h | 191 - platform/frt/detect.py | 185 - platform/frt/dl/bcm.dl | 41 - platform/frt/dl/drm.dl | 39 - platform/frt/dl/egl.dl | 42 - platform/frt/dl/gbm.dl | 36 - platform/frt/dl/gles2.dl | 171 - platform/frt/dl/minidl.sh | 11 - platform/frt/dl/procdl.py | 141 - platform/frt/dl/x11.dl | 45 - platform/frt/doc/Bugs.md | 38 - platform/frt/doc/Compile.md | 158 - platform/frt/doc/Environment.md | 68 - platform/frt/doc/Extensions.md | 101 - platform/frt/doc/Porting.md | 82 - platform/frt/doc/ReleaseNotes.md | 40 - platform/frt/doc/Usage.md | 117 - platform/frt/doc/Utgard.md | 42 - platform/frt/doc/VC4.md | 31 - platform/frt/doc/VC6.md | 10 - platform/frt/envprobe.cpp | 202 - platform/frt/frt.h | 244 -- platform/frt/frt_options.cpp | 156 - platform/frt/gles2_egl.h | 32 - platform/frt/godot_frt.cpp | 116 - platform/frt/import/cursor.h | 11 - platform/frt/import/gdkeys.h | 122 - platform/frt/import/key_mapping_x11.h | 55 - platform/frt/import/key_mapping_x11_3.cpp | 1810 --------- platform/frt/include/joypad_linux.cpp | 32 - platform/frt/include/libudev-so_wrap.c | 26 - platform/frt/keyboard_linux_input.cpp | 240 -- platform/frt/keyboard_x11.cpp | 144 - platform/frt/logo.png | Bin 439 -> 0 bytes platform/frt/mouse_linux_input.cpp | 138 - platform/frt/mouse_x11.cpp | 110 - platform/frt/os_frt.cpp | 624 --- platform/frt/patches/alsa_21.patch | 14 - platform/frt/patches/alsa_30.patch | 14 - platform/frt/patches/alsa_31.patch | 14 - platform/frt/patches/gcc492a_324.patch | 13 - platform/frt/platform_config.h | 38 - platform/frt/porting/All.mk | 43 - platform/frt/porting/BCM.mk | 20 - platform/frt/porting/FBDev.mk | 16 - platform/frt/porting/KMSDRM.mk | 18 - platform/frt/porting/Local.mk | 6 - platform/frt/porting/Makefile | 26 - platform/frt/porting/X11.mk | 25 - platform/frt/porting/test_all.cpp | 111 - platform/frt/porting/test_keyboard.cpp | 71 - platform/frt/porting/test_modules.cpp | 70 - platform/frt/porting/test_mouse.cpp | 77 - platform/frt/porting/test_video.cpp | 122 - platform/frt/release.sh | 111 - platform/frt/video_bcm.cpp | 512 --- platform/frt/video_fbdev.cpp | 160 - platform/frt/video_kmsdrm.cpp | 313 -- platform/frt/video_x11.cpp | 151 - platform/frt_sdl/.gitignore | 6 - platform/frt_sdl/LICENSE | 21 - platform/frt_sdl/Makefile | 20 - platform/frt_sdl/README.md | 96 - platform/frt_sdl/SCsub | 38 - platform/frt_sdl/detect.py | 123 - platform/frt_sdl/dl/gles2.dl | 153 - platform/frt_sdl/dl/procdl.py | 112 - platform/frt_sdl/doc/Compile.md | 77 - platform/frt_sdl/doc/ReleaseNotes.md | 14 - platform/frt_sdl/frt.cc | 42 - platform/frt_sdl/frt.h | 25 - platform/frt_sdl/frt_exe.cc | 28 - platform/frt_sdl/frt_godot3.cc | 405 -- platform/frt_sdl/frt_lib.h | 22 - platform/frt_sdl/gles2_egl.h | 14 - platform/frt_sdl/logo.png | Bin 439 -> 0 bytes platform/frt_sdl/platform_config.h | 11 - platform/frt_sdl/release.sh | 96 - platform/frt_sdl/scripts/compile.sh | 74 - platform/frt_sdl/scripts/for_tags.sh | 26 - platform/frt_sdl/scripts/rolling.sh | 70 - platform/frt_sdl/sdl2_adapter.h | 505 --- platform/frt_sdl/sdl2_godot_mapping.h | 184 - platform/iphone/SCsub | 40 - platform/iphone/api/api.cpp | 48 - platform/iphone/api/api.h | 41 - platform/iphone/app_delegate.h | 40 - platform/iphone/app_delegate.mm | 152 - platform/iphone/detect.py | 202 - platform/iphone/device_metrics.h | 37 - platform/iphone/device_metrics.m | 194 - platform/iphone/display_layer.h | 45 - platform/iphone/display_layer.mm | 196 - platform/iphone/export/export.cpp | 2207 ----------- platform/iphone/export/export.h | 36 - platform/iphone/ios.h | 60 - platform/iphone/ios.mm | 181 - platform/iphone/joypad_iphone.h | 50 - platform/iphone/joypad_iphone.mm | 364 -- platform/iphone/keyboard_input_view.h | 37 - platform/iphone/keyboard_input_view.mm | 196 - platform/iphone/logo.png | Bin 1297 -> 0 bytes platform/iphone/main.m | 51 - platform/iphone/native_video_view.h | 42 - platform/iphone/native_video_view.m | 271 -- platform/iphone/os_iphone.h | 199 - platform/iphone/os_iphone.mm | 800 ---- platform/iphone/pandemonium_app_delegate.h | 41 - platform/iphone/pandemonium_app_delegate.m | 467 --- platform/iphone/pandemonium_iphone.mm | 120 - platform/iphone/pandemonium_view.h | 68 - platform/iphone/pandemonium_view.mm | 457 --- platform/iphone/pandemonium_view_renderer.h | 44 - platform/iphone/pandemonium_view_renderer.mm | 117 - platform/iphone/platform_config.h | 42 - .../iphone/plugin/pandemonium_plugin_config.h | 383 -- platform/iphone/power_iphone.cpp | 70 - platform/iphone/power_iphone.h | 52 - platform/iphone/view_controller.h | 47 - platform/iphone/view_controller.mm | 270 -- platform/javascript/.eslintrc.engine.js | 10 - platform/javascript/.eslintrc.js | 51 - platform/javascript/.eslintrc.libs.js | 26 - platform/javascript/README.md | 15 - platform/javascript/SCsub | 105 - platform/javascript/api/api.cpp | 119 - platform/javascript/api/api.h | 36 - .../javascript/api/javascript_singleton.h | 70 - .../api/javascript_tools_editor_plugin.cpp | 146 - .../api/javascript_tools_editor_plugin.h | 61 - .../javascript/audio_driver_javascript.cpp | 292 -- platform/javascript/audio_driver_javascript.h | 160 - platform/javascript/detect.py | 217 -- platform/javascript/dom_keys.inc | 232 -- platform/javascript/emscripten_helpers.py | 87 - platform/javascript/export/export.cpp | 1047 ------ platform/javascript/export/export.h | 31 - platform/javascript/http_client.h.inc | 51 - .../javascript/http_client_javascript.cpp | 304 -- platform/javascript/javascript_main.cpp | 108 - platform/javascript/javascript_runtime.cpp | 35 - platform/javascript/javascript_singleton.cpp | 361 -- platform/javascript/js/engine/config.js | 358 -- .../javascript/js/engine/engine.externs.js | 4 - platform/javascript/js/engine/engine.js | 289 -- platform/javascript/js/engine/preloader.js | 133 - platform/javascript/js/jsdoc2rst/publish.js | 354 -- platform/javascript/js/libs/audio.worklet.js | 217 -- .../js/libs/library_pandemonium_audio.js | 489 --- .../js/libs/library_pandemonium_display.js | 682 ---- .../js/libs/library_pandemonium_fetch.js | 249 -- .../js/libs/library_pandemonium_input.js | 555 --- ...ibrary_pandemonium_javascript_singleton.js | 335 -- .../js/libs/library_pandemonium_os.js | 428 --- .../js/libs/library_pandemonium_runtime.js | 134 - platform/javascript/logo.png | Bin 1234 -> 0 bytes platform/javascript/os_javascript.cpp | 1104 ------ platform/javascript/os_javascript.h | 205 - platform/javascript/package-lock.json | 2507 ------------- platform/javascript/package.json | 27 - platform/javascript/pandemonium_audio.h | 65 - platform/javascript/pandemonium_js.h | 120 - platform/javascript/platform_config.h | 31 - platform/javascript/run_icon.png | Bin 290 -> 0 bytes platform/javascript/serve.py | 53 - platform/uwp/SCsub | 21 - platform/uwp/app.cpp | 580 --- platform/uwp/app.h | 115 - platform/uwp/context_egl_uwp.cpp | 213 -- platform/uwp/context_egl_uwp.h | 85 - platform/uwp/detect.py | 210 -- platform/uwp/export/export.cpp | 1595 -------- platform/uwp/export/export.h | 36 - platform/uwp/joypad_uwp.cpp | 170 - platform/uwp/joypad_uwp.h | 90 - platform/uwp/logo.png | Bin 1519 -> 0 bytes platform/uwp/os_uwp.cpp | 896 ----- platform/uwp/os_uwp.h | 265 -- platform/uwp/platform_config.h | 31 - platform/uwp/power_uwp.cpp | 77 - platform/uwp/power_uwp.h | 55 - scu_builders.py | 6 +- 391 files changed, 3 insertions(+), 68713 deletions(-) delete mode 100644 platform/android/README.md delete mode 100644 platform/android/SCsub delete mode 100644 platform/android/android_input_handler.cpp delete mode 100644 platform/android/android_input_handler.h delete mode 100644 platform/android/android_keys_utils.cpp delete mode 100644 platform/android/android_keys_utils.h delete mode 100644 platform/android/api/api.cpp delete mode 100644 platform/android/api/api.h delete mode 100644 platform/android/api/java_class_wrapper.h delete mode 100644 platform/android/api/jni_singleton.h delete mode 100644 platform/android/audio_driver_opensl.cpp delete mode 100644 platform/android/audio_driver_opensl.h delete mode 100644 platform/android/detect.py delete mode 100644 platform/android/dir_access_jandroid.cpp delete mode 100644 platform/android/dir_access_jandroid.h delete mode 100644 platform/android/export/export.cpp delete mode 100644 platform/android/export/export.h delete mode 100644 platform/android/export/export_plugin.cpp delete mode 100644 platform/android/export/export_plugin.h delete mode 100644 platform/android/export/gradle_export_util.cpp delete mode 100644 platform/android/export/gradle_export_util.h delete mode 100644 platform/android/export/pandemonium_plugin_config.cpp delete mode 100644 platform/android/export/pandemonium_plugin_config.h delete mode 100644 platform/android/file_access_android.cpp delete mode 100644 platform/android/file_access_android.h delete mode 100644 platform/android/file_access_filesystem_jandroid.cpp delete mode 100644 platform/android/file_access_filesystem_jandroid.h delete mode 100644 platform/android/java/app/AndroidManifest.xml delete mode 100644 platform/android/java/app/assetPacks/installTime/build.gradle delete mode 100644 platform/android/java/app/assets/.gitignore delete mode 100644 platform/android/java/app/build.gradle delete mode 100644 platform/android/java/app/config.gradle delete mode 100644 platform/android/java/app/gradle.properties delete mode 100644 platform/android/java/app/res/drawable-nodpi/splash.png delete mode 100644 platform/android/java/app/res/drawable-nodpi/splash_bg_color.png delete mode 100644 platform/android/java/app/res/drawable/splash_drawable.xml delete mode 100644 platform/android/java/app/res/values-en/pandemonium_project_name_string.xml delete mode 100644 platform/android/java/app/res/values-hu/pandemonium_project_name_string.xml delete mode 100644 platform/android/java/app/res/values/pandemonium_project_name_string.xml delete mode 100644 platform/android/java/app/res/values/themes.xml delete mode 100644 platform/android/java/app/settings.gradle delete mode 100644 platform/android/java/app/src/com/pandemonium/game/PandemoniumApp.java delete mode 100644 platform/android/java/build.gradle delete mode 100644 platform/android/java/editor/build.gradle delete mode 100644 platform/android/java/editor/src/.gitignore delete mode 100644 platform/android/java/editor/src/main/AndroidManifest.xml delete mode 100644 platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumEditor.kt delete mode 100644 platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumGame.kt delete mode 100644 platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumProjectManager.kt delete mode 100644 platform/android/java/editor/src/main/res/values/dimens.xml delete mode 100644 platform/android/java/editor/src/main/res/values/strings.xml delete mode 100644 platform/android/java/gradle.properties delete mode 100644 platform/android/java/gradle/wrapper/gradle-wrapper.jar delete mode 100644 platform/android/java/gradle/wrapper/gradle-wrapper.properties delete mode 100755 platform/android/java/gradlew delete mode 100644 platform/android/java/gradlew.bat delete mode 100644 platform/android/java/lib/AndroidManifest.xml delete mode 100644 platform/android/java/lib/THIRDPARTY.md delete mode 100644 platform/android/java/lib/aidl/com/android/vending/licensing/ILicenseResultListener.aidl delete mode 100644 platform/android/java/lib/aidl/com/android/vending/licensing/ILicensingService.aidl delete mode 100644 platform/android/java/lib/build.gradle delete mode 100644 platform/android/java/lib/patches/com.google.android.vending.expansion.downloader.patch delete mode 100644 platform/android/java/lib/patches/com.google.android.vending.licensing.patch delete mode 100644 platform/android/java/lib/res/layout/downloading_expansion.xml delete mode 100644 platform/android/java/lib/res/layout/pandemonium_app_layout.xml delete mode 100644 platform/android/java/lib/res/layout/status_bar_ongoing_event_progress_bar.xml delete mode 100644 platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml delete mode 100644 platform/android/java/lib/res/mipmap-hdpi/icon.png delete mode 100644 platform/android/java/lib/res/mipmap-hdpi/icon_background.png delete mode 100644 platform/android/java/lib/res/mipmap-hdpi/icon_foreground.png delete mode 100644 platform/android/java/lib/res/mipmap-mdpi/icon.png delete mode 100644 platform/android/java/lib/res/mipmap-mdpi/icon_background.png delete mode 100644 platform/android/java/lib/res/mipmap-mdpi/icon_foreground.png delete mode 100644 platform/android/java/lib/res/mipmap-xhdpi/icon.png delete mode 100644 platform/android/java/lib/res/mipmap-xhdpi/icon_background.png delete mode 100644 platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.png delete mode 100644 platform/android/java/lib/res/mipmap-xxhdpi/icon.png delete mode 100644 platform/android/java/lib/res/mipmap-xxhdpi/icon_background.png delete mode 100644 platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.png delete mode 100644 platform/android/java/lib/res/mipmap-xxxhdpi/icon.png delete mode 100644 platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.png delete mode 100644 platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.png delete mode 100644 platform/android/java/lib/res/mipmap/icon.png delete mode 100644 platform/android/java/lib/res/mipmap/icon_background.png delete mode 100644 platform/android/java/lib/res/mipmap/icon_foreground.png delete mode 100644 platform/android/java/lib/res/values/dimens.xml delete mode 100644 platform/android/java/lib/res/values/strings.xml delete mode 100644 platform/android/java/lib/res/values/styles.xml delete mode 100644 platform/android/java/lib/res/xml/pandemonium_provider_paths.xml delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/Constants.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloadProgressInfo.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/Helpers.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IDownloaderClient.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IDownloaderService.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/IStub.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/SystemFacade.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/CustomIntentService.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadInfo.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/DownloadsDB.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/expansion/downloader/impl/HttpDateTime.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/AESObfuscator.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/APKExpansionPolicy.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/DeviceLimiter.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/LicenseChecker.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/LicenseCheckerCallback.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/LicenseValidator.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/NullDeviceLimiter.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/Obfuscator.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/Policy.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/PreferenceObfuscator.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/ResponseData.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/ServerManagedPolicy.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/StrictPolicy.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/ValidationException.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/util/Base64.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/util/Base64DecoderException.java delete mode 100644 platform/android/java/lib/src/com/google/android/vending/licensing/util/URIQueryDecoder.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/Dictionary.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/FullScreenPandemoniumApp.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/Pandemonium.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/PandemoniumDownloaderAlarmReceiver.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/PandemoniumDownloaderService.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/PandemoniumHost.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/PandemoniumIO.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/PandemoniumLib.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/PandemoniumRenderer.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/PandemoniumView.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/config/RegularConfigChooser.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/config/RegularContextFactory.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/config/RegularFallbackConfigChooser.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/gl/EGLLogWrapper.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/gl/PandemoniumGLSurfaceView.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/input/Joystick.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/input/PandemoniumEditText.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/input/PandemoniumGestureHandler.kt delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/input/PandemoniumInputHandler.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/input/PandemoniumTextInputWrapper.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/io/StorageScope.kt delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/io/directory/AssetsDirectoryAccess.kt delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/io/directory/DirectoryAccessHandler.kt delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/io/directory/FilesystemDirectoryAccess.kt delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/io/file/DataAccess.kt delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/io/file/FileAccessFlags.kt delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/io/file/FileAccessHandler.kt delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/io/file/FileData.kt delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/io/file/MediaStoreData.kt delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/plugin/PandemoniumPlugin.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/plugin/PandemoniumPluginInfoProvider.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/plugin/PandemoniumPluginRegistry.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/plugin/SignalInfo.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/plugin/UsedByPandemonium.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/utils/BenchmarkUtils.kt delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/utils/Crypt.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/utils/GLUtils.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/utils/PandemoniumNetUtils.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/utils/PermissionsUtil.java delete mode 100644 platform/android/java/lib/src/org/pandemoniumengine/pandemonium/utils/ProcessPhoenix.java delete mode 100644 platform/android/java/nativeSrcsConfigs/AndroidManifest.xml delete mode 100644 platform/android/java/nativeSrcsConfigs/CMakeLists.txt delete mode 100644 platform/android/java/nativeSrcsConfigs/README.md delete mode 100644 platform/android/java/nativeSrcsConfigs/build.gradle delete mode 100644 platform/android/java/scripts/publish-module.gradle delete mode 100644 platform/android/java/scripts/publish-root.gradle delete mode 100644 platform/android/java/settings.gradle delete mode 100644 platform/android/java_class_wrapper.cpp delete mode 100644 platform/android/java_pandemonium_io_wrapper.cpp delete mode 100644 platform/android/java_pandemonium_io_wrapper.h delete mode 100644 platform/android/java_pandemonium_lib_jni.cpp delete mode 100644 platform/android/java_pandemonium_lib_jni.h delete mode 100644 platform/android/java_pandemonium_view_wrapper.cpp delete mode 100644 platform/android/java_pandemonium_view_wrapper.h delete mode 100644 platform/android/java_pandemonium_wrapper.cpp delete mode 100644 platform/android/java_pandemonium_wrapper.h delete mode 100644 platform/android/jni_utils.cpp delete mode 100644 platform/android/jni_utils.h delete mode 100644 platform/android/logo.png delete mode 100644 platform/android/net_socket_android.cpp delete mode 100644 platform/android/net_socket_android.h delete mode 100644 platform/android/os_android.cpp delete mode 100644 platform/android/os_android.h delete mode 100644 platform/android/platform_config.h delete mode 100644 platform/android/plugin/pandemonium_plugin_jni.cpp delete mode 100644 platform/android/plugin/pandemonium_plugin_jni.h delete mode 100644 platform/android/power_android.cpp delete mode 100644 platform/android/power_android.h delete mode 100644 platform/android/run_icon.png delete mode 100644 platform/android/string_android.h delete mode 100644 platform/android/thread_jandroid.cpp delete mode 100644 platform/android/thread_jandroid.h delete mode 100644 platform/frt/.clang-format delete mode 100644 platform/frt/.gitignore delete mode 100644 platform/frt/.travis.yml delete mode 100644 platform/frt/CREDITS.txt delete mode 100644 platform/frt/LICENSE.txt delete mode 100644 platform/frt/LICENSE_GODOT.txt delete mode 100644 platform/frt/Local.mk delete mode 100644 platform/frt/Makefile delete mode 100644 platform/frt/README.md delete mode 100644 platform/frt/SCsub delete mode 100644 platform/frt/bits/egl_base_context.h delete mode 100644 platform/frt/bits/frt_app_impl.h delete mode 100644 platform/frt/bits/frt_load_gles.h delete mode 100644 platform/frt/bits/linux_input.h delete mode 100644 platform/frt/bits/mouse_virtual.h delete mode 100644 platform/frt/bits/x11.h delete mode 100644 platform/frt/detect.py delete mode 100644 platform/frt/dl/bcm.dl delete mode 100644 platform/frt/dl/drm.dl delete mode 100644 platform/frt/dl/egl.dl delete mode 100644 platform/frt/dl/gbm.dl delete mode 100644 platform/frt/dl/gles2.dl delete mode 100755 platform/frt/dl/minidl.sh delete mode 100755 platform/frt/dl/procdl.py delete mode 100644 platform/frt/dl/x11.dl delete mode 100644 platform/frt/doc/Bugs.md delete mode 100644 platform/frt/doc/Compile.md delete mode 100644 platform/frt/doc/Environment.md delete mode 100644 platform/frt/doc/Extensions.md delete mode 100644 platform/frt/doc/Porting.md delete mode 100644 platform/frt/doc/ReleaseNotes.md delete mode 100644 platform/frt/doc/Usage.md delete mode 100644 platform/frt/doc/Utgard.md delete mode 100644 platform/frt/doc/VC4.md delete mode 100644 platform/frt/doc/VC6.md delete mode 100644 platform/frt/envprobe.cpp delete mode 100644 platform/frt/frt.h delete mode 100644 platform/frt/frt_options.cpp delete mode 100644 platform/frt/gles2_egl.h delete mode 100644 platform/frt/godot_frt.cpp delete mode 100644 platform/frt/import/cursor.h delete mode 100644 platform/frt/import/gdkeys.h delete mode 100644 platform/frt/import/key_mapping_x11.h delete mode 100644 platform/frt/import/key_mapping_x11_3.cpp delete mode 100644 platform/frt/include/joypad_linux.cpp delete mode 100644 platform/frt/include/libudev-so_wrap.c delete mode 100644 platform/frt/keyboard_linux_input.cpp delete mode 100644 platform/frt/keyboard_x11.cpp delete mode 100644 platform/frt/logo.png delete mode 100644 platform/frt/mouse_linux_input.cpp delete mode 100644 platform/frt/mouse_x11.cpp delete mode 100644 platform/frt/os_frt.cpp delete mode 100644 platform/frt/patches/alsa_21.patch delete mode 100644 platform/frt/patches/alsa_30.patch delete mode 100644 platform/frt/patches/alsa_31.patch delete mode 100644 platform/frt/patches/gcc492a_324.patch delete mode 100644 platform/frt/platform_config.h delete mode 100644 platform/frt/porting/All.mk delete mode 100644 platform/frt/porting/BCM.mk delete mode 100644 platform/frt/porting/FBDev.mk delete mode 100644 platform/frt/porting/KMSDRM.mk delete mode 100644 platform/frt/porting/Local.mk delete mode 100644 platform/frt/porting/Makefile delete mode 100644 platform/frt/porting/X11.mk delete mode 100644 platform/frt/porting/test_all.cpp delete mode 100644 platform/frt/porting/test_keyboard.cpp delete mode 100644 platform/frt/porting/test_modules.cpp delete mode 100644 platform/frt/porting/test_mouse.cpp delete mode 100644 platform/frt/porting/test_video.cpp delete mode 100755 platform/frt/release.sh delete mode 100644 platform/frt/video_bcm.cpp delete mode 100644 platform/frt/video_fbdev.cpp delete mode 100644 platform/frt/video_kmsdrm.cpp delete mode 100644 platform/frt/video_x11.cpp delete mode 100644 platform/frt_sdl/.gitignore delete mode 100644 platform/frt_sdl/LICENSE delete mode 100644 platform/frt_sdl/Makefile delete mode 100644 platform/frt_sdl/README.md delete mode 100644 platform/frt_sdl/SCsub delete mode 100644 platform/frt_sdl/detect.py delete mode 100644 platform/frt_sdl/dl/gles2.dl delete mode 100755 platform/frt_sdl/dl/procdl.py delete mode 100644 platform/frt_sdl/doc/Compile.md delete mode 100644 platform/frt_sdl/doc/ReleaseNotes.md delete mode 100644 platform/frt_sdl/frt.cc delete mode 100644 platform/frt_sdl/frt.h delete mode 100644 platform/frt_sdl/frt_exe.cc delete mode 100644 platform/frt_sdl/frt_godot3.cc delete mode 100644 platform/frt_sdl/frt_lib.h delete mode 100644 platform/frt_sdl/gles2_egl.h delete mode 100644 platform/frt_sdl/logo.png delete mode 100644 platform/frt_sdl/platform_config.h delete mode 100755 platform/frt_sdl/release.sh delete mode 100755 platform/frt_sdl/scripts/compile.sh delete mode 100755 platform/frt_sdl/scripts/for_tags.sh delete mode 100755 platform/frt_sdl/scripts/rolling.sh delete mode 100644 platform/frt_sdl/sdl2_adapter.h delete mode 100644 platform/frt_sdl/sdl2_godot_mapping.h delete mode 100644 platform/iphone/SCsub delete mode 100644 platform/iphone/api/api.cpp delete mode 100644 platform/iphone/api/api.h delete mode 100644 platform/iphone/app_delegate.h delete mode 100644 platform/iphone/app_delegate.mm delete mode 100644 platform/iphone/detect.py delete mode 100644 platform/iphone/device_metrics.h delete mode 100644 platform/iphone/device_metrics.m delete mode 100644 platform/iphone/display_layer.h delete mode 100644 platform/iphone/display_layer.mm delete mode 100644 platform/iphone/export/export.cpp delete mode 100644 platform/iphone/export/export.h delete mode 100644 platform/iphone/ios.h delete mode 100644 platform/iphone/ios.mm delete mode 100644 platform/iphone/joypad_iphone.h delete mode 100644 platform/iphone/joypad_iphone.mm delete mode 100644 platform/iphone/keyboard_input_view.h delete mode 100644 platform/iphone/keyboard_input_view.mm delete mode 100644 platform/iphone/logo.png delete mode 100644 platform/iphone/main.m delete mode 100644 platform/iphone/native_video_view.h delete mode 100644 platform/iphone/native_video_view.m delete mode 100644 platform/iphone/os_iphone.h delete mode 100644 platform/iphone/os_iphone.mm delete mode 100644 platform/iphone/pandemonium_app_delegate.h delete mode 100644 platform/iphone/pandemonium_app_delegate.m delete mode 100644 platform/iphone/pandemonium_iphone.mm delete mode 100644 platform/iphone/pandemonium_view.h delete mode 100644 platform/iphone/pandemonium_view.mm delete mode 100644 platform/iphone/pandemonium_view_renderer.h delete mode 100644 platform/iphone/pandemonium_view_renderer.mm delete mode 100644 platform/iphone/platform_config.h delete mode 100644 platform/iphone/plugin/pandemonium_plugin_config.h delete mode 100644 platform/iphone/power_iphone.cpp delete mode 100644 platform/iphone/power_iphone.h delete mode 100644 platform/iphone/view_controller.h delete mode 100644 platform/iphone/view_controller.mm delete mode 100644 platform/javascript/.eslintrc.engine.js delete mode 100644 platform/javascript/.eslintrc.js delete mode 100644 platform/javascript/.eslintrc.libs.js delete mode 100644 platform/javascript/README.md delete mode 100644 platform/javascript/SCsub delete mode 100644 platform/javascript/api/api.cpp delete mode 100644 platform/javascript/api/api.h delete mode 100644 platform/javascript/api/javascript_singleton.h delete mode 100644 platform/javascript/api/javascript_tools_editor_plugin.cpp delete mode 100644 platform/javascript/api/javascript_tools_editor_plugin.h delete mode 100644 platform/javascript/audio_driver_javascript.cpp delete mode 100644 platform/javascript/audio_driver_javascript.h delete mode 100644 platform/javascript/detect.py delete mode 100644 platform/javascript/dom_keys.inc delete mode 100644 platform/javascript/emscripten_helpers.py delete mode 100644 platform/javascript/export/export.cpp delete mode 100644 platform/javascript/export/export.h delete mode 100644 platform/javascript/http_client.h.inc delete mode 100644 platform/javascript/http_client_javascript.cpp delete mode 100644 platform/javascript/javascript_main.cpp delete mode 100644 platform/javascript/javascript_runtime.cpp delete mode 100644 platform/javascript/javascript_singleton.cpp delete mode 100644 platform/javascript/js/engine/config.js delete mode 100644 platform/javascript/js/engine/engine.externs.js delete mode 100644 platform/javascript/js/engine/engine.js delete mode 100644 platform/javascript/js/engine/preloader.js delete mode 100644 platform/javascript/js/jsdoc2rst/publish.js delete mode 100644 platform/javascript/js/libs/audio.worklet.js delete mode 100644 platform/javascript/js/libs/library_pandemonium_audio.js delete mode 100644 platform/javascript/js/libs/library_pandemonium_display.js delete mode 100644 platform/javascript/js/libs/library_pandemonium_fetch.js delete mode 100644 platform/javascript/js/libs/library_pandemonium_input.js delete mode 100644 platform/javascript/js/libs/library_pandemonium_javascript_singleton.js delete mode 100644 platform/javascript/js/libs/library_pandemonium_os.js delete mode 100644 platform/javascript/js/libs/library_pandemonium_runtime.js delete mode 100644 platform/javascript/logo.png delete mode 100644 platform/javascript/os_javascript.cpp delete mode 100644 platform/javascript/os_javascript.h delete mode 100644 platform/javascript/package-lock.json delete mode 100644 platform/javascript/package.json delete mode 100644 platform/javascript/pandemonium_audio.h delete mode 100644 platform/javascript/pandemonium_js.h delete mode 100644 platform/javascript/platform_config.h delete mode 100644 platform/javascript/run_icon.png delete mode 100644 platform/javascript/serve.py delete mode 100644 platform/uwp/SCsub delete mode 100644 platform/uwp/app.cpp delete mode 100644 platform/uwp/app.h delete mode 100644 platform/uwp/context_egl_uwp.cpp delete mode 100644 platform/uwp/context_egl_uwp.h delete mode 100644 platform/uwp/detect.py delete mode 100644 platform/uwp/export/export.cpp delete mode 100644 platform/uwp/export/export.h delete mode 100644 platform/uwp/joypad_uwp.cpp delete mode 100644 platform/uwp/joypad_uwp.h delete mode 100644 platform/uwp/logo.png delete mode 100644 platform/uwp/os_uwp.cpp delete mode 100644 platform/uwp/os_uwp.h delete mode 100644 platform/uwp/platform_config.h delete mode 100644 platform/uwp/power_uwp.cpp delete mode 100644 platform/uwp/power_uwp.h diff --git a/platform/android/README.md b/platform/android/README.md deleted file mode 100644 index 343e588..0000000 --- a/platform/android/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Android platform port - -This folder contains the Java and C++ (JNI) code for the Android platform port, -using [Gradle](https://gradle.org/) as a build system. - -## Artwork license - -[`logo.png`](logo.png) and [`run_icon.png`](run_icon.png) are licensed under -[Creative Commons Attribution 3.0 Unported](https://developer.android.com/distribute/marketing-tools/brand-guidelines#android_robot) -per the Android logo usage guidelines: - -> The Android robot is reproduced or modified from work created and shared by -> Google and used according to terms described in the Creative Commons 3.0 -> Attribution License. diff --git a/platform/android/SCsub b/platform/android/SCsub deleted file mode 100644 index 79ee1e8..0000000 --- a/platform/android/SCsub +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python - -Import("env") - -android_files = [ - "os_android.cpp", - "android_input_handler.cpp", - "file_access_android.cpp", - "file_access_filesystem_jandroid.cpp", - "audio_driver_opensl.cpp", - "dir_access_jandroid.cpp", - "thread_jandroid.cpp", - "net_socket_android.cpp", - "java_pandemonium_lib_jni.cpp", - "java_class_wrapper.cpp", - "java_pandemonium_wrapper.cpp", - "java_pandemonium_io_wrapper.cpp", - "java_pandemonium_view_wrapper.cpp", - "jni_utils.cpp", - "android_keys_utils.cpp", - "plugin/pandemonium_plugin_jni.cpp", -] - -env_android = env.Clone() - -android_objects = [] -for x in android_files: - android_objects.append(env_android.SharedObject(x)) - -env_thirdparty = env_android.Clone() -env_thirdparty.disable_warnings() -thirdparty_obj = env_thirdparty.SharedObject("#thirdparty/misc/ifaddrs-android.cc") -android_objects.append(thirdparty_obj) - -lib = env_android.add_shared_library("#bin/libpandemonium", [android_objects], SHLIBSUFFIX=env["SHLIBSUFFIX"]) - -# Needed to force rebuilding the platform files when the thirdparty code is updated. -env.Depends(lib, thirdparty_obj) - -lib_arch_dir = "" -if env["android_arch"] == "armv7": - lib_arch_dir = "armeabi-v7a" -elif env["android_arch"] == "arm64v8": - lib_arch_dir = "arm64-v8a" -elif env["android_arch"] == "x86": - lib_arch_dir = "x86" -elif env["android_arch"] == "x86_64": - lib_arch_dir = "x86_64" -else: - print("WARN: Architecture not suitable for embedding into APK; keeping .so at \\bin") - -if lib_arch_dir != "": - if env["target"] == "release": - lib_type_dir = "release" - elif env["target"] == "release_debug": - lib_type_dir = "debug" - else: # debug - lib_type_dir = "dev" - - lib_tools_dir = "" - - out_dir = "#platform/android/java/lib/libs/" + lib_tools_dir + lib_type_dir + "/" + lib_arch_dir - env_android.Command( - out_dir + "/libpandemonium_android.so", "#bin/libpandemonium" + env["SHLIBSUFFIX"], Move("$TARGET", "$SOURCE") - ) - - stl_lib_path = ( - str(env["ANDROID_NDK_ROOT"]) + "/sources/cxx-stl/llvm-libc++/libs/" + lib_arch_dir + "/libc++_shared.so" - ) - env_android.Command(out_dir + "/libc++_shared.so", stl_lib_path, Copy("$TARGET", "$SOURCE")) diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp deleted file mode 100644 index 22c88bb..0000000 --- a/platform/android/android_input_handler.cpp +++ /dev/null @@ -1,419 +0,0 @@ -/*************************************************************************/ -/* android_input_handler.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "android_input_handler.h" - -#include "android_keys_utils.h" - -#include "core/os/os.h" - -void AndroidInputHandler::process_joy_event(const JoypadEvent &p_event) { - switch (p_event.type) { - case JOY_EVENT_BUTTON: - input->joy_button(p_event.device, p_event.index, p_event.pressed); - break; - case JOY_EVENT_AXIS: - input->joy_axis(p_event.device, p_event.index, p_event.value); - break; - case JOY_EVENT_HAT: - input->joy_hat(p_event.device, p_event.hat); - break; - default: - return; - } -} - -void AndroidInputHandler::_set_key_modifier_state(Ref ev) const { - ev->set_shift(shift_mem); - ev->set_alt(alt_mem); - ev->set_metakey(meta_mem); - ev->set_control(control_mem); -} - -void AndroidInputHandler::process_key_event(int p_scancode, int p_physical_scancode, int p_unicode, bool p_pressed) { - Ref ev; - ev.instance(); - - unsigned int physical_scancode = pandemonium_code_from_android_code(p_physical_scancode); - unsigned int scancode = physical_scancode; - if (p_scancode != 0) { - scancode = pandemonium_code_from_unicode(p_scancode); - } - - switch (physical_scancode) { - case KEY_SHIFT: { - shift_mem = p_pressed; - } break; - case KEY_ALT: { - alt_mem = p_pressed; - } break; - case KEY_CONTROL: { - control_mem = p_pressed; - } break; - case KEY_META: { - meta_mem = p_pressed; - } break; - default: - break; - } - - ev->set_scancode(scancode); - ev->set_physical_scancode(physical_scancode); - ev->set_unicode(p_unicode); - ev->set_pressed(p_pressed); - - _set_key_modifier_state(ev); - - if (p_physical_scancode == AKEYCODE_BACK) { - if (MainLoop *main_loop = OS::get_singleton()->get_main_loop()) { - main_loop->call_deferred("notification", MainLoop::NOTIFICATION_WM_GO_BACK_REQUEST); - } - } - - input->parse_input_event(ev); -} - -void AndroidInputHandler::_cancel_all_touch() { - _parse_all_touch(false, true); - touch.clear(); -} - -void AndroidInputHandler::_parse_all_touch(bool p_pressed, bool p_canceled, bool p_double_tap) { - if (touch.size()) { - //end all if exist - for (int i = 0; i < touch.size(); i++) { - Ref ev; - ev.instance(); - ev->set_index(touch[i].id); - ev->set_pressed(p_pressed); - ev->set_canceled(p_canceled); - ev->set_position(touch[i].pos); - ev->set_double_tap(p_double_tap); - input->parse_input_event(ev); - } - } -} - -void AndroidInputHandler::_release_all_touch() { - _parse_all_touch(false); - touch.clear(); -} - -void AndroidInputHandler::process_touch_event(int p_event, int p_pointer, const Vector &p_points, bool p_double_tap) { - switch (p_event) { - case AMOTION_EVENT_ACTION_DOWN: { //gesture begin - // Release any remaining touches or mouse event - _release_mouse_event_info(); - _release_all_touch(); - - touch.resize(p_points.size()); - for (int i = 0; i < p_points.size(); i++) { - touch.write[i].id = p_points[i].id; - touch.write[i].pos = p_points[i].pos; - } - - //send touch - _parse_all_touch(true, false, p_double_tap); - - } break; - case AMOTION_EVENT_ACTION_MOVE: { //motion - if (touch.size() != p_points.size()) { - return; - } - - for (int i = 0; i < touch.size(); i++) { - int idx = -1; - for (int j = 0; j < p_points.size(); j++) { - if (touch[i].id == p_points[j].id) { - idx = j; - break; - } - } - - ERR_CONTINUE(idx == -1); - - if (touch[i].pos == p_points[idx].pos) - continue; //no move unncesearily - - Ref ev; - ev.instance(); - ev->set_index(touch[i].id); - ev->set_position(p_points[idx].pos); - ev->set_relative(p_points[idx].pos - touch[i].pos); - input->parse_input_event(ev); - touch.write[i].pos = p_points[idx].pos; - } - - } break; - case AMOTION_EVENT_ACTION_CANCEL: { - _cancel_all_touch(); - } break; - case AMOTION_EVENT_ACTION_UP: { //release - _release_all_touch(); - } break; - case AMOTION_EVENT_ACTION_POINTER_DOWN: { // add touch - for (int i = 0; i < p_points.size(); i++) { - if (p_points[i].id == p_pointer) { - TouchPos tp = p_points[i]; - touch.push_back(tp); - - Ref ev; - ev.instance(); - - ev->set_index(tp.id); - ev->set_pressed(true); - ev->set_position(tp.pos); - input->parse_input_event(ev); - - break; - } - } - } break; - case AMOTION_EVENT_ACTION_POINTER_UP: { // remove touch - for (int i = 0; i < touch.size(); i++) { - if (touch[i].id == p_pointer) { - Ref ev; - ev.instance(); - ev->set_index(touch[i].id); - ev->set_pressed(false); - ev->set_position(touch[i].pos); - input->parse_input_event(ev); - touch.remove(i); - - break; - } - } - } break; - } -} - -void AndroidInputHandler::_cancel_mouse_event_info(bool p_source_mouse_relative) { - buttons_state = 0; - _parse_mouse_event_info(0, false, true, false, p_source_mouse_relative); - mouse_event_info.valid = false; -} - -void AndroidInputHandler::_parse_mouse_event_info(int buttons_mask, bool p_pressed, bool p_canceled, bool p_double_click, bool p_source_mouse_relative) { - if (!mouse_event_info.valid) { - return; - } - - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - - if (p_source_mouse_relative) { - ev->set_position(hover_prev_pos); - ev->set_global_position(hover_prev_pos); - } else { - ev->set_position(mouse_event_info.pos); - ev->set_global_position(mouse_event_info.pos); - hover_prev_pos = mouse_event_info.pos; - } - - ev->set_pressed(p_pressed); - ev->set_canceled(p_canceled); - int changed_button_mask = buttons_state ^ buttons_mask; - - buttons_state = buttons_mask; - - ev->set_button_index(_button_index_from_mask(changed_button_mask)); - ev->set_button_mask(buttons_mask); - ev->set_doubleclick(p_double_click); - input->parse_input_event(ev); -} - -void AndroidInputHandler::_release_mouse_event_info(bool p_source_mouse_relative) { - _parse_mouse_event_info(0, false, false, false, p_source_mouse_relative); - mouse_event_info.valid = false; -} - -void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click, bool p_source_mouse_relative) { - int event_buttons_mask = _android_button_mask_to_pandemonium_button_mask(p_event_android_buttons_mask); - switch (p_event_action) { - case AMOTION_EVENT_ACTION_HOVER_MOVE: // hover move - case AMOTION_EVENT_ACTION_HOVER_ENTER: // hover enter - case AMOTION_EVENT_ACTION_HOVER_EXIT: { // hover exit - // https://developer.android.com/reference/android/view/MotionEvent.html#ACTION_HOVER_ENTER - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - ev->set_position(p_event_pos); - ev->set_global_position(p_event_pos); - ev->set_relative(p_event_pos - hover_prev_pos); - input->parse_input_event(ev); - hover_prev_pos = p_event_pos; - } break; - case AMOTION_EVENT_ACTION_DOWN: - case AMOTION_EVENT_ACTION_BUTTON_PRESS: { - // Release any remaining touches or mouse event - _release_mouse_event_info(); - _release_all_touch(); - - mouse_event_info.valid = true; - mouse_event_info.pos = p_event_pos; - _parse_mouse_event_info(event_buttons_mask, true, false, p_double_click, p_source_mouse_relative); - } break; - - case AMOTION_EVENT_ACTION_CANCEL: { - _cancel_mouse_event_info(p_source_mouse_relative); - } break; - - case AMOTION_EVENT_ACTION_UP: - case AMOTION_EVENT_ACTION_BUTTON_RELEASE: { - _release_mouse_event_info(p_source_mouse_relative); - } break; - - case AMOTION_EVENT_ACTION_MOVE: { - if (!mouse_event_info.valid) { - return; - } - - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - - if (p_source_mouse_relative) { - ev->set_position(hover_prev_pos); - ev->set_global_position(hover_prev_pos); - ev->set_relative(p_event_pos); - } else { - ev->set_position(p_event_pos); - ev->set_global_position(p_event_pos); - ev->set_relative(p_event_pos - hover_prev_pos); - mouse_event_info.pos = p_event_pos; - hover_prev_pos = p_event_pos; - } - - ev->set_button_mask(event_buttons_mask); - input->parse_input_event(ev); - } break; - - case AMOTION_EVENT_ACTION_SCROLL: { - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - - if (p_source_mouse_relative) { - ev->set_position(hover_prev_pos); - ev->set_global_position(hover_prev_pos); - } else { - ev->set_position(p_event_pos); - ev->set_global_position(p_event_pos); - } - - ev->set_pressed(true); - buttons_state = event_buttons_mask; - if (p_delta.y > 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_UP, p_delta.y); - } else if (p_delta.y < 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_DOWN, -p_delta.y); - } - - if (p_delta.x > 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_RIGHT, p_delta.x); - } else if (p_delta.x < 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_LEFT, -p_delta.x); - } - } break; - } -} - -void AndroidInputHandler::_wheel_button_click(int event_buttons_mask, const Ref &ev, int wheel_button, float factor) { - Ref evd = ev->duplicate(); - evd->set_button_index(wheel_button); - evd->set_button_mask(event_buttons_mask ^ (1 << (wheel_button - 1))); - evd->set_factor(factor); - input->parse_input_event(evd); - Ref evdd = evd->duplicate(); - evdd->set_pressed(false); - evdd->set_button_mask(event_buttons_mask); - input->parse_input_event(evdd); -} - -void AndroidInputHandler::process_magnify(Point2 p_pos, float p_factor) { - Ref magnify_event; - magnify_event.instance(); - _set_key_modifier_state(magnify_event); - magnify_event->set_position(p_pos); - magnify_event->set_factor(p_factor); - input->parse_input_event(magnify_event); -} - -void AndroidInputHandler::process_pan(Point2 p_pos, Vector2 p_delta) { - Ref pan_event; - pan_event.instance(); - _set_key_modifier_state(pan_event); - pan_event->set_position(p_pos); - pan_event->set_delta(p_delta); - input->parse_input_event(pan_event); -} - -int AndroidInputHandler::_button_index_from_mask(int button_mask) { - switch (button_mask) { - case BUTTON_MASK_LEFT: - return BUTTON_LEFT; - case BUTTON_MASK_RIGHT: - return BUTTON_RIGHT; - case BUTTON_MASK_MIDDLE: - return BUTTON_MIDDLE; - case BUTTON_MASK_XBUTTON1: - return BUTTON_XBUTTON1; - case BUTTON_MASK_XBUTTON2: - return BUTTON_XBUTTON2; - default: - return 0; - } -} - -int AndroidInputHandler::_android_button_mask_to_pandemonium_button_mask(int android_button_mask) { - int pandemonium_button_mask = 0; - if (android_button_mask & AMOTION_EVENT_BUTTON_PRIMARY) { - pandemonium_button_mask |= BUTTON_MASK_LEFT; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) { - pandemonium_button_mask |= BUTTON_MASK_RIGHT; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_TERTIARY) { - pandemonium_button_mask |= BUTTON_MASK_MIDDLE; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_BACK) { - pandemonium_button_mask |= BUTTON_MASK_XBUTTON1; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_FORWARD) { - pandemonium_button_mask |= BUTTON_MASK_XBUTTON2; - } - - return pandemonium_button_mask; -} - -void AndroidInputHandler::joy_connection_changed(int p_device, bool p_connected, String p_name) { - input->joy_connection_changed(p_device, p_connected, p_name, ""); -} diff --git a/platform/android/android_input_handler.h b/platform/android/android_input_handler.h deleted file mode 100644 index 39f94ae..0000000 --- a/platform/android/android_input_handler.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef ANDROID_INPUT_HANDLER_H -#define ANDROID_INPUT_HANDLER_H -/*************************************************************************/ -/* android_input_handler.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "main/input_default.h" - -// This class encapsulates all the handling of input events that come from the Android UI thread. -// Remarks: -// - It's not thread-safe by itself, so its functions must only be called on a single thread, which is the Android UI thread. -// - Its functions must only call thread-safe methods. -class AndroidInputHandler { -public: - struct TouchPos { - int id; - Point2 pos; - }; - - struct MouseEventInfo { - bool valid = false; - Point2 pos; - }; - - enum { - JOY_EVENT_BUTTON = 0, - JOY_EVENT_AXIS = 1, - JOY_EVENT_HAT = 2 - }; - - struct JoypadEvent { - int device; - int type; - int index; - bool pressed; - float value; - int hat; - }; - -private: - Vector touch; - MouseEventInfo mouse_event_info; - Point2 hover_prev_pos; // needed to calculate the relative position on hover events - - bool alt_mem = false; - bool shift_mem = false; - bool control_mem = false; - bool meta_mem = false; - - int buttons_state = 0; - - InputDefault *input = static_cast(InputDefault::get_singleton()); - - void _set_key_modifier_state(Ref ev) const; - - static int _button_index_from_mask(int button_mask); - - static int _android_button_mask_to_pandemonium_button_mask(int android_button_mask); - - void _wheel_button_click(int event_buttons_mask, const Ref &ev, int wheel_button, float factor); - - void _parse_mouse_event_info(int buttons_mask, bool p_pressed, bool p_canceled, bool p_double_click, bool p_source_mouse_relative); - - void _release_mouse_event_info(bool p_source_mouse_relative = false); - - void _cancel_mouse_event_info(bool p_source_mouse_relative = false); - - void _parse_all_touch(bool p_pressed, bool p_canceled = false, bool p_double_tap = false); - - void _release_all_touch(); - - void _cancel_all_touch(); - -public: - void process_joy_event(const JoypadEvent &p_event); - void process_key_event(int p_scancode, int p_physical_scancode, int p_unicode, bool p_pressed); - void process_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click, bool p_source_mouse_relative); - void process_touch_event(int p_event, int p_pointer, const Vector &p_points, bool p_double_tap); - void process_magnify(Point2 p_pos, float p_factor); - void process_pan(Point2 p_pos, Vector2 p_delta); - void joy_connection_changed(int p_device, bool p_connected, String p_name); -}; - -#endif diff --git a/platform/android/android_keys_utils.cpp b/platform/android/android_keys_utils.cpp deleted file mode 100644 index 45d2742..0000000 --- a/platform/android/android_keys_utils.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/*************************************************************************/ -/* android_keys_utils.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "android_keys_utils.h" - -unsigned int pandemonium_code_from_android_code(unsigned int p_code) { - for (int i = 0; android_pandemonium_code_pairs[i].android_code != AKEYCODE_MAX; i++) { - if (android_pandemonium_code_pairs[i].android_code == p_code) { - return android_pandemonium_code_pairs[i].pandemonium_code; - } - } - - return KEY_UNKNOWN; -} - -unsigned int pandemonium_code_from_unicode(unsigned int p_code) { - unsigned int code = p_code; - if (code > 0xFF) { - return KEY_UNKNOWN; - } - // Known control codes. - if (code == '\b') { // 0x08 - return KEY_BACKSPACE; - } - if (code == '\t') { // 0x09 - return KEY_TAB; - } - if (code == '\n') { // 0x0A - return KEY_ENTER; - } - if (code == 0x1B) { - return KEY_ESCAPE; - } - if (code == 0x7F) { - return KEY_DELETE; - } - // Unknown control codes. - if (code <= 0x1F || (code >= 0x80 && code <= 0x9F)) { - return KEY_UNKNOWN; - } - // Convert to uppercase. - if (code >= 'a' && code <= 'z') { // 0x61 - 0x7A - code -= ('a' - 'A'); - } - if (code >= u'à' && code <= u'ö') { // 0xE0 - 0xF6 - code -= (u'à' - u'À'); // 0xE0 - 0xC0 - } - if (code >= u'ø' && code <= u'þ') { // 0xF8 - 0xFF - code -= (u'ø' - u'Ø'); // 0xF8 - 0xD8 - } - return code; -} diff --git a/platform/android/android_keys_utils.h b/platform/android/android_keys_utils.h deleted file mode 100644 index 5baf4ab..0000000 --- a/platform/android/android_keys_utils.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef ANDROID_KEYS_UTILS_H -#define ANDROID_KEYS_UTILS_H -/*************************************************************************/ -/* android_keys_utils.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include -#include - -#define AKEYCODE_MAX 0xFFFF - -struct AndroidPandemoniumCodePair { - unsigned int android_code = 0; - unsigned int pandemonium_code = 0; -}; - -static AndroidPandemoniumCodePair android_pandemonium_code_pairs[] = { - { AKEYCODE_UNKNOWN, KEY_UNKNOWN }, // (0) Unknown key code. - { AKEYCODE_BACK, KEY_BACK }, // (4) Back key. - { AKEYCODE_0, KEY_0 }, // (7) '0' key. - { AKEYCODE_1, KEY_1 }, // (8) '1' key. - { AKEYCODE_2, KEY_2 }, // (9) '2' key. - { AKEYCODE_3, KEY_3 }, // (10) '3' key. - { AKEYCODE_4, KEY_4 }, // (11) '4' key. - { AKEYCODE_5, KEY_5 }, // (12) '5' key. - { AKEYCODE_6, KEY_6 }, // (13) '6' key. - { AKEYCODE_7, KEY_7 }, // (14) '7' key. - { AKEYCODE_8, KEY_8 }, // (15) '8' key. - { AKEYCODE_9, KEY_9 }, // (16) '9' key. - { AKEYCODE_STAR, KEY_ASTERISK }, // (17) '*' key. - { AKEYCODE_POUND, KEY_NUMBERSIGN }, // (18) '#' key. - { AKEYCODE_DPAD_UP, KEY_UP }, // (19) Directional Pad Up key. - { AKEYCODE_DPAD_DOWN, KEY_DOWN }, // (20) Directional Pad Down key. - { AKEYCODE_DPAD_LEFT, KEY_LEFT }, // (21) Directional Pad Left key. - { AKEYCODE_DPAD_RIGHT, KEY_RIGHT }, // (22) Directional Pad Right key. - { AKEYCODE_DPAD_CENTER, KEY_ENTER }, // (23) Directional Pad Center key. - { AKEYCODE_VOLUME_UP, KEY_VOLUMEUP }, // (24) Volume Up key. - { AKEYCODE_VOLUME_DOWN, KEY_VOLUMEDOWN }, // (25) Volume Down key. - { AKEYCODE_POWER, KEY_STANDBY }, // (26) Power key. - { AKEYCODE_CLEAR, KEY_CLEAR }, // (28) Clear key. - { AKEYCODE_A, KEY_A }, // (29) 'A' key. - { AKEYCODE_B, KEY_B }, // (30) 'B' key. - { AKEYCODE_C, KEY_C }, // (31) 'C' key. - { AKEYCODE_D, KEY_D }, // (32) 'D' key. - { AKEYCODE_E, KEY_E }, // (33) 'E' key. - { AKEYCODE_F, KEY_F }, // (34) 'F' key. - { AKEYCODE_G, KEY_G }, // (35) 'G' key. - { AKEYCODE_H, KEY_H }, // (36) 'H' key. - { AKEYCODE_I, KEY_I }, // (37) 'I' key. - { AKEYCODE_J, KEY_J }, // (38) 'J' key. - { AKEYCODE_K, KEY_K }, // (39) 'K' key. - { AKEYCODE_L, KEY_L }, // (40) 'L' key. - { AKEYCODE_M, KEY_M }, // (41) 'M' key. - { AKEYCODE_N, KEY_N }, // (42) 'N' key. - { AKEYCODE_O, KEY_O }, // (43) 'O' key. - { AKEYCODE_P, KEY_P }, // (44) 'P' key. - { AKEYCODE_Q, KEY_Q }, // (45) 'Q' key. - { AKEYCODE_R, KEY_R }, // (46) 'R' key. - { AKEYCODE_S, KEY_S }, // (47) 'S' key. - { AKEYCODE_T, KEY_T }, // (48) 'T' key. - { AKEYCODE_U, KEY_U }, // (49) 'U' key. - { AKEYCODE_V, KEY_V }, // (50) 'V' key. - { AKEYCODE_W, KEY_W }, // (51) 'W' key. - { AKEYCODE_X, KEY_X }, // (52) 'X' key. - { AKEYCODE_Y, KEY_Y }, // (53) 'Y' key. - { AKEYCODE_Z, KEY_Z }, // (54) 'Z' key. - { AKEYCODE_COMMA, KEY_COMMA }, // (55) ',’ key. - { AKEYCODE_PERIOD, KEY_PERIOD }, // (56) '.' key. - { AKEYCODE_ALT_LEFT, KEY_ALT }, // (57) Left Alt modifier key. - { AKEYCODE_ALT_RIGHT, KEY_ALT }, // (58) Right Alt modifier key. - { AKEYCODE_SHIFT_LEFT, KEY_SHIFT }, // (59) Left Shift modifier key. - { AKEYCODE_SHIFT_RIGHT, KEY_SHIFT }, // (60) Right Shift modifier key. - { AKEYCODE_TAB, KEY_TAB }, // (61) Tab key. - { AKEYCODE_SPACE, KEY_SPACE }, // (62) Space key. - { AKEYCODE_ENVELOPE, KEY_LAUNCHMAIL }, // (65) Envelope special function key. - { AKEYCODE_ENTER, KEY_ENTER }, // (66) Enter key. - { AKEYCODE_DEL, KEY_BACKSPACE }, // (67) Backspace key. - { AKEYCODE_GRAVE, KEY_QUOTELEFT }, // (68) '`' (backtick) key. - { AKEYCODE_MINUS, KEY_MINUS }, // (69) '-'. - { AKEYCODE_EQUALS, KEY_EQUAL }, // (70) '=' key. - { AKEYCODE_LEFT_BRACKET, KEY_BRACKETLEFT }, // (71) '[' key. - { AKEYCODE_RIGHT_BRACKET, KEY_BRACKETRIGHT }, // (72) ']' key. - { AKEYCODE_BACKSLASH, KEY_BACKSLASH }, // (73) '\' key. - { AKEYCODE_SEMICOLON, KEY_SEMICOLON }, // (74) ';' key. - { AKEYCODE_APOSTROPHE, KEY_APOSTROPHE }, // (75) ''' (apostrophe) key. - { AKEYCODE_SLASH, KEY_SLASH }, // (76) '/' key. - { AKEYCODE_AT, KEY_AT }, // (77) '@' key. - { AKEYCODE_PLUS, KEY_PLUS }, // (81) '+' key. - { AKEYCODE_MENU, KEY_MENU }, // (82) Menu key. - { AKEYCODE_SEARCH, KEY_SEARCH }, // (84) Search key. - { AKEYCODE_MEDIA_STOP, KEY_MEDIASTOP }, // (86) Stop media key. - { AKEYCODE_MEDIA_NEXT, KEY_MEDIANEXT }, // (87) Play Next media key. - { AKEYCODE_MEDIA_PREVIOUS, KEY_MEDIAPREVIOUS }, // (88) Play Previous media key. - { AKEYCODE_PAGE_UP, KEY_PAGEUP }, // (92) Page Up key. - { AKEYCODE_PAGE_DOWN, KEY_PAGEDOWN }, // (93) Page Down key. - { AKEYCODE_ESCAPE, KEY_ESCAPE }, // (111) Escape key. - { AKEYCODE_FORWARD_DEL, KEY_DELETE }, // (112) Forward Delete key. - { AKEYCODE_CTRL_LEFT, KEY_CONTROL }, // (113) Left Control modifier key. - { AKEYCODE_CTRL_RIGHT, KEY_CONTROL }, // (114) Right Control modifier key. - { AKEYCODE_CAPS_LOCK, KEY_CAPSLOCK }, // (115) Caps Lock key. - { AKEYCODE_SCROLL_LOCK, KEY_SCROLLLOCK }, // (116) Scroll Lock key. - { AKEYCODE_META_LEFT, KEY_META }, // (117) Left Meta modifier key. - { AKEYCODE_META_RIGHT, KEY_META }, // (118) Right Meta modifier key. - { AKEYCODE_SYSRQ, KEY_PRINT }, // (120) System Request / Print Screen key. - { AKEYCODE_BREAK, KEY_PAUSE }, // (121) Break / Pause key. - { AKEYCODE_MOVE_HOME, KEY_HOME }, // (122) Home Movement key. - { AKEYCODE_MOVE_END, KEY_END }, // (123) End Movement key. - { AKEYCODE_INSERT, KEY_INSERT }, // (124) Insert key. - { AKEYCODE_FORWARD, KEY_FORWARD }, // (125) Forward key. - { AKEYCODE_MEDIA_PLAY, KEY_MEDIAPLAY }, // (126) Play media key. - { AKEYCODE_MEDIA_RECORD, KEY_MEDIARECORD }, // (130) Record media key. - { AKEYCODE_F1, KEY_F1 }, // (131) F1 key. - { AKEYCODE_F2, KEY_F2 }, // (132) F2 key. - { AKEYCODE_F3, KEY_F3 }, // (133) F3 key. - { AKEYCODE_F4, KEY_F4 }, // (134) F4 key. - { AKEYCODE_F5, KEY_F5 }, // (135) F5 key. - { AKEYCODE_F6, KEY_F6 }, // (136) F6 key. - { AKEYCODE_F7, KEY_F7 }, // (137) F7 key. - { AKEYCODE_F8, KEY_F8 }, // (138) F8 key. - { AKEYCODE_F9, KEY_F9 }, // (139) F9 key. - { AKEYCODE_F10, KEY_F10 }, // (140) F10 key. - { AKEYCODE_F11, KEY_F11 }, // (141) F11 key. - { AKEYCODE_F12, KEY_F12 }, // (142) F12 key. - { AKEYCODE_NUM_LOCK, KEY_NUMLOCK }, // (143) Num Lock key. - { AKEYCODE_NUMPAD_0, KEY_KP_0 }, // (144) Numeric keypad '0' key. - { AKEYCODE_NUMPAD_1, KEY_KP_1 }, // (145) Numeric keypad '1' key. - { AKEYCODE_NUMPAD_2, KEY_KP_2 }, // (146) Numeric keypad '2' key. - { AKEYCODE_NUMPAD_3, KEY_KP_3 }, // (147) Numeric keypad '3' key. - { AKEYCODE_NUMPAD_4, KEY_KP_4 }, // (148) Numeric keypad '4' key. - { AKEYCODE_NUMPAD_5, KEY_KP_5 }, // (149) Numeric keypad '5' key. - { AKEYCODE_NUMPAD_6, KEY_KP_6 }, // (150) Numeric keypad '6' key. - { AKEYCODE_NUMPAD_7, KEY_KP_7 }, // (151) Numeric keypad '7' key. - { AKEYCODE_NUMPAD_8, KEY_KP_8 }, // (152) Numeric keypad '8' key. - { AKEYCODE_NUMPAD_9, KEY_KP_9 }, // (153) Numeric keypad '9' key. - { AKEYCODE_NUMPAD_DIVIDE, KEY_KP_DIVIDE }, // (154) Numeric keypad '/' key (for division). - { AKEYCODE_NUMPAD_MULTIPLY, KEY_KP_MULTIPLY }, // (155) Numeric keypad '*' key (for multiplication). - { AKEYCODE_NUMPAD_SUBTRACT, KEY_KP_SUBTRACT }, // (156) Numeric keypad '-' key (for subtraction). - { AKEYCODE_NUMPAD_ADD, KEY_KP_ADD }, // (157) Numeric keypad '+' key (for addition). - { AKEYCODE_NUMPAD_DOT, KEY_KP_PERIOD }, // (158) Numeric keypad '.' key (for decimals or digit grouping). - { AKEYCODE_NUMPAD_ENTER, KEY_KP_ENTER }, // (160) Numeric keypad Enter key. - { AKEYCODE_VOLUME_MUTE, KEY_VOLUMEMUTE }, // (164) Volume Mute key. - { AKEYCODE_YEN, KEY_YEN }, // (216) Japanese Yen key. - { AKEYCODE_HELP, KEY_HELP }, // (259) Help key. - { AKEYCODE_REFRESH, KEY_REFRESH }, // (285) Refresh key. - { AKEYCODE_MAX, KEY_UNKNOWN } -}; - -unsigned int pandemonium_code_from_android_code(unsigned int p_code); -unsigned int pandemonium_code_from_unicode(unsigned int p_code); - -#endif // ANDROID_KEYS_UTILS_H diff --git a/platform/android/api/api.cpp b/platform/android/api/api.cpp deleted file mode 100644 index d66c908..0000000 --- a/platform/android/api/api.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/*************************************************************************/ -/* api.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "api.h" - -#include "core/config/engine.h" -#include "java_class_wrapper.h" -#include "jni_singleton.h" - -#if !defined(ANDROID_ENABLED) -static JavaClassWrapper *java_class_wrapper = nullptr; -#endif - -void register_android_api() { -#if !defined(ANDROID_ENABLED) - // On Android platforms, the `java_class_wrapper` instantiation and the - // `JNISingleton` registration occurs in - // `platform/android/java_pandemonium_lib_jni.cpp#Java_org_pandemoniumengine_pandemonium_PandemoniumLib_setup` - java_class_wrapper = memnew(JavaClassWrapper); // Dummy - ClassDB::register_class(); -#endif - - ClassDB::register_class(); - ClassDB::register_class(); - Engine::get_singleton()->add_singleton(Engine::Singleton("JavaClassWrapper", JavaClassWrapper::get_singleton())); -} - -void unregister_android_api() { -#if !defined(ANDROID_ENABLED) - memdelete(java_class_wrapper); -#endif -} - -void JavaClassWrapper::_bind_methods() { - ClassDB::bind_method(D_METHOD("wrap", "name"), &JavaClassWrapper::wrap); -} - -#if !defined(ANDROID_ENABLED) - -Variant JavaClass::call(const StringName &, const Variant **, int, Variant::CallError &) { - return Variant(); -} - -JavaClass::JavaClass() { -} - -Variant JavaObject::call(const StringName &, const Variant **, int, Variant::CallError &) { - return Variant(); -} - -JavaClassWrapper *JavaClassWrapper::singleton = nullptr; - -Ref JavaClassWrapper::wrap(const String &) { - return Ref(); -} - -JavaClassWrapper::JavaClassWrapper() { - singleton = this; -} - -#endif diff --git a/platform/android/api/api.h b/platform/android/api/api.h deleted file mode 100644 index 9e0c331..0000000 --- a/platform/android/api/api.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef ANDROID_API_H -#define ANDROID_API_H -/*************************************************************************/ -/* api.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -void register_android_api(); -void unregister_android_api(); - -#endif // ANDROID_API_H diff --git a/platform/android/api/java_class_wrapper.h b/platform/android/api/java_class_wrapper.h deleted file mode 100644 index e7baff4..0000000 --- a/platform/android/api/java_class_wrapper.h +++ /dev/null @@ -1,254 +0,0 @@ -#ifndef JAVA_CLASS_WRAPPER_H -#define JAVA_CLASS_WRAPPER_H -/*************************************************************************/ -/* java_class_wrapper.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "core/object/reference.h" - -#ifdef ANDROID_ENABLED -#include -#include -#endif - -#ifdef ANDROID_ENABLED -class JavaObject; -#endif - -class JavaClass : public Reference { - GDCLASS(JavaClass, Reference); - -#ifdef ANDROID_ENABLED - enum ArgumentType{ - - ARG_TYPE_VOID, - ARG_TYPE_BOOLEAN, - ARG_TYPE_BYTE, - ARG_TYPE_CHAR, - ARG_TYPE_SHORT, - ARG_TYPE_INT, - ARG_TYPE_LONG, - ARG_TYPE_FLOAT, - ARG_TYPE_DOUBLE, - ARG_TYPE_STRING, //special case - ARG_TYPE_CLASS, - ARG_ARRAY_BIT = 1 << 16, - ARG_NUMBER_CLASS_BIT = 1 << 17, - ARG_TYPE_MASK = (1 << 16) - 1 - }; - - RBMap constant_map; - - struct MethodInfo { - bool _static; - Vector param_types; - Vector param_sigs; - uint32_t return_type; - jmethodID method; - }; - - _FORCE_INLINE_ static void _convert_to_variant_type(int p_sig, Variant::Type &r_type, float &likelihood) { - likelihood = 1.0; - r_type = Variant::NIL; - - switch (p_sig) { - case ARG_TYPE_VOID: - r_type = Variant::NIL; - break; - case ARG_TYPE_BOOLEAN | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_BOOLEAN: - r_type = Variant::BOOL; - break; - case ARG_TYPE_BYTE | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_BYTE: - r_type = Variant::INT; - likelihood = 0.1; - break; - case ARG_TYPE_CHAR | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_CHAR: - r_type = Variant::INT; - likelihood = 0.2; - break; - case ARG_TYPE_SHORT | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_SHORT: - r_type = Variant::INT; - likelihood = 0.3; - break; - case ARG_TYPE_INT | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_INT: - r_type = Variant::INT; - likelihood = 1.0; - break; - case ARG_TYPE_LONG | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_LONG: - r_type = Variant::INT; - likelihood = 0.5; - break; - case ARG_TYPE_FLOAT | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_FLOAT: - r_type = Variant::REAL; - likelihood = 1.0; - break; - case ARG_TYPE_DOUBLE | ARG_NUMBER_CLASS_BIT: - case ARG_TYPE_DOUBLE: - r_type = Variant::REAL; - likelihood = 0.5; - break; - case ARG_TYPE_STRING: - r_type = Variant::STRING; - break; - case ARG_TYPE_CLASS: - r_type = Variant::OBJECT; - break; - case ARG_ARRAY_BIT | ARG_TYPE_VOID: - r_type = Variant::NIL; - break; - case ARG_ARRAY_BIT | ARG_TYPE_BOOLEAN: - r_type = Variant::ARRAY; - break; - case ARG_ARRAY_BIT | ARG_TYPE_BYTE: - r_type = Variant::POOL_BYTE_ARRAY; - likelihood = 1.0; - break; - case ARG_ARRAY_BIT | ARG_TYPE_CHAR: - r_type = Variant::POOL_BYTE_ARRAY; - likelihood = 0.5; - break; - case ARG_ARRAY_BIT | ARG_TYPE_SHORT: - r_type = Variant::POOL_INT_ARRAY; - likelihood = 0.3; - break; - case ARG_ARRAY_BIT | ARG_TYPE_INT: - r_type = Variant::POOL_INT_ARRAY; - likelihood = 1.0; - break; - case ARG_ARRAY_BIT | ARG_TYPE_LONG: - r_type = Variant::POOL_INT_ARRAY; - likelihood = 0.5; - break; - case ARG_ARRAY_BIT | ARG_TYPE_FLOAT: - r_type = Variant::POOL_REAL_ARRAY; - likelihood = 1.0; - break; - case ARG_ARRAY_BIT | ARG_TYPE_DOUBLE: - r_type = Variant::POOL_REAL_ARRAY; - likelihood = 0.5; - break; - case ARG_ARRAY_BIT | ARG_TYPE_STRING: - r_type = Variant::POOL_STRING_ARRAY; - break; - case ARG_ARRAY_BIT | ARG_TYPE_CLASS: - r_type = Variant::ARRAY; - break; - } - } - - _FORCE_INLINE_ static bool _convert_object_to_variant(JNIEnv *env, jobject obj, Variant &var, uint32_t p_sig); - - bool _call_method(JavaObject *p_instance, const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error, Variant &ret); - - friend class JavaClassWrapper; - RBMap> methods; - jclass _class; -#endif - -public: - virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); - - JavaClass(); -}; - -class JavaObject : public Reference { - GDCLASS(JavaObject, Reference); - -#ifdef ANDROID_ENABLED - Ref base_class; - friend class JavaClass; - - jobject instance; -#endif - -public: - virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); - -#ifdef ANDROID_ENABLED - JavaObject(const Ref &p_base, jobject *p_instance); - ~JavaObject(); -#endif -}; - -class JavaClassWrapper : public Object { - GDCLASS(JavaClassWrapper, Object); - -#ifdef ANDROID_ENABLED - RBMap> class_cache; - friend class JavaClass; - jclass activityClass; - jmethodID findClass; - jmethodID getDeclaredMethods; - jmethodID getFields; - jmethodID getParameterTypes; - jmethodID getReturnType; - jmethodID getModifiers; - jmethodID getName; - jmethodID Class_getName; - jmethodID Field_getName; - jmethodID Field_getModifiers; - jmethodID Field_get; - jmethodID Boolean_booleanValue; - jmethodID Byte_byteValue; - jmethodID Character_characterValue; - jmethodID Short_shortValue; - jmethodID Integer_integerValue; - jmethodID Long_longValue; - jmethodID Float_floatValue; - jmethodID Double_doubleValue; - jobject classLoader; - - bool _get_type_sig(JNIEnv *env, jobject obj, uint32_t &sig, String &strsig); -#endif - - static JavaClassWrapper *singleton; - -protected: - static void _bind_methods(); - -public: - static JavaClassWrapper *get_singleton() { return singleton; } - - Ref wrap(const String &p_class); - -#ifdef ANDROID_ENABLED - JavaClassWrapper(jobject p_activity = NULL); -#else - JavaClassWrapper(); -#endif -}; - -#endif // JAVA_CLASS_WRAPPER_H diff --git a/platform/android/api/jni_singleton.h b/platform/android/api/jni_singleton.h deleted file mode 100644 index 9971d37..0000000 --- a/platform/android/api/jni_singleton.h +++ /dev/null @@ -1,221 +0,0 @@ -#ifndef JNI_SINGLETON_H -#define JNI_SINGLETON_H -/*************************************************************************/ -/* jni_singleton.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include -#include -#ifdef ANDROID_ENABLED -#include -#endif - -class JNISingleton : public Object { - GDCLASS(JNISingleton, Object); - -#ifdef ANDROID_ENABLED - struct MethodData { - jmethodID method; - Variant::Type ret_type; - Vector argtypes; - }; - - jobject instance; - RBMap method_map; -#endif - -public: - virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { -#ifdef ANDROID_ENABLED - RBMap::Element *E = method_map.find(p_method); - - // Check the method we're looking for is in the JNISingleton map and that - // the arguments match. - bool call_error = !E || E->get().argtypes.size() != p_argcount; - if (!call_error) { - for (int i = 0; i < p_argcount; i++) { - if (!Variant::can_convert(p_args[i]->get_type(), E->get().argtypes[i])) { - call_error = true; - break; - } - } - } - - if (call_error) { - // The method is not in this map, defaulting to the regular instance calls. - return Object::call(p_method, p_args, p_argcount, r_error); - } - - ERR_FAIL_COND_V(!instance, Variant()); - - r_error.error = Variant::CallError::CALL_OK; - - jvalue *v = NULL; - - if (p_argcount) { - v = (jvalue *)alloca(sizeof(jvalue) * p_argcount); - } - - JNIEnv *env = get_jni_env(); - - int res = env->PushLocalFrame(16); - - ERR_FAIL_COND_V(res != 0, Variant()); - - List to_erase; - for (int i = 0; i < p_argcount; i++) { - jvalret vr = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]); - v[i] = vr.val; - if (vr.obj) - to_erase.push_back(vr.obj); - } - - 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) == JNI_TRUE; - } 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); - ret = jstring_to_string((jstring)o, env); - env->DeleteLocalRef(o); - } break; - case Variant::POOL_STRING_ARRAY: { - jobjectArray arr = (jobjectArray)env->CallObjectMethodA(instance, E->get().method, v); - - ret = _jobject_to_variant(env, arr); - - env->DeleteLocalRef(arr); - } break; - case Variant::POOL_INT_ARRAY: { - jintArray arr = (jintArray)env->CallObjectMethodA(instance, E->get().method, v); - - int fCount = env->GetArrayLength(arr); - PoolVector sarr; - sarr.resize(fCount); - - PoolVector::Write w = sarr.write(); - env->GetIntArrayRegion(arr, 0, fCount, w.ptr()); - w.release(); - ret = sarr; - env->DeleteLocalRef(arr); - } break; - case Variant::POOL_REAL_ARRAY: { - jfloatArray arr = (jfloatArray)env->CallObjectMethodA(instance, E->get().method, v); - - int fCount = env->GetArrayLength(arr); - PoolVector sarr; - sarr.resize(fCount); - - PoolVector::Write w = sarr.write(); - env->GetFloatArrayRegion(arr, 0, fCount, w.ptr()); - w.release(); - ret = sarr; - env->DeleteLocalRef(arr); - } break; - - case Variant::DICTIONARY: { - jobject obj = env->CallObjectMethodA(instance, E->get().method, v); - ret = _jobject_to_variant(env, obj); - env->DeleteLocalRef(obj); - - } break; - default: { - env->PopLocalFrame(NULL); - ERR_FAIL_V(Variant()); - } break; - } - - while (to_erase.size()) { - env->DeleteLocalRef(to_erase.front()->get()); - to_erase.pop_front(); - } - - env->PopLocalFrame(NULL); - - return ret; -#else // ANDROID_ENABLED - - // Defaulting to the regular instance calls. - return Object::call(p_method, p_args, p_argcount, r_error); -#endif - } - -#ifdef ANDROID_ENABLED - 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 &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; - } - - void add_signal(const StringName &p_name, const Vector &p_args) { - if (p_args.size() == 0) - ADD_SIGNAL(MethodInfo(p_name)); - else if (p_args.size() == 1) - ADD_SIGNAL(MethodInfo(p_name, PropertyInfo(p_args[0], "arg1"))); - else if (p_args.size() == 2) - ADD_SIGNAL(MethodInfo(p_name, PropertyInfo(p_args[0], "arg1"), PropertyInfo(p_args[1], "arg2"))); - else if (p_args.size() == 3) - ADD_SIGNAL(MethodInfo(p_name, PropertyInfo(p_args[0], "arg1"), PropertyInfo(p_args[1], "arg2"), PropertyInfo(p_args[2], "arg3"))); - else if (p_args.size() == 4) - ADD_SIGNAL(MethodInfo(p_name, PropertyInfo(p_args[0], "arg1"), PropertyInfo(p_args[1], "arg2"), PropertyInfo(p_args[2], "arg3"), PropertyInfo(p_args[3], "arg4"))); - else if (p_args.size() == 5) - ADD_SIGNAL(MethodInfo(p_name, PropertyInfo(p_args[0], "arg1"), PropertyInfo(p_args[1], "arg2"), PropertyInfo(p_args[2], "arg3"), PropertyInfo(p_args[3], "arg4"), PropertyInfo(p_args[4], "arg5"))); - } - -#endif - - JNISingleton() { -#ifdef ANDROID_ENABLED - instance = NULL; -#endif - } -}; - -#endif // JNI_SINGLETON_H diff --git a/platform/android/audio_driver_opensl.cpp b/platform/android/audio_driver_opensl.cpp deleted file mode 100644 index 5bf310c..0000000 --- a/platform/android/audio_driver_opensl.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/*************************************************************************/ -/* audio_driver_opensl.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "audio_driver_opensl.h" - -#include - -#define MAX_NUMBER_INTERFACES 3 -#define MAX_NUMBER_OUTPUT_DEVICES 6 - -/* Structure for passing information to callback function */ - -void AudioDriverOpenSL::_buffer_callback( - SLAndroidSimpleBufferQueueItf queueItf) { - bool mix = true; - - if (pause) { - mix = false; - } else { - mix = mutex.try_lock() == OK; - } - - if (mix) { - audio_server_process(buffer_size, mixdown_buffer); - } else { - int32_t *src_buff = mixdown_buffer; - for (unsigned int i = 0; i < buffer_size * 2; i++) { - src_buff[i] = 0; - } - } - - if (mix) - mutex.unlock(); - - const int32_t *src_buff = mixdown_buffer; - - int16_t *ptr = (int16_t *)buffers[last_free]; - last_free = (last_free + 1) % BUFFER_COUNT; - - for (unsigned int i = 0; i < buffer_size * 2; i++) { - ptr[i] = src_buff[i] >> 16; - } - - (*queueItf)->Enqueue(queueItf, ptr, 4 * buffer_size); -} - -void AudioDriverOpenSL::_buffer_callbacks( - SLAndroidSimpleBufferQueueItf queueItf, - void *pContext) { - AudioDriverOpenSL *ad = (AudioDriverOpenSL *)pContext; - - ad->_buffer_callback(queueItf); -} - -AudioDriverOpenSL *AudioDriverOpenSL::s_ad = NULL; - -const char *AudioDriverOpenSL::get_name() const { - return "Android"; -} - -Error AudioDriverOpenSL::init() { - SLresult res; - SLEngineOption EngineOption[] = { - { (SLuint32)SL_ENGINEOPTION_THREADSAFE, (SLuint32)SL_BOOLEAN_TRUE } - }; - res = slCreateEngine(&sl, 1, EngineOption, 0, NULL, NULL); - ERR_FAIL_COND_V_MSG(res != SL_RESULT_SUCCESS, ERR_INVALID_PARAMETER, "Could not initialize OpenSL."); - - res = (*sl)->Realize(sl, SL_BOOLEAN_FALSE); - ERR_FAIL_COND_V_MSG(res != SL_RESULT_SUCCESS, ERR_INVALID_PARAMETER, "Could not realize OpenSL."); - - return OK; -} - -void AudioDriverOpenSL::start() { - active = false; - - SLresult res; - - buffer_size = 1024; - - for (int i = 0; i < BUFFER_COUNT; i++) { - buffers[i] = memnew_arr(int16_t, buffer_size * 2); - memset(buffers[i], 0, buffer_size * 4); - } - - mixdown_buffer = memnew_arr(int32_t, buffer_size * 2); - - /* Callback context for the buffer queue callback function */ - - /* Get the SL Engine Interface which is implicit */ - res = (*sl)->GetInterface(sl, SL_IID_ENGINE, (void *)&EngineItf); - - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - - { - const SLInterfaceID ids[1] = { SL_IID_ENVIRONMENTALREVERB }; - const SLboolean req[1] = { SL_BOOLEAN_FALSE }; - res = (*EngineItf)->CreateOutputMix(EngineItf, &OutputMix, 0, ids, req); - } - - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - // Realizing the Output Mix object in synchronous mode. - res = (*OutputMix)->Realize(OutputMix, SL_BOOLEAN_FALSE); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - - SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, BUFFER_COUNT }; - //bufferQueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE; - //bufferQueue.numBuffers = BUFFER_COUNT; /* Four buffers in our buffer queue */ - /* Setup the format of the content in the buffer queue */ - pcm.formatType = SL_DATAFORMAT_PCM; - pcm.numChannels = 2; - pcm.samplesPerSec = SL_SAMPLINGRATE_44_1; - pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; - pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16; - pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; -#ifdef BIG_ENDIAN_ENABLED - pcm.endianness = SL_BYTEORDER_BIGENDIAN; -#else - pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; -#endif - audioSource.pFormat = (void *)&pcm; - audioSource.pLocator = (void *)&loc_bufq; - - /* Setup the data sink structure */ - locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; - locator_outputmix.outputMix = OutputMix; - audioSink.pLocator = (void *)&locator_outputmix; - audioSink.pFormat = NULL; - /* Initialize the context for Buffer queue callbacks */ - //cntxt.pDataBase = (void*)&pcmData; - //cntxt.pData = cntxt.pDataBase; - //cntxt.size = sizeof(pcmData); - - /* Create the music player */ - - { - const SLInterfaceID ids[2] = { SL_IID_BUFFERQUEUE, SL_IID_EFFECTSEND }; - const SLboolean req[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; - - res = (*EngineItf)->CreateAudioPlayer(EngineItf, &player, &audioSource, &audioSink, 1, ids, req); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - } - /* Realizing the player in synchronous mode. */ - res = (*player)->Realize(player, SL_BOOLEAN_FALSE); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - /* Get seek and play interfaces */ - res = (*player)->GetInterface(player, SL_IID_PLAY, (void *)&playItf); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - res = (*player)->GetInterface(player, SL_IID_BUFFERQUEUE, - (void *)&bufferQueueItf); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - /* Setup to receive buffer queue event callbacks */ - res = (*bufferQueueItf)->RegisterCallback(bufferQueueItf, _buffer_callbacks, this); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - - last_free = 0; - - //fill up buffers - for (int i = 0; i < BUFFER_COUNT; i++) { - /* Enqueue a few buffers to get the ball rolling */ - res = (*bufferQueueItf)->Enqueue(bufferQueueItf, buffers[i], 4 * buffer_size); /* Size given in */ - } - - res = (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); - - active = true; -} - -void AudioDriverOpenSL::_record_buffer_callback(SLAndroidSimpleBufferQueueItf queueItf) { - for (int i = 0; i < rec_buffer.size(); i++) { - int32_t sample = rec_buffer[i] << 16; - input_buffer_write(sample); - input_buffer_write(sample); // call twice to convert to Stereo - } - - SLresult res = (*recordBufferQueueItf)->Enqueue(recordBufferQueueItf, rec_buffer.ptrw(), rec_buffer.size() * sizeof(int16_t)); - ERR_FAIL_COND(res != SL_RESULT_SUCCESS); -} - -void AudioDriverOpenSL::_record_buffer_callbacks(SLAndroidSimpleBufferQueueItf queueItf, void *pContext) { - AudioDriverOpenSL *ad = (AudioDriverOpenSL *)pContext; - - ad->_record_buffer_callback(queueItf); -} - -Error AudioDriverOpenSL::capture_init_device() { - SLDataLocator_IODevice loc_dev = { - SL_DATALOCATOR_IODEVICE, - SL_IODEVICE_AUDIOINPUT, - SL_DEFAULTDEVICEID_AUDIOINPUT, - NULL - }; - SLDataSource recSource = { &loc_dev, NULL }; - - SLDataLocator_AndroidSimpleBufferQueue loc_bq = { - SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, - 2 - }; - SLDataFormat_PCM format_pcm = { - SL_DATAFORMAT_PCM, - 1, - SL_SAMPLINGRATE_44_1, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_SPEAKER_FRONT_CENTER, - SL_BYTEORDER_LITTLEENDIAN - }; - SLDataSink recSnk = { &loc_bq, &format_pcm }; - - const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION }; - const SLboolean req[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; - - SLresult res = (*EngineItf)->CreateAudioRecorder(EngineItf, &recorder, &recSource, &recSnk, 2, ids, req); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recorder)->Realize(recorder, SL_BOOLEAN_FALSE); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recorder)->GetInterface(recorder, SL_IID_RECORD, (void *)&recordItf); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recorder)->GetInterface(recorder, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, (void *)&recordBufferQueueItf); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recordBufferQueueItf)->RegisterCallback(recordBufferQueueItf, _record_buffer_callbacks, this); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - SLuint32 state; - res = (*recordItf)->GetRecordState(recordItf, &state); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - if (state != SL_RECORDSTATE_STOPPED) { - res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recordBufferQueueItf)->Clear(recordBufferQueueItf); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - } - - const int rec_buffer_frames = 2048; - rec_buffer.resize(rec_buffer_frames); - input_buffer_init(rec_buffer_frames); - - res = (*recordBufferQueueItf)->Enqueue(recordBufferQueueItf, rec_buffer.ptrw(), rec_buffer.size() * sizeof(int16_t)); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - return OK; -} - -Error AudioDriverOpenSL::capture_start() { - if (OS::get_singleton()->request_permission("RECORD_AUDIO")) { - return capture_init_device(); - } - - WARN_PRINT("Unable to start audio capture - No RECORD_AUDIO permission"); - return ERR_UNAUTHORIZED; -} - -Error AudioDriverOpenSL::capture_stop() { - SLuint32 state; - SLresult res = (*recordItf)->GetRecordState(recordItf, &state); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - if (state != SL_RECORDSTATE_STOPPED) { - res = (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - - res = (*recordBufferQueueItf)->Clear(recordBufferQueueItf); - ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN); - } - - return OK; -} - -int AudioDriverOpenSL::get_mix_rate() const { - return 44100; // hardcoded for Android, as selected by SL_SAMPLINGRATE_44_1 -} - -AudioDriver::SpeakerMode AudioDriverOpenSL::get_speaker_mode() const { - return SPEAKER_MODE_STEREO; -} - -void AudioDriverOpenSL::lock() { - if (active) - mutex.lock(); -} - -void AudioDriverOpenSL::unlock() { - if (active) - mutex.unlock(); -} - -void AudioDriverOpenSL::finish() { - (*sl)->Destroy(sl); -} - -void AudioDriverOpenSL::set_pause(bool p_pause) { - pause = p_pause; - - if (active) { - if (pause) { - (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED); - } else { - (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); - } - } -} - -AudioDriverOpenSL::AudioDriverOpenSL() { - s_ad = this; - pause = false; - active = false; -} diff --git a/platform/android/audio_driver_opensl.h b/platform/android/audio_driver_opensl.h deleted file mode 100644 index e257cd0..0000000 --- a/platform/android/audio_driver_opensl.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef AUDIO_DRIVER_OPENSL_H -#define AUDIO_DRIVER_OPENSL_H -/*************************************************************************/ -/* audio_driver_opensl.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "core/os/mutex.h" -#include "servers/audio_server.h" - -#include -#include - -class AudioDriverOpenSL : public AudioDriver { - bool active; - Mutex mutex; - - enum { - - BUFFER_COUNT = 2 - }; - - bool pause; - - uint32_t buffer_size; - int16_t *buffers[BUFFER_COUNT]; - int32_t *mixdown_buffer; - int last_free; - - Vector rec_buffer; - - SLPlayItf playItf; - SLRecordItf recordItf; - SLObjectItf sl; - SLEngineItf EngineItf; - SLObjectItf OutputMix; - SLObjectItf player; - SLObjectItf recorder; - SLAndroidSimpleBufferQueueItf bufferQueueItf; - SLAndroidSimpleBufferQueueItf recordBufferQueueItf; - SLDataSource audioSource; - SLDataFormat_PCM pcm; - SLDataSink audioSink; - SLDataLocator_OutputMix locator_outputmix; - - static AudioDriverOpenSL *s_ad; - - void _buffer_callback( - SLAndroidSimpleBufferQueueItf queueItf); - - static void _buffer_callbacks( - SLAndroidSimpleBufferQueueItf queueItf, - void *pContext); - - void _record_buffer_callback( - SLAndroidSimpleBufferQueueItf queueItf); - - static void _record_buffer_callbacks( - SLAndroidSimpleBufferQueueItf queueItf, - void *pContext); - - virtual Error capture_init_device(); - -public: - virtual const char *get_name() const; - - virtual Error init(); - virtual void start(); - virtual int get_mix_rate() const; - virtual SpeakerMode get_speaker_mode() const; - virtual void lock(); - virtual void unlock(); - virtual void finish(); - - virtual void set_pause(bool p_pause); - - virtual Error capture_start(); - virtual Error capture_stop(); - - AudioDriverOpenSL(); -}; - -#endif // AUDIO_DRIVER_ANDROID_H diff --git a/platform/android/detect.py b/platform/android/detect.py deleted file mode 100644 index 973da36..0000000 --- a/platform/android/detect.py +++ /dev/null @@ -1,197 +0,0 @@ -import os -import sys -import platform -import subprocess - -def is_active(): - return True - -def get_name(): - return "Android" - -def can_build(): - return os.path.exists(get_env_android_sdk_root()) - -def get_opts(): - from SCons.Variables import BoolVariable, EnumVariable - - return [ - ("ANDROID_SDK_ROOT", "Path to the Android SDK", get_env_android_sdk_root()), - ("ndk_platform", 'Target platform (android-, e.g. "android-19")', "android-19"), - EnumVariable("android_arch", "Target architecture", "armv7", ("armv7", "arm64v8", "x86", "x86_64")), - BoolVariable("android_neon", "Enable NEON support (armv7 only)", True), - ] - -# Return the ANDROID_SDK_ROOT environment variable. -def get_env_android_sdk_root(): - return os.environ.get("ANDROID_SDK_ROOT", -1) - -def get_min_sdk_version(platform): - return int(platform.split("-")[1]) - -def get_android_ndk_root(env): - return env["ANDROID_SDK_ROOT"] + "/ndk/" + get_ndk_version() - -# This is kept in sync with the value in 'platform/android/java/app/config.gradle'. -def get_ndk_version(): - return "23.2.8568313" - -def get_flags(): - return [ - ("tools", False), - ] - -# Check if Android NDK version is installed -# If not, install it. -def install_ndk_if_needed(env): - print("Checking for Android NDK...") - sdk_root = env["ANDROID_SDK_ROOT"] - if not os.path.exists(get_android_ndk_root(env)): - extension = ".bat" if os.name == "nt" else "" - - sdkmanager = sdk_root + "/cmdline-tools/latest/bin/sdkmanager" + extension - if os.path.exists(sdkmanager): - # Install the Android NDK - print("Installing Android NDK...") - ndk_download_args = "ndk;" + get_ndk_version() - subprocess.check_call([sdkmanager, ndk_download_args]) - else: - print("Cannot find " + sdkmanager) - print( - "Please ensure ANDROID_SDK_ROOT is correct and cmdline-tools are installed, or install NDK version " - + get_ndk_version() - + " manually." - ) - sys.exit() - - env["ANDROID_NDK_ROOT"] = get_android_ndk_root(env) - -def configure(env): - install_ndk_if_needed(env) - ndk_root = env["ANDROID_NDK_ROOT"] - - # Architecture - - if env["android_arch"] not in ["armv7", "arm64v8", "x86", "x86_64"]: - env["android_arch"] = "arm64v8" - - neon_text = "" - if env["android_arch"] == "armv7" and env["android_neon"]: - neon_text = " (with NEON)" - print("Building for Android (" + env["android_arch"] + ")" + neon_text) - - if get_min_sdk_version(env["ndk_platform"]) < 21: - if env["android_arch"] == "x86_64" or env["android_arch"] == "arm64v8": - print( - "WARNING: android_arch=" - + env["android_arch"] - + " is not supported by ndk_platform lower than android-21; setting ndk_platform=android-21" - ) - env["ndk_platform"] = "android-21" - - if env["android_arch"] == "armv7": - target_triple = "armv7a-linux-androideabi" - if env["android_neon"]: - env.extra_suffix = ".armv7.neon" + env.extra_suffix - else: - env.extra_suffix = ".armv7" + env.extra_suffix - elif env["android_arch"] == "arm64v8": - target_triple = "aarch64-linux-android" - env.extra_suffix = ".armv8" + env.extra_suffix - elif env["android_arch"] == "x86": - target_triple = "i686-linux-android" - env.extra_suffix = ".x86" + env.extra_suffix - elif env["android_arch"] == "x86_64": - target_triple = "x86_64-linux-android" - env.extra_suffix = ".x86_64" + env.extra_suffix - - target_option = ["-target", target_triple + str(get_min_sdk_version(env["ndk_platform"]))] - env.Append(ASFLAGS=[target_option, "-c"]) - env.Append(CCFLAGS=target_option) - env.Append(LINKFLAGS=target_option) - - # Build type - - if env["target"].startswith("release"): - if env["optimize"] == "speed": # optimize for speed (default) - # `-O2` is more friendly to debuggers than `-O3`, leading to better crash backtraces - # when using `target=release_debug`. - opt = "-O3" if env["target"] == "release" else "-O2" - env.Append(CCFLAGS=[opt]) - elif env["optimize"] == "size": # optimize for size - env.Append(CCFLAGS=["-Oz"]) - elif env["target"] == "debug": - env.Append(LINKFLAGS=["-O0"]) - env.Append(CCFLAGS=["-O0", "-g"]) - - # LTO - - if env["lto"] == "auto": # LTO benefits for Android (size, performance) haven't been clearly established yet. - env["lto"] = "none" - - if env["lto"] != "none": - if env["lto"] == "thin": - env.Append(CCFLAGS=["-flto=thin"]) - env.Append(LINKFLAGS=["-flto=thin"]) - else: - env.Append(CCFLAGS=["-flto"]) - env.Append(LINKFLAGS=["-flto"]) - - # Compiler configuration - - env["SHLIBSUFFIX"] = ".so" - - if env["PLATFORM"] == "win32": - env.use_windows_spawn_fix() - - if sys.platform.startswith("linux"): - host_subpath = "linux-x86_64" - elif sys.platform.startswith("darwin"): - host_subpath = "darwin-x86_64" - elif sys.platform.startswith("win"): - if platform.machine().endswith("64"): - host_subpath = "windows-x86_64" - else: - host_subpath = "windows" - - toolchain_path = ndk_root + "/toolchains/llvm/prebuilt/" + host_subpath - compiler_path = toolchain_path + "/bin" - - env["CC"] = compiler_path + "/clang" - env["CXX"] = compiler_path + "/clang++" - env["AR"] = compiler_path + "/llvm-ar" - env["RANLIB"] = compiler_path + "/llvm-ranlib" - env["AS"] = compiler_path + "/clang" - - env.Append( - CCFLAGS="-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing".split() - ) - env.Append(CPPDEFINES=["NO_STATVFS", "GLES_ENABLED"]) - - if get_min_sdk_version(env["ndk_platform"]) >= 24: - env.Append(CPPDEFINES=[("_FILE_OFFSET_BITS", 64)]) - - env["neon_enabled"] = False - if env["android_arch"] == "x86": - env.Append(CCFLAGS=["-mstackrealign"]) - elif env["android_arch"] == "armv7": - env.Append(CCFLAGS="-march=armv7-a -mfloat-abi=softfp".split()) - env.Append(CPPDEFINES=["__ARM_ARCH_7__", "__ARM_ARCH_7A__"]) - if env["android_neon"]: - env["neon_enabled"] = True - env.Append(CPPDEFINES=["__ARM_NEON__"]) - else: - env.Append(CCFLAGS=["-mfpu=vfpv3-d16"]) - elif env["android_arch"] == "arm64v8": - env.Append(CCFLAGS=["-mfix-cortex-a53-835769"]) - env.Append(CPPDEFINES=["__ARM_ARCH_8A__"]) - - # Link flags - env.Append(LINKFLAGS="-Wl,--gc-sections -Wl,--no-undefined -Wl,-z,now".split()) - env.Append(LINKFLAGS="-Wl,-soname,libgodot_android.so") - - env.Prepend(CPPPATH=["#platform/android"]) - env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED", "NO_FCNTL"]) - env.Append(LIBS=["OpenSLES", "EGL", "GLESv3", "GLESv2", "android", "log", "z", "dl"]) - - diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp deleted file mode 100644 index 78ad9c7..0000000 --- a/platform/android/dir_access_jandroid.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/*************************************************************************/ -/* dir_access_jandroid.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "dir_access_jandroid.h" -#include "core/string/print_string.h" -#include "file_access_android.h" -#include "string_android.h" -#include "thread_jandroid.h" - -jobject DirAccessJAndroid::dir_access_handler = nullptr; -jclass DirAccessJAndroid::cls = NULL; -jmethodID DirAccessJAndroid::_dir_open = NULL; -jmethodID DirAccessJAndroid::_dir_next = NULL; -jmethodID DirAccessJAndroid::_dir_close = NULL; -jmethodID DirAccessJAndroid::_dir_is_dir = NULL; -jmethodID DirAccessJAndroid::_dir_exists = nullptr; -jmethodID DirAccessJAndroid::_file_exists = nullptr; -jmethodID DirAccessJAndroid::_get_drive_count = nullptr; -jmethodID DirAccessJAndroid::_get_drive = nullptr; -jmethodID DirAccessJAndroid::_make_dir = nullptr; -jmethodID DirAccessJAndroid::_get_space_left = nullptr; -jmethodID DirAccessJAndroid::_rename = nullptr; -jmethodID DirAccessJAndroid::_remove = nullptr; -jmethodID DirAccessJAndroid::_current_is_hidden = nullptr; - -Error DirAccessJAndroid::list_dir_begin() { - list_dir_end(); - - int res = dir_open(current_dir); - if (res <= 0) { - return ERR_CANT_OPEN; - } - - id = res; - - return OK; -} - -String DirAccessJAndroid::get_next() { - ERR_FAIL_COND_V(id == 0, ""); - - if (_dir_next) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ""); - jstring str = (jstring)env->CallObjectMethod(dir_access_handler, _dir_next, get_access_type(), id); - - if (!str) { - return ""; - } - - String ret = jstring_to_string((jstring)str, env); - env->DeleteLocalRef((jobject)str); - return ret; - } else { - return ""; - } -} - -bool DirAccessJAndroid::current_is_dir() const { - if (_dir_is_dir) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - return env->CallBooleanMethod(dir_access_handler, _dir_is_dir, get_access_type(), id); - } else { - return false; - } -} - -bool DirAccessJAndroid::current_is_hidden() const { - if (_current_is_hidden) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - return env->CallBooleanMethod(dir_access_handler, _current_is_hidden, get_access_type(), id); - } - return false; -} - -void DirAccessJAndroid::list_dir_end() { - if (id == 0) - return; - - dir_close(id); - id = 0; -} - -int DirAccessJAndroid::get_drive_count() { - if (_get_drive_count) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - return env->CallIntMethod(dir_access_handler, _get_drive_count, get_access_type()); - } else { - return 0; - } -} - -String DirAccessJAndroid::get_drive(int p_drive) { - if (_get_drive) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ""); - jstring j_drive = (jstring)env->CallObjectMethod(dir_access_handler, _get_drive, get_access_type(), p_drive); - - if (!j_drive) { - return ""; - } - - String drive = jstring_to_string(j_drive, env); - env->DeleteLocalRef(j_drive); - return drive; - } else { - return ""; - } -} - -String DirAccessJAndroid::_get_root_string() const { - if (get_access_type() == ACCESS_FILESYSTEM) { - return "/"; - } - return DirAccessUnix::_get_root_string(); -} - -String DirAccessJAndroid::get_current_dir() { - String base = _get_root_path(); - String bd = current_dir; - if (!base.empty()) { - bd = current_dir.replace_first(base, ""); - } - - String root_string = _get_root_string(); - if (bd.begins_with(root_string)) { - return bd; - } else if (bd.begins_with("/")) { - return root_string + bd.substr(1, bd.length()); - } else { - return root_string + bd; - } -} - -Error DirAccessJAndroid::change_dir(String p_dir) { - String new_dir = get_absolute_path(p_dir); - if (new_dir == current_dir) { - return OK; - } - - if (!dir_exists(new_dir)) { - return ERR_INVALID_PARAMETER; - } - - current_dir = new_dir; - - return OK; -} - -String DirAccessJAndroid::get_absolute_path(String p_path) { - if (current_dir != "" && p_path == current_dir) { - return current_dir; - } - - if (p_path.is_rel_path()) { - p_path = get_current_dir().plus_file(p_path); - } - - p_path = fix_path(p_path); - p_path = p_path.simplify_path(); - return p_path; -} - -bool DirAccessJAndroid::file_exists(String p_file) { - if (_file_exists) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - - String path = get_absolute_path(p_file); - jstring j_path = env->NewStringUTF(path.utf8().get_data()); - bool result = env->CallBooleanMethod(dir_access_handler, _file_exists, get_access_type(), j_path); - env->DeleteLocalRef(j_path); - return result; - } else { - return false; - } -} - -bool DirAccessJAndroid::dir_exists(String p_dir) { - if (_dir_exists) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - - String path = get_absolute_path(p_dir); - jstring j_path = env->NewStringUTF(path.utf8().get_data()); - bool result = env->CallBooleanMethod(dir_access_handler, _dir_exists, get_access_type(), j_path); - env->DeleteLocalRef(j_path); - return result; - } else { - return false; - } -} - -Error DirAccessJAndroid::make_dir_recursive(String p_dir) { - // Check if the directory exists already - if (dir_exists(p_dir)) { - return ERR_ALREADY_EXISTS; - } - - if (_make_dir) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED); - - String path = get_absolute_path(p_dir); - jstring j_dir = env->NewStringUTF(path.utf8().get_data()); - bool result = env->CallBooleanMethod(dir_access_handler, _make_dir, get_access_type(), j_dir); - env->DeleteLocalRef(j_dir); - if (result) { - return OK; - } else { - return FAILED; - } - } else { - return ERR_UNCONFIGURED; - } -} - -Error DirAccessJAndroid::make_dir(String p_dir) { - return make_dir_recursive(p_dir); -} - -Error DirAccessJAndroid::rename(String p_from, String p_to) { - if (_rename) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED); - - String from_path = get_absolute_path(p_from); - jstring j_from = env->NewStringUTF(from_path.utf8().get_data()); - - String to_path = get_absolute_path(p_to); - jstring j_to = env->NewStringUTF(to_path.utf8().get_data()); - - bool result = env->CallBooleanMethod(dir_access_handler, _rename, get_access_type(), j_from, j_to); - env->DeleteLocalRef(j_from); - env->DeleteLocalRef(j_to); - if (result) { - return OK; - } else { - return FAILED; - } - } else { - return ERR_UNCONFIGURED; - } -} - -Error DirAccessJAndroid::remove(String p_name) { - if (_remove) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED); - - String path = get_absolute_path(p_name); - jstring j_name = env->NewStringUTF(path.utf8().get_data()); - bool result = env->CallBooleanMethod(dir_access_handler, _remove, get_access_type(), j_name); - env->DeleteLocalRef(j_name); - if (result) { - return OK; - } else { - return FAILED; - } - } else { - return ERR_UNCONFIGURED; - } -} - -uint64_t DirAccessJAndroid::get_space_left() { - if (_get_space_left) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - return env->CallLongMethod(dir_access_handler, _get_space_left, get_access_type()); - } else { - return 0; - } -} - -void DirAccessJAndroid::setup(jobject p_dir_access_handler) { - JNIEnv *env = get_jni_env(); - dir_access_handler = env->NewGlobalRef(p_dir_access_handler); - - jclass c = env->GetObjectClass(dir_access_handler); - cls = (jclass)env->NewGlobalRef(c); - - _dir_open = env->GetMethodID(cls, "dirOpen", "(ILjava/lang/String;)I"); - _dir_next = env->GetMethodID(cls, "dirNext", "(II)Ljava/lang/String;"); - _dir_close = env->GetMethodID(cls, "dirClose", "(II)V"); - _dir_is_dir = env->GetMethodID(cls, "dirIsDir", "(II)Z"); - _dir_exists = env->GetMethodID(cls, "dirExists", "(ILjava/lang/String;)Z"); - _file_exists = env->GetMethodID(cls, "fileExists", "(ILjava/lang/String;)Z"); - _get_drive_count = env->GetMethodID(cls, "getDriveCount", "(I)I"); - _get_drive = env->GetMethodID(cls, "getDrive", "(II)Ljava/lang/String;"); - _make_dir = env->GetMethodID(cls, "makeDir", "(ILjava/lang/String;)Z"); - _get_space_left = env->GetMethodID(cls, "getSpaceLeft", "(I)J"); - _rename = env->GetMethodID(cls, "rename", "(ILjava/lang/String;Ljava/lang/String;)Z"); - _remove = env->GetMethodID(cls, "remove", "(ILjava/lang/String;)Z"); - _current_is_hidden = env->GetMethodID(cls, "isCurrentHidden", "(II)Z"); -} - -DirAccessJAndroid::DirAccessJAndroid() { - id = 0; -} - -DirAccessJAndroid::~DirAccessJAndroid() { - list_dir_end(); -} - -int DirAccessJAndroid::dir_open(String p_path) { - if (_dir_open) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - - String path = get_absolute_path(p_path); - jstring js = env->NewStringUTF(path.utf8().get_data()); - int dirId = env->CallIntMethod(dir_access_handler, _dir_open, get_access_type(), js); - env->DeleteLocalRef(js); - return dirId; - } else { - return 0; - } -} - -void DirAccessJAndroid::dir_close(int p_id) { - if (_dir_close) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - env->CallVoidMethod(dir_access_handler, _dir_close, get_access_type(), p_id); - } -} diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h deleted file mode 100644 index ee8560f..0000000 --- a/platform/android/dir_access_jandroid.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef DIR_ACCESS_JANDROID_H -#define DIR_ACCESS_JANDROID_H -/*************************************************************************/ -/* dir_access_jandroid.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "core/os/dir_access.h" -#include "drivers/unix/dir_access_unix.h" -#include "java_pandemonium_lib_jni.h" -#include - -/// Android implementation of the DirAccess interface used to provide access to -/// ACCESS_FILESYSTEM and ACCESS_RESOURCES directory resources. -/// The implementation use jni in order to comply with Android filesystem -/// access restriction. -class DirAccessJAndroid : public DirAccessUnix { - static jobject dir_access_handler; - - static jclass cls; - - static jmethodID _dir_open; - static jmethodID _dir_next; - static jmethodID _dir_close; - static jmethodID _dir_is_dir; - - static jmethodID _dir_exists; - static jmethodID _file_exists; - static jmethodID _get_drive_count; - static jmethodID _get_drive; - static jmethodID _make_dir; - static jmethodID _get_space_left; - static jmethodID _rename; - static jmethodID _remove; - static jmethodID _current_is_hidden; - -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 bool dir_exists(String p_dir); - - virtual Error make_dir(String p_dir); - virtual Error make_dir_recursive(String p_dir); - - virtual Error rename(String p_from, String p_to); - virtual Error remove(String p_name); - - virtual bool is_link(String p_file) { return false; } - virtual String read_link(String p_file) { return p_file; } - virtual Error create_link(String p_source, String p_target) { return FAILED; } - - virtual uint64_t get_space_left(); - - static void setup(jobject p_dir_access_handler); - - DirAccessJAndroid(); - ~DirAccessJAndroid(); - -protected: - String _get_root_string() const; - -private: - int id; - - int dir_open(String p_path); - void dir_close(int p_id); - String get_absolute_path(String p_path); -}; - -#endif // DIR_ACCESS_JANDROID_H diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp deleted file mode 100644 index df1b491..0000000 --- a/platform/android/export/export.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/*************************************************************************/ -/* export.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "export.h" - -#include "export_plugin.h" - -#include "editor/editor_settings.h" - -void register_android_exporter() { -#ifndef ANDROID_ENABLED - String exe_ext; - if (OS::get_singleton()->get_name() == "Windows") { - exe_ext = "*.exe"; - } - - EDITOR_DEF("export/android/android_sdk_path", ""); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/android_sdk_path", PROPERTY_HINT_GLOBAL_DIR)); - EDITOR_DEF("export/android/debug_keystore", ""); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks")); - EDITOR_DEF("export/android/debug_keystore_user", "androiddebugkey"); - EDITOR_DEF("export/android/debug_keystore_pass", "android"); - EDITOR_DEF("export/android/force_system_user", false); - - EDITOR_DEF("export/android/shutdown_adb_on_exit", true); -#endif - - Ref exporter = Ref(memnew(EditorExportPlatformAndroid)); - EditorExport::get_singleton()->add_export_platform(exporter); -} diff --git a/platform/android/export/export.h b/platform/android/export/export.h deleted file mode 100644 index 82ce40f..0000000 --- a/platform/android/export/export.h +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************/ -/* export.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 ANDROID_EXPORT_H -#define ANDROID_EXPORT_H - -void register_android_exporter(); - -#endif // ANDROID_EXPORT_H diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp deleted file mode 100644 index 8182e6f..0000000 --- a/platform/android/export/export_plugin.cpp +++ /dev/null @@ -1,3338 +0,0 @@ -/*************************************************************************/ -/* export_plugin.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "export_plugin.h" - -static const char *android_perms[] = { - "ACCESS_CHECKIN_PROPERTIES", - "ACCESS_COARSE_LOCATION", - "ACCESS_FINE_LOCATION", - "ACCESS_LOCATION_EXTRA_COMMANDS", - "ACCESS_MOCK_LOCATION", - "ACCESS_NETWORK_STATE", - "ACCESS_SURFACE_FLINGER", - "ACCESS_WIFI_STATE", - "ACCOUNT_MANAGER", - "ADD_VOICEMAIL", - "AUTHENTICATE_ACCOUNTS", - "BATTERY_STATS", - "BIND_ACCESSIBILITY_SERVICE", - "BIND_APPWIDGET", - "BIND_DEVICE_ADMIN", - "BIND_INPUT_METHOD", - "BIND_NFC_SERVICE", - "BIND_NOTIFICATION_LISTENER_SERVICE", - "BIND_PRINT_SERVICE", - "BIND_REMOTEVIEWS", - "BIND_TEXT_SERVICE", - "BIND_VPN_SERVICE", - "BIND_WALLPAPER", - "BLUETOOTH", - "BLUETOOTH_ADMIN", - "BLUETOOTH_PRIVILEGED", - "BRICK", - "BROADCAST_PACKAGE_REMOVED", - "BROADCAST_SMS", - "BROADCAST_STICKY", - "BROADCAST_WAP_PUSH", - "CALL_PHONE", - "CALL_PRIVILEGED", - "CAMERA", - "CAPTURE_AUDIO_OUTPUT", - "CAPTURE_SECURE_VIDEO_OUTPUT", - "CAPTURE_VIDEO_OUTPUT", - "CHANGE_COMPONENT_ENABLED_STATE", - "CHANGE_CONFIGURATION", - "CHANGE_NETWORK_STATE", - "CHANGE_WIFI_MULTICAST_STATE", - "CHANGE_WIFI_STATE", - "CLEAR_APP_CACHE", - "CLEAR_APP_USER_DATA", - "CONTROL_LOCATION_UPDATES", - "DELETE_CACHE_FILES", - "DELETE_PACKAGES", - "DEVICE_POWER", - "DIAGNOSTIC", - "DISABLE_KEYGUARD", - "DUMP", - "EXPAND_STATUS_BAR", - "FACTORY_TEST", - "FLASHLIGHT", - "FORCE_BACK", - "GET_ACCOUNTS", - "GET_PACKAGE_SIZE", - "GET_TASKS", - "GET_TOP_ACTIVITY_INFO", - "GLOBAL_SEARCH", - "HARDWARE_TEST", - "INJECT_EVENTS", - "INSTALL_LOCATION_PROVIDER", - "INSTALL_PACKAGES", - "INSTALL_SHORTCUT", - "INTERNAL_SYSTEM_WINDOW", - "INTERNET", - "KILL_BACKGROUND_PROCESSES", - "LOCATION_HARDWARE", - "MANAGE_ACCOUNTS", - "MANAGE_APP_TOKENS", - "MANAGE_DOCUMENTS", - "MANAGE_EXTERNAL_STORAGE", - "MASTER_CLEAR", - "MEDIA_CONTENT_CONTROL", - "MODIFY_AUDIO_SETTINGS", - "MODIFY_PHONE_STATE", - "MOUNT_FORMAT_FILESYSTEMS", - "MOUNT_UNMOUNT_FILESYSTEMS", - "NFC", - "PERSISTENT_ACTIVITY", - "PROCESS_OUTGOING_CALLS", - "READ_CALENDAR", - "READ_CALL_LOG", - "READ_CONTACTS", - "READ_EXTERNAL_STORAGE", - "READ_FRAME_BUFFER", - "READ_HISTORY_BOOKMARKS", - "READ_INPUT_STATE", - "READ_LOGS", - "READ_PHONE_STATE", - "READ_PROFILE", - "READ_SMS", - "READ_SOCIAL_STREAM", - "READ_SYNC_SETTINGS", - "READ_SYNC_STATS", - "READ_USER_DICTIONARY", - "REBOOT", - "RECEIVE_BOOT_COMPLETED", - "RECEIVE_MMS", - "RECEIVE_SMS", - "RECEIVE_WAP_PUSH", - "RECORD_AUDIO", - "REORDER_TASKS", - "RESTART_PACKAGES", - "SEND_RESPOND_VIA_MESSAGE", - "SEND_SMS", - "SET_ACTIVITY_WATCHER", - "SET_ALARM", - "SET_ALWAYS_FINISH", - "SET_ANIMATION_SCALE", - "SET_DEBUG_APP", - "SET_ORIENTATION", - "SET_POINTER_SPEED", - "SET_PREFERRED_APPLICATIONS", - "SET_PROCESS_LIMIT", - "SET_TIME", - "SET_TIME_ZONE", - "SET_WALLPAPER", - "SET_WALLPAPER_HINTS", - "SIGNAL_PERSISTENT_PROCESSES", - "STATUS_BAR", - "SUBSCRIBED_FEEDS_READ", - "SUBSCRIBED_FEEDS_WRITE", - "SYSTEM_ALERT_WINDOW", - "TRANSMIT_IR", - "UNINSTALL_SHORTCUT", - "UPDATE_DEVICE_STATS", - "USE_CREDENTIALS", - "USE_SIP", - "VIBRATE", - "WAKE_LOCK", - "WRITE_APN_SETTINGS", - "WRITE_CALENDAR", - "WRITE_CALL_LOG", - "WRITE_CONTACTS", - "WRITE_EXTERNAL_STORAGE", - "WRITE_GSERVICES", - "WRITE_HISTORY_BOOKMARKS", - "WRITE_PROFILE", - "WRITE_SECURE_SETTINGS", - "WRITE_SETTINGS", - "WRITE_SMS", - "WRITE_SOCIAL_STREAM", - "WRITE_SYNC_SETTINGS", - "WRITE_USER_DICTIONARY", - nullptr -}; - -static const char *SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi/splash.png"; -static const char *LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi-v4/splash.png"; -static const char *SPLASH_BG_COLOR_PATH = "res/drawable-nodpi/splash_bg_color.png"; -static const char *LEGACY_BUILD_SPLASH_BG_COLOR_PATH = "res/drawable-nodpi-v4/splash_bg_color.png"; -static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash_drawable.xml"; -static const char *GDNATIVE_LIBS_PATH = "res://android/build/libs/gdnativelibs.json"; - -static const int icon_densities_count = 6; -static const char *launcher_icon_option = "launcher_icons/main_192x192"; -static const char *launcher_adaptive_icon_foreground_option = "launcher_icons/adaptive_foreground_432x432"; -static const char *launcher_adaptive_icon_background_option = "launcher_icons/adaptive_background_432x432"; - -static const LauncherIcon launcher_icons[icon_densities_count] = { - { "res/mipmap-xxxhdpi-v4/icon.png", 192 }, - { "res/mipmap-xxhdpi-v4/icon.png", 144 }, - { "res/mipmap-xhdpi-v4/icon.png", 96 }, - { "res/mipmap-hdpi-v4/icon.png", 72 }, - { "res/mipmap-mdpi-v4/icon.png", 48 }, - { "res/mipmap/icon.png", 192 } -}; - -static const LauncherIcon launcher_adaptive_icon_foregrounds[icon_densities_count] = { - { "res/mipmap-xxxhdpi-v4/icon_foreground.png", 432 }, - { "res/mipmap-xxhdpi-v4/icon_foreground.png", 324 }, - { "res/mipmap-xhdpi-v4/icon_foreground.png", 216 }, - { "res/mipmap-hdpi-v4/icon_foreground.png", 162 }, - { "res/mipmap-mdpi-v4/icon_foreground.png", 108 }, - { "res/mipmap/icon_foreground.png", 432 } -}; - -static const LauncherIcon launcher_adaptive_icon_backgrounds[icon_densities_count] = { - { "res/mipmap-xxxhdpi-v4/icon_background.png", 432 }, - { "res/mipmap-xxhdpi-v4/icon_background.png", 324 }, - { "res/mipmap-xhdpi-v4/icon_background.png", 216 }, - { "res/mipmap-hdpi-v4/icon_background.png", 162 }, - { "res/mipmap-mdpi-v4/icon_background.png", 108 }, - { "res/mipmap/icon_background.png", 432 } -}; - -static const int EXPORT_FORMAT_APK = 0; -static const int EXPORT_FORMAT_AAB = 1; - -static const char *APK_ASSETS_DIRECTORY = "res://android/build/assets"; -static const char *AAB_ASSETS_DIRECTORY = "res://android/build/assetPacks/installTime/src/main/assets"; - -static const int DEFAULT_MIN_SDK_VERSION = 19; // Should match the value in 'platform/android/java/app/config.gradle#minSdk' -static const int DEFAULT_TARGET_SDK_VERSION = 33; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk' -const String SDK_VERSION_RANGE = vformat("%s,%s,1", DEFAULT_MIN_SDK_VERSION, DEFAULT_TARGET_SDK_VERSION); - -#ifndef ANDROID_ENABLED -void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) { - EditorExportPlatformAndroid *ea = (EditorExportPlatformAndroid *)ud; - - while (!ea->quit_request.is_set()) { - // Check for plugins updates - { - // Nothing to do if we already know the plugins have changed. - if (!ea->plugins_changed.is_set()) { - Vector loaded_plugins = get_plugins(); - - ea->plugins_lock.lock(); - - if (ea->plugins.size() != loaded_plugins.size()) { - ea->plugins_changed.set(); - } else { - for (int i = 0; i < ea->plugins.size(); i++) { - if (ea->plugins[i].name != loaded_plugins[i].name) { - ea->plugins_changed.set(); - break; - } - } - } - - if (ea->plugins_changed.is_set()) { - ea->plugins = loaded_plugins; - } - - ea->plugins_lock.unlock(); - } - } - - // Check for devices updates - String adb = get_adb_path(); - if (FileAccess::exists(adb)) { - String devices; - List args; - args.push_back("devices"); - int ec; - OS::get_singleton()->execute(adb, args, true, nullptr, &devices, &ec); - - Vector ds = devices.split("\n"); - Vector ldevices; - for (int i = 1; i < ds.size(); i++) { - String d = ds[i]; - int dpos = d.find("device"); - if (dpos == -1) { - continue; - } - d = d.substr(0, dpos).strip_edges(); - ldevices.push_back(d); - } - - ea->device_lock.lock(); - - bool different = false; - - if (ea->devices.size() != ldevices.size()) { - different = true; - } else { - for (int i = 0; i < ea->devices.size(); i++) { - if (ea->devices[i].id != ldevices[i]) { - different = true; - break; - } - } - } - - if (different) { - Vector ndevices; - - for (int i = 0; i < ldevices.size(); i++) { - Device d; - d.id = ldevices[i]; - for (int j = 0; j < ea->devices.size(); j++) { - if (ea->devices[j].id == ldevices[i]) { - d.description = ea->devices[j].description; - d.name = ea->devices[j].name; - d.api_level = ea->devices[j].api_level; - } - } - - if (d.description == "") { - //in the oven, request! - args.clear(); - args.push_back("-s"); - args.push_back(d.id); - args.push_back("shell"); - args.push_back("getprop"); - int ec2; - String dp; - - OS::get_singleton()->execute(adb, args, true, nullptr, &dp, &ec2); - - Vector props = dp.split("\n"); - String vendor; - String device; - d.description = "Device ID: " + d.id + "\n"; - d.api_level = 0; - for (int j = 0; j < props.size(); j++) { - // got information by `shell cat /system/build.prop` before and its format is "property=value" - // it's now changed to use `shell getporp` because of permission issue with Android 8.0 and above - // its format is "[property]: [value]" so changed it as like build.prop - String p = props[j]; - p = p.replace("]: ", "="); - p = p.replace("[", ""); - p = p.replace("]", ""); - - if (p.begins_with("ro.product.model=")) { - device = p.get_slice("=", 1).strip_edges(); - } else if (p.begins_with("ro.product.brand=")) { - vendor = p.get_slice("=", 1).strip_edges().capitalize(); - } else if (p.begins_with("ro.build.display.id=")) { - d.description += "Build: " + p.get_slice("=", 1).strip_edges() + "\n"; - } else if (p.begins_with("ro.build.version.release=")) { - d.description += "Release: " + p.get_slice("=", 1).strip_edges() + "\n"; - } else if (p.begins_with("ro.build.version.sdk=")) { - d.api_level = p.get_slice("=", 1).to_int(); - } else if (p.begins_with("ro.product.cpu.abi=")) { - d.description += "CPU: " + p.get_slice("=", 1).strip_edges() + "\n"; - } else if (p.begins_with("ro.product.manufacturer=")) { - d.description += "Manufacturer: " + p.get_slice("=", 1).strip_edges() + "\n"; - } else if (p.begins_with("ro.board.platform=")) { - d.description += "Chipset: " + p.get_slice("=", 1).strip_edges() + "\n"; - } else if (p.begins_with("ro.opengles.version=")) { - uint32_t opengl = p.get_slice("=", 1).to_int(); - d.description += "OpenGL: " + itos(opengl >> 16) + "." + itos((opengl >> 8) & 0xFF) + "." + itos((opengl)&0xFF) + "\n"; - } - } - - d.name = vendor + " " + device; - if (device == String()) { - continue; - } - } - - ndevices.push_back(d); - } - - ea->devices = ndevices; - ea->devices_changed.set(); - } - - ea->device_lock.unlock(); - } - - uint64_t sleep = 300'000; - uint64_t wait = 3'000'000; - uint64_t time = OS::get_singleton()->get_ticks_usec(); - while (OS::get_singleton()->get_ticks_usec() - time < wait) { - OS::get_singleton()->delay_usec(sleep); - if (ea->quit_request.is_set()) { - break; - } - } - } - - if (EditorSettings::get_singleton()->get("export/android/shutdown_adb_on_exit")) { - String adb = get_adb_path(); - if (!FileAccess::exists(adb)) { - return; //adb not configured - } - - List args; - args.push_back("kill-server"); - OS::get_singleton()->execute(adb, args, true); - } -} -#endif - -String EditorExportPlatformAndroid::get_project_name(const String &p_name) const { - String aname; - if (p_name != "") { - aname = p_name; - } else { - aname = ProjectSettings::get_singleton()->get("application/config/name"); - } - - if (aname == "") { - aname = VERSION_NAME; - } - - return aname; -} - -String EditorExportPlatformAndroid::get_package_name(const String &p_package) const { - String pname = p_package; - String basename = ProjectSettings::get_singleton()->get("application/config/name"); - basename = basename.to_lower(); - - String name; - bool first = true; - for (int i = 0; i < basename.length(); i++) { - CharType c = basename[i]; - if (c >= '0' && c <= '9' && first) { - continue; - } - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) { - name += String::chr(c); - first = false; - } - } - if (name == "") { - name = "noname"; - } - - pname = pname.replace("$genname", name); - - return pname; -} - -String EditorExportPlatformAndroid::get_assets_directory(const Ref &p_preset, int p_export_format) const { - return p_export_format == EXPORT_FORMAT_AAB ? AAB_ASSETS_DIRECTORY : APK_ASSETS_DIRECTORY; -} - -bool EditorExportPlatformAndroid::is_package_name_valid(const String &p_package, String *r_error) const { - String pname = p_package; - - if (pname.length() == 0) { - if (r_error) { - *r_error = TTR("Package name 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 = TTR("Package 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 = vformat(TTR("The character '%s' is not allowed in Android application package names."), String::chr(c)); - } - return false; - } - if (first && (c >= '0' && c <= '9')) { - if (r_error) { - *r_error = TTR("A digit cannot be the first character in a package segment."); - } - return false; - } - if (first && c == '_') { - if (r_error) { - *r_error = vformat(TTR("The character '%s' cannot be the first character in a package segment."), String::chr(c)); - } - return false; - } - first = false; - } - - if (segments == 0) { - if (r_error) { - *r_error = TTR("The package must have at least one '.' separator."); - } - return false; - } - - if (first) { - if (r_error) { - *r_error = TTR("Package segments must be of non-zero length."); - } - return false; - } - - return true; -} - -bool EditorExportPlatformAndroid::_should_compress_asset(const String &p_path, const Vector &p_data) { - /* - * By not compressing files with little or not benefit in doing so, - * a performance gain is expected attime. Moreover, if the APK is - * zip-aligned, assets stored as they are can be efficiently read by - * Android by memory-mapping them. - */ - - // -- Unconditional uncompress to mimic AAPT plus some other - - static const char *unconditional_compress_ext[] = { - // From https://github.com/android/platform_frameworks_base/blob/master/tools/aapt/Package.cpp - // These formats are already compressed, or don't compress well: - ".jpg", ".jpeg", ".png", ".gif", - ".wav", ".mp2", ".mp3", ".ogg", ".aac", - ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", - ".rtttl", ".imy", ".xmf", ".mp4", ".m4a", - ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2", - ".amr", ".awb", ".wma", ".wmv", - // Pandemonium-specific: - ".webp", // Same reasoning as .png - ".cfb", // Don't let small config files slow-down startup - ".scn", // Binary scenes are usually already compressed - ".stex", // Streamable textures are usually already compressed - // Trailer for easier processing - nullptr - }; - - for (const char **ext = unconditional_compress_ext; *ext; ++ext) { - if (p_path.to_lower().ends_with(String(*ext))) { - return false; - } - } - - // -- Compressed resource? - - if (p_data.size() >= 4 && p_data[0] == 'R' && p_data[1] == 'S' && p_data[2] == 'C' && p_data[3] == 'C') { - // Already compressed - return false; - } - - // --- TODO: Decide on texture resources according to their image compression setting - - return true; -} - -zip_fileinfo EditorExportPlatformAndroid::get_zip_fileinfo() { - OS::Time time = OS::get_singleton()->get_time(); - OS::Date date = OS::get_singleton()->get_date(); - - zip_fileinfo zipfi; - zipfi.tmz_date.tm_hour = time.hour; - zipfi.tmz_date.tm_mday = date.day; - zipfi.tmz_date.tm_min = time.min; - zipfi.tmz_date.tm_mon = date.month - 1; // tm_mon is zero indexed - zipfi.tmz_date.tm_sec = time.sec; - zipfi.tmz_date.tm_year = date.year; - zipfi.dosDate = 0; - zipfi.external_fa = 0; - zipfi.internal_fa = 0; - - return zipfi; -} - -Vector EditorExportPlatformAndroid::get_abis() { - Vector abis; - abis.push_back("armeabi-v7a"); - abis.push_back("arm64-v8a"); - abis.push_back("x86"); - abis.push_back("x86_64"); - return abis; -} - -/// List the gdap files in the directory specified by the p_path parameter. -Vector EditorExportPlatformAndroid::list_gdap_files(const String &p_path) { - Vector dir_files; - DirAccessRef da = DirAccess::open(p_path); - if (da) { - da->list_dir_begin(); - while (true) { - String file = da->get_next(); - if (file == "") { - break; - } - - if (da->current_is_dir() || da->current_is_hidden()) { - continue; - } - - if (file.ends_with(PluginConfigAndroid::PLUGIN_CONFIG_EXT)) { - dir_files.push_back(file); - } - } - da->list_dir_end(); - } - - return dir_files; -} - -Vector EditorExportPlatformAndroid::get_plugins() { - Vector loaded_plugins; - - String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("android/plugins"); - - // Add the prebuilt plugins - loaded_plugins.append_array(PluginConfigAndroid::get_prebuilt_plugins(plugins_dir)); - - if (DirAccess::exists(plugins_dir)) { - Vector plugins_filenames = list_gdap_files(plugins_dir); - - if (!plugins_filenames.empty()) { - Ref config_file = memnew(ConfigFile); - for (int i = 0; i < plugins_filenames.size(); i++) { - PluginConfigAndroid config = PluginConfigAndroid::load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i])); - if (config.valid_config) { - loaded_plugins.push_back(config); - } else { - print_error("Invalid plugin config file " + plugins_filenames[i]); - } - } - } - } - - return loaded_plugins; -} - -Vector EditorExportPlatformAndroid::get_enabled_plugins(const Ref &p_presets) { - Vector enabled_plugins; - Vector all_plugins = get_plugins(); - for (int i = 0; i < all_plugins.size(); i++) { - PluginConfigAndroid plugin = all_plugins[i]; - bool enabled = p_presets->get("plugins/" + plugin.name); - if (enabled) { - enabled_plugins.push_back(plugin); - } - } - - return enabled_plugins; -} - -Error EditorExportPlatformAndroid::store_in_apk(APKExportData *ed, const String &p_path, const Vector &p_data, int compression_method) { - zip_fileinfo zipfi = get_zip_fileinfo(); - zipOpenNewFileInZip(ed->apk, - p_path.utf8().get_data(), - &zipfi, - nullptr, - 0, - nullptr, - 0, - nullptr, - compression_method, - Z_DEFAULT_COMPRESSION); - - zipWriteInFileInZip(ed->apk, p_data.ptr(), p_data.size()); - zipCloseFileInZip(ed->apk); - - return OK; -} - -Error EditorExportPlatformAndroid::save_apk_so(void *p_userdata, const SharedObject &p_so) { - if (!p_so.path.get_file().begins_with("lib")) { - String err = "Android .so file names must start with \"lib\", but got: " + p_so.path; - ERR_PRINT(err); - return FAILED; - } - APKExportData *ed = (APKExportData *)p_userdata; - Vector abis = get_abis(); - bool exported = false; - for (int i = 0; i < p_so.tags.size(); ++i) { - // shared objects can be fat (compatible with multiple ABIs) - int abi_index = abis.find(p_so.tags[i]); - if (abi_index != -1) { - exported = true; - String abi = abis[abi_index]; - String dst_path = String("lib").plus_file(abi).plus_file(p_so.path.get_file()); - Vector array = FileAccess::get_file_as_array(p_so.path); - Error store_err = store_in_apk(ed, dst_path, array); - ERR_FAIL_COND_V_MSG(store_err, store_err, "Cannot store in apk file '" + dst_path + "'."); - } - } - if (!exported) { - String abis_string = String(" ").join(abis); - String err = "Cannot determine ABI for library \"" + p_so.path + "\". One of the supported ABIs must be used as a tag: " + abis_string; - ERR_PRINT(err); - return FAILED; - } - return OK; -} - -Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total) { - APKExportData *ed = (APKExportData *)p_userdata; - String dst_path = p_path.replace_first("res://", "assets/"); - - store_in_apk(ed, dst_path, p_data, _should_compress_asset(p_path, p_data) ? Z_DEFLATED : 0); - return OK; -} - -Error EditorExportPlatformAndroid::ignore_apk_file(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total) { - return OK; -} - -Error EditorExportPlatformAndroid::copy_gradle_so(void *p_userdata, const SharedObject &p_so) { - ERR_FAIL_COND_V_MSG(!p_so.path.get_file().begins_with("lib"), FAILED, - "Android .so file names must start with \"lib\", but got: " + p_so.path); - Vector abis = get_abis(); - CustomExportData *export_data = (CustomExportData *)p_userdata; - bool exported = false; - for (int i = 0; i < p_so.tags.size(); ++i) { - int abi_index = abis.find(p_so.tags[i]); - if (abi_index != -1) { - exported = true; - String base = "res://android/build/libs"; - String type = export_data->debug ? "debug" : "release"; - String abi = abis[abi_index]; - String filename = p_so.path.get_file(); - String dst_path = base.plus_file(type).plus_file(abi).plus_file(filename); - Vector data = FileAccess::get_file_as_array(p_so.path); - print_verbose("Copying .so file from " + p_so.path + " to " + dst_path); - Error err = store_file_at_path(dst_path, data); - ERR_FAIL_COND_V_MSG(err, err, "Failed to copy .so file from " + p_so.path + " to " + dst_path); - export_data->libs.push_back(dst_path); - } - } - ERR_FAIL_COND_V_MSG(!exported, FAILED, - "Cannot determine ABI for library \"" + p_so.path + "\". One of the supported ABIs must be used as a tag: " + String(" ").join(abis)); - return OK; -} - -bool EditorExportPlatformAndroid::_has_read_write_storage_permission(const Vector &p_permissions) { - return p_permissions.find("android.permission.READ_EXTERNAL_STORAGE") != -1 || p_permissions.find("android.permission.WRITE_EXTERNAL_STORAGE") != -1; -} - -bool EditorExportPlatformAndroid::_has_manage_external_storage_permission(const Vector &p_permissions) { - return p_permissions.find("android.permission.MANAGE_EXTERNAL_STORAGE") != -1; -} - -void EditorExportPlatformAndroid::_get_permissions(const Ref &p_preset, bool p_give_internet, Vector &r_permissions) { - const char **aperms = android_perms; - while (*aperms) { - bool enabled = p_preset->get("permissions/" + String(*aperms).to_lower()); - if (enabled) { - r_permissions.push_back("android.permission." + String(*aperms)); - } - aperms++; - } - 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()) { - r_permissions.push_back(user_perm); - } - } - if (p_give_internet) { - if (r_permissions.find("android.permission.INTERNET") == -1) { - r_permissions.push_back("android.permission.INTERNET"); - } - } -} - -void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref &p_preset, bool p_give_internet, bool p_debug) { - print_verbose("Building temporary manifest.."); - String manifest_text = - "\n" - "\n"; - - manifest_text += _get_screen_sizes_tag(p_preset); - manifest_text += _get_gles_tag(); - - Vector perms; - _get_permissions(p_preset, p_give_internet, perms); - for (int i = 0; i < perms.size(); i++) { - String permission = perms.get(i); - if (permission == "android.permission.WRITE_EXTERNAL_STORAGE" || (permission == "android.permission.READ_EXTERNAL_STORAGE" && _has_manage_external_storage_permission(perms))) { - manifest_text += vformat(" \n", permission); - } else { - manifest_text += vformat(" \n", permission); - } - } - - manifest_text += _get_application_tag(p_preset, _has_read_write_storage_permission(perms)); - manifest_text += "\n"; - String manifest_path = vformat("res://android/build/src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release")); - - print_verbose("Storing manifest into " + manifest_path + ": " + "\n" + manifest_text); - store_string_at_path(manifest_path, manifest_text); -} - -void EditorExportPlatformAndroid::_fix_manifest(const Ref &p_preset, Vector &p_manifest, bool p_give_internet) { - // Leaving the unused types commented because looking these constants up - // again later would be annoying - // const int CHUNK_AXML_FILE = 0x00080003; - // const int CHUNK_RESOURCEIDS = 0x00080180; - const int CHUNK_STRINGS = 0x001C0001; - // const int CHUNK_XML_END_NAMESPACE = 0x00100101; - const int CHUNK_XML_END_TAG = 0x00100103; - // const int CHUNK_XML_START_NAMESPACE = 0x00100100; - const int CHUNK_XML_START_TAG = 0x00100102; - // const int CHUNK_XML_TEXT = 0x00100104; - const int UTF8_FLAG = 0x00000100; - - Vector string_table; - - uint32_t ofs = 8; - - uint32_t string_count = 0; - //uint32_t styles_count = 0; - uint32_t string_flags = 0; - uint32_t string_data_offset = 0; - - //uint32_t styles_offset = 0; - uint32_t string_table_begins = 0; - uint32_t string_table_ends = 0; - Vector stable_extra; - - String version_name = p_preset->get("version/name"); - int version_code = p_preset->get("version/code"); - String package_name = p_preset->get("package/unique_name"); - - const int screen_orientation = _get_android_orientation_value( - OS::get_singleton()->get_screen_orientation_from_string(GLOBAL_GET("display/window/handheld/orientation"))); - - bool min_gles3 = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name") == "GLES3" && - !ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2"); - bool screen_support_small = p_preset->get("screen/support_small"); - bool screen_support_normal = p_preset->get("screen/support_normal"); - bool screen_support_large = p_preset->get("screen/support_large"); - bool screen_support_xlarge = p_preset->get("screen/support_xlarge"); - - bool backup_allowed = p_preset->get("user_data_backup/allow"); - bool classify_as_game = p_preset->get("package/classify_as_game"); - bool retain_data_on_uninstall = p_preset->get("package/retain_data_on_uninstall"); - bool exclude_from_recents = p_preset->get("package/exclude_from_recents"); - bool is_resizeable = bool(GLOBAL_GET("display/window/size/resizable")); - - Vector perms; - // Write permissions into the perms variable. - _get_permissions(p_preset, p_give_internet, perms); - bool has_read_write_storage_permission = _has_read_write_storage_permission(perms); - - while (ofs < (uint32_t)p_manifest.size()) { - uint32_t chunk = decode_uint32(&p_manifest[ofs]); - uint32_t size = decode_uint32(&p_manifest[ofs + 4]); - - switch (chunk) { - case CHUNK_STRINGS: { - int iofs = ofs + 8; - - string_count = decode_uint32(&p_manifest[iofs]); - // iofs + 4 is `styles_count`. - string_flags = decode_uint32(&p_manifest[iofs + 8]); - string_data_offset = decode_uint32(&p_manifest[iofs + 12]); - // iofs + 16 is `styles_offset`. - - uint32_t st_offset = iofs + 20; - string_table.resize(string_count); - uint32_t string_end = 0; - - string_table_begins = st_offset; - - for (uint32_t i = 0; i < string_count; i++) { - uint32_t string_at = decode_uint32(&p_manifest[st_offset + i * 4]); - string_at += st_offset + string_count * 4; - - ERR_FAIL_COND_MSG(string_flags & UTF8_FLAG, "Unimplemented, can't read UTF-8 string table."); - - if (string_flags & UTF8_FLAG) { - } else { - uint32_t len = decode_uint16(&p_manifest[string_at]); - Vector ucstring; - ucstring.resize(len + 1); - for (uint32_t j = 0; j < len; j++) { - uint16_t c = decode_uint16(&p_manifest[string_at + 2 + 2 * j]); - ucstring.write[j] = c; - } - string_end = MAX(string_at + 2 + 2 * len, string_end); - ucstring.write[len] = 0; - string_table.write[i] = ucstring.ptr(); - } - } - - for (uint32_t i = string_end; i < (ofs + size); i++) { - stable_extra.push_back(p_manifest[i]); - } - - string_table_ends = ofs + size; - - } break; - case CHUNK_XML_START_TAG: { - int iofs = ofs + 8; - uint32_t name = decode_uint32(&p_manifest[iofs + 12]); - - String tname = string_table[name]; - uint32_t attrcount = decode_uint32(&p_manifest[iofs + 20]); - iofs += 28; - - for (uint32_t i = 0; i < attrcount; i++) { - uint32_t attr_nspace = decode_uint32(&p_manifest[iofs]); - uint32_t attr_name = decode_uint32(&p_manifest[iofs + 4]); - uint32_t attr_value = decode_uint32(&p_manifest[iofs + 8]); - uint32_t attr_resid = decode_uint32(&p_manifest[iofs + 16]); - - const String value = (attr_value != 0xFFFFFFFF) ? string_table[attr_value] : "Res #" + itos(attr_resid); - String attrname = string_table[attr_name]; - const String nspace = (attr_nspace != 0xFFFFFFFF) ? string_table[attr_nspace] : ""; - - //replace project information - if (tname == "manifest" && attrname == "package") { - string_table.write[attr_value] = get_package_name(package_name); - } - - if (tname == "manifest" && attrname == "versionCode") { - encode_uint32(version_code, &p_manifest.write[iofs + 16]); - } - - if (tname == "manifest" && attrname == "versionName") { - if (attr_value == 0xFFFFFFFF) { - WARN_PRINT("Version name in a resource, should be plain text"); - } else { - string_table.write[attr_value] = version_name; - } - } - - if (tname == "application" && attrname == "requestLegacyExternalStorage") { - encode_uint32(has_read_write_storage_permission ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); - } - - if (tname == "application" && attrname == "allowBackup") { - encode_uint32(backup_allowed, &p_manifest.write[iofs + 16]); - } - - if (tname == "application" && attrname == "isGame") { - encode_uint32(classify_as_game, &p_manifest.write[iofs + 16]); - } - - if (tname == "application" && attrname == "hasFragileUserData") { - encode_uint32(retain_data_on_uninstall, &p_manifest.write[iofs + 16]); - } - - if (tname == "activity" && attrname == "screenOrientation") { - encode_uint32(screen_orientation, &p_manifest.write[iofs + 16]); - } - - if (tname == "activity" && attrname == "excludeFromRecents") { - encode_uint32(exclude_from_recents, &p_manifest.write[iofs + 16]); - } - - if (tname == "activity" && attrname == "resizeableActivity") { - encode_uint32(is_resizeable, &p_manifest.write[iofs + 16]); - } - - if (tname == "provider" && attrname == "authorities") { - string_table.write[attr_value] = get_package_name(package_name) + String(".fileprovider"); - } - - if (tname == "supports-screens") { - if (attrname == "smallScreens") { - encode_uint32(screen_support_small ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); - - } else if (attrname == "normalScreens") { - encode_uint32(screen_support_normal ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); - - } else if (attrname == "largeScreens") { - encode_uint32(screen_support_large ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); - - } else if (attrname == "xlargeScreens") { - encode_uint32(screen_support_xlarge ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); - } - } - - if (tname == "uses-feature" && attrname == "glEsVersion") { - encode_uint32(min_gles3 ? 0x00030000 : 0x00020000, &p_manifest.write[iofs + 16]); - } - - iofs += 20; - } - - } break; - case CHUNK_XML_END_TAG: { - int iofs = ofs + 8; - uint32_t name = decode_uint32(&p_manifest[iofs + 12]); - String tname = string_table[name]; - - if (tname == "uses-feature") { - Vector feature_names; - Vector feature_required_list; - Vector feature_versions; - - if (feature_names.size() > 0) { - ofs += 24; // skip over end tag - - // save manifest ending so we can restore it - Vector manifest_end; - uint32_t manifest_cur_size = p_manifest.size(); - - manifest_end.resize(p_manifest.size() - ofs); - memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size()); - - int32_t attr_name_string = string_table.find("name"); - ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute."); - - int32_t ns_android_string = string_table.find("http://schemas.android.com/apk/res/android"); - if (ns_android_string == -1) { - string_table.push_back("http://schemas.android.com/apk/res/android"); - ns_android_string = string_table.size() - 1; - } - - int32_t attr_uses_feature_string = string_table.find("uses-feature"); - if (attr_uses_feature_string == -1) { - string_table.push_back("uses-feature"); - attr_uses_feature_string = string_table.size() - 1; - } - - int32_t attr_required_string = string_table.find("required"); - if (attr_required_string == -1) { - string_table.push_back("required"); - attr_required_string = string_table.size() - 1; - } - - for (int i = 0; i < feature_names.size(); i++) { - String feature_name = feature_names[i]; - bool feature_required = feature_required_list[i]; - int feature_version = feature_versions[i]; - bool has_version_attribute = feature_version != -1; - - print_line("Adding feature " + feature_name); - - int32_t feature_string = string_table.find(feature_name); - if (feature_string == -1) { - string_table.push_back(feature_name); - feature_string = string_table.size() - 1; - } - - String required_value_string = feature_required ? "true" : "false"; - int32_t required_value = string_table.find(required_value_string); - if (required_value == -1) { - string_table.push_back(required_value_string); - required_value = string_table.size() - 1; - } - - int32_t attr_version_string = -1; - int32_t version_value = -1; - int tag_size; - int attr_count; - if (has_version_attribute) { - attr_version_string = string_table.find("version"); - if (attr_version_string == -1) { - string_table.push_back("version"); - attr_version_string = string_table.size() - 1; - } - - version_value = string_table.find(itos(feature_version)); - if (version_value == -1) { - string_table.push_back(itos(feature_version)); - version_value = string_table.size() - 1; - } - - tag_size = 96; // node and three attrs + end node - attr_count = 3; - } else { - tag_size = 76; // node and two attrs + end node - attr_count = 2; - } - manifest_cur_size += tag_size + 24; - p_manifest.resize(manifest_cur_size); - - // start tag - encode_uint16(0x102, &p_manifest.write[ofs]); // type - encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize - encode_uint32(tag_size, &p_manifest.write[ofs + 4]); // size - encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno - encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment - encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns - encode_uint32(attr_uses_feature_string, &p_manifest.write[ofs + 20]); // name - encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start - encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size - encode_uint16(attr_count, &p_manifest.write[ofs + 28]); // num_attrs - encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index - encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index - encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index - - // android:name attribute - encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns - encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name' - encode_uint32(feature_string, &p_manifest.write[ofs + 44]); // raw_value - encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size - p_manifest.write[ofs + 50] = 0; // typedvalue_always0 - p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string) - encode_uint32(feature_string, &p_manifest.write[ofs + 52]); // typedvalue reference - - // android:required attribute - encode_uint32(ns_android_string, &p_manifest.write[ofs + 56]); // ns - encode_uint32(attr_required_string, &p_manifest.write[ofs + 60]); // 'name' - encode_uint32(required_value, &p_manifest.write[ofs + 64]); // raw_value - encode_uint16(8, &p_manifest.write[ofs + 68]); // typedvalue_size - p_manifest.write[ofs + 70] = 0; // typedvalue_always0 - p_manifest.write[ofs + 71] = 0x03; // typedvalue_type (string) - encode_uint32(required_value, &p_manifest.write[ofs + 72]); // typedvalue reference - - ofs += 76; - - if (has_version_attribute) { - // android:version attribute - encode_uint32(ns_android_string, &p_manifest.write[ofs]); // ns - encode_uint32(attr_version_string, &p_manifest.write[ofs + 4]); // 'name' - encode_uint32(version_value, &p_manifest.write[ofs + 8]); // raw_value - encode_uint16(8, &p_manifest.write[ofs + 12]); // typedvalue_size - p_manifest.write[ofs + 14] = 0; // typedvalue_always0 - p_manifest.write[ofs + 15] = 0x03; // typedvalue_type (string) - encode_uint32(version_value, &p_manifest.write[ofs + 16]); // typedvalue reference - - ofs += 20; - } - - // end tag - encode_uint16(0x103, &p_manifest.write[ofs]); // type - encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize - encode_uint32(24, &p_manifest.write[ofs + 4]); // size - encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno - encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment - encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns - encode_uint32(attr_uses_feature_string, &p_manifest.write[ofs + 20]); // name - - ofs += 24; - } - memcpy(&p_manifest.write[ofs], manifest_end.ptr(), manifest_end.size()); - ofs -= 24; // go back over back end - } - } - if (tname == "manifest") { - // save manifest ending so we can restore it - Vector manifest_end; - uint32_t manifest_cur_size = p_manifest.size(); - - manifest_end.resize(p_manifest.size() - ofs); - memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size()); - - int32_t attr_name_string = string_table.find("name"); - ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute."); - - int32_t ns_android_string = string_table.find("android"); - ERR_FAIL_COND_MSG(ns_android_string == -1, "Template does not have 'android' namespace."); - - int32_t attr_uses_permission_string = string_table.find("uses-permission"); - if (attr_uses_permission_string == -1) { - string_table.push_back("uses-permission"); - attr_uses_permission_string = string_table.size() - 1; - } - - for (int i = 0; i < perms.size(); ++i) { - print_line("Adding permission " + perms[i]); - - manifest_cur_size += 56 + 24; // node + end node - p_manifest.resize(manifest_cur_size); - - // Add permission to the string pool - int32_t perm_string = string_table.find(perms[i]); - if (perm_string == -1) { - string_table.push_back(perms[i]); - perm_string = string_table.size() - 1; - } - - // start tag - encode_uint16(0x102, &p_manifest.write[ofs]); // type - encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize - encode_uint32(56, &p_manifest.write[ofs + 4]); // size - encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno - encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment - encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns - encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name - encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start - encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size - encode_uint16(1, &p_manifest.write[ofs + 28]); // num_attrs - encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index - encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index - encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index - - // attribute - encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns - encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name' - encode_uint32(perm_string, &p_manifest.write[ofs + 44]); // raw_value - encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size - p_manifest.write[ofs + 50] = 0; // typedvalue_always0 - p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string) - encode_uint32(perm_string, &p_manifest.write[ofs + 52]); // typedvalue reference - - ofs += 56; - - // end tag - encode_uint16(0x103, &p_manifest.write[ofs]); // type - encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize - encode_uint32(24, &p_manifest.write[ofs + 4]); // size - encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno - encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment - encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns - encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name - - ofs += 24; - } - - // copy footer back in - memcpy(&p_manifest.write[ofs], manifest_end.ptr(), manifest_end.size()); - } - } break; - } - - ofs += size; - } - - //create new andriodmanifest binary - - Vector ret; - ret.resize(string_table_begins + string_table.size() * 4); - - for (uint32_t i = 0; i < string_table_begins; i++) { - ret.write[i] = p_manifest[i]; - } - - ofs = 0; - for (int i = 0; i < string_table.size(); i++) { - encode_uint32(ofs, &ret.write[string_table_begins + i * 4]); - ofs += string_table[i].length() * 2 + 2 + 2; - } - - ret.resize(ret.size() + ofs); - string_data_offset = ret.size() - ofs; - uint8_t *chars = &ret.write[string_data_offset]; - for (int i = 0; i < string_table.size(); i++) { - String s = string_table[i]; - encode_uint16(s.length(), chars); - chars += 2; - for (int j = 0; j < s.length(); j++) { - encode_uint16(s[j], chars); - chars += 2; - } - encode_uint16(0, chars); - chars += 2; - } - - for (int i = 0; i < stable_extra.size(); i++) { - ret.push_back(stable_extra[i]); - } - - //pad - while (ret.size() % 4) { - ret.push_back(0); - } - - uint32_t new_stable_end = ret.size(); - - uint32_t extra = (p_manifest.size() - string_table_ends); - ret.resize(new_stable_end + extra); - for (uint32_t i = 0; i < extra; i++) { - ret.write[new_stable_end + i] = p_manifest[string_table_ends + i]; - } - - while (ret.size() % 4) { - ret.push_back(0); - } - encode_uint32(ret.size(), &ret.write[4]); //update new file size - - encode_uint32(new_stable_end - 8, &ret.write[12]); //update new string table size - encode_uint32(string_table.size(), &ret.write[16]); //update new number of strings - encode_uint32(string_data_offset - 8, &ret.write[28]); //update new string data offset - - p_manifest = ret; -} - -String EditorExportPlatformAndroid::_parse_string(const uint8_t *p_bytes, bool p_utf8) { - uint32_t offset = 0; - uint32_t len = 0; - - if (p_utf8) { - uint8_t byte = p_bytes[offset]; - if (byte & 0x80) { - offset += 2; - } else { - offset += 1; - } - byte = p_bytes[offset]; - offset++; - if (byte & 0x80) { - len = byte & 0x7F; - len = (len << 8) + p_bytes[offset]; - offset++; - } else { - len = byte; - } - } else { - len = decode_uint16(&p_bytes[offset]); - offset += 2; - if (len & 0x8000) { - len &= 0x7FFF; - len = (len << 16) + decode_uint16(&p_bytes[offset]); - offset += 2; - } - } - - if (p_utf8) { - Vector str8; - str8.resize(len + 1); - for (uint32_t i = 0; i < len; i++) { - str8.write[i] = p_bytes[offset + i]; - } - str8.write[len] = 0; - String str; - str.parse_utf8((const char *)str8.ptr()); - return str; - } else { - String str; - for (uint32_t i = 0; i < len; i++) { - CharType c = decode_uint16(&p_bytes[offset + i * 2]); - if (c == 0) { - break; - } - str += String::chr(c); - } - return str; - } -} - -void EditorExportPlatformAndroid::_fix_resources(const Ref &p_preset, Vector &r_manifest) { - const int UTF8_FLAG = 0x00000100; - - uint32_t string_block_len = decode_uint32(&r_manifest[16]); - uint32_t string_count = decode_uint32(&r_manifest[20]); - uint32_t string_flags = decode_uint32(&r_manifest[28]); - const uint32_t string_table_begins = 40; - - Vector string_table; - - String package_name = p_preset->get("package/name"); - - for (uint32_t i = 0; i < string_count; i++) { - uint32_t offset = decode_uint32(&r_manifest[string_table_begins + i * 4]); - offset += string_table_begins + string_count * 4; - - String str = _parse_string(&r_manifest[offset], string_flags & UTF8_FLAG); - - if (str.begins_with("pandemonium-project-name")) { - if (str == "pandemonium-project-name") { - //project name - str = get_project_name(package_name); - - } else { - String lang = str.substr(str.rfind("-") + 1, str.length()).replace("-", "_"); - String prop = "application/config/name_" + lang; - if (ProjectSettings::get_singleton()->has_setting(prop)) { - str = ProjectSettings::get_singleton()->get(prop); - } else { - str = get_project_name(package_name); - } - } - } - - string_table.push_back(str); - } - - //write a new string table, but use 16 bits - Vector ret; - ret.resize(string_table_begins + string_table.size() * 4); - - for (uint32_t i = 0; i < string_table_begins; i++) { - ret.write[i] = r_manifest[i]; - } - - int ofs = 0; - for (int i = 0; i < string_table.size(); i++) { - encode_uint32(ofs, &ret.write[string_table_begins + i * 4]); - ofs += string_table[i].length() * 2 + 2 + 2; - } - - ret.resize(ret.size() + ofs); - uint8_t *chars = &ret.write[ret.size() - ofs]; - for (int i = 0; i < string_table.size(); i++) { - String s = string_table[i]; - encode_uint16(s.length(), chars); - chars += 2; - for (int j = 0; j < s.length(); j++) { - encode_uint16(s[j], chars); - chars += 2; - } - encode_uint16(0, chars); - chars += 2; - } - - //pad - while (ret.size() % 4) { - ret.push_back(0); - } - - //change flags to not use utf8 - encode_uint32(string_flags & ~0x100, &ret.write[28]); - //change length - encode_uint32(ret.size() - 12, &ret.write[16]); - //append the rest... - int rest_from = 12 + string_block_len; - int rest_to = ret.size(); - int rest_len = (r_manifest.size() - rest_from); - ret.resize(ret.size() + (r_manifest.size() - rest_from)); - for (int i = 0; i < rest_len; i++) { - ret.write[rest_to + i] = r_manifest[rest_from + i]; - } - //finally update the size - encode_uint32(ret.size(), &ret.write[4]); - - r_manifest = ret; -} - -void EditorExportPlatformAndroid::_load_image_data(const Ref &p_splash_image, Vector &p_data) { - PoolVector png_buffer; - Error err = PNGDriverCommon::image_to_png(p_splash_image, png_buffer); - if (err == OK) { - p_data.resize(png_buffer.size()); - memcpy(p_data.ptrw(), png_buffer.read().ptr(), p_data.size()); - } else { - String err_str = String("Failed to convert splash image to png."); - WARN_PRINT(err_str.utf8().get_data()); - } -} - -void EditorExportPlatformAndroid::_process_launcher_icons(const String &p_file_name, const Ref &p_source_image, int dimension, Vector &p_data) { - Ref working_image = p_source_image; - - if (p_source_image->get_width() != dimension || p_source_image->get_height() != dimension) { - working_image = p_source_image->duplicate(); - working_image->resize(dimension, dimension, Image::Interpolation::INTERPOLATE_LANCZOS); - } - - PoolVector png_buffer; - Error err = PNGDriverCommon::image_to_png(working_image, png_buffer); - if (err == OK) { - p_data.resize(png_buffer.size()); - memcpy(p_data.ptrw(), png_buffer.read().ptr(), p_data.size()); - } else { - String err_str = String("Failed to convert resized icon (") + p_file_name + ") to png."; - WARN_PRINT(err_str.utf8().get_data()); - } -} - -String EditorExportPlatformAndroid::load_splash_refs(Ref &splash_image, Ref &splash_bg_color_image) { - bool scale_splash = ProjectSettings::get_singleton()->get("application/boot_splash/fullsize"); - bool apply_filter = ProjectSettings::get_singleton()->get("application/boot_splash/use_filter"); - String project_splash_path = ProjectSettings::get_singleton()->get("application/boot_splash/image"); - - if (!project_splash_path.empty()) { - splash_image.instance(); - print_verbose("Loading splash image: " + project_splash_path); - const Error err = ImageLoader::load_image(project_splash_path, splash_image); - if (err) { - if (OS::get_singleton()->is_stdout_verbose()) { - print_error("- unable to load splash image from " + project_splash_path + " (" + itos(err) + ")"); - } - splash_image.unref(); - } - } - - if (splash_image.is_null()) { - // Use the default - print_verbose("Using default splash image."); - - // Create a 1×1 transparent image. This will effectively hide the splash image. - splash_image.instance(); - splash_image->create(1, 1, false, Image::FORMAT_RGBA8); - splash_image->lock(); - splash_image->set_pixel(0, 0, Color(0, 0, 0, 0)); - splash_image->unlock(); - } - - if (scale_splash) { - Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); - int width, height; - if (screen_size.width > screen_size.height) { - // scale horizontally - height = screen_size.height; - width = splash_image->get_width() * screen_size.height / splash_image->get_height(); - } else { - // scale vertically - width = screen_size.width; - height = splash_image->get_height() * screen_size.width / splash_image->get_width(); - } - splash_image->resize(width, height); - } - - // Setup the splash bg color - bool bg_color_valid; - Color bg_color = ProjectSettings::get_singleton()->get("application/boot_splash/bg_color", &bg_color_valid); - if (!bg_color_valid) { - bg_color = Color(0.14, 0.14, 0.14); - } - - print_verbose("Creating splash background color image."); - splash_bg_color_image.instance(); - splash_bg_color_image->create(splash_image->get_width(), splash_image->get_height(), false, splash_image->get_format()); - splash_bg_color_image->fill(bg_color); - - String processed_splash_config_xml = vformat(SPLASH_CONFIG_XML_CONTENT, bool_to_string(apply_filter)); - return processed_splash_config_xml; -} - -void EditorExportPlatformAndroid::load_icon_refs(const Ref &p_preset, Ref &icon, Ref &foreground, Ref &background) { - String project_icon_path = ProjectSettings::get_singleton()->get("application/config/icon"); - - icon.instance(); - foreground.instance(); - background.instance(); - - // Regular icon: user selection -> project icon -> default. - String path = static_cast(p_preset->get(launcher_icon_option)).strip_edges(); - print_verbose("Loading regular icon from " + path); - if (path.empty() || ImageLoader::load_image(path, icon) != OK) { - print_verbose("- falling back to project icon: " + project_icon_path); - ImageLoader::load_image(project_icon_path, icon); - } - - // Adaptive foreground: user selection -> regular icon (user selection -> project icon -> default). - path = static_cast(p_preset->get(launcher_adaptive_icon_foreground_option)).strip_edges(); - print_verbose("Loading adaptive foreground icon from " + path); - if (path.empty() || ImageLoader::load_image(path, foreground) != OK) { - print_verbose("- falling back to using the regular icon"); - foreground = icon; - } - - // Adaptive background: user selection -> default. - path = static_cast(p_preset->get(launcher_adaptive_icon_background_option)).strip_edges(); - if (!path.empty()) { - print_verbose("Loading adaptive background icon from " + path); - ImageLoader::load_image(path, background); - } -} - -void EditorExportPlatformAndroid::store_image(const LauncherIcon launcher_icon, const Vector &data) { - store_image(launcher_icon.export_path, data); -} - -void EditorExportPlatformAndroid::store_image(const String &export_path, const Vector &data) { - String img_path = export_path.insert(0, "res://android/build/"); - store_file_at_path(img_path, data); -} - -void EditorExportPlatformAndroid::_copy_icons_to_gradle_project(const Ref &p_preset, - const String &processed_splash_config_xml, - const Ref &splash_image, - const Ref &splash_bg_color_image, - const Ref &main_image, - const Ref &foreground, - const Ref &background) { - // Store the splash configuration - if (!processed_splash_config_xml.empty()) { - print_verbose("Storing processed splash configuration: " + String("\n") + processed_splash_config_xml); - store_string_at_path(SPLASH_CONFIG_PATH, processed_splash_config_xml); - } - - // Store the splash image - if (splash_image.is_valid() && !splash_image->empty()) { - print_verbose("Storing splash image in " + String(SPLASH_IMAGE_EXPORT_PATH)); - Vector data; - _load_image_data(splash_image, data); - store_image(SPLASH_IMAGE_EXPORT_PATH, data); - } - - // Store the splash bg color image - if (splash_bg_color_image.is_valid() && !splash_bg_color_image->empty()) { - print_verbose("Storing splash background image in " + String(SPLASH_BG_COLOR_PATH)); - Vector data; - _load_image_data(splash_bg_color_image, data); - store_image(SPLASH_BG_COLOR_PATH, data); - } - - // Prepare images to be resized for the icons. If some image ends up being uninitialized, - // the default image from the export template will be used. - - for (int i = 0; i < icon_densities_count; ++i) { - if (main_image.is_valid() && !main_image->empty()) { - print_verbose("Processing launcher icon for dimension " + itos(launcher_icons[i].dimensions) + " into " + launcher_icons[i].export_path); - Vector data; - _process_launcher_icons(launcher_icons[i].export_path, main_image, launcher_icons[i].dimensions, data); - store_image(launcher_icons[i], data); - } - - if (foreground.is_valid() && !foreground->empty()) { - print_verbose("Processing launcher adaptive icon foreground for dimension " + itos(launcher_adaptive_icon_foregrounds[i].dimensions) + " into " + launcher_adaptive_icon_foregrounds[i].export_path); - Vector data; - _process_launcher_icons(launcher_adaptive_icon_foregrounds[i].export_path, foreground, - launcher_adaptive_icon_foregrounds[i].dimensions, data); - store_image(launcher_adaptive_icon_foregrounds[i], data); - } - - if (background.is_valid() && !background->empty()) { - print_verbose("Processing launcher adaptive icon background for dimension " + itos(launcher_adaptive_icon_backgrounds[i].dimensions) + " into " + launcher_adaptive_icon_backgrounds[i].export_path); - Vector data; - _process_launcher_icons(launcher_adaptive_icon_backgrounds[i].export_path, background, - launcher_adaptive_icon_backgrounds[i].dimensions, data); - store_image(launcher_adaptive_icon_backgrounds[i], data); - } - } -} - -Vector EditorExportPlatformAndroid::get_enabled_abis(const Ref &p_preset) { - Vector abis = get_abis(); - Vector enabled_abis; - for (int i = 0; i < abis.size(); ++i) { - bool is_enabled = p_preset->get("architectures/" + abis[i]); - if (is_enabled) { - enabled_abis.push_back(abis[i]); - } - } - return enabled_abis; -} - -void EditorExportPlatformAndroid::get_preset_features(const Ref &p_preset, List *r_features) { - String driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name"); - if (driver == "GLES2") { - r_features->push_back("etc"); - } else if (driver == "GLES3") { - r_features->push_back("etc2"); - if (ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2")) { - r_features->push_back("etc"); - } - } - - Vector abis = get_enabled_abis(p_preset); - for (int i = 0; i < abis.size(); ++i) { - r_features->push_back(abis[i]); - } -} - -void EditorExportPlatformAndroid::get_export_options(List *r_options) { - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_template/use_custom_build"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "custom_template/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK)); - - Vector plugins_configs = get_plugins(); - for (int i = 0; i < plugins_configs.size(); i++) { - print_verbose("Found Android plugin " + plugins_configs[i].name); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + plugins_configs[i].name), false)); - } - plugins_changed.clear(); - - Vector abis = get_abis(); - for (int i = 0; i < abis.size(); ++i) { - String abi = abis[i]; - bool is_default = (abi == "armeabi-v7a" || abi == "arm64-v8a"); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "architectures/" + abi), is_default)); - } - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_user"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_user"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password"), "")); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "one_click_deploy/clear_previous_install"), false)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name"), "1.0")); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/min_sdk", PROPERTY_HINT_RANGE, SDK_VERSION_RANGE), DEFAULT_MIN_SDK_VERSION)); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/target_sdk", PROPERTY_HINT_RANGE, SDK_VERSION_RANGE), DEFAULT_TARGET_SDK_VERSION)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "net.relintai.pandemonium.$genname")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name [default if blank]"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/signed"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/classify_as_game"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/retain_data_on_uninstall"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/exclude_from_recents"), false)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icon_option, PROPERTY_HINT_FILE, "*.png"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_foreground_option, PROPERTY_HINT_FILE, "*.png"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_background_option, PROPERTY_HINT_FILE, "*.png"), "")); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "graphics/opengl_debug"), false)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/immersive_mode"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_small"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_normal"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_large"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_xlarge"), true)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data_backup/allow"), false)); - - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), "")); - - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "apk_expansion/enable"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "apk_expansion/SALT"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "apk_expansion/public_key", PROPERTY_HINT_MULTILINE_TEXT), "")); - - 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++; - } -} - -String EditorExportPlatformAndroid::get_name() const { - return "Android"; -} - -String EditorExportPlatformAndroid::get_os_name() const { - return "Android"; -} - -Ref EditorExportPlatformAndroid::get_logo() const { - return logo; -} - -bool EditorExportPlatformAndroid::should_update_export_options() { - bool export_options_changed = plugins_changed.is_set(); - if (export_options_changed) { - // don't clear unless we're reporting true, to avoid race - plugins_changed.clear(); - } - return export_options_changed; -} - -bool EditorExportPlatformAndroid::poll_export() { - bool dc = devices_changed.is_set(); - if (dc) { - // don't clear unless we're reporting true, to avoid race - devices_changed.clear(); - } - return dc; -} - -int EditorExportPlatformAndroid::get_options_count() const { - device_lock.lock(); - int dc = devices.size(); - device_lock.unlock(); - - return dc; -} - -String EditorExportPlatformAndroid::get_options_tooltip() const { - return TTR("Select device from the list"); -} - -String EditorExportPlatformAndroid::get_option_label(int p_index) const { - ERR_FAIL_INDEX_V(p_index, devices.size(), ""); - device_lock.lock(); - String s = devices[p_index].name; - device_lock.unlock(); - return s; -} - -String EditorExportPlatformAndroid::get_option_tooltip(int p_index) const { - ERR_FAIL_INDEX_V(p_index, devices.size(), ""); - device_lock.lock(); - String s = devices[p_index].description; - if (devices.size() == 1) { - // Tooltip will be: - // Name - // Description - s = devices[p_index].name + "\n\n" + s; - } - device_lock.unlock(); - return s; -} - -Error EditorExportPlatformAndroid::run(const Ref &p_preset, int p_device, int p_debug_flags) { - ERR_FAIL_INDEX_V(p_device, devices.size(), ERR_INVALID_PARAMETER); - - String can_export_error; - bool can_export_missing_templates; - if (!can_export(p_preset, can_export_error, can_export_missing_templates)) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), can_export_error); - return ERR_UNCONFIGURED; - } - - device_lock.lock(); - - EditorProgress ep("run", vformat(TTR("Running on %s"), devices[p_device].name), 3); - - String adb = get_adb_path(); - - // Export_temp APK. - if (ep.step(TTR("Exporting APK..."), 0)) { - device_lock.unlock(); - return ERR_SKIP; - } - - const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT); - const bool use_reverse = devices[p_device].api_level >= 21; - - if (use_reverse) { - p_debug_flags |= DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST; - } - - String tmp_export_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport." + uitos(OS::get_singleton()->get_unix_time()) + ".apk"); - -#define CLEANUP_AND_RETURN(m_err) \ - { \ - DirAccess::remove_file_or_error(tmp_export_path); \ - device_lock.unlock(); \ - return m_err; \ - } - - // Export to temporary APK before sending to device. - Error err = export_project_helper(p_preset, true, tmp_export_path, EXPORT_FORMAT_APK, true, p_debug_flags); - - if (err != OK) { - CLEANUP_AND_RETURN(err); - } - - List args; - int rv; - String output; - - bool remove_prev = p_preset->get("one_click_deploy/clear_previous_install"); - String version_name = p_preset->get("version/name"); - String package_name = p_preset->get("package/unique_name"); - - if (remove_prev) { - if (ep.step(TTR("Uninstalling..."), 1)) { - CLEANUP_AND_RETURN(ERR_SKIP); - } - - print_line("Uninstalling previous version: " + devices[p_device].name); - - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("uninstall"); - args.push_back(get_package_name(package_name)); - - output.clear(); - err = OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - } - - print_line("Installing to device (please wait...): " + devices[p_device].name); - if (ep.step(TTR("Installing to device, please wait..."), 2)) { - CLEANUP_AND_RETURN(ERR_SKIP); - } - - args.clear(); - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("install"); - args.push_back("-r"); - args.push_back(tmp_export_path); - - output.clear(); - err = OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - if (err || rv != 0) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), vformat(TTR("Could not install to device: %s"), output)); - CLEANUP_AND_RETURN(ERR_CANT_CREATE); - } - - if (use_remote) { - if (use_reverse) { - static const char *const msg = "--- Device API >= 21; debugging over USB ---"; - EditorNode::get_singleton()->get_log()->add_message(msg, EditorLog::MSG_TYPE_EDITOR); - print_line(String(msg).to_upper()); - - args.clear(); - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("reverse"); - args.push_back("--remove-all"); - output.clear(); - OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - - if (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) { - int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port"); - args.clear(); - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("reverse"); - args.push_back("tcp:" + itos(dbg_port)); - args.push_back("tcp:" + itos(dbg_port)); - - output.clear(); - OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - print_line("Reverse result: " + itos(rv)); - } - - if (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT) { - int fs_port = EditorSettings::get_singleton()->get("filesystem/file_server/port"); - - args.clear(); - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("reverse"); - args.push_back("tcp:" + itos(fs_port)); - args.push_back("tcp:" + itos(fs_port)); - - output.clear(); - err = OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - print_line("Reverse result2: " + itos(rv)); - } - } else { - static const char *const msg = "--- Device API < 21; debugging over Wi-Fi ---"; - EditorNode::get_singleton()->get_log()->add_message(msg, EditorLog::MSG_TYPE_EDITOR); - print_line(String(msg).to_upper()); - } - } - - if (ep.step(TTR("Running on device..."), 3)) { - CLEANUP_AND_RETURN(ERR_SKIP); - } - args.clear(); - args.push_back("-s"); - args.push_back(devices[p_device].id); - args.push_back("shell"); - args.push_back("am"); - args.push_back("start"); - if ((bool)EditorSettings::get_singleton()->get("export/android/force_system_user") && devices[p_device].api_level >= 17) { // Multi-user introduced in Android 17 - args.push_back("--user"); - args.push_back("0"); - } - args.push_back("-a"); - args.push_back("android.intent.action.MAIN"); - args.push_back("-n"); - args.push_back(get_package_name(package_name) + "/com.pandemonium.game.PandemoniumApp"); - - output.clear(); - err = OS::get_singleton()->execute(adb, args, true, nullptr, &output, &rv, true); - print_verbose(output); - if (err || rv != 0) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Run"), TTR("Could not execute on device.")); - CLEANUP_AND_RETURN(ERR_CANT_CREATE); - } - - CLEANUP_AND_RETURN(OK); -#undef CLEANUP_AND_RETURN -} - -Ref EditorExportPlatformAndroid::get_run_icon() const { - return run_icon; -} - -String EditorExportPlatformAndroid::get_adb_path() { - String exe_ext = ""; - if (OS::get_singleton()->get_name() == "Windows") { - exe_ext = ".exe"; - } - String sdk_path = EditorSettings::get_singleton()->get("export/android/android_sdk_path"); - return sdk_path.plus_file("platform-tools/adb" + exe_ext); -} - -String EditorExportPlatformAndroid::get_apksigner_path() { - String exe_ext = ""; - if (OS::get_singleton()->get_name() == "Windows") { - exe_ext = ".bat"; - } - String apksigner_command_name = "apksigner" + exe_ext; - String sdk_path = EditorSettings::get_singleton()->get("export/android/android_sdk_path"); - String apksigner_path = ""; - - Error errn; - String build_tools_dir = sdk_path.plus_file("build-tools"); - DirAccessRef da = DirAccess::open(build_tools_dir, &errn); - if (errn != OK) { - print_error("Unable to open Android 'build-tools' directory."); - return apksigner_path; - } - - // There are additional versions directories we need to go through. - da->list_dir_begin(); - String sub_dir = da->get_next(); - while (!sub_dir.empty()) { - if (!sub_dir.begins_with(".") && da->current_is_dir()) { - // Check if the tool is here. - String tool_path = build_tools_dir.plus_file(sub_dir).plus_file(apksigner_command_name); - if (FileAccess::exists(tool_path)) { - apksigner_path = tool_path; - break; - } - } - sub_dir = da->get_next(); - } - da->list_dir_end(); - - if (apksigner_path.empty()) { - print_error("Unable to find the 'apksigner' tool."); - } - - return apksigner_path; -} - -bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref &p_preset, String &r_error, bool &r_missing_templates) const { - String err; - bool valid = false; - const bool custom_build_enabled = p_preset->get("custom_template/use_custom_build"); - - // Look for export templates (first official, and if defined custom templates). - - if (!custom_build_enabled) { - String template_err; - bool dvalid = false; - bool rvalid = false; - bool has_export_templates = false; - - if (p_preset->get("custom_template/debug") != "") { - dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); - if (!dvalid) { - template_err += TTR("Custom debug template not found.") + "\n"; - } - } else { - has_export_templates |= exists_export_template("android_debug.apk", &template_err); - } - - if (p_preset->get("custom_template/release") != "") { - rvalid = FileAccess::exists(p_preset->get("custom_template/release")); - if (!rvalid) { - template_err += TTR("Custom release template not found.") + "\n"; - } - } else { - has_export_templates |= exists_export_template("android_release.apk", &template_err); - } - - r_missing_templates = !has_export_templates; - valid = dvalid || rvalid || has_export_templates; - if (!valid) { - err += template_err; - } - } else { - bool installed_android_build_template = FileAccess::exists("res://android/build/build.gradle"); - if (!installed_android_build_template) { - r_missing_templates = !exists_export_template("android_source.zip", &err); - err += TTR("Android build template not installed in the project. Install it from the Project menu.") + "\n"; - } else { - r_missing_templates = false; - } - - valid = installed_android_build_template && !r_missing_templates; - } - - // Validate the rest of the export configuration. - - String dk = p_preset->get("keystore/debug"); - String dk_user = p_preset->get("keystore/debug_user"); - String dk_password = p_preset->get("keystore/debug_password"); - - if ((dk.empty() || dk_user.empty() || dk_password.empty()) && (!dk.empty() || !dk_user.empty() || !dk_password.empty())) { - valid = false; - err += TTR("Either Debug Keystore, Debug User AND Debug Password settings must be configured OR none of them.") + "\n"; - } - - if (!FileAccess::exists(dk)) { - dk = EditorSettings::get_singleton()->get("export/android/debug_keystore"); - if (!FileAccess::exists(dk)) { - valid = false; - err += TTR("Debug keystore not configured in the Editor Settings nor in the preset.") + "\n"; - } - } - - String rk = p_preset->get("keystore/release"); - String rk_user = p_preset->get("keystore/release_user"); - String rk_password = p_preset->get("keystore/release_password"); - - if ((rk.empty() || rk_user.empty() || rk_password.empty()) && (!rk.empty() || !rk_user.empty() || !rk_password.empty())) { - valid = false; - err += TTR("Either Release Keystore, Release User AND Release Password settings must be configured OR none of them.") + "\n"; - } - - if (!rk.empty() && !FileAccess::exists(rk)) { - valid = false; - err += TTR("Release keystore incorrectly configured in the export preset.") + "\n"; - } - - String sdk_path = EditorSettings::get_singleton()->get("export/android/android_sdk_path"); - if (sdk_path == "") { - err += TTR("A valid Android SDK path is required in Editor Settings.") + "\n"; - valid = false; - } else { - Error errn; - // Check for the platform-tools directory. - DirAccessRef da = DirAccess::open(sdk_path.plus_file("platform-tools"), &errn); - if (errn != OK) { - err += TTR("Invalid Android SDK path in Editor Settings."); - err += TTR("Missing 'platform-tools' directory!"); - err += "\n"; - valid = false; - } - - // Validate that adb is available - String adb_path = get_adb_path(); - if (!FileAccess::exists(adb_path)) { - err += TTR("Unable to find Android SDK platform-tools' adb command."); - err += TTR("Please check in the Android SDK directory specified in Editor Settings."); - err += "\n"; - valid = false; - } - - // Check for the build-tools directory. - DirAccessRef build_tools_da = DirAccess::open(sdk_path.plus_file("build-tools"), &errn); - if (errn != OK) { - err += TTR("Invalid Android SDK path in Editor Settings."); - err += TTR("Missing 'build-tools' directory!"); - err += "\n"; - valid = false; - } - - // Validate that apksigner is available - String apksigner_path = get_apksigner_path(); - if (!FileAccess::exists(apksigner_path)) { - err += TTR("Unable to find Android SDK build-tools' apksigner command."); - err += TTR("Please check in the Android SDK directory specified in Editor Settings."); - err += "\n"; - valid = false; - } - } - - if (!err.empty()) { - r_error = err; - } - - return valid; -} - -bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref &p_preset, String &r_error) const { - String err; - bool valid = true; - const bool custom_build_enabled = p_preset->get("custom_build/use_custom_build"); - - // Validate the project configuration. - bool apk_expansion = p_preset->get("apk_expansion/enable"); - - if (apk_expansion) { - String apk_expansion_pkey = p_preset->get("apk_expansion/public_key"); - - if (apk_expansion_pkey == "") { - valid = false; - - err += TTR("Invalid public key for APK expansion.") + "\n"; - } - } - - String pn = p_preset->get("package/unique_name"); - String pn_err; - - if (!is_package_name_valid(get_package_name(pn), &pn_err)) { - valid = false; - err += TTR("Invalid package name:") + " " + pn_err + "\n"; - } - - String etc_error = test_etc2(); - if (etc_error != String()) { - valid = false; - err += etc_error; - } - - // The PandemoniumPaymentV3 module was converted to the external PandemoniumGooglePlayBilling plugin in Pandemonium 3.2.2, - // this check helps users to notice the change to ensure that they change their settings. - String modules = ProjectSettings::get_singleton()->get("android/modules"); - if (modules.find("org/pandemoniumengine/pandemonium/PandemoniumPaymentV3") != -1) { - bool pandemonium_google_play_billing_enabled = p_preset->get("plugins/PandemoniumGooglePlayBilling"); - if (!pandemonium_google_play_billing_enabled) { - valid = false; - err += TTR("Invalid \"PandemoniumPaymentV3\" module included in the \"android/modules\" project setting (changed in Pandemonium 3.2.2).\nReplace it with the first-party \"PandemoniumGooglePlayBilling\" plugin.\nNote that the singleton was also renamed from \"PandemoniumPayments\" to \"PandemoniumGooglePlayBilling\"."); - err += "\n"; - } - } - - // Ensure that `Use Custom Build` is enabled if a plugin is selected. - String enabled_plugins_names = PluginConfigAndroid::get_plugins_names(get_enabled_plugins(p_preset)); - if (!enabled_plugins_names.empty() && !custom_build_enabled) { - valid = false; - err += TTR("\"Use Custom Build\" must be enabled to use the plugins."); - err += "\n"; - } - - if (int(p_preset->get("custom_build/export_format")) == EXPORT_FORMAT_AAB && !custom_build_enabled) { - valid = false; - err += TTR("\"Export AAB\" is only valid when \"Use Custom Build\" is enabled."); - err += "\n"; - } - - // Check the min sdk version - int min_sdk_version = p_preset->get("version/min_sdk"); - if (min_sdk_version != DEFAULT_MIN_SDK_VERSION && !custom_build_enabled) { - valid = false; - err += TTR("Changing the \"Min Sdk\" is only valid when \"Use Custom Build\" is enabled."); - err += "\n"; - } - - // Check the target sdk version - int target_sdk_version = p_preset->get("version/target_sdk"); - if (target_sdk_version != DEFAULT_TARGET_SDK_VERSION && !custom_build_enabled) { - valid = false; - err += TTR("Changing the \"Target Sdk\" is only valid when \"Use Custom Build\" is enabled."); - err += "\n"; - } - - if (target_sdk_version < min_sdk_version) { - valid = false; - err += TTR("\"Target Sdk\" version must be greater or equal to \"Min Sdk\" version."); - err += "\n"; - } - - if (!err.empty()) { - r_error = err; - } - - return valid; -} - -List EditorExportPlatformAndroid::get_binary_extensions(const Ref &p_preset) const { - List list; - list.push_back("apk"); - list.push_back("aab"); - return list; -} - -void EditorExportPlatformAndroid::_update_custom_build_project() { - print_verbose("Updating custom build project.."); - DirAccessRef da = DirAccess::open("res://android"); - - ERR_FAIL_COND_MSG(!da, "Cannot open directory 'res://android'."); - RBMap> directory_paths; - RBMap> manifest_sections; - RBMap> gradle_sections; - da->list_dir_begin(); - String d = da->get_next(); - while (d != String()) { - if (!d.begins_with(".") && d != "build" && da->current_is_dir()) { //a dir and not the build dir - //add directories found - DirAccessRef ds = DirAccess::open(String("res://android").plus_file(d)); - if (ds) { - ds->list_dir_begin(); - String sd = ds->get_next(); - while (sd != String()) { - if (!sd.begins_with(".") && ds->current_is_dir()) { - String key = sd.to_upper(); - if (!directory_paths.has(key)) { - directory_paths[key] = List(); - } - String path = ProjectSettings::get_singleton()->get_resource_path().plus_file("android").plus_file(d).plus_file(sd); - directory_paths[key].push_back(path); - print_line("Add: " + sd + ":" + path); - } - - sd = ds->get_next(); - } - ds->list_dir_end(); - } - //parse manifest - { - FileAccessRef f = FileAccess::open(String("res://android").plus_file(d).plus_file("AndroidManifest.conf"), FileAccess::READ); - if (f) { - String section; - while (!f->eof_reached()) { - String l = f->get_line(); - String k = l.strip_edges(); - if (k.begins_with("[")) { - section = k.substr(1, k.length() - 2).strip_edges().to_upper(); - print_line("Section: " + section); - } else if (k != String()) { - if (!manifest_sections.has(section)) { - manifest_sections[section] = List(); - } - manifest_sections[section].push_back(l); - } - } - - f->close(); - } - } - //parse gradle - { - FileAccessRef f = FileAccess::open(String("res://android").plus_file(d).plus_file("gradle.conf"), FileAccess::READ); - if (f) { - String section; - while (!f->eof_reached()) { - String l = f->get_line().strip_edges(); - String k = l.strip_edges(); - if (k.begins_with("[")) { - section = k.substr(1, k.length() - 2).strip_edges().to_upper(); - print_line("Section: " + section); - } else if (k != String()) { - if (!gradle_sections.has(section)) { - gradle_sections[section] = List(); - } - gradle_sections[section].push_back(l); - } - } - } - } - } - d = da->get_next(); - } - da->list_dir_end(); - - { //fix gradle build - - String new_file; - { - FileAccessRef f = FileAccess::open("res://android/build/build.gradle", FileAccess::READ); - if (f) { - while (!f->eof_reached()) { - String l = f->get_line(); - - bool append_line = false; - if (l.begins_with("//CHUNK_")) { - String text = l.replace_first("//CHUNK_", ""); - int begin_pos = text.find("_BEGIN"); - if (begin_pos != -1) { - text = text.substr(0, begin_pos); - text = text.to_upper(); //just in case - - String end_marker = "//CHUNK_" + text + "_END"; - uint64_t pos = f->get_position(); - bool found = false; - while (!f->eof_reached()) { - l = f->get_line(); - if (l.begins_with(end_marker)) { - found = true; - break; - } - } - - new_file += "//CHUNK_" + text + "_BEGIN\n"; - - if (!found) { - ERR_PRINT("No end marker found in build.gradle for chunk: " + text); - f->seek(pos); - } else { - //add chunk lines - if (gradle_sections.has(text)) { - for (List::Element *E = gradle_sections[text].front(); E; E = E->next()) { - new_file += E->get() + "\n"; - } - } - if (f->eof_reached()) { - new_file += end_marker; - } else { - new_file += end_marker + "\n"; - } - } - } else { - append_line = true; - } - } else if (l.begins_with("//DIR_")) { - String text = l.replace_first("//DIR_", ""); - int begin_pos = text.find("_BEGIN"); - if (begin_pos != -1) { - text = text.substr(0, begin_pos); - text = text.to_upper(); //just in case - - String end_marker = "//DIR_" + text + "_END"; - uint64_t pos = f->get_position(); - bool found = false; - while (!f->eof_reached()) { - l = f->get_line(); - if (l.begins_with(end_marker)) { - found = true; - break; - } - } - - new_file += "//DIR_" + text + "_BEGIN\n"; - - if (!found) { - ERR_PRINT("No end marker found in build.gradle for dir: " + text); - f->seek(pos); - } else { - //add chunk lines - if (directory_paths.has(text)) { - for (List::Element *E = directory_paths[text].front(); E; E = E->next()) { - new_file += ",'" + E->get().replace("'", "\'") + "'"; - new_file += "\n"; - } - } - if (f->eof_reached()) { - new_file += end_marker; - } else { - new_file += end_marker + "\n"; - } - } - } else { - append_line = true; - } - } else { - append_line = true; - } - - if (append_line) { - if (f->eof_reached()) { - new_file += l; - } else { - new_file += l + "\n"; - } - } - } - } - } - - FileAccessRef f = FileAccess::open("res://android/build/build.gradle", FileAccess::WRITE); - f->store_string(new_file); - f->close(); - } - - { //fix manifest - - String new_file; - { - FileAccessRef f = FileAccess::open("res://android/build/AndroidManifest.xml", FileAccess::READ); - if (f) { - while (!f->eof_reached()) { - String l = f->get_line(); - - bool append_line = false; - if (l.begins_with(""); - if (begin_pos != -1) { - text = text.substr(0, begin_pos); - text = text.to_upper(); //just in case - - String end_marker = ""; - uint64_t pos = f->get_position(); - bool found = false; - while (!f->eof_reached()) { - l = f->get_line(); - if (l.begins_with(end_marker)) { - found = true; - break; - } - } - - new_file += "\n"; - - if (!found) { - ERR_PRINT("No end marker found in AndroidManifest.xml for chunk: " + text); - f->seek(pos); - } else { - //add chunk lines - if (manifest_sections.has(text)) { - for (List::Element *E = manifest_sections[text].front(); E; E = E->next()) { - new_file += E->get() + "\n"; - } - } - if (f->eof_reached()) { - new_file += end_marker; - } else { - new_file += end_marker + "\n"; - } - } - } else { - append_line = true; - } - - } else if (l.strip_edges().begins_with("::Element *E = manifest_sections["APPLICATION_ATTRIBS"].front(); E; E = E->next()) { - String to_add = E->get().strip_edges(); - base += " " + to_add + " "; - } - } - base += ">\n"; - new_file += base; - } - } else { - append_line = true; - } - - if (append_line) { - new_file += l; - if (!f->eof_reached()) { - new_file += "\n"; - } - } - } - } - } - - FileAccessRef f = FileAccess::open("res://android/build/AndroidManifest.xml", FileAccess::WRITE); - f->store_string(new_file); - f->close(); - } -} - -String EditorExportPlatformAndroid::get_apk_expansion_fullpath(const Ref &p_preset, const String &p_path) { - int version_code = p_preset->get("version/code"); - String package_name = p_preset->get("package/unique_name"); - String apk_file_name = "main." + itos(version_code) + "." + get_package_name(package_name) + ".obb"; - String fullpath = p_path.get_base_dir().plus_file(apk_file_name); - return fullpath; -} - -Error EditorExportPlatformAndroid::save_apk_expansion_file(const Ref &p_preset, const String &p_path) { - String fullpath = get_apk_expansion_fullpath(p_preset, p_path); - Error err = save_pack(p_preset, fullpath); - return err; -} - -void EditorExportPlatformAndroid::get_command_line_flags(const Ref &p_preset, const String &p_path, int p_flags, Vector &r_command_line_flags) { - String cmdline = p_preset->get("command_line/extra_args"); - Vector command_line_strings = cmdline.strip_edges().split(" "); - for (int i = 0; i < command_line_strings.size(); i++) { - if (command_line_strings[i].strip_edges().length() == 0) { - command_line_strings.remove(i); - i--; - } - } - - gen_export_flags(command_line_strings, p_flags); - - bool apk_expansion = p_preset->get("apk_expansion/enable"); - if (apk_expansion) { - String fullpath = get_apk_expansion_fullpath(p_preset, p_path); - String apk_expansion_public_key = p_preset->get("apk_expansion/public_key"); - - command_line_strings.push_back("--use_apk_expansion"); - command_line_strings.push_back("--apk_expansion_md5"); - command_line_strings.push_back(FileAccess::get_md5(fullpath)); - command_line_strings.push_back("--apk_expansion_key"); - command_line_strings.push_back(apk_expansion_public_key.strip_edges()); - } - - bool immersive = p_preset->get("screen/immersive_mode"); - if (immersive) { - command_line_strings.push_back("--use_immersive"); - } - - bool debug_opengl = p_preset->get("graphics/opengl_debug"); - if (debug_opengl) { - command_line_strings.push_back("--debug_opengl"); - } - - bool translucent = ProjectSettings::get_singleton()->get("display/window/per_pixel_transparency/enabled"); - if (translucent) { - command_line_strings.push_back("--translucent"); - } - - if (command_line_strings.size()) { - r_command_line_flags.resize(4); - encode_uint32(command_line_strings.size(), &r_command_line_flags.write[0]); - for (int i = 0; i < command_line_strings.size(); i++) { - print_line(itos(i) + " param: " + command_line_strings[i]); - CharString command_line_argument = command_line_strings[i].utf8(); - int base = r_command_line_flags.size(); - int length = command_line_argument.length(); - if (length == 0) { - continue; - } - r_command_line_flags.resize(base + 4 + length); - encode_uint32(length, &r_command_line_flags.write[base]); - memcpy(&r_command_line_flags.write[base + 4], command_line_argument.ptr(), length); - } - } -} - -Error EditorExportPlatformAndroid::sign_apk(const Ref &p_preset, bool p_debug, const String &export_path, EditorProgress &ep) { - int export_format = int(p_preset->get("custom_template/export_format")); - String export_label = export_format == EXPORT_FORMAT_AAB ? "AAB" : "APK"; - String release_keystore = p_preset->get("keystore/release"); - String release_username = p_preset->get("keystore/release_user"); - String release_password = p_preset->get("keystore/release_password"); - - String apksigner = get_apksigner_path(); - print_verbose("Starting signing of the " + export_label + " binary using " + apksigner); - if (!FileAccess::exists(apksigner)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("'apksigner' could not be found. Please check that the command is available in the Android SDK build-tools directory. The resulting %s is unsigned."), export_label)); - return OK; - } - - String keystore; - String password; - String user; - if (p_debug) { - keystore = p_preset->get("keystore/debug"); - password = p_preset->get("keystore/debug_password"); - user = p_preset->get("keystore/debug_user"); - - if (keystore.empty()) { - keystore = EditorSettings::get_singleton()->get("export/android/debug_keystore"); - password = EditorSettings::get_singleton()->get("export/android/debug_keystore_pass"); - user = EditorSettings::get_singleton()->get("export/android/debug_keystore_user"); - } - - if (ep.step(vformat(TTR("Signing debug %s..."), export_label), 104)) { - return ERR_SKIP; - } - - } else { - keystore = release_keystore; - password = release_password; - user = release_username; - - if (ep.step(vformat(TTR("Signing release %s..."), export_label), 104)) { - return ERR_SKIP; - } - } - - if (!FileAccess::exists(keystore)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not find keystore, unable to export.")); - return ERR_FILE_CANT_OPEN; - } - - String output; - List args; - args.push_back("sign"); - args.push_back("--verbose"); - args.push_back("--ks"); - args.push_back(keystore); - args.push_back("--ks-pass"); - args.push_back("pass:" + password); - args.push_back("--ks-key-alias"); - args.push_back(user); - args.push_back(export_path); - if (p_debug) { - // We only print verbose logs for debug builds to avoid leaking release keystore credentials. - print_verbose("Signing debug binary using: " + String("\n") + apksigner + " " + join_list(args, String(" "))); - } - int retval; - output.clear(); - - Error err = OS::get_singleton()->execute(apksigner, args, true, nullptr, &output, &retval, true); - if (err != OK) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start apksigner executable.")); - return err; - } - - print_verbose(output); - if (retval) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("'apksigner' returned with error #%d"), retval)); - return ERR_CANT_CREATE; - } - - if (ep.step(vformat(TTR("Verifying %s..."), export_label), 105)) { - return ERR_SKIP; - } - - args.clear(); - args.push_back("verify"); - args.push_back("--verbose"); - args.push_back(export_path); - if (p_debug) { - print_verbose("Verifying signed build using: " + String("\n") + apksigner + " " + join_list(args, String(" "))); - } - - output.clear(); - - err = OS::get_singleton()->execute(apksigner, args, true, nullptr, &output, &retval, true); - if (err != OK) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start apksigner executable.")); - return err; - } - - print_verbose(output); - if (retval) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("'apksigner' verification of %s failed."), export_label)); - return ERR_CANT_CREATE; - } - - print_verbose("Successfully completed signing build."); - return OK; -} - -void EditorExportPlatformAndroid::_clear_assets_directory() { - DirAccessRef da_res = DirAccess::create(DirAccess::ACCESS_RESOURCES); - - // Clear the APK assets directory - if (da_res->dir_exists(APK_ASSETS_DIRECTORY)) { - print_verbose("Clearing APK assets directory.."); - DirAccessRef da_assets = DirAccess::open(APK_ASSETS_DIRECTORY); - da_assets->erase_contents_recursive(); - da_res->remove(APK_ASSETS_DIRECTORY); - } - - // Clear the AAB assets directory - if (da_res->dir_exists(AAB_ASSETS_DIRECTORY)) { - print_verbose("Clearing AAB assets directory.."); - DirAccessRef da_assets = DirAccess::open(AAB_ASSETS_DIRECTORY); - da_assets->erase_contents_recursive(); - da_res->remove(AAB_ASSETS_DIRECTORY); - } -} - -void EditorExportPlatformAndroid::_remove_copied_libs() { - print_verbose("Removing previously installed libraries..."); - Error error; - String libs_json = FileAccess::get_file_as_string(GDNATIVE_LIBS_PATH, &error); - if (error || libs_json.empty()) { - print_verbose("No previously installed libraries found"); - return; - } - - Variant result; - String error_string; - int error_line; - error = JSON::parse(libs_json, result, error_string, error_line); - ERR_FAIL_COND_MSG(error, "Error parsing \"" + libs_json + "\" on line " + itos(error_line) + ": " + error_string); - - Vector libs = result; - DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); - for (int i = 0; i < libs.size(); i++) { - print_verbose("Removing previously installed library " + libs[i]); - da->remove(libs[i]); - } - da->remove(GDNATIVE_LIBS_PATH); -} - -String EditorExportPlatformAndroid::join_list(List parts, const String &separator) const { - String ret; - for (int i = 0; i < parts.size(); ++i) { - if (i > 0) { - ret += separator; - } - ret += parts[i]; - } - return ret; -} - -Error EditorExportPlatformAndroid::export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags) { - int export_format = int(p_preset->get("custom_template/export_format")); - bool should_sign = p_preset->get("package/signed"); - return export_project_helper(p_preset, p_debug, p_path, export_format, should_sign, p_flags); -} - -Error EditorExportPlatformAndroid::export_project_helper(const Ref &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags) { - ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags); - - String src_apk; - Error err; - - EditorProgress ep("export", TTR("Exporting for Android"), 105, true); - - bool use_custom_build = bool(p_preset->get("custom_template/use_custom_build")); - bool p_give_internet = p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG); - bool apk_expansion = p_preset->get("apk_expansion/enable"); - Vector enabled_abis = get_enabled_abis(p_preset); - - print_verbose("Exporting for Android..."); - print_verbose("- debug build: " + bool_to_string(p_debug)); - print_verbose("- export path: " + p_path); - print_verbose("- export format: " + itos(export_format)); - print_verbose("- sign build: " + bool_to_string(should_sign)); - print_verbose("- custom build enabled: " + bool_to_string(use_custom_build)); - print_verbose("- apk expansion enabled: " + bool_to_string(apk_expansion)); - print_verbose("- enabled abis: " + String(",").join(enabled_abis)); - print_verbose("- export filter: " + itos(p_preset->get_export_filter())); - print_verbose("- include filter: " + p_preset->get_include_filter()); - print_verbose("- exclude filter: " + p_preset->get_exclude_filter()); - - Ref splash_image; - Ref splash_bg_color_image; - String processed_splash_config_xml = load_splash_refs(splash_image, splash_bg_color_image); - - Ref main_image; - Ref foreground; - Ref background; - - load_icon_refs(p_preset, main_image, foreground, background); - - Vector command_line_flags; - // Write command line flags into the command_line_flags variable. - get_command_line_flags(p_preset, p_path, p_flags, command_line_flags); - - if (export_format == EXPORT_FORMAT_AAB) { - if (!p_path.ends_with(".aab")) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Invalid filename! Android App Bundle requires the *.aab extension.")); - return ERR_UNCONFIGURED; - } - if (apk_expansion) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("APK Expansion not compatible with Android App Bundle.")); - return ERR_UNCONFIGURED; - } - } - if (export_format == EXPORT_FORMAT_APK && !p_path.ends_with(".apk")) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Invalid filename! Android APK requires the *.apk extension.")); - return ERR_UNCONFIGURED; - } - if (export_format > EXPORT_FORMAT_AAB || export_format < EXPORT_FORMAT_APK) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Unsupported export format!")); - return ERR_UNCONFIGURED; - } - - if (use_custom_build) { - print_verbose("Starting custom build.."); - //test that installed build version is alright - { - print_verbose("Checking build version.."); - FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::READ); - if (!f) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu.")); - return ERR_UNCONFIGURED; - } - String version = f->get_line().strip_edges(); - print_verbose("- build version: " + version); - f->close(); - if (version != VERSION_FULL_CONFIG) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Android build version mismatch: Template installed: %s, Godot version: %s. Please reinstall Android build template from 'Project' menu."), version, VERSION_FULL_CONFIG)); - return ERR_UNCONFIGURED; - } - } - const String assets_directory = get_assets_directory(p_preset, export_format); - String sdk_path = EDITOR_GET("export/android/android_sdk_path"); - ERR_FAIL_COND_V_MSG(sdk_path.empty(), ERR_UNCONFIGURED, "Android SDK path must be configured in Editor Settings at 'export/android/android_sdk_path'."); - print_verbose("Android sdk path: " + sdk_path); - - // TODO: should we use "package/name" or "application/config/name"? - String project_name = get_project_name(p_preset->get("package/name")); - err = _create_project_name_strings_files(p_preset, project_name); //project name localization. - if (err != OK) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Unable to overwrite res://android/build/res/*.xml files with project name.")); - } - // Copies the project icon files into the appropriate Gradle project directory. - _copy_icons_to_gradle_project(p_preset, processed_splash_config_xml, splash_image, splash_bg_color_image, main_image, foreground, background); - // Write an AndroidManifest.xml file into the Gradle project directory. - _write_tmp_manifest(p_preset, p_give_internet, p_debug); - _update_custom_build_project(); - //stores all the project files inside the Gradle project directory. Also includes all ABIs - _clear_assets_directory(); - _remove_copied_libs(); - if (!apk_expansion) { - print_verbose("Exporting project files.."); - CustomExportData user_data; - user_data.assets_directory = assets_directory; - user_data.debug = p_debug; - err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so); - if (err != OK) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not export project files to gradle project.")); - return err; - } - if (user_data.libs.size() > 0) { - FileAccessRef fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE); - fa->store_string(JSON::print(user_data.libs, "\t")); - fa->close(); - } - } else { - print_verbose("Saving apk expansion file.."); - err = save_apk_expansion_file(p_preset, p_path); - if (err != OK) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not write expansion package file!")); - return err; - } - } - print_verbose("Storing command line flags.."); - store_file_at_path(assets_directory + "/_cl_", command_line_flags); - - print_verbose("Updating ANDROID_HOME environment to " + sdk_path); - OS::get_singleton()->set_environment("ANDROID_HOME", sdk_path); //set and overwrite if required - String build_command; - -#ifdef WINDOWS_ENABLED - build_command = "gradlew.bat"; -#else - build_command = "gradlew"; -#endif - - String build_path = ProjectSettings::get_singleton()->get_resource_path().plus_file("android/build"); - build_command = build_path.plus_file(build_command); - - String package_name = get_package_name(p_preset->get("package/unique_name")); - String version_code = itos(p_preset->get("version/code")); - String version_name = p_preset->get("version/name"); - String min_sdk_version = itos(p_preset->get("version/min_sdk")); - String target_sdk_version = itos(p_preset->get("version/target_sdk")); - String enabled_abi_string = String("|").join(enabled_abis); - String sign_flag = should_sign ? "true" : "false"; - String zipalign_flag = "true"; - - Vector enabled_plugins = get_enabled_plugins(p_preset); - String local_plugins_binaries = PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_LOCAL, enabled_plugins); - String remote_plugins_binaries = PluginConfigAndroid::get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_REMOTE, enabled_plugins); - String custom_maven_repos = PluginConfigAndroid::get_plugins_custom_maven_repos(enabled_plugins); - bool clean_build_required = is_clean_build_required(enabled_plugins); - - List cmdline; - if (clean_build_required) { - cmdline.push_back("clean"); - } - - String build_type = p_debug ? "Debug" : "Release"; - if (export_format == EXPORT_FORMAT_AAB) { - String bundle_build_command = vformat("bundle%s", build_type); - cmdline.push_back(bundle_build_command); - } else if (export_format == EXPORT_FORMAT_APK) { - String apk_build_command = vformat("assemble%s", build_type); - cmdline.push_back(apk_build_command); - } - - cmdline.push_back("-p"); // argument to specify the start directory. - cmdline.push_back(build_path); // start directory. - cmdline.push_back("-Pexport_package_name=" + package_name); // argument to specify the package name. - cmdline.push_back("-Pexport_version_code=" + version_code); // argument to specify the version code. - cmdline.push_back("-Pexport_version_name=" + version_name); // argument to specify the version name. - cmdline.push_back("-Pexport_version_min_sdk=" + min_sdk_version); // argument to specify the min sdk. - cmdline.push_back("-Pexport_version_target_sdk=" + target_sdk_version); // argument to specify the target sdk. - cmdline.push_back("-Pexport_enabled_abis=" + enabled_abi_string); // argument to specify enabled ABIs. - cmdline.push_back("-Pplugins_local_binaries=" + local_plugins_binaries); // argument to specify the list of plugins local dependencies. - cmdline.push_back("-Pplugins_remote_binaries=" + remote_plugins_binaries); // argument to specify the list of plugins remote dependencies. - cmdline.push_back("-Pplugins_maven_repos=" + custom_maven_repos); // argument to specify the list of custom maven repos for the plugins dependencies. - cmdline.push_back("-Pperform_zipalign=" + zipalign_flag); // argument to specify whether the build should be zipaligned. - cmdline.push_back("-Pperform_signing=" + sign_flag); // argument to specify whether the build should be signed. - cmdline.push_back("-Ppandemonium_editor_version=" + String(VERSION_FULL_CONFIG)); - - // NOTE: The release keystore is not included in the verbose logging - // to avoid accidentally leaking sensitive information when sharing verbose logs for troubleshooting. - // Any non-sensitive additions to the command line arguments must be done above this section. - // Sensitive additions must be done below the logging statement. - print_verbose("Build Android project using gradle command: " + String("\n") + build_command + " " + join_list(cmdline, String(" "))); - - if (should_sign) { - if (p_debug) { - String debug_keystore = p_preset->get("keystore/debug"); - String debug_password = p_preset->get("keystore/debug_password"); - String debug_user = p_preset->get("keystore/debug_user"); - - if (debug_keystore.empty()) { - debug_keystore = EditorSettings::get_singleton()->get("export/android/debug_keystore"); - debug_password = EditorSettings::get_singleton()->get("export/android/debug_keystore_pass"); - debug_user = EditorSettings::get_singleton()->get("export/android/debug_keystore_user"); - } - if (debug_keystore.is_rel_path()) { - debug_keystore = OS::get_singleton()->get_resource_dir().plus_file(debug_keystore).simplify_path(); - } - if (!FileAccess::exists(debug_keystore)) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Could not find keystore, unable to export.")); - return ERR_FILE_CANT_OPEN; - } - - cmdline.push_back("-Pdebug_keystore_file=" + debug_keystore); // argument to specify the debug keystore file. - cmdline.push_back("-Pdebug_keystore_alias=" + debug_user); // argument to specify the debug keystore alias. - cmdline.push_back("-Pdebug_keystore_password=" + debug_password); // argument to specify the debug keystore password. - } else { - // Pass the release keystore info as well - String release_keystore = p_preset->get("keystore/release"); - String release_username = p_preset->get("keystore/release_user"); - String release_password = p_preset->get("keystore/release_password"); - if (release_keystore.is_rel_path()) { - release_keystore = OS::get_singleton()->get_resource_dir().plus_file(release_keystore).simplify_path(); - } - if (!FileAccess::exists(release_keystore)) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Could not find keystore, unable to export.")); - return ERR_FILE_CANT_OPEN; - } - - cmdline.push_back("-Prelease_keystore_file=" + release_keystore); // argument to specify the release keystore file. - cmdline.push_back("-Prelease_keystore_alias=" + release_username); // argument to specify the release keystore alias. - cmdline.push_back("-Prelease_keystore_password=" + release_password); // argument to specify the release keystore password. - } - } - - int result = EditorNode::get_singleton()->execute_and_show_output(TTR("Building Android Project (gradle)"), build_command, cmdline); - if (result != 0) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Building of Android project failed, check output for the error. Alternatively visit docs.pandemoniumengine.org for Android build documentation.")); - return ERR_CANT_CREATE; - } - - List copy_args; - String copy_command; - if (export_format == EXPORT_FORMAT_AAB) { - copy_command = vformat("copyAndRename%sAab", build_type); - } else if (export_format == EXPORT_FORMAT_APK) { - copy_command = vformat("copyAndRename%sApk", build_type); - } - - copy_args.push_back(copy_command); - - copy_args.push_back("-p"); // argument to specify the start directory. - copy_args.push_back(build_path); // start directory. - - String export_filename = p_path.get_file(); - String export_path = p_path.get_base_dir(); - if (export_path.is_rel_path()) { - export_path = OS::get_singleton()->get_resource_dir().plus_file(export_path); - } - export_path = ProjectSettings::get_singleton()->globalize_path(export_path).simplify_path(); - - copy_args.push_back("-Pexport_path=file:" + export_path); - copy_args.push_back("-Pexport_filename=" + export_filename); - - print_verbose("Copying Android binary using gradle command: " + String("\n") + build_command + " " + join_list(copy_args, String(" "))); - int copy_result = EditorNode::get_singleton()->execute_and_show_output(TTR("Moving output"), build_command, copy_args); - if (copy_result != 0) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Unable to copy and rename export file, check gradle project directory for outputs.")); - return ERR_CANT_CREATE; - } - - print_verbose("Successfully completed Android custom build."); - return OK; - } - // This is the start of the Legacy build system - print_verbose("Starting legacy build system.."); - if (p_debug) { - src_apk = p_preset->get("custom_template/debug"); - } else { - src_apk = p_preset->get("custom_template/release"); - } - - src_apk = src_apk.strip_edges(); - if (src_apk == "") { - if (p_debug) { - src_apk = find_export_template("android_debug.apk"); - } else { - src_apk = find_export_template("android_release.apk"); - } - if (src_apk == "") { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Package not found: \"%s\"."), src_apk)); - return ERR_FILE_NOT_FOUND; - } - } - - if (!DirAccess::exists(p_path.get_base_dir())) { - return ERR_FILE_BAD_PATH; - } - - FileAccess *src_f = nullptr; - zlib_filefunc_def io = zipio_create_io_from_file(&src_f); - - if (ep.step(TTR("Creating APK..."), 0)) { - return ERR_SKIP; - } - - unzFile pkg = unzOpen2(src_apk.utf8().get_data(), &io); - if (!pkg) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not find template APK to export: \"%s\"."), src_apk)); - return ERR_FILE_NOT_FOUND; - } - - int ret = unzGoToFirstFile(pkg); - - zlib_filefunc_def io2 = io; - FileAccess *dst_f = nullptr; - io2.opaque = &dst_f; - - String tmp_unaligned_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport-unaligned." + uitos(OS::get_singleton()->get_unix_time()) + ".apk"); - -#define CLEANUP_AND_RETURN(m_err) \ - { \ - DirAccess::remove_file_or_error(tmp_unaligned_path); \ - return m_err; \ - } - - zipFile unaligned_apk = zipOpen2(tmp_unaligned_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io2); - - String cmdline = p_preset->get("command_line/extra_args"); - - String version_name = p_preset->get("version/name"); - String package_name = p_preset->get("package/unique_name"); - - String apk_expansion_pkey = p_preset->get("apk_expansion/public_key"); - - Vector invalid_abis(enabled_abis); - while (ret == UNZ_OK) { - //get filename - unz_file_info info; - char fname[16384]; - ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, nullptr, 0, nullptr, 0); - - bool skip = false; - - String file = String::utf8(fname); - - Vector data; - data.resize(info.uncompressed_size); - - //read - unzOpenCurrentFile(pkg); - unzReadCurrentFile(pkg, data.ptrw(), data.size()); - unzCloseCurrentFile(pkg); - - //write - if (file == "AndroidManifest.xml") { - _fix_manifest(p_preset, data, p_give_internet); - } - if (file == "resources.arsc") { - _fix_resources(p_preset, data); - } - - // Process the splash image - if ((file == SPLASH_IMAGE_EXPORT_PATH || file == LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH) && splash_image.is_valid() && !splash_image->empty()) { - _load_image_data(splash_image, data); - } - - // Process the splash bg color image - if ((file == SPLASH_BG_COLOR_PATH || file == LEGACY_BUILD_SPLASH_BG_COLOR_PATH) && splash_bg_color_image.is_valid() && !splash_bg_color_image->empty()) { - _load_image_data(splash_bg_color_image, data); - } - - for (int i = 0; i < icon_densities_count; ++i) { - if (main_image.is_valid() && !main_image->empty()) { - if (file == launcher_icons[i].export_path) { - _process_launcher_icons(file, main_image, launcher_icons[i].dimensions, data); - } - } - if (foreground.is_valid() && !foreground->empty()) { - if (file == launcher_adaptive_icon_foregrounds[i].export_path) { - _process_launcher_icons(file, foreground, launcher_adaptive_icon_foregrounds[i].dimensions, data); - } - } - if (background.is_valid() && !background->empty()) { - if (file == launcher_adaptive_icon_backgrounds[i].export_path) { - _process_launcher_icons(file, background, launcher_adaptive_icon_backgrounds[i].dimensions, data); - } - } - } - - if (file.ends_with(".so")) { - bool enabled = false; - for (int i = 0; i < enabled_abis.size(); ++i) { - if (file.begins_with("lib/" + enabled_abis[i] + "/")) { - invalid_abis.erase(enabled_abis[i]); - enabled = true; - break; - } - } - if (!enabled) { - skip = true; - } - } - - if (file.begins_with("META-INF") && should_sign) { - skip = true; - } - - if (!skip) { - print_line("ADDING: " + file); - - // Respect decision on compression made by AAPT for the export template - const bool uncompressed = info.compression_method == 0; - - zip_fileinfo zipfi = get_zip_fileinfo(); - - zipOpenNewFileInZip(unaligned_apk, - file.utf8().get_data(), - &zipfi, - nullptr, - 0, - nullptr, - 0, - nullptr, - uncompressed ? 0 : Z_DEFLATED, - Z_DEFAULT_COMPRESSION); - - zipWriteInFileInZip(unaligned_apk, data.ptr(), data.size()); - zipCloseFileInZip(unaligned_apk); - } - - ret = unzGoToNextFile(pkg); - } - - if (!invalid_abis.empty()) { - String unsupported_arch = String(", ").join(invalid_abis); - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Missing libraries in the export template for the selected architectures: %s. Please build a template with all required libraries, or uncheck the missing architectures in the export preset."), unsupported_arch)); - CLEANUP_AND_RETURN(ERR_FILE_NOT_FOUND); - } - - if (ep.step(TTR("Adding files..."), 1)) { - CLEANUP_AND_RETURN(ERR_SKIP); - } - err = OK; - - if (p_flags & DEBUG_FLAG_DUMB_CLIENT) { - APKExportData ed; - ed.ep = &ep; - ed.apk = unaligned_apk; - err = export_project_files(p_preset, ignore_apk_file, &ed, save_apk_so); - } else { - if (apk_expansion) { - err = save_apk_expansion_file(p_preset, p_path); - if (err != OK) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not write expansion package file!")); - return err; - } - } else { - APKExportData ed; - ed.ep = &ep; - ed.apk = unaligned_apk; - err = export_project_files(p_preset, save_apk_file, &ed, save_apk_so); - } - } - - if (err != OK) { - unzClose(pkg); - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not export project files."))); - CLEANUP_AND_RETURN(ERR_SKIP); - } - - zip_fileinfo zipfi = get_zip_fileinfo(); - zipOpenNewFileInZip(unaligned_apk, - "assets/_cl_", - &zipfi, - nullptr, - 0, - nullptr, - 0, - nullptr, - 0, // No compress (little size gain and potentially slower startup) - Z_DEFAULT_COMPRESSION); - zipWriteInFileInZip(unaligned_apk, command_line_flags.ptr(), command_line_flags.size()); - zipCloseFileInZip(unaligned_apk); - - zipClose(unaligned_apk, nullptr); - unzClose(pkg); - - if (err != OK) { - CLEANUP_AND_RETURN(err); - } - - // Let's zip-align (must be done before signing) - - static const int ZIP_ALIGNMENT = 4; - - // If we're not signing the apk, then the next step should be the last. - const int next_step = should_sign ? 103 : 105; - if (ep.step(TTR("Aligning APK..."), next_step)) { - CLEANUP_AND_RETURN(ERR_SKIP); - } - - unzFile tmp_unaligned = unzOpen2(tmp_unaligned_path.utf8().get_data(), &io); - if (!tmp_unaligned) { - add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not unzip temporary unaligned APK."))); - CLEANUP_AND_RETURN(ERR_FILE_NOT_FOUND); - } - - ret = unzGoToFirstFile(tmp_unaligned); - - io2 = io; - dst_f = nullptr; - io2.opaque = &dst_f; - zipFile final_apk = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io2); - - // Take files from the unaligned APK and write them out to the aligned one - // in raw mode, i.e. not uncompressing and recompressing, aligning them as needed, - // following what is done in https://github.com/android/platform_build/blob/master/tools/zipalign/ZipAlign.cpp - int bias = 0; - while (ret == UNZ_OK) { - unz_file_info info; - memset(&info, 0, sizeof(info)); - - char fname[16384]; - char extra[16384]; - ret = unzGetCurrentFileInfo(tmp_unaligned, &info, fname, 16384, extra, 16384 - ZIP_ALIGNMENT, nullptr, 0); - - String file = String::utf8(fname); - - Vector data; - data.resize(info.compressed_size); - - // read - int method, level; - unzOpenCurrentFile2(tmp_unaligned, &method, &level, 1); // raw read - long file_offset = unzGetCurrentFileZStreamPos64(tmp_unaligned); - unzReadCurrentFile(tmp_unaligned, data.ptrw(), data.size()); - unzCloseCurrentFile(tmp_unaligned); - - // align - int padding = 0; - if (!info.compression_method) { - // Uncompressed file => Align - long new_offset = file_offset + bias; - padding = (ZIP_ALIGNMENT - (new_offset % ZIP_ALIGNMENT)) % ZIP_ALIGNMENT; - } - - memset(extra + info.size_file_extra, 0, padding); - - zip_fileinfo fileinfo = get_zip_fileinfo(); - zipOpenNewFileInZip2(final_apk, - file.utf8().get_data(), - &fileinfo, - extra, - info.size_file_extra + padding, - nullptr, - 0, - nullptr, - method, - level, - 1); // raw write - zipWriteInFileInZip(final_apk, data.ptr(), data.size()); - zipCloseFileInZipRaw(final_apk, info.uncompressed_size, info.crc); - - bias += padding; - - ret = unzGoToNextFile(tmp_unaligned); - } - - zipClose(final_apk, nullptr); - unzClose(tmp_unaligned); - - if (should_sign) { - // Signing must be done last as any additional modifications to the - // file will invalidate the signature. - err = sign_apk(p_preset, p_debug, p_path, ep); - if (err != OK) { - CLEANUP_AND_RETURN(err); - } - } - - CLEANUP_AND_RETURN(OK); -} - -void EditorExportPlatformAndroid::get_platform_features(List *r_features) { - r_features->push_back("mobile"); - r_features->push_back("Android"); -} - -void EditorExportPlatformAndroid::resolve_platform_feature_priorities(const Ref &p_preset, RBSet &p_features) { -} - -EditorExportPlatformAndroid::EditorExportPlatformAndroid() { - Ref img = memnew(Image(_android_logo)); - logo.instance(); - logo->create_from_image(img); - - img = Ref(memnew(Image(_android_run_icon))); - run_icon.instance(); - run_icon->create_from_image(img); - - devices_changed.set(); - plugins_changed.set(); -#ifndef ANDROID_ENABLED - check_for_changes_thread.start(_check_for_changes_poll_thread, this); -#endif -} - -EditorExportPlatformAndroid::~EditorExportPlatformAndroid() { -#ifndef ANDROID_ENABLED - quit_request.set(); - check_for_changes_thread.wait_to_finish(); -#endif -} diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h deleted file mode 100644 index 0fd0d62..0000000 --- a/platform/android/export/export_plugin.h +++ /dev/null @@ -1,261 +0,0 @@ -/*************************************************************************/ -/* export_plugin.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "core/config/project_settings.h" -#include "core/io/image_loader.h" -#include "core/io/json.h" -#include "core/io/marshalls.h" -#include "core/io/zip_io.h" -#include "core/os/dir_access.h" -#include "core/os/file_access.h" -#include "core/os/os.h" -#include "core/os/safe_refcount.h" -#include "core/version.h" -#include "drivers/png/png_driver_common.h" -#include "editor/editor_export.h" -#include "editor/editor_log.h" -#include "editor/editor_node.h" -#include "editor/editor_settings.h" -#include "platform/android/logo.gen.h" -#include "platform/android/run_icon.gen.h" - -#include "gradle_export_util.h" -#include "pandemonium_plugin_config.h" - -#include - -const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH( - - - - - - -)SPLASH"; - -struct LauncherIcon { - const char *export_path; - int dimensions; -}; - -class EditorExportPlatformAndroid : public EditorExportPlatform { - GDCLASS(EditorExportPlatformAndroid, EditorExportPlatform); - - Ref logo; - Ref run_icon; - - struct Device { - String id; - String name; - String description; - int api_level; - }; - - struct APKExportData { - zipFile apk; - EditorProgress *ep; - }; - - Vector plugins; - String last_plugin_names; - uint64_t last_custom_build_time = 0; - SafeFlag plugins_changed; - Mutex plugins_lock; - Vector devices; - SafeFlag devices_changed; - Mutex device_lock; - -#ifndef ANDROID_ENABLED - Thread check_for_changes_thread; - SafeFlag quit_request; - - static void _check_for_changes_poll_thread(void *ud); -#endif - - String get_project_name(const String &p_name) const; - - String get_package_name(const String &p_package) const; - - String get_assets_directory(const Ref &p_preset, int p_export_format) const; - - bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const; - - static bool _should_compress_asset(const String &p_path, const Vector &p_data); - - static zip_fileinfo get_zip_fileinfo(); - - static Vector get_abis(); - - /// List the gdap files in the directory specified by the p_path parameter. - static Vector list_gdap_files(const String &p_path); - - static Vector get_plugins(); - - static Vector get_enabled_plugins(const Ref &p_presets); - - static Error store_in_apk(APKExportData *ed, const String &p_path, const Vector &p_data, int compression_method = Z_DEFLATED); - - static Error save_apk_so(void *p_userdata, const SharedObject &p_so); - - static Error save_apk_file(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total); - - static Error ignore_apk_file(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total); - - static Error copy_gradle_so(void *p_userdata, const SharedObject &p_so); - - bool _has_read_write_storage_permission(const Vector &p_permissions); - - bool _has_manage_external_storage_permission(const Vector &p_permissions); - - void _get_permissions(const Ref &p_preset, bool p_give_internet, Vector &r_permissions); - - void _write_tmp_manifest(const Ref &p_preset, bool p_give_internet, bool p_debug); - - void _fix_manifest(const Ref &p_preset, Vector &p_manifest, bool p_give_internet); - - static String _parse_string(const uint8_t *p_bytes, bool p_utf8); - - void _fix_resources(const Ref &p_preset, Vector &r_manifest); - - void _load_image_data(const Ref &p_splash_image, Vector &p_data); - - void _process_launcher_icons(const String &p_file_name, const Ref &p_source_image, int dimension, Vector &p_data); - - String load_splash_refs(Ref &splash_image, Ref &splash_bg_color_image); - - void load_icon_refs(const Ref &p_preset, Ref &icon, Ref &foreground, Ref &background); - - void store_image(const LauncherIcon launcher_icon, const Vector &data); - - void store_image(const String &export_path, const Vector &data); - - void _copy_icons_to_gradle_project(const Ref &p_preset, - const String &processed_splash_config_xml, - const Ref &splash_image, - const Ref &splash_bg_color_image, - const Ref &main_image, - const Ref &foreground, - const Ref &background); - - static Vector get_enabled_abis(const Ref &p_preset); - -public: - typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total); - -public: - virtual void get_preset_features(const Ref &p_preset, List *r_features); - - virtual void get_export_options(List *r_options); - - virtual String get_name() const; - - virtual String get_os_name() const; - - virtual Ref get_logo() const; - - virtual bool should_update_export_options(); - - virtual bool poll_export(); - - virtual int get_options_count() const; - - virtual String get_options_tooltip() const; - - virtual String get_option_label(int p_index) const; - - virtual String get_option_tooltip(int p_index) const; - - virtual Error run(const Ref &p_preset, int p_device, int p_debug_flags); - - virtual Ref get_run_icon() const; - - static String get_adb_path(); - - static String get_apksigner_path(); - - virtual bool has_valid_export_configuration(const Ref &p_preset, String &r_error, bool &r_missing_templates) const; - virtual bool has_valid_project_configuration(const Ref &p_preset, String &r_error) const; - - virtual List get_binary_extensions(const Ref &p_preset) const; - - void _update_custom_build_project(); - - inline bool is_clean_build_required(Vector enabled_plugins) { - String plugin_names = PluginConfigAndroid::get_plugins_names(enabled_plugins); - bool first_build = last_custom_build_time == 0; - bool have_plugins_changed = false; - - if (!first_build) { - have_plugins_changed = plugin_names != last_plugin_names; - if (!have_plugins_changed) { - for (int i = 0; i < enabled_plugins.size(); i++) { - if (enabled_plugins.get(i).last_updated > last_custom_build_time) { - have_plugins_changed = true; - break; - } - } - } - } - - last_custom_build_time = OS::get_singleton()->get_unix_time(); - last_plugin_names = plugin_names; - - return have_plugins_changed || first_build; - } - - String get_apk_expansion_fullpath(const Ref &p_preset, const String &p_path); - - Error save_apk_expansion_file(const Ref &p_preset, const String &p_path); - - void get_command_line_flags(const Ref &p_preset, const String &p_path, int p_flags, Vector &r_command_line_flags); - - Error sign_apk(const Ref &p_preset, bool p_debug, const String &export_path, EditorProgress &ep); - - void _clear_assets_directory(); - - void _remove_copied_libs(); - - String join_list(List parts, const String &separator) const; - - virtual Error export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags = 0); - - Error export_project_helper(const Ref &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags); - - virtual void get_platform_features(List *r_features); - - virtual void resolve_platform_feature_priorities(const Ref &p_preset, RBSet &p_features); - - EditorExportPlatformAndroid(); - - ~EditorExportPlatformAndroid(); -}; diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp deleted file mode 100644 index d93c459..0000000 --- a/platform/android/export/gradle_export_util.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/*************************************************************************/ -/* gradle_export_util.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "gradle_export_util.h" - -#include "core/config/project_settings.h" - -int _get_android_orientation_value(OS::ScreenOrientation screen_orientation) { - switch (screen_orientation) { - case OS::SCREEN_PORTRAIT: - return 1; - case OS::SCREEN_REVERSE_LANDSCAPE: - return 8; - case OS::SCREEN_REVERSE_PORTRAIT: - return 9; - case OS::SCREEN_SENSOR_LANDSCAPE: - return 11; - case OS::SCREEN_SENSOR_PORTRAIT: - return 12; - case OS::SCREEN_SENSOR: - return 13; - case OS::SCREEN_LANDSCAPE: - default: - return 0; - } -} - -String _get_android_orientation_label(OS::ScreenOrientation screen_orientation) { - switch (screen_orientation) { - case OS::SCREEN_PORTRAIT: - return "portrait"; - case OS::SCREEN_REVERSE_LANDSCAPE: - return "reverseLandscape"; - case OS::SCREEN_REVERSE_PORTRAIT: - return "reversePortrait"; - case OS::SCREEN_SENSOR_LANDSCAPE: - return "userLandscape"; - case OS::SCREEN_SENSOR_PORTRAIT: - return "userPortrait"; - case OS::SCREEN_SENSOR: - return "fullUser"; - case OS::SCREEN_LANDSCAPE: - default: - return "landscape"; - } -} - -// Utility method used to create a directory. -Error create_directory(const String &p_dir) { - if (!DirAccess::exists(p_dir)) { - DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_RESOURCES); - ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'."); - Error err = filesystem_da->make_dir_recursive(p_dir); - ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'."); - memdelete(filesystem_da); - } - return OK; -} - -// Writes p_data into a file at p_path, creating directories if necessary. -// Note: this will overwrite the file at p_path if it already exists. -Error store_file_at_path(const String &p_path, const Vector &p_data) { - String dir = p_path.get_base_dir(); - Error err = create_directory(dir); - if (err != OK) { - return err; - } - FileAccess *fa = FileAccess::open(p_path, FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create file '" + p_path + "'."); - fa->store_buffer(p_data.ptr(), p_data.size()); - memdelete(fa); - return OK; -} - -// Writes string p_data into a file at p_path, creating directories if necessary. -// Note: this will overwrite the file at p_path if it already exists. -Error store_string_at_path(const String &p_path, const String &p_data) { - String dir = p_path.get_base_dir(); - Error err = create_directory(dir); - if (err != OK) { - if (OS::get_singleton()->is_stdout_verbose()) { - print_error("Unable to write data into " + p_path); - } - return err; - } - FileAccess *fa = FileAccess::open(p_path, FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create file '" + p_path + "'."); - fa->store_string(p_data); - memdelete(fa); - return OK; -} - -// Implementation of EditorExportSaveFunction. -// This method will only be called as an input to export_project_files. -// It is used by the export_project_files method to save all the asset files into the gradle project. -// It's functionality mirrors that of the method save_apk_file. -// This method will be called ONLY when custom build is enabled. -Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total) { - CustomExportData *export_data = (CustomExportData *)p_userdata; - String dst_path = p_path.replace_first("res://", export_data->assets_directory + "/"); - print_verbose("Saving project files from " + p_path + " into " + dst_path); - Error err = store_file_at_path(dst_path, p_data); - return err; -} - -String _android_xml_escape(const String &p_string) { - // Android XML requires strings to be both valid XML (`xml_escape()`) but also - // to escape characters which are valid XML but have special meaning in Android XML. - // https://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling - // Note: Didn't handle U+XXXX unicode chars, could be done if needed. - return p_string - .replace("@", "\\@") - .replace("?", "\\?") - .replace("'", "\\'") - .replace("\"", "\\\"") - .replace("\n", "\\n") - .replace("\t", "\\t") - .xml_escape(false); -} - -// Creates strings.xml files inside the gradle project for different locales. -Error _create_project_name_strings_files(const Ref &p_preset, const String &project_name) { - print_verbose("Creating strings resources for supported locales for project " + project_name); - // Stores the string into the default values directory. - String processed_default_xml_string = vformat(pandemonium_project_name_xml_string, _android_xml_escape(project_name)); - store_string_at_path("res://android/build/res/values/pandemonium_project_name_string.xml", processed_default_xml_string); - - // Searches the Gradle project res/ directory to find all supported locales - DirAccessRef da = DirAccess::open("res://android/build/res"); - if (!da) { - if (OS::get_singleton()->is_stdout_verbose()) { - print_error("Unable to open Android resources directory."); - } - return ERR_CANT_OPEN; - } - da->list_dir_begin(); - while (true) { - String file = da->get_next(); - if (file == "") { - break; - } - if (!file.begins_with("values-")) { - // NOTE: This assumes all directories that start with "values-" are for localization. - continue; - } - String locale = file.replace("values-", "").replace("-r", "_"); - String property_name = "application/config/name_" + locale; - String locale_directory = "res://android/build/res/" + file + "/pandemonium_project_name_string.xml"; - if (ProjectSettings::get_singleton()->has_setting(property_name)) { - String locale_project_name = ProjectSettings::get_singleton()->get(property_name); - String processed_xml_string = vformat(pandemonium_project_name_xml_string, _android_xml_escape(locale_project_name)); - print_verbose("Storing project name for locale " + locale + " under " + locale_directory); - store_string_at_path(locale_directory, processed_xml_string); - } else { - // TODO: Once the legacy build system is deprecated we don't need to have xml files for this else branch - store_string_at_path(locale_directory, processed_default_xml_string); - } - } - da->list_dir_end(); - return OK; -} - -String bool_to_string(bool v) { - return v ? "true" : "false"; -} - -String _get_gles_tag() { - bool min_gles3 = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name") == "GLES3" && - !ProjectSettings::get_singleton()->get("rendering/quality/driver/fallback_to_gles2"); - return min_gles3 ? " \n" : ""; -} - -String _get_screen_sizes_tag(const Ref &p_preset) { - String manifest_screen_sizes = " get(feature_name)); - String xml_entry = vformat("\n android:%sScreens=\"%s\"", sizes[i], feature_support); - manifest_screen_sizes += xml_entry; - } - manifest_screen_sizes += " />\n"; - return manifest_screen_sizes; -} - -String _get_activity_tag(const Ref &p_preset) { - String orientation = _get_android_orientation_label( - OS::get_singleton()->get_screen_orientation_from_string(GLOBAL_GET("display/window/handheld/orientation"))); - String manifest_activity_text = vformat( - " \n", - bool_to_string(p_preset->get("package/exclude_from_recents")), - orientation, - bool_to_string(bool(GLOBAL_GET("display/window/size/resizable")))); - manifest_activity_text += " \n"; - manifest_activity_text += " \n"; - return manifest_activity_text; -} - -String _get_application_tag(const Ref &p_preset, bool p_has_read_write_storage_permission) { - String manifest_application_text = vformat( - " \n\n", - bool_to_string(p_preset->get("user_data_backup/allow")), - bool_to_string(p_preset->get("package/classify_as_game")), - bool_to_string(p_preset->get("package/retain_data_on_uninstall")), - bool_to_string(p_has_read_write_storage_permission)); - - manifest_application_text += " \n"; - manifest_application_text += _get_activity_tag(p_preset); - manifest_application_text += " \n"; - return manifest_application_text; -} diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h deleted file mode 100644 index 7b0d045..0000000 --- a/platform/android/export/gradle_export_util.h +++ /dev/null @@ -1,88 +0,0 @@ -/*************************************************************************/ -/* gradle_export_util.h */ -/*************************************************************************/ -/* This file is part of: */ -/* PANDEMONIUM ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 PANDEMONIUM_GRADLE_EXPORT_UTIL_H -#define PANDEMONIUM_GRADLE_EXPORT_UTIL_H - -#include "core/io/zip_io.h" -#include "core/os/dir_access.h" -#include "core/os/file_access.h" -#include "core/os/os.h" -#include "editor/editor_export.h" - -const String pandemonium_project_name_xml_string = R"( - - - %s - -)"; - -struct CustomExportData { - String assets_directory; - bool debug; - Vector libs; -}; - -int _get_android_orientation_value(OS::ScreenOrientation screen_orientation); - -String _get_android_orientation_label(OS::ScreenOrientation screen_orientation); - -// Utility method used to create a directory. -Error create_directory(const String &p_dir); - -// Writes p_data into a file at p_path, creating directories if necessary. -// Note: this will overwrite the file at p_path if it already exists. -Error store_file_at_path(const String &p_path, const Vector &p_data); - -// Writes string p_data into a file at p_path, creating directories if necessary. -// Note: this will overwrite the file at p_path if it already exists. -Error store_string_at_path(const String &p_path, const String &p_data); - -// Implementation of EditorExportSaveFunction. -// This method will only be called as an input to export_project_files. -// It is used by the export_project_files method to save all the asset files into the gradle project. -// It's functionality mirrors that of the method save_apk_file. -// This method will be called ONLY when custom build is enabled. -Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total); - -// Creates strings.xml files inside the gradle project for different locales. -Error _create_project_name_strings_files(const Ref &p_preset, const String &project_name); - -String bool_to_string(bool v); - -String _get_gles_tag(); - -String _get_screen_sizes_tag(const Ref &p_preset); - -String _get_activity_tag(const Ref &p_preset); - -String _get_application_tag(const Ref &p_preset, bool p_has_read_write_storage_permission); - -#endif //PANDEMONIUM_GRADLE_EXPORT_UTIL_H diff --git a/platform/android/export/pandemonium_plugin_config.cpp b/platform/android/export/pandemonium_plugin_config.cpp deleted file mode 100644 index 234f974..0000000 --- a/platform/android/export/pandemonium_plugin_config.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/*************************************************************************/ -/* pandemonium_plugin_config.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "pandemonium_plugin_config.h" - -const char *PluginConfigAndroid::PLUGIN_CONFIG_EXT = ".gdap"; - -const char *PluginConfigAndroid::CONFIG_SECTION = "config"; -const char *PluginConfigAndroid::CONFIG_NAME_KEY = "name"; -const char *PluginConfigAndroid::CONFIG_BINARY_TYPE_KEY = "binary_type"; -const char *PluginConfigAndroid::CONFIG_BINARY_KEY = "binary"; - -const char *PluginConfigAndroid::DEPENDENCIES_SECTION = "dependencies"; -const char *PluginConfigAndroid::DEPENDENCIES_LOCAL_KEY = "local"; -const char *PluginConfigAndroid::DEPENDENCIES_REMOTE_KEY = "remote"; -const char *PluginConfigAndroid::DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY = "custom_maven_repos"; - -const char *PluginConfigAndroid::BINARY_TYPE_LOCAL = "local"; -const char *PluginConfigAndroid::BINARY_TYPE_REMOTE = "remote"; - -const char *PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR = "|"; - -/* - * Set of prebuilt plugins. - * Currently unused, this is just for future reference: - */ -// static const PluginConfigAndroid MY_PREBUILT_PLUGIN = { -// /*.valid_config =*/true, -// /*.last_updated =*/0, -// /*.name =*/"PandemoniumPayment", -// /*.binary_type =*/"local", -// /*.binary =*/"res://android/build/libs/plugins/PandemoniumPayment.release.aar", -// /*.local_dependencies =*/{}, -// /*.remote_dependencies =*/String("com.android.billingclient:billing:2.2.1").split("|"), -// /*.custom_maven_repos =*/{} -// }; - -String PluginConfigAndroid::resolve_local_dependency_path(String plugin_config_dir, String dependency_path) { - String absolute_path; - if (!dependency_path.empty()) { - if (dependency_path.is_abs_path()) { - absolute_path = ProjectSettings::get_singleton()->globalize_path(dependency_path); - } else { - absolute_path = plugin_config_dir.plus_file(dependency_path); - } - } - - return absolute_path; -} - -PluginConfigAndroid PluginConfigAndroid::resolve_prebuilt_plugin(PluginConfigAndroid prebuilt_plugin, String plugin_config_dir) { - PluginConfigAndroid resolved = prebuilt_plugin; - resolved.binary = resolved.binary_type == PluginConfigAndroid::BINARY_TYPE_LOCAL ? resolve_local_dependency_path(plugin_config_dir, prebuilt_plugin.binary) : prebuilt_plugin.binary; - if (!prebuilt_plugin.local_dependencies.empty()) { - resolved.local_dependencies.clear(); - for (int i = 0; i < prebuilt_plugin.local_dependencies.size(); i++) { - resolved.local_dependencies.push_back(resolve_local_dependency_path(plugin_config_dir, prebuilt_plugin.local_dependencies[i])); - } - } - return resolved; -} - -Vector PluginConfigAndroid::get_prebuilt_plugins(String plugins_base_dir) { - Vector prebuilt_plugins; - // prebuilt_plugins.push_back(resolve_prebuilt_plugin(MY_PREBUILT_PLUGIN, plugins_base_dir)); - return prebuilt_plugins; -} - -bool PluginConfigAndroid::is_plugin_config_valid(PluginConfigAndroid plugin_config) { - bool valid_name = !plugin_config.name.empty(); - bool valid_binary_type = plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_LOCAL || - plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_REMOTE; - - bool valid_binary = false; - if (valid_binary_type) { - valid_binary = !plugin_config.binary.empty() && - (plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_REMOTE || - FileAccess::exists(plugin_config.binary)); - } - - bool valid_local_dependencies = true; - if (!plugin_config.local_dependencies.empty()) { - for (int i = 0; i < plugin_config.local_dependencies.size(); i++) { - if (!FileAccess::exists(plugin_config.local_dependencies[i])) { - valid_local_dependencies = false; - break; - } - } - } - return valid_name && valid_binary && valid_binary_type && valid_local_dependencies; -} - -uint64_t PluginConfigAndroid::get_plugin_modification_time(const PluginConfigAndroid &plugin_config, const String &config_path) { - uint64_t last_modified = FileAccess::get_modified_time(config_path); - last_modified = MAX(last_modified, FileAccess::get_modified_time(plugin_config.binary)); - - for (int i = 0; i < plugin_config.local_dependencies.size(); i++) { - String local_dependency = plugin_config.local_dependencies.get(i); - last_modified = MAX(last_modified, FileAccess::get_modified_time(local_dependency)); - } - - return last_modified; -} - -PluginConfigAndroid PluginConfigAndroid::load_plugin_config(Ref config_file, const String &path) { - PluginConfigAndroid plugin_config = {}; - - if (config_file.is_valid()) { - Error err = config_file->load(path); - if (err == OK) { - String config_base_dir = path.get_base_dir(); - - plugin_config.name = config_file->get_value(PluginConfigAndroid::CONFIG_SECTION, PluginConfigAndroid::CONFIG_NAME_KEY, String()); - plugin_config.binary_type = config_file->get_value(PluginConfigAndroid::CONFIG_SECTION, PluginConfigAndroid::CONFIG_BINARY_TYPE_KEY, String()); - - String binary_path = config_file->get_value(PluginConfigAndroid::CONFIG_SECTION, PluginConfigAndroid::CONFIG_BINARY_KEY, String()); - plugin_config.binary = plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_LOCAL ? resolve_local_dependency_path(config_base_dir, binary_path) : binary_path; - - if (config_file->has_section(PluginConfigAndroid::DEPENDENCIES_SECTION)) { - Vector local_dependencies_paths = config_file->get_value(PluginConfigAndroid::DEPENDENCIES_SECTION, PluginConfigAndroid::DEPENDENCIES_LOCAL_KEY, Vector()); - if (!local_dependencies_paths.empty()) { - for (int i = 0; i < local_dependencies_paths.size(); i++) { - plugin_config.local_dependencies.push_back(resolve_local_dependency_path(config_base_dir, local_dependencies_paths[i])); - } - } - - plugin_config.remote_dependencies = config_file->get_value(PluginConfigAndroid::DEPENDENCIES_SECTION, PluginConfigAndroid::DEPENDENCIES_REMOTE_KEY, Vector()); - plugin_config.custom_maven_repos = config_file->get_value(PluginConfigAndroid::DEPENDENCIES_SECTION, PluginConfigAndroid::DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY, Vector()); - } - - plugin_config.valid_config = is_plugin_config_valid(plugin_config); - plugin_config.last_updated = get_plugin_modification_time(plugin_config, path); - } - } - - return plugin_config; -} - -String PluginConfigAndroid::get_plugins_binaries(String type, Vector plugins_configs) { - String plugins_binaries; - if (!plugins_configs.empty()) { - Vector binaries; - for (int i = 0; i < plugins_configs.size(); i++) { - PluginConfigAndroid config = plugins_configs[i]; - if (!config.valid_config) { - continue; - } - - if (config.binary_type == type) { - binaries.push_back(config.binary); - } - - if (type == PluginConfigAndroid::BINARY_TYPE_LOCAL) { - binaries.append_array(config.local_dependencies); - } - - if (type == PluginConfigAndroid::BINARY_TYPE_REMOTE) { - binaries.append_array(config.remote_dependencies); - } - } - - plugins_binaries = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(binaries); - } - - return plugins_binaries; -} - -String PluginConfigAndroid::get_plugins_custom_maven_repos(Vector plugins_configs) { - String maven_repos; - if (!plugins_configs.empty()) { - Vector repos_urls; - for (int i = 0; i < plugins_configs.size(); i++) { - PluginConfigAndroid config = plugins_configs[i]; - if (!config.valid_config) { - continue; - } - - repos_urls.append_array(config.custom_maven_repos); - } - - maven_repos = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(repos_urls); - } - return maven_repos; -} - -String PluginConfigAndroid::get_plugins_names(Vector plugins_configs) { - String plugins_names; - if (!plugins_configs.empty()) { - Vector names; - for (int i = 0; i < plugins_configs.size(); i++) { - PluginConfigAndroid config = plugins_configs[i]; - if (!config.valid_config) { - continue; - } - - names.push_back(config.name); - } - plugins_names = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(names); - } - - return plugins_names; -} diff --git a/platform/android/export/pandemonium_plugin_config.h b/platform/android/export/pandemonium_plugin_config.h deleted file mode 100644 index f1afa39..0000000 --- a/platform/android/export/pandemonium_plugin_config.h +++ /dev/null @@ -1,106 +0,0 @@ -/*************************************************************************/ -/* pandemonium_plugin_config.h */ -/*************************************************************************/ -/* This file is part of: */ -/* PANDEMONIUM ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 ANDROID_PANDEMONIUM_PLUGIN_CONFIG_H -#define ANDROID_PANDEMONIUM_PLUGIN_CONFIG_H - -#include "core/error/error_list.h" -#include "core/io/config_file.h" -#include "core/config/project_settings.h" -#include "core/string/ustring.h" - -/* - The `config` section and fields are required and defined as follow: -- **name**: name of the plugin. -- **binary_type**: can be either `local` or `remote`. The type affects the **binary** field. -- **binary**: - - if **binary_type** is `local`, then this should be the filename of the plugin `aar` file in the `res://android/plugins` directory (e.g: `MyPlugin.aar`). - - if **binary_type** is `remote`, then this should be a declaration for a remote gradle binary (e.g: "org.pandemonium.example:my-plugin:0.0.0"). - -The `dependencies` section and fields are optional and defined as follow: -- **local**: contains a list of local `.aar` binary files the plugin depends on. The local binary dependencies must also be located in the `res://android/plugins` directory. -- **remote**: contains a list of remote binary gradle dependencies for the plugin. -- **custom_maven_repos**: contains a list of urls specifying custom maven repos required for the plugin's dependencies. - - See https://github.com/pandemoniumengine/pandemonium/issues/38157#issuecomment-618773871 - */ -struct PluginConfigAndroid { - static const char *PLUGIN_CONFIG_EXT; - - static const char *CONFIG_SECTION; - static const char *CONFIG_NAME_KEY; - static const char *CONFIG_BINARY_TYPE_KEY; - static const char *CONFIG_BINARY_KEY; - - static const char *DEPENDENCIES_SECTION; - static const char *DEPENDENCIES_LOCAL_KEY; - static const char *DEPENDENCIES_REMOTE_KEY; - static const char *DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY; - - static const char *BINARY_TYPE_LOCAL; - static const char *BINARY_TYPE_REMOTE; - - static const char *PLUGIN_VALUE_SEPARATOR; - - // Set to true when the config file is properly loaded. - bool valid_config = false; - // Unix timestamp of last change to this plugin. - uint64_t last_updated = 0; - - // Required config section - String name; - String binary_type; - String binary; - - // Optional dependencies section - Vector local_dependencies; - Vector remote_dependencies; - Vector custom_maven_repos; - - static String resolve_local_dependency_path(String plugin_config_dir, String dependency_path); - - static PluginConfigAndroid resolve_prebuilt_plugin(PluginConfigAndroid prebuilt_plugin, String plugin_config_dir); - - static Vector get_prebuilt_plugins(String plugins_base_dir); - - static bool is_plugin_config_valid(PluginConfigAndroid plugin_config); - - static uint64_t get_plugin_modification_time(const PluginConfigAndroid &plugin_config, const String &config_path); - - static PluginConfigAndroid load_plugin_config(Ref config_file, const String &path); - - static String get_plugins_binaries(String type, Vector plugins_configs); - - static String get_plugins_custom_maven_repos(Vector plugins_configs); - - static String get_plugins_names(Vector plugins_configs); -}; - -#endif // ANDROID_PANDEMONIUM_PLUGIN_CONFIG_H diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp deleted file mode 100644 index b16353e..0000000 --- a/platform/android/file_access_android.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/*************************************************************************/ -/* file_access_android.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "file_access_android.h" -#include "core/string/print_string.h" - -AAssetManager *FileAccessAndroid::asset_manager = NULL; - -String FileAccessAndroid::get_path() const { - return path_src; -} - -String FileAccessAndroid::get_path_absolute() const { - return absolute_path; -} - -Error FileAccessAndroid::_open(const String &p_path, int p_mode_flags) { - path_src = p_path; - - String path = fix_path(p_path).simplify_path(); - absolute_path = path; - - if (path.begins_with("/")) { - path = path.substr(1, path.length()); - } else if (path.begins_with("res://")) { - path = path.substr(6, path.length()); - } - - ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, ERR_UNAVAILABLE); //can't write on android.. - a = AAssetManager_open(asset_manager, path.utf8().get_data(), AASSET_MODE_STREAMING); - - if (!a) { - return ERR_CANT_OPEN; - } - - //ERR_FAIL_COND_V(!a,ERR_FILE_NOT_FOUND); - len = AAsset_getLength(a); - pos = 0; - eof = false; - - return OK; -} - -void FileAccessAndroid::close() { - if (!a) { - return; - } - - AAsset_close(a); - a = NULL; -} - -bool FileAccessAndroid::is_open() const { - return a != NULL; -} - -void FileAccessAndroid::seek(uint64_t p_position) { - ERR_FAIL_COND(!a); - - AAsset_seek(a, p_position, SEEK_SET); - pos = p_position; - if (pos > len) { - pos = len; - eof = true; - } else { - eof = false; - } -} - -void FileAccessAndroid::seek_end(int64_t p_position) { - ERR_FAIL_COND(!a); - AAsset_seek(a, p_position, SEEK_END); - pos = len + p_position; -} - -uint64_t FileAccessAndroid::get_position() const { - return pos; -} - -uint64_t FileAccessAndroid::get_len() const { - return len; -} - -bool FileAccessAndroid::eof_reached() const { - return eof; -} - -uint8_t FileAccessAndroid::get_8() const { - if (pos >= len) { - eof = true; - return 0; - } - - uint8_t byte; - AAsset_read(a, &byte, 1); - pos++; - return byte; -} - -uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const { - ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); - - int r = AAsset_read(a, p_dst, p_length); - - if (pos + p_length > len) { - eof = true; - } - - if (r >= 0) { - pos += r; - if (pos > len) { - pos = len; - } - } - return r; -} - -Error FileAccessAndroid::get_error() const { - return eof ? ERR_FILE_EOF : OK; // not sure what else it may happen -} - -void FileAccessAndroid::flush() { - ERR_FAIL(); -} - -void FileAccessAndroid::store_8(uint8_t p_dest) { - ERR_FAIL(); -} - -bool FileAccessAndroid::file_exists(const String &p_path) { - String path = fix_path(p_path).simplify_path(); - if (path.begins_with("/")) - path = path.substr(1, path.length()); - else if (path.begins_with("res://")) - path = path.substr(6, path.length()); - - AAsset *at = AAssetManager_open(asset_manager, path.utf8().get_data(), AASSET_MODE_STREAMING); - - if (!at) - return false; - - AAsset_close(at); - return true; -} - -FileAccessAndroid::FileAccessAndroid() { - a = NULL; - eof = false; -} - -FileAccessAndroid::~FileAccessAndroid() { - close(); -} diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h deleted file mode 100644 index def4c3b..0000000 --- a/platform/android/file_access_android.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef FILE_ACCESS_ANDROID_H -#define FILE_ACCESS_ANDROID_H -/*************************************************************************/ -/* file_access_android.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "core/os/file_access.h" -#include -#include -#include -//#include - -class FileAccessAndroid : public FileAccess { - mutable AAsset *a; - mutable uint64_t len; - mutable uint64_t pos; - mutable bool eof; - - String absolute_path; - String path_src; - -public: - static AAssetManager *asset_manager; - - virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual void close(); ///< close a file - virtual bool is_open() const; ///< true when file is open - - /// returns the path for the current open file - virtual String get_path() const; - /// returns the absolute path for the current open file - virtual String get_path_absolute() const; - - virtual void seek(uint64_t p_position); ///< seek to a given position - virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual uint64_t get_position() const; ///< get position in the file - virtual uint64_t get_len() const; ///< get size of the file - - virtual bool eof_reached() const; ///< reading passed EOF - - virtual uint8_t get_8() const; ///< get a byte - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; - - virtual Error get_error() const; ///< get last error - - virtual void flush(); - virtual void store_8(uint8_t p_dest); ///< store a byte - - virtual bool file_exists(const String &p_path); ///< return true if a file exists - - virtual uint64_t _get_modified_time(const String &p_file) { return 0; } - virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; } - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; } - - //static void make_default(); - - FileAccessAndroid(); - ~FileAccessAndroid(); -}; - -#endif // FILE_ACCESS_ANDROID_H diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp deleted file mode 100644 index df23ffc..0000000 --- a/platform/android/file_access_filesystem_jandroid.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/*************************************************************************/ -/* file_access_filesystem_jandroid.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -#include "file_access_filesystem_jandroid.h" - -#include "core/os/os.h" -#include "thread_jandroid.h" - -#include - -jobject FileAccessFilesystemJAndroid::file_access_handler = nullptr; -jclass FileAccessFilesystemJAndroid::cls; - -jmethodID FileAccessFilesystemJAndroid::_file_open = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_get_size = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_seek = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_seek_end = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_read = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_tell = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_eof = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_set_eof = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_close = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_write = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_flush = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_exists = nullptr; -jmethodID FileAccessFilesystemJAndroid::_file_last_modified = nullptr; - -String FileAccessFilesystemJAndroid::get_path() const { - return path_src; -} - -String FileAccessFilesystemJAndroid::get_path_absolute() const { - return absolute_path; -} - -Error FileAccessFilesystemJAndroid::_open(const String &p_path, int p_mode_flags) { - if (is_open()) { - close(); - } - - if (_file_open) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, ERR_UNCONFIGURED); - - String path = fix_path(p_path).simplify_path(); - jstring js = env->NewStringUTF(path.utf8().get_data()); - int res = env->CallIntMethod(file_access_handler, _file_open, js, p_mode_flags); - env->DeleteLocalRef(js); - - if (res <= 0) { - switch (res) { - case 0: - default: - return ERR_FILE_CANT_OPEN; - - case -1: - return ERR_FILE_NOT_FOUND; - } - } - - id = res; - path_src = p_path; - absolute_path = path; - return OK; - } else { - return ERR_UNCONFIGURED; - } -} - -void FileAccessFilesystemJAndroid::close() { - if (!is_open()) { - return; - } - - if (_file_close) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - env->CallVoidMethod(file_access_handler, _file_close, id); - } - id = 0; -} - -bool FileAccessFilesystemJAndroid::is_open() const { - return id != 0; -} - -void FileAccessFilesystemJAndroid::seek(uint64_t p_position) { - if (_file_seek) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); - env->CallVoidMethod(file_access_handler, _file_seek, id, p_position); - } -} - -void FileAccessFilesystemJAndroid::seek_end(int64_t p_position) { - if (_file_seek_end) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); - env->CallVoidMethod(file_access_handler, _file_seek_end, id, p_position); - } -} - -uint64_t FileAccessFilesystemJAndroid::get_position() const { - if (_file_tell) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); - return env->CallLongMethod(file_access_handler, _file_tell, id); - } else { - return 0; - } -} - -uint64_t FileAccessFilesystemJAndroid::get_len() const { - if (_file_get_size) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); - return env->CallLongMethod(file_access_handler, _file_get_size, id); - } else { - return 0; - } -} - -bool FileAccessFilesystemJAndroid::eof_reached() const { - if (_file_eof) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - ERR_FAIL_COND_V_MSG(!is_open(), false, "File must be opened before use."); - return env->CallBooleanMethod(file_access_handler, _file_eof, id); - } else { - return false; - } -} - -void FileAccessFilesystemJAndroid::_set_eof(bool eof) { - if (_file_set_eof) { - ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); - - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - env->CallVoidMethod(file_access_handler, _file_set_eof, id, eof); - } -} - -uint8_t FileAccessFilesystemJAndroid::get_8() const { - ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); - uint8_t byte; - get_buffer(&byte, 1); - return byte; -} - -String FileAccessFilesystemJAndroid::get_line() const { - ERR_FAIL_COND_V_MSG(!is_open(), String(), "File must be opened before use."); - - const size_t buffer_size_limit = 2048; - const uint64_t file_size = get_len(); - const uint64_t start_position = get_position(); - - String result; - LocalVector line_buffer; - size_t current_buffer_size = 0; - uint64_t line_buffer_position = 0; - - while (true) { - size_t line_buffer_size = MIN(buffer_size_limit, file_size - get_position()); - if (line_buffer_size <= 0) { - const_cast(this)->_set_eof(true); - break; - } - - current_buffer_size += line_buffer_size; - line_buffer.resize(current_buffer_size); - - uint64_t bytes_read = get_buffer(&line_buffer[line_buffer_position], current_buffer_size - line_buffer_position); - if (bytes_read <= 0) { - break; - } - - for (; bytes_read > 0; line_buffer_position++, bytes_read--) { - uint8_t elem = line_buffer[line_buffer_position]; - if (elem == '\n' || elem == '\0') { - // Found the end of the line - const_cast(this)->seek(start_position + line_buffer_position + 1); - if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) { - return String(); - } - return result; - } - } - } - - if (result.parse_utf8((const char *)line_buffer.ptr(), line_buffer_position, true)) { - return String(); - } - return result; -} - -uint64_t FileAccessFilesystemJAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const { - if (_file_read) { - ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); - if (p_length == 0) { - return 0; - } - - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, 0); - - jobject j_buffer = env->NewDirectByteBuffer(p_dst, p_length); - int length = env->CallIntMethod(file_access_handler, _file_read, id, j_buffer); - env->DeleteLocalRef(j_buffer); - return length; - } else { - return 0; - } -} - -void FileAccessFilesystemJAndroid::store_8(uint8_t p_dest) { - store_buffer(&p_dest, 1); -} - -void FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) { - if (_file_write) { - ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); - if (p_length == 0) { - return; - } - - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - - jobject j_buffer = env->NewDirectByteBuffer((void *)p_src, p_length); - env->CallVoidMethod(file_access_handler, _file_write, id, j_buffer); - env->DeleteLocalRef(j_buffer); - } -} - -Error FileAccessFilesystemJAndroid::get_error() const { - if (eof_reached()) { - return ERR_FILE_EOF; - } - return OK; -} - -void FileAccessFilesystemJAndroid::flush() { - if (_file_flush) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND(env == nullptr); - ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); - env->CallVoidMethod(file_access_handler, _file_flush, id); - } -} - -bool FileAccessFilesystemJAndroid::file_exists(const String &p_path) { - if (_file_exists) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - - String path = fix_path(p_path).simplify_path(); - jstring js = env->NewStringUTF(path.utf8().get_data()); - bool result = env->CallBooleanMethod(file_access_handler, _file_exists, js); - env->DeleteLocalRef(js); - return result; - } else { - return false; - } -} - -uint64_t FileAccessFilesystemJAndroid::_get_modified_time(const String &p_file) { - if (_file_last_modified) { - JNIEnv *env = get_jni_env(); - ERR_FAIL_COND_V(env == nullptr, false); - - String path = fix_path(p_file).simplify_path(); - jstring js = env->NewStringUTF(path.utf8().get_data()); - uint64_t result = env->CallLongMethod(file_access_handler, _file_last_modified, js); - env->DeleteLocalRef(js); - return result; - } else { - return 0; - } -} - -void FileAccessFilesystemJAndroid::setup(jobject p_file_access_handler) { - JNIEnv *env = get_jni_env(); - file_access_handler = env->NewGlobalRef(p_file_access_handler); - - jclass c = env->GetObjectClass(file_access_handler); - cls = (jclass)env->NewGlobalRef(c); - - _file_open = env->GetMethodID(cls, "fileOpen", "(Ljava/lang/String;I)I"); - _file_get_size = env->GetMethodID(cls, "fileGetSize", "(I)J"); - _file_tell = env->GetMethodID(cls, "fileGetPosition", "(I)J"); - _file_eof = env->GetMethodID(cls, "isFileEof", "(I)Z"); - _file_set_eof = env->GetMethodID(cls, "setFileEof", "(IZ)V"); - _file_seek = env->GetMethodID(cls, "fileSeek", "(IJ)V"); - _file_seek_end = env->GetMethodID(cls, "fileSeekFromEnd", "(IJ)V"); - _file_read = env->GetMethodID(cls, "fileRead", "(ILjava/nio/ByteBuffer;)I"); - _file_close = env->GetMethodID(cls, "fileClose", "(I)V"); - _file_write = env->GetMethodID(cls, "fileWrite", "(ILjava/nio/ByteBuffer;)V"); - _file_flush = env->GetMethodID(cls, "fileFlush", "(I)V"); - _file_exists = env->GetMethodID(cls, "fileExists", "(Ljava/lang/String;)Z"); - _file_last_modified = env->GetMethodID(cls, "fileLastModified", "(Ljava/lang/String;)J"); -} - -FileAccessFilesystemJAndroid::FileAccessFilesystemJAndroid() { - id = 0; -} - -FileAccessFilesystemJAndroid::~FileAccessFilesystemJAndroid() { - if (is_open()) { - close(); - } -} diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h deleted file mode 100644 index 8c335f6..0000000 --- a/platform/android/file_access_filesystem_jandroid.h +++ /dev/null @@ -1,100 +0,0 @@ -/*************************************************************************/ -/* file_access_filesystem_jandroid.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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 FILE_ACCESS_FILESYSTEM_JANDROID_H -#define FILE_ACCESS_FILESYSTEM_JANDROID_H - -#include "core/os/file_access.h" -#include "java_pandemonium_lib_jni.h" - -class FileAccessFilesystemJAndroid : public FileAccess { - static jobject file_access_handler; - static jclass cls; - - static jmethodID _file_open; - static jmethodID _file_get_size; - static jmethodID _file_seek; - static jmethodID _file_seek_end; - static jmethodID _file_tell; - static jmethodID _file_eof; - static jmethodID _file_set_eof; - static jmethodID _file_read; - static jmethodID _file_write; - static jmethodID _file_flush; - static jmethodID _file_close; - static jmethodID _file_exists; - static jmethodID _file_last_modified; - - int id; - String absolute_path; - String path_src; - - void _set_eof(bool eof); - -public: - virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file - virtual void close(); ///< close a file - virtual bool is_open() const; ///< true when file is open - - /// returns the path for the current open file - virtual String get_path() const; - /// returns the absolute path for the current open file - virtual String get_path_absolute() const; - - virtual void seek(uint64_t p_position); ///< seek to a given position - virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - virtual uint64_t get_position() const; ///< get position in the file - virtual uint64_t get_len() const; ///< get size of the file - - virtual bool eof_reached() const; ///< reading passed EOF - - virtual uint8_t get_8() const; ///< get a byte - virtual String get_line() const; ///< get a line - virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; - - virtual Error get_error() const; ///< get last error - - virtual void flush(); - virtual void store_8(uint8_t p_dest); ///< store a byte - virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); - - virtual bool file_exists(const String &p_path); ///< return true if a file exists - - static void setup(jobject p_file_access_handler); - - virtual uint64_t _get_modified_time(const String &p_file); - virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; } - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; } - - FileAccessFilesystemJAndroid(); - ~FileAccessFilesystemJAndroid(); -}; - -#endif // FILE_ACCESS_FILESYSTEM_JANDROID_H diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml deleted file mode 100644 index 13b4c8e..0000000 --- a/platform/android/java/app/AndroidManifest.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/platform/android/java/app/assetPacks/installTime/build.gradle b/platform/android/java/app/assetPacks/installTime/build.gradle deleted file mode 100644 index b06faac..0000000 --- a/platform/android/java/app/assetPacks/installTime/build.gradle +++ /dev/null @@ -1,8 +0,0 @@ -apply plugin: 'com.android.asset-pack' - -assetPack { - packName = "installTime" // Directory name for the asset pack - dynamicDelivery { - deliveryType = "install-time" // Delivery mode - } -} diff --git a/platform/android/java/app/assets/.gitignore b/platform/android/java/app/assets/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/platform/android/java/app/assets/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle deleted file mode 100644 index b95d7c9..0000000 --- a/platform/android/java/app/build.gradle +++ /dev/null @@ -1,288 +0,0 @@ -// Gradle build config for Pandemonium Engine's Android port. -// -// Do not remove/modify comments ending with BEGIN/END, they are used to inject -// addon-specific configuration. -buildscript { - apply from: 'config.gradle' - - repositories { - google() - mavenCentral() -//CHUNK_BUILDSCRIPT_REPOSITORIES_BEGIN -//CHUNK_BUILDSCRIPT_REPOSITORIES_END - } - dependencies { - classpath libraries.androidGradlePlugin - classpath libraries.kotlinGradlePlugin -//CHUNK_BUILDSCRIPT_DEPENDENCIES_BEGIN -//CHUNK_BUILDSCRIPT_DEPENDENCIES_END - } -} - -plugins { - id 'com.android.application' - id 'org.jetbrains.kotlin.android' -} - -apply from: 'config.gradle' - -allprojects { - repositories { - google() - mavenCentral() -//CHUNK_ALLPROJECTS_REPOSITORIES_BEGIN -//CHUNK_ALLPROJECTS_REPOSITORIES_END - - // Pandemonium user plugins custom maven repos - String[] mavenRepos = getPandemoniumPluginsMavenRepos() - if (mavenRepos != null && mavenRepos.size() > 0) { - for (String repoUrl : mavenRepos) { - maven { - url repoUrl - } - } - } - } -} - -configurations { - // Initializes a placeholder for the devImplementation dependency configuration. - devImplementation {} -} - -dependencies { - implementation libraries.kotlinStdLib - implementation libraries.androidxFragment - - if (rootProject.findProject(":lib")) { - implementation project(":lib") - } else if (rootProject.findProject(":pandemonium:lib")) { - implementation project(":pandemonium:lib") - } else { - // Custom build mode. In this scenario this project is the only one around and the Pandemonium - // library is available through the pre-generated pandemonium-lib.*.aar android archive files. - debugImplementation fileTree(dir: 'libs/debug', include: ['*.jar', '*.aar']) - devImplementation fileTree(dir: 'libs/dev', include: ['*.jar', '*.aar']) - releaseImplementation fileTree(dir: 'libs/release', include: ['*.jar', '*.aar']) - } - - // Pandemonium user plugins remote dependencies - String[] remoteDeps = getPandemoniumPluginsRemoteBinaries() - if (remoteDeps != null && remoteDeps.size() > 0) { - for (String dep : remoteDeps) { - implementation dep - } - } - - // Pandemonium user plugins local dependencies - String[] pluginsBinaries = getPandemoniumPluginsLocalBinaries() - if (pluginsBinaries != null && pluginsBinaries.size() > 0) { - implementation files(pluginsBinaries) - } - -//CHUNK_DEPENDENCIES_BEGIN -//CHUNK_DEPENDENCIES_END -} - -android { - compileSdkVersion versions.compileSdk - buildToolsVersion versions.buildTools - ndkVersion versions.ndkVersion - - compileOptions { - sourceCompatibility versions.javaVersion - targetCompatibility versions.javaVersion - } - - kotlinOptions { - jvmTarget = versions.javaVersion - } - - assetPacks = [":assetPacks:installTime"] - - defaultConfig { - // The default ignore pattern for the 'assets' directory includes hidden files and directories which are used by Pandemonium projects. - aaptOptions { - ignoreAssetsPattern "!.svn:!.git:!.gitignore:!.ds_store:!*.scc:_*:!CVS:!thumbs.db:!picasa.ini:!*~" - } - - ndk { - String[] export_abi_list = getExportEnabledABIs() - abiFilters export_abi_list - } - - manifestPlaceholders = [pandemoniumEditorVersion: getPandemoniumEditorVersion()] - - // Feel free to modify the application id to your own. - applicationId getExportPackageName() - versionCode getExportVersionCode() - versionName getExportVersionName() - minSdkVersion getExportMinSdkVersion() - targetSdkVersion getExportTargetSdkVersion() - - missingDimensionStrategy 'products', 'template' -//CHUNK_ANDROID_DEFAULTCONFIG_BEGIN -//CHUNK_ANDROID_DEFAULTCONFIG_END - } - - lintOptions { - abortOnError false - disable 'MissingTranslation', 'UnusedResources' - } - - ndkVersion versions.ndkVersion - - packagingOptions { - exclude 'META-INF/LICENSE' - exclude 'META-INF/NOTICE' - - // 'doNotStrip' is enabled for development within Android Studio - if (shouldNotStrip()) { - doNotStrip '**/*.so' - } - } - - signingConfigs { - debug { - if (hasCustomDebugKeystore()) { - storeFile new File(getDebugKeystoreFile()) - storePassword getDebugKeystorePassword() - keyAlias getDebugKeyAlias() - keyPassword getDebugKeystorePassword() - } - } - - release { - File keystoreFile = new File(getReleaseKeystoreFile()) - if (keystoreFile.isFile()) { - storeFile keystoreFile - storePassword getReleaseKeystorePassword() - keyAlias getReleaseKeyAlias() - keyPassword getReleaseKeystorePassword() - } - } - } - - buildTypes { - - debug { - // Signing and zip-aligning are skipped for prebuilt builds, but - // performed for custom builds. - zipAlignEnabled shouldZipAlign() - if (shouldSign()) { - signingConfig signingConfigs.debug - } else { - signingConfig null - } - } - - dev { - initWith debug - // Signing and zip-aligning are skipped for prebuilt builds, but - // performed for custom builds. - zipAlignEnabled shouldZipAlign() - if (shouldSign()) { - signingConfig signingConfigs.debug - } else { - signingConfig null - } - } - - release { - // Signing and zip-aligning are skipped for prebuilt builds, but - // performed for custom builds. - zipAlignEnabled shouldZipAlign() - if (shouldSign()) { - signingConfig signingConfigs.release - } else { - signingConfig null - } - } - } - - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = [ - 'src' -//DIR_SRC_BEGIN -//DIR_SRC_END - ] - res.srcDirs = [ - 'res' -//DIR_RES_BEGIN -//DIR_RES_END - ] - aidl.srcDirs = [ - 'aidl' -//DIR_AIDL_BEGIN -//DIR_AIDL_END - ] - assets.srcDirs = [ - 'assets' -//DIR_ASSETS_BEGIN -//DIR_ASSETS_END - ] - } - debug.jniLibs.srcDirs = [ - 'libs/debug' -//DIR_JNI_DEBUG_BEGIN -//DIR_JNI_DEBUG_END - ] - dev.jniLibs.srcDirs = [ - 'libs/dev' -//DIR_JNI_DEV_BEGIN -//DIR_JNI_DEV_END - ] - release.jniLibs.srcDirs = [ - 'libs/release' -//DIR_JNI_RELEASE_BEGIN -//DIR_JNI_RELEASE_END - ] - } - - applicationVariants.all { variant -> - variant.outputs.all { output -> - output.outputFileName = "android_${variant.name}.apk" - } - } -} - -task copyAndRenameDebugApk(type: Copy) { - from "$buildDir/outputs/apk/debug/android_debug.apk" - into getExportPath() - rename "android_debug.apk", getExportFilename() -} - -task copyAndRenameDevApk(type: Copy) { - from "$buildDir/outputs/apk/dev/android_dev.apk" - into getExportPath() - rename "android_dev.apk", getExportFilename() -} - -task copyAndRenameReleaseApk(type: Copy) { - from "$buildDir/outputs/apk/release/android_release.apk" - into getExportPath() - rename "android_release.apk", getExportFilename() -} - -task copyAndRenameDebugAab(type: Copy) { - from "$buildDir/outputs/bundle/debug/build-debug.aab" - into getExportPath() - rename "build-debug.aab", getExportFilename() -} - -task copyAndRenameDevAab(type: Copy) { - from "$buildDir/outputs/bundle/dev/build-dev.aab" - into getExportPath() - rename "build-dev.aab", getExportFilename() -} - -task copyAndRenameReleaseAab(type: Copy) { - from "$buildDir/outputs/bundle/release/build-release.aab" - into getExportPath() - rename "build-release.aab", getExportFilename() -} - -//CHUNK_GLOBAL_BEGIN -//CHUNK_GLOBAL_END diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle deleted file mode 100644 index 0fc1fa2..0000000 --- a/platform/android/java/app/config.gradle +++ /dev/null @@ -1,315 +0,0 @@ -ext.versions = [ - androidGradlePlugin: '7.2.1', - compileSdk : 33, - minSdk : 19, // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_MIN_SDK_VERSION' - targetSdk : 33, // Also update 'platform/android/export/export_plugin.cpp#DEFAULT_TARGET_SDK_VERSION' - buildTools : '33.0.2', - kotlinVersion : '1.7.0', - fragmentVersion : '1.3.6', - nexusPublishVersion: '1.1.0', - javaVersion : 11, - ndkVersion : '23.2.8568313' // Also update 'platform/android/detect.py#get_ndk_version' when this is updated. - -] - -ext.libraries = [ - androidGradlePlugin: "com.android.tools.build:gradle:$versions.androidGradlePlugin", - kotlinGradlePlugin : "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlinVersion", - kotlinStdLib : "org.jetbrains.kotlin:kotlin-stdlib:$versions.kotlinVersion", - androidxFragment : "androidx.fragment:fragment:$versions.fragmentVersion", -] - -ext.getExportPackageName = { -> - // Retrieve the app id from the project property set by the Pandemonium build command. - String appId = project.hasProperty("export_package_name") ? project.property("export_package_name") : "" - // Check if the app id is valid, otherwise use the default. - if (appId == null || appId.isEmpty()) { - appId = "com.pandemonium.game" - } - return appId -} - -ext.getExportVersionCode = { -> - String versionCode = project.hasProperty("export_version_code") ? project.property("export_version_code") : "" - if (versionCode == null || versionCode.isEmpty()) { - versionCode = "1" - } - try { - return Integer.parseInt(versionCode) - } catch (NumberFormatException ignored) { - return 1 - } -} - -ext.getExportVersionName = { -> - String versionName = project.hasProperty("export_version_name") ? project.property("export_version_name") : "" - if (versionName == null || versionName.isEmpty()) { - versionName = "1.0" - } - return versionName -} - -ext.getExportMinSdkVersion = { -> - String minSdkVersion = project.hasProperty("export_version_min_sdk") ? project.property("export_version_min_sdk") : "" - if (minSdkVersion == null || minSdkVersion.isEmpty()) { - minSdkVersion = "$versions.minSdk" - } - try { - return Integer.parseInt(minSdkVersion) - } catch (NumberFormatException ignored) { - return versions.minSdk - } -} - -ext.getExportTargetSdkVersion = { -> - String targetSdkVersion = project.hasProperty("export_version_target_sdk") ? project.property("export_version_target_sdk") : "" - if (targetSdkVersion == null || targetSdkVersion.isEmpty()) { - targetSdkVersion = "$versions.targetSdk" - } - try { - return Integer.parseInt(targetSdkVersion) - } catch (NumberFormatException ignored) { - return versions.targetSdk - } -} - -ext.getPandemoniumEditorVersion = { -> - String editorVersion = project.hasProperty("pandemonium_editor_version") ? project.property("pandemonium_editor_version") : "" - if (editorVersion == null || editorVersion.isEmpty()) { - // Try the library version first - editorVersion = getPandemoniumLibraryVersionName() - - if (editorVersion.isEmpty()) { - // Fallback value. - editorVersion = "custom_build" - } - } - return editorVersion -} - -ext.getPandemoniumLibraryVersionCode = { -> - String versionName = "" - int versionCode = 1 - (versionName, versionCode) = getPandemoniumLibraryVersion() - return versionCode -} - -ext.getPandemoniumLibraryVersionName = { -> - String versionName = "" - int versionCode = 1 - (versionName, versionCode) = getPandemoniumLibraryVersion() - return versionName -} - -ext.getPandemoniumLibraryVersion = { -> - // Attempt to read the version from the `version.py` file. - String libraryVersionName = "" - int libraryVersionCode = 1 - - File versionFile = new File("../../../version.py") - if (versionFile.isFile()) { - List requiredKeys = ["major", "minor", "patch", "status", "module_config"] - def map = [:] - - List lines = versionFile.readLines() - for (String line in lines) { - String[] keyValue = line.split("=") - String key = keyValue[0].trim() - String value = keyValue[1].trim().replaceAll("\"", "") - - if (requiredKeys.contains(key)) { - if (!value.isEmpty()) { - map[key] = value - } - requiredKeys.remove(key) - } - } - - if (requiredKeys.empty) { - libraryVersionName = map.values().join(".") - try { - libraryVersionCode = Integer.parseInt(map["patch"]) + - (Integer.parseInt(map["minor"]) * 100) + - (Integer.parseInt(map["major"]) * 10000) - } catch (NumberFormatException ignore) {} - } - } - - if (libraryVersionName.isEmpty()) { - // Fallback value in case we're unable to read the file. - libraryVersionName = "custom_build" - } - return [libraryVersionName, libraryVersionCode] -} - -final String VALUE_SEPARATOR_REGEX = "\\|" - -// get the list of ABIs the project should be exported to -ext.getExportEnabledABIs = { -> - String enabledABIs = project.hasProperty("export_enabled_abis") ? project.property("export_enabled_abis") : ""; - if (enabledABIs == null || enabledABIs.isEmpty()) { - enabledABIs = "armeabi-v7a|arm64-v8a|x86|x86_64|" - } - Set exportAbiFilter = []; - for (String abi_name : enabledABIs.split(VALUE_SEPARATOR_REGEX)) { - if (!abi_name.trim().isEmpty()){ - exportAbiFilter.add(abi_name); - } - } - return exportAbiFilter; -} - -ext.getExportPath = { - String exportPath = project.hasProperty("export_path") ? project.property("export_path") : "" - if (exportPath == null || exportPath.isEmpty()) { - exportPath = "." - } - return exportPath -} - -ext.getExportFilename = { - String exportFilename = project.hasProperty("export_filename") ? project.property("export_filename") : "" - if (exportFilename == null || exportFilename.isEmpty()) { - exportFilename = "pandemonium_android" - } - return exportFilename -} - -/** - * Parse the project properties for the 'plugins_maven_repos' property and return the list - * of maven repos. - */ -ext.getPandemoniumPluginsMavenRepos = { -> - Set mavenRepos = [] - - // Retrieve the list of maven repos. - if (project.hasProperty("plugins_maven_repos")) { - String mavenReposProperty = project.property("plugins_maven_repos") - if (mavenReposProperty != null && !mavenReposProperty.trim().isEmpty()) { - for (String mavenRepoUrl : mavenReposProperty.split(VALUE_SEPARATOR_REGEX)) { - mavenRepos += mavenRepoUrl.trim() - } - } - } - - return mavenRepos -} - -/** - * Parse the project properties for the 'plugins_remote_binaries' property and return - * it for inclusion in the build dependencies. - */ -ext.getPandemoniumPluginsRemoteBinaries = { -> - Set remoteDeps = [] - - // Retrieve the list of remote plugins binaries. - if (project.hasProperty("plugins_remote_binaries")) { - String remoteDepsList = project.property("plugins_remote_binaries") - if (remoteDepsList != null && !remoteDepsList.trim().isEmpty()) { - for (String dep: remoteDepsList.split(VALUE_SEPARATOR_REGEX)) { - remoteDeps += dep.trim() - } - } - } - return remoteDeps -} - -/** - * Parse the project properties for the 'plugins_local_binaries' property and return - * their binaries for inclusion in the build dependencies. - */ -ext.getPandemoniumPluginsLocalBinaries = { -> - Set binDeps = [] - - // Retrieve the list of local plugins binaries. - if (project.hasProperty("plugins_local_binaries")) { - String pluginsList = project.property("plugins_local_binaries") - if (pluginsList != null && !pluginsList.trim().isEmpty()) { - for (String plugin : pluginsList.split(VALUE_SEPARATOR_REGEX)) { - binDeps += plugin.trim() - } - } - } - - return binDeps -} - -ext.getDebugKeystoreFile = { -> - String keystoreFile = project.hasProperty("debug_keystore_file") ? project.property("debug_keystore_file") : "" - if (keystoreFile == null || keystoreFile.isEmpty()) { - keystoreFile = "." - } - return keystoreFile -} - -ext.hasCustomDebugKeystore = { -> - File keystoreFile = new File(getDebugKeystoreFile()) - return keystoreFile.isFile() -} - -ext.getDebugKeystorePassword = { -> - String keystorePassword = project.hasProperty("debug_keystore_password") ? project.property("debug_keystore_password") : "" - if (keystorePassword == null || keystorePassword.isEmpty()) { - keystorePassword = "android" - } - return keystorePassword -} - -ext.getDebugKeyAlias = { -> - String keyAlias = project.hasProperty("debug_keystore_alias") ? project.property("debug_keystore_alias") : "" - if (keyAlias == null || keyAlias.isEmpty()) { - keyAlias = "androiddebugkey" - } - return keyAlias -} - -ext.getReleaseKeystoreFile = { -> - String keystoreFile = project.hasProperty("release_keystore_file") ? project.property("release_keystore_file") : "" - if (keystoreFile == null || keystoreFile.isEmpty()) { - keystoreFile = "." - } - return keystoreFile -} - -ext.getReleaseKeystorePassword = { -> - String keystorePassword = project.hasProperty("release_keystore_password") ? project.property("release_keystore_password") : "" - return keystorePassword -} - -ext.getReleaseKeyAlias = { -> - String keyAlias = project.hasProperty("release_keystore_alias") ? project.property("release_keystore_alias") : "" - return keyAlias -} - -ext.isAndroidStudio = { -> - def sysProps = System.getProperties() - return sysProps != null && sysProps['idea.platform.prefix'] != null -} - -ext.shouldZipAlign = { -> - String zipAlignFlag = project.hasProperty("perform_zipalign") ? project.property("perform_zipalign") : "" - if (zipAlignFlag == null || zipAlignFlag.isEmpty()) { - if (isAndroidStudio()) { - zipAlignFlag = "true" - } else { - zipAlignFlag = "false" - } - } - return Boolean.parseBoolean(zipAlignFlag) -} - -ext.shouldSign = { -> - String signFlag = project.hasProperty("perform_signing") ? project.property("perform_signing") : "" - if (signFlag == null || signFlag.isEmpty()) { - if (isAndroidStudio()) { - signFlag = "true" - } else { - signFlag = "false" - } - } - return Boolean.parseBoolean(signFlag) -} - -ext.shouldNotStrip = { -> - return isAndroidStudio() || project.hasProperty("doNotStrip") -} diff --git a/platform/android/java/app/gradle.properties b/platform/android/java/app/gradle.properties deleted file mode 100644 index d203e76..0000000 --- a/platform/android/java/app/gradle.properties +++ /dev/null @@ -1,25 +0,0 @@ -# Pandemonium custom build Gradle settings. -# These properties apply when running custom build from the Pandemonium editor. -# NOTE: This should be kept in sync with 'pandemonium/platform/android/java/gradle.properties' except -# where otherwise specified. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -android.enableJetifier=true -android.useAndroidX=true - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx4536m - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true - -org.gradle.warning.mode=all - -# Enable resource optimizations for release build. -# NOTE: This is turned off for template release build in order to support the build legacy process. -android.enableResourceOptimizations=true diff --git a/platform/android/java/app/res/drawable-nodpi/splash.png b/platform/android/java/app/res/drawable-nodpi/splash.png deleted file mode 100644 index b6bdb20a724424eb542fbc69ff7b76780b292541..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31538 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 diff --git a/platform/android/java/app/res/drawable/splash_drawable.xml b/platform/android/java/app/res/drawable/splash_drawable.xml deleted file mode 100644 index 30627b9..0000000 --- a/platform/android/java/app/res/drawable/splash_drawable.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/platform/android/java/app/res/values-en/pandemonium_project_name_string.xml b/platform/android/java/app/res/values-en/pandemonium_project_name_string.xml deleted file mode 100644 index c369591..0000000 --- a/platform/android/java/app/res/values-en/pandemonium_project_name_string.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - pandemonium-project-name-en - diff --git a/platform/android/java/app/res/values-hu/pandemonium_project_name_string.xml b/platform/android/java/app/res/values-hu/pandemonium_project_name_string.xml deleted file mode 100644 index d3dcea2..0000000 --- a/platform/android/java/app/res/values-hu/pandemonium_project_name_string.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - pandemonium-project-name-hu - diff --git a/platform/android/java/app/res/values/pandemonium_project_name_string.xml b/platform/android/java/app/res/values/pandemonium_project_name_string.xml deleted file mode 100644 index 2149dec..0000000 --- a/platform/android/java/app/res/values/pandemonium_project_name_string.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - pandemonium-project-name - diff --git a/platform/android/java/app/res/values/themes.xml b/platform/android/java/app/res/values/themes.xml deleted file mode 100644 index 1f97f9f..0000000 --- a/platform/android/java/app/res/values/themes.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - diff --git a/platform/android/java/app/settings.gradle b/platform/android/java/app/settings.gradle deleted file mode 100644 index 237d44a..0000000 --- a/platform/android/java/app/settings.gradle +++ /dev/null @@ -1,15 +0,0 @@ -// This is the root directory of the Pandemonium custom build. -pluginManagement { - apply from: 'config.gradle' - - plugins { - id 'com.android.application' version versions.androidGradlePlugin - id 'org.jetbrains.kotlin.android' version versions.kotlinVersion - } - repositories { - gradlePluginPortal() - google() - } -} - -include ':assetPacks:installTime' diff --git a/platform/android/java/app/src/com/pandemonium/game/PandemoniumApp.java b/platform/android/java/app/src/com/pandemonium/game/PandemoniumApp.java deleted file mode 100644 index 1fbaf98..0000000 --- a/platform/android/java/app/src/com/pandemonium/game/PandemoniumApp.java +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************/ -/* PandemoniumApp.java */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -package com.pandemonium.game; - -import org.pandemoniumengine.pandemonium.FullScreenPandemoniumApp; - -import android.os.Bundle; - -/** - * Template activity for Pandemonium Android custom builds. - * Feel free to extend and modify this class for your custom logic. - */ -public class PandemoniumApp extends FullScreenPandemoniumApp { - @Override - public void onCreate(Bundle savedInstanceState) { - setTheme(R.style.PandemoniumAppMainTheme); - super.onCreate(savedInstanceState); - } -} diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle deleted file mode 100644 index 8b5e2b8..0000000 --- a/platform/android/java/build.gradle +++ /dev/null @@ -1,330 +0,0 @@ - -buildscript { - apply from: 'app/config.gradle' - - repositories { - google() - mavenCentral() - } - dependencies { - classpath libraries.androidGradlePlugin - classpath libraries.kotlinGradlePlugin - } -} - -plugins { - id 'io.github.gradle-nexus.publish-plugin' -} - -apply from: 'app/config.gradle' -//apply from: 'scripts/publish-root.gradle' - -allprojects { - repositories { - google() - mavenCentral() - } -} - -ext { - supportedAbis = ["armv7", "arm64v8", "x86", "x86_64"] - supportedTargetsMap = [release: "release", dev: "debug", debug: "release_debug"] - supportedFlavors = ["editor", "template"] - - // Used by gradle to specify which architecture to build for by default when running - // `./gradlew build` (this command is usually used by Android Studio). - // If building manually on the command line, it's recommended to use the - // `./gradlew generatePandemoniumTemplates` build command instead after running the `scons` command(s). - // The {selectedAbis} values must be from the {supportedAbis} values. - selectedAbis = ["arm64v8"] -} - -def rootDir = "../../.." -def binDir = "$rootDir/bin/" - -def getSconsTaskName(String flavor, String buildType, String abi) { - return "compilePandemoniumNativeLibs" + flavor.capitalize() + buildType.capitalize() + abi.capitalize() -} - -/** - * Copy the generated 'android_debug.apk' binary template into the Pandemonium bin directory. - * Depends on the app build task to ensure the binary is generated prior to copying. - */ -task copyDebugBinaryToBin(type: Copy) { - dependsOn ':app:assembleDebug' - from('app/build/outputs/apk/debug') - into(binDir) - include('android_debug.apk') -} - -/** - * Copy the generated 'android_dev.apk' binary template into the Pandemonium bin directory. - * Depends on the app build task to ensure the binary is generated prior to copying. - */ -task copyDevBinaryToBin(type: Copy) { - dependsOn ':app:assembleDev' - from('app/build/outputs/apk/dev') - into(binDir) - include('android_dev.apk') -} - -/** - * Copy the generated 'android_release.apk' binary template into the Pandemonium bin directory. - * Depends on the app build task to ensure the binary is generated prior to copying. - */ -task copyReleaseBinaryToBin(type: Copy) { - dependsOn ':app:assembleRelease' - from('app/build/outputs/apk/release') - into(binDir) - include('android_release.apk') -} - -/** - * Copy the Pandemonium android library archive debug file into the app module debug libs directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyDebugAARToAppModule(type: Copy) { - dependsOn ':lib:assembleTemplateDebug' - from('lib/build/outputs/aar') - into('app/libs/debug') - include('pandemonium-lib.debug.aar') -} - -/** - * Copy the Pandemonium android library archive debug file into the root bin directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyDebugAARToBin(type: Copy) { - dependsOn ':lib:assembleTemplateDebug' - from('lib/build/outputs/aar') - into(binDir) - include('pandemonium-lib.debug.aar') -} - -/** - * Copy the Pandemonium android library archive dev file into the app module dev libs directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyDevAARToAppModule(type: Copy) { - dependsOn ':lib:assembleTemplateDev' - from('lib/build/outputs/aar') - into('app/libs/dev') - include('pandemonium-lib.dev.aar') -} - -/** - * Copy the Pandemonium android library archive dev file into the root bin directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyDevAARToBin(type: Copy) { - dependsOn ':lib:assembleTemplateDev' - from('lib/build/outputs/aar') - into(binDir) - include('pandemonium-lib.dev.aar') -} - -/** - * Copy the Pandemonium android library archive release file into the app module release libs directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyReleaseAARToAppModule(type: Copy) { - dependsOn ':lib:assembleTemplateRelease' - from('lib/build/outputs/aar') - into('app/libs/release') - include('pandemonium-lib.release.aar') -} - -/** - * Copy the Pandemonium android library archive release file into the root bin directory. - * Depends on the library build task to ensure the AAR file is generated prior to copying. - */ -task copyReleaseAARToBin(type: Copy) { - dependsOn ':lib:assembleTemplateRelease' - from('lib/build/outputs/aar') - into(binDir) - include('pandemonium-lib.release.aar') -} - -/** - * Generate Pandemonium custom build template by zipping the source files from the app directory, as well - * as the AAR files generated by 'copyDebugAAR', 'copyDevAAR' and 'copyReleaseAAR'. - * The zip file also includes some gradle tools to allow building of the custom build. - */ -task zipCustomBuild(type: Zip) { - onlyIf { generatePandemoniumTemplates.state.executed || generateDevTemplate.state.executed } - doFirst { - logger.lifecycle("Generating Pandemonium custom build template") - } - from(fileTree(dir: 'app', excludes: ['**/build/**', '**/.gradle/**', '**/*.iml']), fileTree(dir: '.', includes: ['gradlew', 'gradlew.bat', 'gradle/**'])) - include '**/*' - archiveFileName = 'android_source.zip' - destinationDirectory = file(binDir) -} - -def templateExcludedBuildTask() { - // We exclude these gradle tasks so we can run the scons command manually. - def excludedTasks = [] - if (!isAndroidStudio()) { - logger.lifecycle("Excluding Android studio build tasks") - for (String flavor : supportedFlavors) { - for (String buildType : supportedTargetsMap.keySet()) { - if (buildType == "release" && flavor == "editor") { - // The editor can't be used with target=release as debugging tools are then not - // included, and it would crash on errors instead of reporting them. - continue - } - - for (String abi : selectedAbis) { - excludedTasks += ":lib:" + getSconsTaskName(flavor, buildType, abi) - } - } - } - } - return excludedTasks -} - -def templateBuildTasks() { - def tasks = [] - - // Only build the apks and aar files for which we have native shared libraries. - for (String target : supportedTargetsMap.keySet()) { - File targetLibs = new File("lib/libs/" + target) - if (targetLibs != null - && targetLibs.isDirectory() - && targetLibs.listFiles() != null - && targetLibs.listFiles().length > 0) { - String capitalizedTarget = target.capitalize() - // Copy the generated aar library files to the custom build directory. - tasks += "copy" + capitalizedTarget + "AARToAppModule" - // Copy the generated aar library files to the bin directory. - tasks += "copy" + capitalizedTarget + "AARToBin" - // Copy the prebuilt binary templates to the bin directory. - tasks += "copy" + capitalizedTarget + "BinaryToBin" - } else { - logger.lifecycle("No native shared libs for target $target. Skipping build.") - } - } - - return tasks -} - -def isAndroidStudio() { - def sysProps = System.getProperties() - return sysProps != null && sysProps['idea.platform.prefix'] != null -} - -task copyEditorDebugBinaryToBin(type: Copy) { - dependsOn ':editor:assembleDebug' - from('editor/build/outputs/apk/debug') - into(binDir) - include('android_editor.apk') -} - -task copyEditorDevBinaryToBin(type: Copy) { - dependsOn ':editor:assembleDev' - from('editor/build/outputs/apk/dev') - into(binDir) - include('android_editor_dev.apk') -} - -/** - * Generate the Pandemonium Editor Android apk. - * - * Note: The Pandemonium 'tools' shared libraries must have been generated (via scons) prior to running - * this gradle task. The task will only build the apk(s) for which the shared libraries is - * available. - */ -task generatePandemoniumEditor { - gradle.startParameter.excludedTaskNames += templateExcludedBuildTask() - - def tasks = [] - - for (String target : supportedTargetsMap.keySet()) { - if (target == "release") { - // The editor can't be used with target=release as debugging tools are then not - // included, and it would crash on errors instead of reporting them. - continue - } - File targetLibs = new File("lib/libs/tools/" + target) - if (targetLibs != null - && targetLibs.isDirectory() - && targetLibs.listFiles() != null - && targetLibs.listFiles().length > 0) { - tasks += "copyEditor${target.capitalize()}BinaryToBin" - } - } - - dependsOn = tasks -} - -/** - * Master task used to coordinate the tasks defined above to generate the set of Pandemonium templates. - */ -task generatePandemoniumTemplates { - gradle.startParameter.excludedTaskNames += templateExcludedBuildTask() - dependsOn = templateBuildTasks() - - finalizedBy 'zipCustomBuild' -} - -task clean(type: Delete) { - dependsOn 'cleanPandemoniumEditor' - dependsOn 'cleanPandemoniumTemplates' -} - -/** - * Generates the same output as generatePandemoniumTemplates but with dev symbols - */ -task generateDevTemplate { - // add parameter to set symbols to true - gradle.startParameter.projectProperties += [doNotStrip: true] - - gradle.startParameter.excludedTaskNames += templateExcludedBuildTask() - dependsOn = templateBuildTasks() - - finalizedBy 'zipCustomBuild' -} - -/** -* Clean the generated editor artifacts. - */ -task cleanPandemoniumEditor(type: Delete) { - // Delete the generated native tools libs - delete("lib/libs/tools") - - // Delete the library generated AAR files - delete("lib/build/outputs/aar") - - // Delete the generated binary apks - delete("editor/build/outputs/apk") - - // Delete the Pandemonium editor apks in the Pandemonium bin directory - delete("$binDir/android_editor.apk") - delete("$binDir/android_editor_dev.apk") -} - -/** - * Clean the generated template artifacts. - */ -task cleanPandemoniumTemplates(type: Delete) { - // Delete the generated native libs - delete("lib/libs") - - // Delete the library generated AAR files - delete("lib/build/outputs/aar") - - // Delete the app libs directory contents - delete("app/libs") - - // Delete the generated binary apks - delete("app/build/outputs/apk") - - // Delete the Pandemonium templates in the Pandemonium bin directory - delete("$binDir/android_debug.apk") - delete("$binDir/android_dev.apk") - delete("$binDir/android_release.apk") - delete("$binDir/android_source.zip") - delete("$binDir/pandemonium-lib.debug.aar") - delete("$binDir/pandemonium-lib.dev.aar") - delete("$binDir/pandemonium-lib.release.aar") -} diff --git a/platform/android/java/editor/build.gradle b/platform/android/java/editor/build.gradle deleted file mode 100644 index adda4ea..0000000 --- a/platform/android/java/editor/build.gradle +++ /dev/null @@ -1,81 +0,0 @@ -// Gradle build config for Pandemonium Engine's Android port. -plugins { - id 'com.android.application' - id 'org.jetbrains.kotlin.android' -} - -dependencies { - implementation libraries.kotlinStdLib - implementation libraries.androidxFragment - implementation project(":lib") - - implementation "androidx.window:window:1.0.0" -} - -android { - compileSdkVersion versions.compileSdk - buildToolsVersion versions.buildTools - ndkVersion versions.ndkVersion - - defaultConfig { - // The 'applicationId' suffix allows to install Pandemonium 3.x(v3) and 4.x(v4) on the same device - applicationId "org.pandemoniumengine.editor.v3" - versionCode getPandemoniumLibraryVersionCode() - versionName getPandemoniumLibraryVersionName() - minSdkVersion versions.minSdk - targetSdkVersion versions.targetSdk - missingDimensionStrategy 'products', 'editor' - } - - compileOptions { - sourceCompatibility versions.javaVersion - targetCompatibility versions.javaVersion - } - - kotlinOptions { - jvmTarget = versions.javaVersion - } - - buildTypes { - dev { - initWith debug - applicationIdSuffix ".dev" - } - - debug { - initWith release - - // Need to swap with the release signing config when this is ready for public release. - signingConfig signingConfigs.debug - } - - release { - // This buildtype is disabled below. - // The editor can't be used with target=release only, as debugging tools are then not - // included, and it would crash on errors instead of reporting them. - } - } - - packagingOptions { - // 'doNotStrip' is enabled for development within Android Studio - if (shouldNotStrip()) { - doNotStrip '**/*.so' - } - } - - // Disable 'release' buildtype. - // The editor can't be used with target=release only, as debugging tools are then not - // included, and it would crash on errors instead of reporting them. - variantFilter { variant -> - if (variant.buildType.name == "release") { - setIgnore(true) - } - } - - applicationVariants.all { variant -> - variant.outputs.all { output -> - def suffix = variant.name == "dev" ? "_dev" : "" - output.outputFileName = "android_editor${suffix}.apk" - } - } -} diff --git a/platform/android/java/editor/src/.gitignore b/platform/android/java/editor/src/.gitignore deleted file mode 100644 index c081ec3..0000000 --- a/platform/android/java/editor/src/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!/debug diff --git a/platform/android/java/editor/src/main/AndroidManifest.xml b/platform/android/java/editor/src/main/AndroidManifest.xml deleted file mode 100644 index b451c1d..0000000 --- a/platform/android/java/editor/src/main/AndroidManifest.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumEditor.kt b/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumEditor.kt deleted file mode 100644 index 0a5277e..0000000 --- a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumEditor.kt +++ /dev/null @@ -1,396 +0,0 @@ -/*************************************************************************/ -/* PandemoniumEditor.kt */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -package org.pandemoniumengine.editor - -import org.pandemoniumengine.pandemonium.FullScreenPandemoniumApp -import org.pandemoniumengine.pandemonium.utils.PermissionsUtil -import org.pandemoniumengine.pandemonium.utils.ProcessPhoenix -import org.pandemoniumengine.pandemonium.PandemoniumLib - -import android.Manifest -import android.app.ActivityManager -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.os.* -import android.util.Log -import android.widget.Toast - -import androidx.window.layout.WindowMetricsCalculator; - -import java.util.* -import kotlin.math.min - -/** - * Base class for the Pandemonium Android Editor activities. - * - * This provides the basic templates for the activities making up this application. - * Each derived activity runs in its own process, which enable up to have several instances of - * the Pandemonium engine up and running at the same time. - * - * It also plays the role of the primary editor window. - */ -open class PandemoniumEditor : FullScreenPandemoniumApp() { - companion object { - private val TAG = PandemoniumEditor::class.java.simpleName - - private const val WAIT_FOR_DEBUGGER = false - - private const val EXTRA_COMMAND_LINE_PARAMS = "command_line_params" - - private const val EDITOR_ID = 777 - private const val EDITOR_ARG = "--editor" - private const val EDITOR_ARG_SHORT = "-e" - private const val EDITOR_PROCESS_NAME_SUFFIX = ":PandemoniumEditor" - - private const val GAME_ID = 667 - private const val GAME_PROCESS_NAME_SUFFIX = ":PandemoniumGame" - - private const val PROJECT_MANAGER_ID = 555 - private const val PROJECT_MANAGER_ARG = "--project-manager" - private const val PROJECT_MANAGER_ARG_SHORT = "-p" - private const val PROJECT_MANAGER_PROCESS_NAME_SUFFIX = ":PandemoniumProjectManager" - - /** - * Sets of constants to specify the window to use to run the project. - * - * Should match the values in 'editor/editor_settings.cpp' for the - * 'run/window_placement/android_window' setting. - */ - private const val ANDROID_WINDOW_AUTO = 0 - private const val ANDROID_WINDOW_SAME_AS_EDITOR = 1 - private const val ANDROID_WINDOW_SIDE_BY_SIDE_WITH_EDITOR = 2 - } - - private val commandLineParams = ArrayList() - - override fun onCreate(savedInstanceState : Bundle?) { - // We exclude certain permissions from the set we request at startup, as they'll be - // requested on demand based on use-cases. - PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO)) - - val params = intent.getStringArrayExtra(EXTRA_COMMAND_LINE_PARAMS) - Log.d(TAG, "Received parameters ${params.contentToString()}") - updateCommandLineParams(params) - - if (BuildConfig.BUILD_TYPE == "dev" && WAIT_FOR_DEBUGGER) { - Debug.waitForDebugger(); - } - - super.onCreate(savedInstanceState); - } - - override fun onPandemoniumSetupCompleted() { - super.onPandemoniumSetupCompleted() - val longPressEnabled = enableLongPressGestures() - val panScaleEnabled = enablePanAndScaleGestures() - - checkForProjectPermissionsToEnable() - - runOnUiThread { - // Enable long press, panning and scaling gestures - pandemoniumFragment?.renderView?.inputHandler?.apply { - enableLongPress(longPressEnabled) - enablePanningAndScalingGestures(panScaleEnabled) - } - } - } - - /** - * Check for project permissions to enable - */ - protected open fun checkForProjectPermissionsToEnable() { - // Check for RECORD_AUDIO permission - val audioInputEnabled = java.lang.Boolean.parseBoolean(PandemoniumLib.getGlobal("audio/enable_audio_input")); - if (audioInputEnabled) { - PermissionsUtil.requestPermission(Manifest.permission.RECORD_AUDIO, this) - } - } - - private fun updateCommandLineParams(args: Array?) { - // Update the list of command line params with the new args - commandLineParams.clear() - if (!args.isNullOrEmpty()) { - commandLineParams.addAll(listOf(*args)) - } - if (BuildConfig.BUILD_TYPE == "dev") { - commandLineParams.add("--benchmark") - } - } - - override fun getCommandLine() = commandLineParams - - override fun onNewPandemoniumInstanceRequested(args: Array): Int { - // Parse the arguments to figure out which activity to start. - var targetClass: Class<*> = PandemoniumGame::class.java - var instanceId = GAME_ID - - // Whether we should launch the new pandemonium instance in an adjacent window - // https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_LAUNCH_ADJACENT - var launchAdjacent = shouldGameLaunchAdjacent() - - for (arg in args) { - if (EDITOR_ARG == arg || EDITOR_ARG_SHORT == arg) { - targetClass = PandemoniumEditor::class.java - launchAdjacent = false - instanceId = EDITOR_ID - break - } - - if (PROJECT_MANAGER_ARG == arg || PROJECT_MANAGER_ARG_SHORT == arg) { - targetClass = PandemoniumProjectManager::class.java - launchAdjacent = false - instanceId = PROJECT_MANAGER_ID - break - } - } - - // Launch a new activity - val newInstance = Intent(this, targetClass).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra(EXTRA_COMMAND_LINE_PARAMS, args) - - if (launchAdjacent) { - newInstance.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT) - } - - if (targetClass == javaClass) { - Log.d(TAG, "Restarting $targetClass with parameters ${args.contentToString()}") - ProcessPhoenix.triggerRebirth(this, newInstance) - } else { - Log.d(TAG, "Starting $targetClass with parameters ${args.contentToString()}") - newInstance.putExtra(EXTRA_NEW_LAUNCH, true) - startActivity(newInstance) - } - - return instanceId - } - - override fun enableForStealingFocus(processId: Int) { - if (shouldGameLaunchAdjacent()) { - return; - } - - var reorder_intent : Intent? = null; - - when (processId) { - GAME_ID -> { - reorder_intent = Intent(this, PandemoniumGame::class.java); - } - EDITOR_ID -> { - reorder_intent = Intent(this, PandemoniumEditor::class.java); - } - PROJECT_MANAGER_ID -> { - reorder_intent = Intent(this, PandemoniumProjectManager::class.java); - } - else -> { - // An unknown PID means the original editor instance - reorder_intent = Intent(this, PandemoniumEditor::class.java); - } - } - - if (reorder_intent != null) { - reorder_intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - reorder_intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - startActivity(reorder_intent); - } - } - - override fun moveWindowToForeground() { - if (shouldGameLaunchAdjacent()) { - return; - } - - var reorder_intent : Intent = Intent(this, javaClass); - reorder_intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - reorder_intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - startActivity(reorder_intent); - } - - override fun onPandemoniumForceQuit(pandemoniumInstanceId: Int): Boolean { - val targetClass: Class<*>? - val processNameSuffix: String - - when (pandemoniumInstanceId) { - GAME_ID -> { - processNameSuffix = GAME_PROCESS_NAME_SUFFIX - targetClass = PandemoniumGame::class.java - } - EDITOR_ID -> { - processNameSuffix = EDITOR_PROCESS_NAME_SUFFIX - targetClass = PandemoniumEditor::class.java - } - PROJECT_MANAGER_ID -> { - processNameSuffix = PROJECT_MANAGER_PROCESS_NAME_SUFFIX - targetClass = PandemoniumProjectManager::class.java - } - else -> { - processNameSuffix = "" - targetClass = null - } - } - - if (targetClass == javaClass) { - Log.d(TAG, "Force quitting $targetClass") - ProcessPhoenix.forceQuit(this) - return true - } - - if (processNameSuffix.isBlank()) { - return false - } - - val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager - val runningProcesses = activityManager.runningAppProcesses - for (runningProcess in runningProcesses) { - if (runningProcess.processName.endsWith(processNameSuffix)) { - if (targetClass == null) { - // Killing process directly - Log.v(TAG, "Killing Pandemonium process ${runningProcess.processName}") - Process.killProcess(runningProcess.pid) - } else { - // Activity is running; sending a request for self termination. - Log.v(TAG, "Sending force quit request to $targetClass running on process ${runningProcess.processName}") - val forceQuitIntent = Intent(this, targetClass).putExtra(EXTRA_FORCE_QUIT, true) - startActivity(forceQuitIntent) - } - - return true - } - } - - return false - } - - // Get the screen's density scale - protected val isLargeScreen: Boolean - // Get the minimum window size // Correspond to the EXPANDED window size class. - get() { - val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this) - - // Get the screen's density scale - val scale = resources.displayMetrics.density - - // Get the minimum window size - val minSize = min(metrics.bounds.width(), metrics.bounds.height()).toFloat() - val minSizeDp = minSize / scale - return minSizeDp >= 840f // Correspond to the EXPANDED window size class. - } - - override fun setRequestedOrientation(requestedOrientation: Int) { - if (!overrideOrientationRequest()) { - super.setRequestedOrientation(requestedOrientation) - } - } - - /** - * The Android Editor sets its own orientation via its AndroidManifest - */ - protected open fun overrideOrientationRequest() = true - - /** - * Enable long press gestures for the Pandemonium Android editor. - */ - protected open fun enableLongPressGestures() = - java.lang.Boolean.parseBoolean(PandemoniumLib.getEditorSetting("interface/touchscreen/enable_long_press_as_right_click")) - - /** - * Enable pan and scale gestures for the Pandemonium Android editor. - */ - protected open fun enablePanAndScaleGestures() = - java.lang.Boolean.parseBoolean(PandemoniumLib.getEditorSetting("interface/touchscreen/enable_pan_and_scale_gestures")) - - - - protected open fun shouldGameLaunchAdjacent(): Boolean { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - try { - when (Integer.parseInt(PandemoniumLib.getEditorSetting("run/window_placement/android_window"))) { - ANDROID_WINDOW_SAME_AS_EDITOR -> false - ANDROID_WINDOW_SIDE_BY_SIDE_WITH_EDITOR -> true - else -> { - // ANDROID_WINDOW_AUTO - isInMultiWindowMode || isLargeScreen - } - } - } catch (e: NumberFormatException) { - // Fall-back to the 'Auto' behavior - isInMultiWindowMode || isLargeScreen - } - } else { - false - } - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - // Check if we got the MANAGE_EXTERNAL_STORAGE permission - if (requestCode == PermissionsUtil.REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - if (!Environment.isExternalStorageManager()) { - Toast.makeText( - this, - R.string.denied_storage_permission_error_msg, - Toast.LENGTH_LONG - ).show() - } - } - } - } - - override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, - grantResults: IntArray - ) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - // Check if we got access to the necessary storage permissions - if (requestCode == PermissionsUtil.REQUEST_ALL_PERMISSION_REQ_CODE) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { - var hasReadAccess = false - var hasWriteAccess = false - for (i in permissions.indices) { - if (Manifest.permission.READ_EXTERNAL_STORAGE == permissions[i] && grantResults[i] == PackageManager.PERMISSION_GRANTED) { - hasReadAccess = true - } - if (Manifest.permission.WRITE_EXTERNAL_STORAGE == permissions[i] && grantResults[i] == PackageManager.PERMISSION_GRANTED) { - hasWriteAccess = true - } - } - if (!hasReadAccess || !hasWriteAccess) { - Toast.makeText( - this, - R.string.denied_storage_permission_error_msg, - Toast.LENGTH_LONG - ).show() - } - } - } - } -} diff --git a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumGame.kt b/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumGame.kt deleted file mode 100644 index dac7148..0000000 --- a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumGame.kt +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************/ -/* PandemoniumGame.kt */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -package org.pandemoniumengine.editor - -import android.content.Intent -import android.os.* - -/** - * Drives the 'run project' window of the Pandemonium Editor. - */ -class PandemoniumGame : PandemoniumEditor() { - private var isAdjacentFlagSet = false - - override fun overrideOrientationRequest() = false - - override fun enableLongPressGestures() = false - - override fun enablePanAndScaleGestures() = false - - override fun checkForProjectPermissionsToEnable() { - // Nothing to do.. by the time we get here, the project permissions will have already - // been requested by the Editor window. - } - - override fun onCreate(savedInstanceState : Bundle?) { - isAdjacentFlagSet = (getIntent().getFlags() and Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0; - - super.onCreate(savedInstanceState); - } - - override fun shouldGameLaunchAdjacent(): Boolean { - return isAdjacentFlagSet - } -} diff --git a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumProjectManager.kt b/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumProjectManager.kt deleted file mode 100644 index 1eec77c..0000000 --- a/platform/android/java/editor/src/main/java/org/pandemoniumengine/editor/PandemoniumProjectManager.kt +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************/ -/* PandemoniumProjectManager.kt */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 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. */ -/*************************************************************************/ - -package org.pandemoniumengine.editor - -/** - * Launcher activity for the Pandemonium Android Editor. - * - * It presents the user with the project manager interface. - * Upon selection of a project, this activity (via its parent logic) starts the - * [PandemoniumEditor] activity. - */ - -class PandemoniumProjectManager : PandemoniumEditor() { - override fun checkForProjectPermissionsToEnable() { - // Nothing to do here.. we have yet to select a project to load. - } - - override fun shouldGameLaunchAdjacent(): Boolean { - return false - } -} - diff --git a/platform/android/java/editor/src/main/res/values/dimens.xml b/platform/android/java/editor/src/main/res/values/dimens.xml deleted file mode 100644 index 4b05895..0000000 --- a/platform/android/java/editor/src/main/res/values/dimens.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - 600dp - 800dp - \ No newline at end of file diff --git a/platform/android/java/editor/src/main/res/values/strings.xml b/platform/android/java/editor/src/main/res/values/strings.xml deleted file mode 100644 index 590cfc1..0000000 --- a/platform/android/java/editor/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - Pandemonium Editor - Missing storage access permission! - \ No newline at end of file diff --git a/platform/android/java/gradle.properties b/platform/android/java/gradle.properties deleted file mode 100644 index 7ed5419..0000000 --- a/platform/android/java/gradle.properties +++ /dev/null @@ -1,28 +0,0 @@ -# Project-wide Gradle settings. -# NOTE: This should be kept in sync with 'pandemonium/platform/android/java/app/gradle.properties' except -# where otherwise specified. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -android.enableJetifier=true -android.useAndroidX=true - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx4536m - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true - -org.gradle.warning.mode=all - -# Disable resource optimizations for template release build. -# NOTE: This is turned on for custom build in order to improve the release build. -android.enableResourceOptimizations=false diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.jar b/platform/android/java/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59203 zcma&O1CT9Y(k9%tZQHhO+qUh#ZQHhO+qmuS+qP|E@9xZO?0h@l{(r>DQ>P;GjjD{w zH}lENr;dU&FbEU?00aa80D$0M0RRB{U*7-#kbjS|qAG&4l5%47zyJ#WrfA#1$1Ctx zf&Z_d{GW=lf^w2#qRJ|CvSJUi(^E3iv~=^Z(zH}F)3Z%V3`@+rNB7gTVU{Bb~90p|f+0(v;nz01EG7yDMX9@S~__vVgv%rS$+?IH+oZ03D5zYrv|^ zC1J)SruYHmCki$jLBlTaE5&dFG9-kq3!^i>^UQL`%gn6)jz54$WDmeYdsBE9;PqZ_ zoGd=P4+|(-u4U1dbAVQrFWoNgNd;0nrghPFbQrJctO>nwDdI`Q^i0XJDUYm|T|RWc zZ3^Qgo_Qk$%Fvjj-G}1NB#ZJqIkh;kX%V{THPqOyiq)d)0+(r9o(qKlSp*hmK#iIY zA^)Vr$-Hz<#SF=0@tL@;dCQsm`V9s1vYNq}K1B)!XSK?=I1)tX+bUV52$YQu*0%fnWEukW>mxkz+%3-S!oguE8u#MGzST8_Dy^#U?fA@S#K$S@9msUiX!gd_ow>08w5)nX{-KxqMOo7d?k2&?Vf z&diGDtZr(0cwPe9z9FAUSD9KC)7(n^lMWuayCfxzy8EZsns%OEblHFSzP=cL6}?J| z0U$H!4S_TVjj<`6dy^2j`V`)mC;cB%* z8{>_%E1^FH!*{>4a7*C1v>~1*@TMcLK{7nEQ!_igZC}ikJ$*<$yHy>7)oy79A~#xE zWavoJOIOC$5b6*q*F_qN1>2#MY)AXVyr$6x4b=$x^*aqF*L?vmj>Mgv+|ITnw_BoW zO?jwHvNy^prH{9$rrik1#fhyU^MpFqF2fYEt(;4`Q&XWOGDH8k6M=%@fics4ajI;st# zCU^r1CK&|jzUhRMv;+W~6N;u<;#DI6cCw-otsc@IsN3MoSD^O`eNflIoR~l4*&-%RBYk@gb^|-JXs&~KuSEmMxB}xSb z@K76cXD=Y|=I&SNC2E+>Zg?R6E%DGCH5J1nU!A|@eX9oS(WPaMm==k2s_ueCqdZw| z&hqHp)47`c{BgwgvY2{xz%OIkY1xDwkw!<0veB#yF4ZKJyabhyyVS`gZepcFIk%e2 zTcrmt2@-8`7i-@5Nz>oQWFuMC_KlroCl(PLSodswHqJ3fn<;gxg9=}~3x_L3P`9Sn zChIf}8vCHvTriz~T2~FamRi?rh?>3bX1j}%bLH+uFX+p&+^aXbOK7clZxdU~6Uxgy z8R=obwO4dL%pmVo*Ktf=lH6hnlz_5k3cG;m8lgaPp~?eD!Yn2kf)tU6PF{kLyn|oI@eQ`F z3IF7~Blqg8-uwUuWZScRKn%c2_}dXB6Dx_&xR*n9M9LXasJhtZdr$vBY!rP{c@=)& z#!?L$2UrkvClwQO>U*fSMs67oSj2mxiJ$t;E|>q%Kh_GzzWWO&3;ufU%2z%ucBU8H z3WIwr$n)cfCXR&>tyB7BcSInK>=ByZA%;cVEJhcg<#6N{aZC4>K41XF>ZgjG`z_u& zGY?;Ad?-sgiOnI`oppF1o1Gurqbi*;#x2>+SSV6|1^G@ooVy@fg?wyf@0Y!UZ4!}nGuLeC^l)6pwkh|oRY`s1Pm$>zZ3u-83T|9 zGaKJIV3_x+u1>cRibsaJpJqhcm%?0-L;2 zitBrdRxNmb0OO2J%Y&Ym(6*`_P3&&5Bw157{o7LFguvxC$4&zTy#U=W*l&(Q2MNO} zfaUwYm{XtILD$3864IA_nn34oVa_g^FRuHL5wdUd)+W-p-iWCKe8m_cMHk+=? zeKX)M?Dt(|{r5t7IenkAXo%&EXIb-i^w+0CX0D=xApC=|Xy(`xy+QG^UyFe z+#J6h_&T5i#sV)hj3D4WN%z;2+jJcZxcI3*CHXGmOF3^)JD5j&wfX)e?-|V0GPuA+ zQFot%aEqGNJJHn$!_}#PaAvQ^{3-Ye7b}rWwrUmX53(|~i0v{}G_sI9uDch_brX&6 zWl5Ndj-AYg(W9CGfQf<6!YmY>Ey)+uYd_JNXH=>|`OH-CDCmcH(0%iD_aLlNHKH z7bcW-^5+QV$jK?R*)wZ>r9t}loM@XN&M-Pw=F#xn(;u3!(3SXXY^@=aoj70;_=QE9 zGghsG3ekq#N||u{4We_25U=y#T*S{4I{++Ku)> zQ!DZW;pVcn>b;&g2;YE#+V`v*Bl&Y-i@X6D*OpNA{G@JAXho&aOk(_j^weW{#3X5Y z%$q_wpb07EYPdmyH(1^09i$ca{O<}7) zRWncXdSPgBE%BM#by!E>tdnc$8RwUJg1*x($6$}ae$e9Knj8gvVZe#bLi!<+&BkFj zg@nOpDneyc+hU9P-;jmOSMN|*H#>^Ez#?;%C3hg_65leSUm;iz)UkW)jX#p)e&S&M z1|a?wDzV5NVnlhRBCd_;F87wp>6c<&nkgvC+!@KGiIqWY4l}=&1w7|r6{oBN8xyzh zG$b#2=RJp_iq6)#t5%yLkKx(0@D=C3w+oiXtSuaQ%I1WIb-eiE$d~!)b@|4XLy!CZ z9p=t=%3ad@Ep+<9003D2KZ5VyP~_n$=;~r&YUg5UZ0KVD&tR1DHy9x)qWtKJp#Kq# zP*8p#W(8JJ_*h_3W}FlvRam?<4Z+-H77^$Lvi+#vmhL9J zJ<1SV45xi;SrO2f=-OB(7#iNA5)x1uNC-yNxUw|!00vcW2PufRm>e~toH;M0Q85MQLWd?3O{i8H+5VkR@l9Dg-ma ze2fZ%>G(u5(k9EHj2L6!;(KZ8%8|*-1V|B#EagbF(rc+5iL_5;Eu)L4Z-V;0HfK4d z*{utLse_rvHZeQ>V5H=f78M3Ntg1BPxFCVD{HbNA6?9*^YIq;B-DJd{Ca2L#)qWP? zvX^NhFmX?CTWw&Ns}lgs;r3i+Bq@y}Ul+U%pzOS0Fcv9~aB(0!>GT0)NO?p=25LjN z2bh>6RhgqD7bQj#k-KOm@JLgMa6>%-ok1WpOe)FS^XOU{c?d5shG(lIn3GiVBxmg`u%-j=)^v&pX1JecJics3&jvPI)mDut52? z3jEA)DM%}BYbxxKrizVYwq?(P&19EXlwD9^-6J+4!}9{ywR9Gk42jjAURAF&EO|~N z)?s>$Da@ikI4|^z0e{r`J8zIs>SpM~Vn^{3fArRu;?+43>lD+^XtUcY1HidJwnR6+ z!;oG2=B6Z_=M%*{z-RaHc(n|1RTKQdNjjV!Pn9lFt^4w|AeN06*j}ZyhqZ^!-=cyGP_ShV1rGxkx8t zB;8`h!S{LD%ot``700d0@Grql(DTt4Awgmi+Yr0@#jbe=2#UkK%rv=OLqF)9D7D1j z!~McAwMYkeaL$~kI~90)5vBhBzWYc3Cj1WI0RS`z000R8-@ET0dA~*r(gSiCJmQMN&4%1D zyVNf0?}sBH8zNbBLn>~(W{d3%@kL_eQ6jEcR{l>C|JK z(R-fA!z|TTRG40|zv}7E@PqCAXP3n`;%|SCQ|ZS%ym$I{`}t3KPL&^l5`3>yah4*6 zifO#{VNz3)?ZL$be;NEaAk9b#{tV?V7 zP|wf5YA*1;s<)9A4~l3BHzG&HH`1xNr#%){4xZ!jq%o=7nN*wMuXlFV{HaiQLJ`5G zBhDi#D(m`Q1pLh@Tq+L;OwuC52RdW7b8}~60WCOK5iYMUad9}7aWBuILb({5=z~YF zt?*Jr5NG+WadM{mDL>GyiByCuR)hd zA=HM?J6l1Xv0Dl+LW@w$OTcEoOda^nFCw*Sy^I@$sSuneMl{4ys)|RY#9&NxW4S)9 zq|%83IpslTLoz~&vTo!Ga@?rj_kw{|k{nv+w&Ku?fyk4Ki4I?);M|5Axm)t+BaE)D zm(`AQ#k^DWrjbuXoJf2{Aj^KT zFb1zMSqxq|vceV+Mf-)$oPflsO$@*A0n0Z!R{&(xh8s}=;t(lIy zv$S8x>m;vQNHuRzoaOo?eiWFe{0;$s`Bc+Osz~}Van${u;g(su`3lJ^TEfo~nERfP z)?aFzpDgnLYiERsKPu|0tq4l2wT)Atr6Qb%m-AUn6HnCue*yWICp7TjW$@sO zm5rm4aTcPQ(rfi7a`xP7cKCFrJD}*&_~xgLyr^-bmsL}y;A5P|al8J3WUoBSjqu%v zxC;mK!g(7r6RRJ852Z~feoC&sD3(6}^5-uLK8o)9{8L_%%rItZK9C){UxB|;G>JbP zsRRtS4-3B*5c+K2kvmgZK8472%l>3cntWUOVHxB|{Ay~aOg5RN;{PJgeVD*H%ac+y!h#wi%o2bF2Ca8IyMyH{>4#{E_8u^@+l-+n=V}Sq?$O z{091@v%Bd*3pk0^2UtiF9Z+(a@wy6 zUdw8J*ze$K#=$48IBi1U%;hmhO>lu!uU;+RS}p&6@rQila7WftH->*A4=5W|Fmtze z)7E}jh@cbmr9iup^i%*(uF%LG&!+Fyl@LFA-}Ca#bxRfDJAiR2dt6644TaYw1Ma79 zt8&DYj31j^5WPNf5P&{)J?WlCe@<3u^78wnd(Ja4^a>{^Tw}W>|Cjt^If|7l^l)^Q zbz|7~CF(k_9~n|h;ysZ+jHzkXf(*O*@5m zLzUmbHp=x!Q|!9NVXyipZ3)^GuIG$k;D)EK!a5=8MFLI_lpf`HPKl=-Ww%z8H_0$j ztJ||IfFG1lE9nmQ0+jPQy zCBdKkjArH@K7jVcMNz);Q(Q^R{d5G?-kk;Uu_IXSyWB)~KGIizZL(^&qF;|1PI7!E zTP`%l)gpX|OFn&)M%txpQ2F!hdA~hX1Cm5)IrdljqzRg!f{mN%G~H1&oqe`5eJCIF zHdD7O;AX-{XEV(a`gBFJ9ews#CVS2y!&>Cm_dm3C8*n3MA*e67(WC?uP@8TXuMroq z{#w$%z@CBIkRM7?}Xib+>hRjy?%G!fiw8! z8(gB+8J~KOU}yO7UGm&1g_MDJ$IXS!`+*b*QW2x)9>K~Y*E&bYMnjl6h!{17_8d!%&9D`a7r&LKZjC<&XOvTRaKJ1 zUY@hl5^R&kZl3lU3njk`3dPzxj$2foOL26r(9zsVF3n_F#v)s5vv3@dgs|lP#eylq62{<-vczqP!RpVBTgI>@O6&sU>W|do17+#OzQ7o5A$ICH z?GqwqnK^n2%LR;$^oZM;)+>$X3s2n}2jZ7CdWIW0lnGK-b#EG01)P@aU`pg}th&J-TrU`tIpb5t((0eu|!u zQz+3ZiOQ^?RxxK4;zs=l8q!-n7X{@jSwK(iqNFiRColuEOg}!7cyZi`iBX4g1pNBj zAPzL?P^Ljhn;1$r8?bc=#n|Ed7wB&oHcw()&*k#SS#h}jO?ZB246EGItsz*;^&tzp zu^YJ0=lwsi`eP_pU8}6JA7MS;9pfD;DsSsLo~ogzMNP70@@;Fm8f0^;>$Z>~}GWRw!W5J3tNX*^2+1f3hz{~rIzJo z6W%J(H!g-eI_J1>0juX$X4Cl6i+3wbc~k146UIX&G22}WE>0ga#WLsn9tY(&29zBvH1$`iWtTe zG2jYl@P!P)eb<5DsR72BdI7-zP&cZNI{7q3e@?N8IKc4DE#UVr->|-ryuJXk^u^>4 z$3wE~=q390;XuOQP~TNoDR?#|NSPJ%sTMInA6*rJ%go|=YjGe!B>z6u$IhgQSwoV* zjy3F2#I>uK{42{&IqP59)Y(1*Z>>#W8rCf4_eVsH)`v!P#^;BgzKDR`ARGEZzkNX+ zJUQu=*-ol=Xqqt5=`=pA@BIn@6a9G8C{c&`i^(i+BxQO9?YZ3iu%$$da&Kb?2kCCo zo7t$UpSFWqmydXf@l3bVJ=%K?SSw)|?srhJ-1ZdFu*5QhL$~-IQS!K1s@XzAtv6*Y zl8@(5BlWYLt1yAWy?rMD&bwze8bC3-GfNH=p zynNFCdxyX?K&G(ZZ)afguQ2|r;XoV^=^(;Cku#qYn4Lus`UeKt6rAlFo_rU`|Rq z&G?~iWMBio<78of-2X(ZYHx~=U0Vz4btyXkctMKdc9UM!vYr~B-(>)(Hc|D zMzkN4!PBg%tZoh+=Gba!0++d193gbMk2&krfDgcbx0jI92cq?FFESVg0D$>F+bil} zY~$)|>1HZsX=5sAZ2WgPB5P=8X#TI+NQ(M~GqyVB53c6IdX=k>Wu@A0Svf5#?uHaF zsYn|koIi3$(%GZ2+G+7Fv^lHTb#5b8sAHSTnL^qWZLM<(1|9|QFw9pnRU{svj}_Al zL)b9>fN{QiA($8peNEJyy`(a{&uh-T4_kdZFIVsKKVM(?05}76EEz?#W za^fiZOAd14IJ4zLX-n7Lq0qlQ^lW8Cvz4UKkV9~P}>sq0?xD3vg+$4vLm~C(+ zM{-3Z#qnZ09bJ>}j?6ry^h+@PfaD7*jZxBEY4)UG&daWb??6)TP+|3#Z&?GL?1i+280CFsE|vIXQbm| zM}Pk!U`U5NsNbyKzkrul-DzwB{X?n3E6?TUHr{M&+R*2%yOiXdW-_2Yd6?38M9Vy^ z*lE%gA{wwoSR~vN0=no}tP2Ul5Gk5M(Xq`$nw#ndFk`tcpd5A=Idue`XZ!FS>Q zG^0w#>P4pPG+*NC9gLP4x2m=cKP}YuS!l^?sHSFftZy{4CoQrb_ z^20(NnG`wAhMI=eq)SsIE~&Gp9Ne0nD4%Xiu|0Fj1UFk?6avDqjdXz{O1nKao*46y zT8~iA%Exu=G#{x=KD;_C&M+Zx4+n`sHT>^>=-1YM;H<72k>$py1?F3#T1*ef9mLZw z5naLQr?n7K;2l+{_uIw*_1nsTn~I|kkCgrn;|G~##hM;9l7Jy$yJfmk+&}W@JeKcF zx@@Woiz8qdi|D%aH3XTx5*wDlbs?dC1_nrFpm^QbG@wM=i2?Zg;$VK!c^Dp8<}BTI zyRhAq@#%2pGV49*Y5_mV4+OICP|%I(dQ7x=6Ob}>EjnB_-_18*xrY?b%-yEDT(wrO z9RY2QT0`_OpGfMObKHV;QLVnrK%mc?$WAdIT`kJQT^n%GuzE7|9@k3ci5fYOh(287 zuIbg!GB3xLg$YN=n)^pHGB0jH+_iIiC=nUcD;G6LuJsjn2VI1cyZx=a?ShCsF==QK z;q~*m&}L<-cb+mDDXzvvrRsybcgQ;Vg21P(uLv5I+eGc7o7tc6`;OA9{soHFOz zT~2?>Ts}gprIX$wRBb4yE>ot<8+*Bv`qbSDv*VtRi|cyWS>)Fjs>fkNOH-+PX&4(~ z&)T8Zam2L6puQl?;5zg9h<}k4#|yH9czHw;1jw-pwBM*O2hUR6yvHATrI%^mvs9q_ z&ccT0>f#eDG<^WG^q@oVqlJrhxH)dcq2cty@l3~|5#UDdExyXUmLQ}f4#;6fI{f^t zDCsgIJ~0`af%YR%Ma5VQq-p21k`vaBu6WE?66+5=XUd%Ay%D$irN>5LhluRWt7 zov-=f>QbMk*G##&DTQyou$s7UqjjW@k6=!I@!k+S{pP8R(2=e@io;N8E`EOB;OGoI zw6Q+{X1_I{OO0HPpBz!X!@`5YQ2)t{+!?M_iH25X(d~-Zx~cXnS9z>u?+If|iNJbx zyFU2d1!ITX64D|lE0Z{dLRqL1Ajj=CCMfC4lD3&mYR_R_VZ>_7_~|<^o*%_&jevU+ zQ4|qzci=0}Jydw|LXLCrOl1_P6Xf@c0$ieK2^7@A9UbF{@V_0p%lqW|L?5k>bVM8|p5v&2g;~r>B8uo<4N+`B zH{J)h;SYiIVx@#jI&p-v3dwL5QNV1oxPr8J%ooezTnLW>i*3Isb49%5i!&ac_dEXv zvXmVUck^QHmyrF8>CGXijC_R-y(Qr{3Zt~EmW)-nC!tiH`wlw5D*W7Pip;T?&j%kX z6DkZX4&}iw>hE(boLyjOoupf6JpvBG8}jIh!!VhnD0>}KSMMo{1#uU6kiFcA04~|7 zVO8eI&x1`g4CZ<2cYUI(n#wz2MtVFHx47yE5eL~8bot~>EHbevSt}LLMQX?odD{Ux zJMnam{d)W4da{l7&y-JrgiU~qY3$~}_F#G7|MxT)e;G{U`In&?`j<5D->}cb{}{T(4DF0BOk-=1195KB-E*o@c?`>y#4=dMtYtSY=&L{!TAjFVcq0y@AH`vH! z$41+u!Ld&}F^COPgL(EE{0X7LY&%D7-(?!kjFF7=qw<;`V{nwWBq<)1QiGJgUc^Vz ztMUlq1bZqKn17|6x6iAHbWc~l1HcmAxr%$Puv!znW)!JiukwIrqQ00|H$Z)OmGG@= zv%A8*4cq}(?qn4rN6o`$Y))(MyXr8R<2S^J+v(wmFmtac!%VOfN?&(8Nr!T@kV`N; z*Q33V3t`^rN&aBiHet)18wy{*wi1=W!B%B-Q6}SCrUl$~Hl{@!95ydml@FK8P=u4s z4e*7gV2s=YxEvskw2Ju!2%{8h01rx-3`NCPc(O zH&J0VH5etNB2KY6k4R@2Wvl^Ck$MoR3=)|SEclT2ccJ!RI9Nuter7u9@;sWf-%um;GfI!=eEIQ2l2p_YWUd{|6EG ze{yO6;lMc>;2tPrsNdi@&1K6(1;|$xe8vLgiouj%QD%gYk`4p{Ktv9|j+!OF-P?@p z;}SV|oIK)iwlBs+`ROXkhd&NK zzo__r!B>tOXpBJMDcv!Mq54P+n4(@dijL^EpO1wdg~q+!DT3lB<>9AANSe!T1XgC=J^)IP0XEZ()_vpu!!3HQyJhwh?r`Ae%Yr~b% zO*NY9t9#qWa@GCPYOF9aron7thfWT`eujS4`t2uG6)~JRTI;f(ZuoRQwjZjp5Pg34 z)rp$)Kr?R+KdJ;IO;pM{$6|2y=k_siqvp%)2||cHTe|b5Ht8&A{wazGNca zX$Ol?H)E_R@SDi~4{d-|8nGFhZPW;Cts1;08TwUvLLv&_2$O6Vt=M)X;g%HUr$&06 zISZb(6)Q3%?;3r~*3~USIg=HcJhFtHhIV(siOwV&QkQe#J%H9&E21!C*d@ln3E@J* zVqRO^<)V^ky-R|%{(9`l-(JXq9J)1r$`uQ8a}$vr9E^nNiI*thK8=&UZ0dsFN_eSl z(q~lnD?EymWLsNa3|1{CRPW60>DSkY9YQ;$4o3W7Ms&@&lv9eH!tk~N&dhqX&>K@} zi1g~GqglxkZ5pEFkllJ)Ta1I^c&Bt6#r(QLQ02yHTaJB~- zCcE=5tmi`UA>@P=1LBfBiqk)HB4t8D?02;9eXj~kVPwv?m{5&!&TFYhu>3=_ zsGmYZ^mo*-j69-42y&Jj0cBLLEulNRZ9vXE)8~mt9C#;tZs;=#M=1*hebkS;7(aGf zcs7zH(I8Eui9UU4L--))yy`&d&$In&VA2?DAEss4LAPCLd>-$i?lpXvn!gu^JJ$(DoUlc6wE98VLZ*z`QGQov5l4Fm_h?V-;mHLYDVOwKz7>e4+%AzeO>P6v}ndPW| zM>m#6Tnp7K?0mbK=>gV}=@k*0Mr_PVAgGMu$j+pWxzq4MAa&jpCDU&-5eH27Iz>m^ zax1?*HhG%pJ((tkR(V(O(L%7v7L%!_X->IjS3H5kuXQT2!ow(;%FDE>16&3r){!ex zhf==oJ!}YU89C9@mfDq!P3S4yx$aGB?rbtVH?sHpg?J5C->!_FHM%Hl3#D4eplxzQ zRA+<@LD%LKSkTk2NyWCg7u=$%F#;SIL44~S_OGR}JqX}X+=bc@swpiClB`Zbz|f!4 z7Ysah7OkR8liXfI`}IIwtEoL}(URrGe;IM8%{>b1SsqXh)~w}P>yiFRaE>}rEnNkT z!HXZUtxUp1NmFm)Dm@-{FI^aRQqpSkz}ZSyKR%Y}YHNzBk)ZIp} zMtS=aMvkgWKm9&oTcU0?S|L~CDqA+sHpOxwnswF-fEG)cXCzUR?ps@tZa$=O)=L+5 zf%m58cq8g_o}3?Bhh+c!w4(7AjxwQ3>WnVi<{{38g7yFboo>q|+7qs<$8CPXUFAN< zG&}BHbbyQ5n|qqSr?U~GY{@GJ{(Jny{bMaOG{|IkUj7tj^9pa9|FB_<+KHLxSxR;@ zHpS$4V)PP+tx}22fWx(Ku9y+}Ap;VZqD0AZW4gCDTPCG=zgJmF{|x;(rvdM|2|9a}cex6xrMkERnkE;}jvU-kmzd%_J50$M`lIPCKf+^*zL=@LW`1SaEc%=m zQ+lT06Gw+wVwvQ9fZ~#qd430v2HndFsBa9WjD0P}K(rZYdAt^5WQIvb%D^Q|pkVE^ zte$&#~zmULFACGfS#g=2OLOnIf2Of-k!(BIHjs77nr!5Q1*I9 z1%?=~#Oss!rV~?-6Gm~BWJiA4mJ5TY&iPm_$)H1_rTltuU1F3I(qTQ^U$S>%$l z)Wx1}R?ij0idp@8w-p!Oz{&*W;v*IA;JFHA9%nUvVDy7Q8woheC#|8QuDZb-L_5@R zOqHwrh|mVL9b=+$nJxM`3eE{O$sCt$UK^2@L$R(r^-_+z?lOo+me-VW=Zw z-Bn>$4ovfWd%SPY`ab-u9{INc*k2h+yH%toDHIyqQ zO68=u`N}RIIs7lsn1D){)~%>ByF<>i@qFb<-axvu(Z+6t7v<^z&gm9McRB~BIaDn$ z#xSGT!rzgad8o>~kyj#h1?7g96tOcCJniQ+*#=b7wPio>|6a1Z?_(TS{)KrPe}(8j z!#&A=k(&Pj^F;r)CI=Z{LVu>uj!_W1q4b`N1}E(i%;BWjbEcnD=mv$FL$l?zS6bW!{$7j1GR5ocn94P2u{ z70tAAcpqtQo<@cXw~@i-@6B23;317|l~S>CB?hR5qJ%J3EFgyBdJd^fHZu7AzHF(BQ!tyAz^L0`X z23S4Fe{2X$W0$zu9gm%rg~A>ijaE#GlYlrF9$ds^QtaszE#4M(OLVP2O-;XdT(XIC zatwzF*)1c+t~c{L=fMG8Z=k5lv>U0;C{caN1NItnuSMp)6G3mbahu>E#sj&oy94KC zpH}8oEw{G@N3pvHhp{^-YaZeH;K+T_1AUv;IKD<=mv^&Ueegrb!yf`4VlRl$M?wsl zZyFol(2|_QM`e_2lYSABpKR{{NlxlDSYQNkS;J66aT#MSiTx~;tUmvs-b*CrR4w=f z8+0;*th6kfZ3|5!Icx3RV11sp=?`0Jy3Fs0N4GZQMN=8HmT6%x9@{Dza)k}UwL6JT zHRDh;%!XwXr6yuuy`4;Xsn0zlR$k%r%9abS1;_v?`HX_hI|+EibVnlyE@3aL5vhQq zlIG?tN^w@0(v9M*&L+{_+RQZw=o|&BRPGB>e5=ys7H`nc8nx)|-g;s7mRc7hg{GJC zAe^vCIJhajmm7C6g! zL&!WAQ~5d_5)00?w_*|*H>3$loHrvFbitw#WvLB!JASO?#5Ig5$Ys10n>e4|3d;tS zELJ0|R4n3Az(Fl3-r^QiV_C;)lQ1_CW{5bKS15U|E9?ZgLec@%kXr84>5jV2a5v=w z?pB1GPdxD$IQL4)G||B_lI+A=08MUFFR4MxfGOu07vfIm+j=z9tp~5i_6jb`tR>qV z$#`=BQ*jpCjm$F0+F)L%xRlnS%#&gro6PiRfu^l!EVan|r3y}AHJQOORGx4~ z&<)3=K-tx518DZyp%|!EqpU!+X3Et7n2AaC5(AtrkW>_57i}$eqs$rupubg0a1+WO zGHZKLN2L0D;ab%{_S1Plm|hx8R?O14*w*f&2&bB050n!R2by zw!@XOQx$SqZ5I<(Qu$V6g>o#A!JVwErWv#(Pjx=KeS0@hxr4?13zj#oWwPS(7Ro|v z>Mp@Kmxo79q|}!5qtX2-O@U&&@6s~!I&)1WQIl?lTnh6UdKT_1R640S4~f=_xoN3- zI+O)$R@RjV$F=>Ti7BlnG1-cFKCC(t|Qjm{SalS~V-tX#+2ekRhwmN zZr`8{QF6y~Z!D|{=1*2D-JUa<(1Z=;!Ei!KiRNH?o{p5o3crFF=_pX9O-YyJchr$~ zRC`+G+8kx~fD2k*ZIiiIGR<8r&M@3H?%JVOfE>)})7ScOd&?OjgAGT@WVNSCZ8N(p zuQG~76GE3%(%h1*vUXg$vH{ua0b`sQ4f0*y=u~lgyb^!#CcPJa2mkSEHGLsnO^kb$ zru5_l#nu=Y{rSMWiYx?nO{8I!gH+?wEj~UM?IrG}E|bRIBUM>UlY<`T1EHpRr36vv zBi&dG8oxS|J$!zoaq{+JpJy+O^W(nt*|#g32bd&K^w-t>!Vu9N!k9eA8r!Xc{utY> zg9aZ(D2E0gL#W0MdjwES-7~Wa8iubPrd?8-$C4BP?*wok&O8+ykOx{P=Izx+G~hM8 z*9?BYz!T8~dzcZr#ux8kS7u7r@A#DogBH8km8Ry4slyie^n|GrTbO|cLhpqgMdsjX zJ_LdmM#I&4LqqsOUIXK8gW;V0B(7^$y#h3h>J0k^WJfAMeYek%Y-Dcb_+0zPJez!GM zAmJ1u;*rK=FNM0Nf}Y!!P9c4)HIkMnq^b;JFd!S3?_Qi2G#LIQ)TF|iHl~WKK6JmK zbv7rPE6VkYr_%_BT}CK8h=?%pk@3cz(UrZ{@h40%XgThP*-Oeo`T0eq9 zA8BnWZKzCy5e&&_GEsU4*;_k}(8l_&al5K-V*BFM=O~;MgRkYsOs%9eOY6s6AtE*<7GQAR2ulC3RAJrG_P1iQK5Z~&B z&f8X<>yJV6)oDGIlS$Y*D^Rj(cszTy5c81a5IwBr`BtnC6_e`ArI8CaTX_%rx7;cn zR-0?J_LFg*?(#n~G8cXut(1nVF0Oka$A$1FGcERU<^ggx;p@CZc?3UB41RY+wLS`LWFNSs~YP zuw1@DNN3lTd|jDL7gjBsd9}wIw}4xT2+8dBQzI00m<@?c2L%>}QLfK5%r!a-iII`p zX@`VEUH)uj^$;7jVUYdADQ2k*!1O3WdfgF?OMtUXNpQ1}QINamBTKDuv19^{$`8A1 zeq%q*O0mi@(%sZU>Xdb0Ru96CFqk9-L3pzLVsMQ`Xpa~N6CR{9Rm2)A|CI21L(%GW zh&)Y$BNHa=FD+=mBw3{qTgw)j0b!Eahs!rZnpu)z!!E$*eXE~##yaXz`KE5(nQM`s zD!$vW9XH)iMxu9R>r$VlLk9oIR%HxpUiW=BK@4U)|1WNQ=mz9a z^!KkO=>GaJ!GBXm{KJj^;kh-MkUlEQ%lza`-G&}C5y1>La1sR6hT=d*NeCnuK%_LV zOXt$}iP6(YJKc9j-Fxq~*ItVUqljQ8?oaysB-EYtFQp9oxZ|5m0^Hq(qV!S+hq#g( z?|i*H2MIr^Kxgz+3vIljQ*Feejy6S4v~jKEPTF~Qhq!(ms5>NGtRgO5vfPPc4Z^AM zTj!`5xEreIN)vaNxa|q6qWdg>+T`Ol0Uz)ckXBXEGvPNEL3R8hB3=C5`@=SYgAju1 z!)UBr{2~=~xa{b8>x2@C7weRAEuatC)3pkRhT#pMPTpSbA|tan%U7NGMvzmF?c!V8 z=pEWxbdXbTAGtWTyI?Fml%lEr-^AE}w#l(<7OIw;ctw}imYax&vR4UYNJZK6P7ZOd zP87XfhnUHxCUHhM@b*NbTi#(-8|wcv%3BGNs#zRCVV(W?1Qj6^PPQa<{yaBwZ`+<`w|;rqUY_C z&AeyKwwf*q#OW-F()lir=T^<^wjK65Lif$puuU5+tk$;e_EJ;Lu+pH>=-8=PDhkBg z8cWt%@$Sc#C6F$Vd+0507;{OOyT7Hs%nKS88q-W!$f~9*WGBpHGgNp}=C*7!RiZ5s zn1L_DbKF@B8kwhDiLKRB@lsXVVLK|ph=w%_`#owlf@s@V(pa`GY$8h%;-#h@TsO|Y8V=n@*!Rog7<7Cid%apR|x zOjhHCyfbIt%+*PCveTEcuiDi%Wx;O;+K=W?OFUV%)%~6;gl?<0%)?snDDqIvkHF{ zyI02)+lI9ov42^hL>ZRrh*HhjF9B$A@=H94iaBESBF=eC_KT$8A@uB^6$~o?3Wm5t1OIaqF^~><2?4e3c&)@wKn9bD? zoeCs;H>b8DL^F&>Xw-xjZEUFFTv>JD^O#1E#)CMBaG4DX9bD(Wtc8Rzq}9soQ8`jf zeSnHOL}<+WVSKp4kkq&?SbETjq6yr@4%SAqOG=9E(3YeLG9dtV+8vmzq+6PFPk{L; z(&d++iu=^F%b+ea$i2UeTC{R*0Isk;vFK!no<;L+(`y`3&H-~VTdKROkdyowo1iqR zbVW(3`+(PQ2>TKY>N!jGmGo7oeoB8O|P_!Ic@ zZ^;3dnuXo;WJ?S+)%P>{Hcg!Jz#2SI(s&dY4QAy_vRlmOh)QHvs_7c&zkJCmJGVvV zX;Mtb>QE+xp`KyciG$Cn*0?AK%-a|=o!+7x&&yzHQOS>8=B*R=niSnta^Pxp1`=md z#;$pS$4WCT?mbiCYU?FcHGZ#)kHVJTTBt^%XE(Q};aaO=Zik0UgLcc0I(tUpt(>|& zcxB_|fxCF7>&~5eJ=Dpn&5Aj{A^cV^^}(7w#p;HG&Q)EaN~~EqrE1qKrMAc&WXIE;>@<&)5;gD2?={Xf@Mvn@OJKw=8Mgn z!JUFMwD+s==JpjhroT&d{$kQAy%+d`a*XxDEVxy3`NHzmITrE`o!;5ClXNPb4t*8P zzAivdr{j_v!=9!^?T3y?gzmqDWX6mkzhIzJ-3S{T5bcCFMr&RPDryMcdwbBuZbsgN zGrp@^i?rcfN7v0NKGzDPGE#4yszxu=I_`MI%Z|10nFjU-UjQXXA?k8Pk|OE<(?ae) zE%vG#eZAlj*E7_3dx#Zz4kMLj>H^;}33UAankJiDy5ZvEhrjr`!9eMD8COp}U*hP+ zF}KIYx@pkccIgyxFm#LNw~G&`;o&5)2`5aogs`1~7cMZQ7zj!%L4E`2yzlQN6REX20&O<9 zKV6fyr)TScJPPzNTC2gL+0x#=u>(({{D7j)c-%tvqls3#Y?Z1m zV5WUE)zdJ{$p>yX;^P!UcXP?UD~YM;IRa#Rs5~l+*$&nO(;Ers`G=0D!twR(0GF@c zHl9E5DQI}Oz74n zfKP>&$q0($T4y$6w(p=ERAFh+>n%iaeRA%!T%<^+pg?M)@ucY<&59$x9M#n+V&>}=nO9wCV{O~lg&v#+jcUj(tQ z`0u1YH)-`U$15a{pBkGyPL0THv1P|4e@pf@3IBZS4dVJPo#H>pWq%Lr0YS-SeWash z8R7=jb28KPMI|_lo#GEO|5B?N_e``H*23{~a!AmUJ+fb4HX-%QI@lSEUxKlGV7z7Q zSKw@-TR>@1RL%w{x}dW#k1NgW+q4yt2Xf1J62Bx*O^WG8OJ|FqI4&@d3_o8Id@*)4 zYrk=>@!wv~mh7YWv*bZhxqSmFh2Xq)o=m;%n$I?GSz49l1$xRpPu_^N(vZ>*>Z<04 z2+rP70oM=NDysd!@fQdM2OcyT?3T^Eb@lIC-UG=Bw{BjQ&P`KCv$AcJ;?`vdZ4){d z&gkoUK{$!$$K`3*O-jyM1~p-7T*qb)Ys>Myt^;#1&a%O@x8A+E>! zY8=eD`ZG)LVagDLBeHg>=atOG?Kr%h4B%E6m@J^C+U|y)XX@f z8oyJDW|9g=<#f<{JRr{y#~euMnv)`7j=%cHWLc}ngjq~7k**6%4u>Px&W%4D94(r* z+akunK}O0DC2A%Xo9jyF;DobX?!1I(7%}@7F>i%&nk*LMO)bMGg2N+1iqtg+r(70q zF5{Msgsm5GS7DT`kBsjMvOrkx&|EU!{{~gL4d2MWrAT=KBQ-^zQCUq{5PD1orxlIL zq;CvlWx#f1NWvh`hg011I%?T_s!e38l*lWVt|~z-PO4~~1g)SrJ|>*tXh=QfXT)%( z+ex+inPvD&O4Ur;JGz>$sUOnWdpSLcm1X%aQDw4{dB!cnj`^muI$CJ2%p&-kULVCE z>$eMR36kN$wCPR+OFDM3-U(VOrp9k3)lI&YVFqd;Kpz~K)@Fa&FRw}L(SoD z9B4a+hQzZT-BnVltst&=kq6Y(f^S4hIGNKYBgMxGJ^;2yrO}P3;r)(-I-CZ)26Y6? z&rzHI_1GCvGkgy-t1E;r^3Le30|%$ebDRu2+gdLG)r=A~Qz`}~&L@aGJ{}vVs_GE* zVUjFnzHiXfKQbpv&bR&}l2bzIjAooB)=-XNcYmrGmBh(&iu@o!^hn0^#}m2yZZUK8 zufVm7Gq0y`Mj;9b>`c?&PZkU0j4>IL=UL&-Lp3j&47B5pAW4JceG{!XCA)kT<%2nqCxj<)uy6XR_uws~>_MEKPOpAQ!H zkn>FKh)<9DwwS*|Y(q?$^N!6(51O0 z^JM~Ax{AI1Oj$fs-S5d4T7Z_i1?{%0SsIuQ&r8#(JA=2iLcTN+?>wOL532%&dMYkT z*T5xepC+V6zxhS@vNbMoi|i)=rpli@R9~P!39tWbSSb904ekv7D#quKbgFEMTb48P zuq(VJ+&L8aWU(_FCD$3^uD!YM%O^K(dvy~Wm2hUuh6bD|#(I39Xt>N1Y{ZqXL`Fg6 zKQ?T2htHN!(Bx;tV2bfTtIj7e)liN-29s1kew>v(D^@)#v;}C4-G=7x#;-dM4yRWm zyY`cS21ulzMK{PoaQ6xChEZ}o_#}X-o}<&0)$1#3we?+QeLt;aVCjeA)hn!}UaKt< zat1fHEx13y-rXNMvpUUmCVzocPmN~-Y4(YJvQ#db)4|%B!rBsgAe+*yor~}FrNH08 z3V!97S}D7d$zbSD{$z;@IYMxM6aHdypIuS*pr_U6;#Y!_?0i|&yU*@16l z*dcMqDQgfNBf}?quiu4e>H)yTVfsp#f+Du0@=Kc41QockXkCkvu>FBd6Q+@FL!(Yx z2`YuX#eMEiLEDhp+9uFqME_E^faV&~9qjBHJkIp~%$x^bN=N)K@kvSVEMdDuzA0sn z88CBG?`RX1@#hQNd`o^V{37)!w|nA)QfiYBE^m=yQKv-fQF+UCMcuEe1d4BH7$?>b zJl-r9@0^Ie=)guO1vOd=i$_4sz>y3x^R7n4ED!5oXL3@5**h(xr%Hv)_gILarO46q+MaDOF%ChaymKoI6JU5Pg;7#2n9-18|S1;AK+ zgsn6;k6-%!QD>D?cFy}8F;r@z8H9xN1jsOBw2vQONVqBVEbkiNUqgw~*!^##ht>w0 zUOykwH=$LwX2j&nLy=@{hr)2O&-wm-NyjW7n~Zs9UlH;P7iP3 zI}S(r0YFVYacnKH(+{*)Tbw)@;6>%=&Th=+Z6NHo_tR|JCI8TJiXv2N7ei7M^Q+RM z?9o`meH$5Yi;@9XaNR#jIK^&{N|DYNNbtdb)XW1Lv2k{E>;?F`#Pq|&_;gm~&~Zc9 zf+6ZE%{x4|{YdtE?a^gKyzr}dA>OxQv+pq|@IXL%WS0CiX!V zm$fCePA%lU{%pTKD7|5NJHeXg=I0jL@$tOF@K*MI$)f?om)D63K*M|r`gb9edD1~Y zc|w7N)Y%do7=0{RC|AziW7#am$)9jciRJ?IWl9PE{G3U+$%FcyKs_0Cgq`=K3@ttV z9g;M!3z~f_?P%y3-ph%vBMeS@p7P&Ea8M@97+%XEj*(1E6vHj==d zjsoviB>j^$_^OI_DEPvFkVo(BGRo%cJeD){6Uckei=~1}>sp299|IRjhXe)%?uP0I zF5+>?0#Ye}T^Y$u_rc4=lPcq4K^D(TZG-w30-YiEM=dcK+4#o*>lJ8&JLi+3UcpZk z!^?95S^C0ja^jwP`|{<+3cBVog$(mRdQmadS+Vh~z zS@|P}=|z3P6uS+&@QsMp0no9Od&27O&14zHXGAOEy zh~OKpymK5C%;LLb467@KgIiVwYbYd6wFxI{0-~MOGfTq$nBTB!{SrWmL9Hs}C&l&l#m?s*{tA?BHS4mVKHAVMqm63H<|c5n0~k)-kbg zXidai&9ZUy0~WFYYKT;oe~rytRk?)r8bptITsWj(@HLI;@=v5|XUnSls7$uaxFRL+ zRVMGuL3w}NbV1`^=Pw*0?>bm8+xfeY(1PikW*PB>>Tq(FR`91N0c2&>lL2sZo5=VD zQY{>7dh_TX98L2)n{2OV=T10~*YzX27i2Q7W86M4$?gZIXZaBq#sA*{PH8){|GUi;oM>e?ua7eF4WFuFYZSG| zze?srg|5Ti8Og{O zeFxuw9!U+zhyk?@w zjsA6(oKD=Ka;A>Ca)oPORxK+kxH#O@zhC!!XS4@=swnuMk>t+JmLmFiE^1aX3f<)D@`%K0FGK^gg1a1j>zi z2KhV>sjU7AX3F$SEqrXSC}fRx64GDoc%!u2Yag68Lw@w9v;xOONf@o)Lc|Uh3<21ctTYu-mFZuHk*+R{GjXHIGq3p)tFtQp%TYqD=j1&y)>@zxoxUJ!G@ zgI0XKmP6MNzw>nRxK$-Gbzs}dyfFzt>#5;f6oR27ql!%+{tr+(`(>%51|k`ML} zY4eE)Lxq|JMas(;JibNQds1bUB&r}ydMQXBY4x(^&fY_&LlQC)3hylc$~8&~|06-D z#T+%66rYbHX%^KuqJED_wuGB+=h`nWA!>1n0)3wZrBG3%`b^Ozv6__dNa@%V14|!D zQ?o$z5u0^8`giv%qE!BzZ!3j;BlDlJDk)h@9{nSQeEk!z9RGW) z${RSF3phEM*ce*>Xdp}585vj$|40=&S{S-GTiE?Op*vY&Lvr9}BO$XWy80IF+6@%n z5*2ueT_g@ofP#u5pxb7n*fv^Xtt7&?SRc{*2Ka-*!BuOpf}neHGCiHy$@Ka1^Dint z;DkmIL$-e)rj4o2WQV%Gy;Xg(_Bh#qeOsTM2f@KEe~4kJ8kNLQ+;(!j^bgJMcNhvklP5Z6I+9Fq@c&D~8Fb-4rmDT!MB5QC{Dsb;BharP*O;SF4& zc$wj-7Oep7#$WZN!1nznc@Vb<_Dn%ga-O#J(l=OGB`dy=Sy&$(5-n3zzu%d7E#^8`T@}V+5B;PP8J14#4cCPw-SQTdGa2gWL0*zKM z#DfSXs_iWOMt)0*+Y>Lkd=LlyoHjublNLefhKBv@JoC>P7N1_#> zv=mLWe96%EY;!ZGSQDbZWb#;tzqAGgx~uk+-$+2_8U`!ypbwXl z^2E-FkM1?lY@yt8=J3%QK+xaZ6ok=-y%=KXCD^0r!5vUneW>95PzCkOPO*t}p$;-> ze5j-BLT_;)cZQzR2CEsm@rU7GZfFtdp*a|g4wDr%8?2QkIGasRfDWT-Dvy*U{?IHT z*}wGnzdlSptl#ZF^sf)KT|BJs&kLG91^A6ls{CzFprZ6-Y!V0Xysh%9p%iMd7HLsS zN+^Un$tDV)T@i!v?3o0Fsx2qI(AX_$dDkBzQ@fRM%n zRXk6hb9Py#JXUs+7)w@eo;g%QQ95Yq!K_d=z{0dGS+pToEI6=Bo8+{k$7&Z zo4>PH(`ce8E-Ps&uv`NQ;U$%t;w~|@E3WVOCi~R4oj5wP?%<*1C%}Jq%a^q~T7u>K zML5AKfQDv6>PuT`{SrKHRAF+^&edg6+5R_#H?Lz3iGoWo#PCEd0DS;)2U({{X#zU^ zw_xv{4x7|t!S)>44J;KfA|DC?;uQ($l+5Vp7oeqf7{GBF9356nx|&B~gs+@N^gSdd zvb*>&W)|u#F{Z_b`f#GVtQ`pYv3#||N{xj1NgB<#=Odt6{eB%#9RLt5v zIi|0u70`#ai}9fJjKv7dE!9ZrOIX!3{$z_K5FBd-Kp-&e4(J$LD-)NMTp^_pB`RT; zftVVlK2g@+1Ahv2$D){@Y#cL#dUj9*&%#6 zd2m9{1NYp>)6=oAvqdCn5#cx{AJ%S8skUgMglu2*IAtd+z1>B&`MuEAS(D(<6X#Lj z?f4CFx$)M&$=7*>9v1ER4b6!SIz-m0e{o0BfkySREchp?WdVPpQCh!q$t>?rL!&Jg zd#heM;&~A}VEm8Dvy&P|J*eAV&w!&Nx6HFV&B8jJFVTmgLaswn!cx$&%JbTsloz!3 zMEz1d`k==`Ueub_JAy_&`!ogbwx27^ZXgFNAbx=g_I~5nO^r)}&myw~+yY*cJl4$I znNJ32M&K=0(2Dj_>@39`3=FX!v3nZHno_@q^!y}%(yw0PqOo=);6Y@&ylVe>nMOZ~ zd>j#QQSBn3oaWd;qy$&5(5H$Ayi)0haAYO6TH>FR?rhqHmNOO+(})NB zLI@B@v0)eq!ug`>G<@htRlp3n!EpU|n+G+AvXFrWSUsLMBfL*ZB`CRsIVHNTR&b?K zxBgsN0BjfB>UVcJ|x%=-zb%OV7lmZc& zxiupadZVF7)6QuhoY;;FK2b*qL0J-Rn-8!X4ZY$-ZSUXV5DFd7`T41c(#lAeLMoeT z4%g655v@7AqT!i@)Edt5JMbN(=Q-6{=L4iG8RA%}w;&pKmtWvI4?G9pVRp|RTw`g0 zD5c12B&A2&P6Ng~8WM2eIW=wxd?r7A*N+&!Be7PX3s|7~z=APxm=A?5 zt>xB4WG|*Td@VX{Rs)PV0|yK`oI3^xn(4c_j&vgxk_Y3o(-`_5o`V zRTghg6%l@(qodXN;dB#+OKJEEvhfcnc#BeO2|E(5df-!fKDZ!%9!^BJ_4)9P+9Dq5 zK1=(v?KmIp34r?z{NEWnLB3Px{XYwy-akun4F7xTRr2^zeYW{gcK9)>aJDdU5;w5@ zak=<+-PLH-|04pelTb%ULpuuuJC7DgyT@D|p{!V!0v3KpDnRjANN12q6SUR3mb9<- z>2r~IApQGhstZ!3*?5V z8#)hJ0TdZg0M-BK#nGFP>$i=qk82DO z7h;Ft!D5E15OgW)&%lej*?^1~2=*Z5$2VX>V{x8SC+{i10BbtUk9@I#Vi&hX)q
Q!LwySI{Bnv%Sm)yh{^sSVJ8&h_D-BJ_YZe5eCaAWU9b$O2c z$T|{vWVRtOL!xC0DTc(Qbe`ItNtt5hr<)VijD0{U;T#bUEp381_y`%ZIav?kuYG{iyYdEBPW=*xNSc;Rlt6~F4M`5G+VtOjc z*0qGzCb@gME5udTjJA-9O<&TWd~}ysBd(eVT1-H82-doyH9RST)|+Pb{o*;$j9Tjs zhU!IlsPsj8=(x3bAKJTopW3^6AKROHR^7wZ185wJGVhA~hEc|LP;k7NEz-@4p5o}F z`AD6naG3(n=NF9HTH81=F+Q|JOz$7wm9I<+#BSmB@o_cLt2GkW9|?7mM;r!JZp89l zbo!Hp8=n!XH1{GwaDU+k)pGp`C|cXkCU5%vcH)+v@0eK>%7gWxmuMu9YLlChA|_D@ zi#5zovN_!a-0?~pUV-Rj*1P)KwdU-LguR>YM&*Nen+ln8Q$?WFCJg%DY%K}2!!1FE zDv-A%Cbwo^p(lzac&_TZ-l#9kq`mhLcY3h9ZTUVCM(Ad&=EriQY5{jJv<5K&g|*Lk zgV%ILnf1%8V2B0E&;Sp4sYbYOvvMebLwYwzkRQ#F8GpTQq#uv=J`uaSJ34OWITeSGo6+-8Xw znCk*n{kdDEi)Hi&u^)~cs@iyCkFWB2SWZU|Uc%^43ZIZQ-vWNExCCtDWjqHs;;tWf$v{}0{p0Rvxkq``)*>+Akq%|Na zA`@~-Vfe|+(AIlqru+7Ceh4nsVmO9p9jc8}HX^W&ViBDXT+uXbT#R#idPn&L>+#b6 zflC-4C5-X;kUnR~L>PSLh*gvL68}RBsu#2l`s_9KjUWRhiqF`j)`y`2`YU(>3bdBj z?>iyjEhe-~$^I5!nn%B6Wh+I`FvLNvauve~eX<+Ipl&04 zT}};W&1a3%W?dJ2=N#0t?e+aK+%t}5q%jSLvp3jZ%?&F}nOOWr>+{GFIa%wO_2`et z=JzoRR~}iKuuR+azPI8;Gf9)z3kyA4EIOSl!sRR$DlW}0>&?GbgPojmjmnln;cTqCt=ADbE zZ8GAnoM+S1(5$i8^O4t`ue;vO4i}z0wz-QEIVe5_u03;}-!G1NyY8;h^}y;tzY}i5 zqQr#Ur3Fy8sSa$Q0ys+f`!`+>9WbvU_I`Sj;$4{S>O3?#inLHCrtLy~!s#WXV=oVP zeE93*Nc`PBi4q@%Ao$x4lw9vLHM!6mn3-b_cebF|n-2vt-zYVF_&sDE--J-P;2WHo z+@n2areE0o$LjvjlV2X7ZU@j+`{*8zq`JR3gKF#EW|#+{nMyo-a>nFFTg&vhyT=b} zDa8+v0(Dgx0yRL@ZXOYIlVSZ0|MFizy0VPW8;AfA5|pe!#j zX}Py^8fl5SyS4g1WSKKtnyP+_PoOwMMwu`(i@Z)diJp~U54*-miOchy7Z35eL>^M z4p<-aIxH4VUZgS783@H%M7P9hX>t{|RU7$n4T(brCG#h9e9p! z+o`i;EGGq3&pF;~5V~eBD}lC)>if$w%Vf}AFxGqO88|ApfHf&Bvu+xdG)@vuF}Yvk z)o;~k-%+0K0g+L`Wala!$=ZV|z$e%>f0%XoLib%)!R^RoS+{!#X?h-6uu zF&&KxORdZU&EwQFITIRLo(7TA3W}y6X{?Y%y2j0It!ekU#<)$qghZtpcS>L3uh`Uj z7GY;6f$9qKynP#oS3$$a{p^{D+0oJQ71`1?OAn_m8)UGZmj3l*ZI)`V-a>MKGGFG< z&^jg#Ok%(hhm>hSrZ5;Qga4u(?^i>GiW_j9%_7M>j(^|Om$#{k+^*ULnEgzW_1gCICtAD^WpC`A z{9&DXkG#01Xo)U$OC(L5Y$DQ|Q4C6CjUKk1UkPj$nXH##J{c8e#K|&{mA*;b$r0E4 zUNo0jthwA(c&N1l=PEe8Rw_8cEl|-eya9z&H3#n`B$t#+aJ03RFMzrV@gowbe8v(c zIFM60^0&lCFO10NU4w@|61xiZ4CVXeaKjd;d?sv52XM*lS8XiVjgWpRB;&U_C0g+`6B5V&w|O6B*_q zsATxL!M}+$He)1eOWECce#eS@2n^xhlB4<_Nn?yCVEQWDs(r`|@2GqLe<#(|&P0U? z$7V5IgpWf09uIf_RazRwC?qEqRaHyL?iiS05UiGesJy%^>-C{{ypTBI&B0-iUYhk> zIk<5xpsuV@g|z(AZD+C-;A!fTG=df1=<%nxy(a(IS+U{ME4ZbDEBtcD_3V=icT6*_ z)>|J?>&6%nvHhZERBtjK+s4xnut*@>GAmA5m*OTp$!^CHTr}vM4n(X1Q*;{e-Rd2BCF-u@1ZGm z!S8hJ6L=Gl4T_SDa7Xx|-{4mxveJg=ctf`BJ*fy!yF6Dz&?w(Q_6B}WQVtNI!BVBC zKfX<>7vd6C96}XAQmF-Jd?1Q4eTfRB3q7hCh0f!(JkdWT5<{iAE#dKy*Jxq&3a1@~ z8C||Dn2mFNyrUV|<-)C^_y7@8c2Fz+2jrae9deBDu;U}tJ{^xAdxCD248(k;dCJ%o z`y3sADe>U%suxwwv~8A1+R$VB=Q?%U?4joI$um;aH+eCrBqpn- z%79D_7rb;R-;-9RTrwi9dPlg8&@tfWhhZ(Vx&1PQ+6(huX`;M9x~LrW~~#3{j0Bh2kDU$}@!fFQej4VGkJv?M4rU^x!RU zEwhu$!CA_iDjFjrJa`aocySDX16?~;+wgav;}Zut6Mg%C4>}8FL?8)Kgwc(Qlj{@#2Pt0?G`$h7P#M+qoXtlV@d}%c&OzO+QYKK`kyXaK{U(O^2DyIXCZlNQjt0^8~8JzNGrIxhj}}M z&~QZlbx%t;MJ(Vux;2tgNKGlAqphLq%pd}JG9uoVHUo?|hN{pLQ6Em%r*+7t^<);X zm~6=qChlNAVXNN*Sow->*4;}T;l;D1I-5T{Bif@4_}=>l`tK;qqDdt5zvisCKhMAH z#r}`)7VW?LZqfdmXQ%zo5bJ00{Xb9^YKrk0Nf|oIW*K@(=`o2Vndz}ZDyk{!u}PVx zzd--+_WC*U{~DH3{?GI64IB+@On&@9X>EUAo&L+G{L^dozaI4C3G#2wr~hseW@K&g zKWs{uHu-9Je!3;4pE>eBltKUXb^*hG8I&413)$J&{D4N%7PcloU6bn%jPxJyQL?g* z9g+YFFEDiE`8rW^laCNzQmi7CTnPfwyg3VDHRAl>h=In6jeaVOP@!-CP60j3+#vpL zEYmh_oP0{-gTe7Or`L6x)6w?77QVi~jD8lWN@3RHcm80iV%M1A!+Y6iHM)05iC64tb$X2lV_%Txk@0l^hZqi^%Z?#- zE;LE0uFx)R08_S-#(wC=dS&}vj6P4>5ZWjhthP=*Hht&TdLtKDR;rXEX4*z0h74FA zMCINqrh3Vq;s%3MC1YL`{WjIAPkVL#3rj^9Pj9Ss7>7duy!9H0vYF%>1jh)EPqvlr6h%R%CxDsk| z!BACz7E%j?bm=pH6Eaw{+suniuY7C9Ut~1cWfOX9KW9=H><&kQlinPV3h9R>3nJvK z4L9(DRM=x;R&d#a@oFY7mB|m8h4692U5eYfcw|QKwqRsshN(q^v$4$)HgPpAJDJ`I zkqjq(8Cd!K!+wCd=d@w%~e$=gdUgD&wj$LQ1r>-E=O@c ze+Z$x{>6(JA-fNVr)X;*)40Eym1TtUZI1Pwwx1hUi+G1Jlk~vCYeXMNYtr)1?qwyg zsX_e*$h?380O00ou?0R@7-Fc59o$UvyVs4cUbujHUA>sH!}L54>`e` zHUx#Q+Hn&Og#YVOuo*niy*GU3rH;%f``nk#NN5-xrZ34NeH$l`4@t);4(+0|Z#I>Y z)~Kzs#exIAaf--65L0UHT_SvV8O2WYeD>Mq^Y6L!Xu8%vnpofG@w!}R7M28?i1*T&zp3X4^OMCY6(Dg<-! zXmcGQrRgHXGYre7GfTJ)rhl|rs%abKT_Nt24_Q``XH{88NVPW+`x4ZdrMuO0iZ0g` z%p}y};~T5gbb9SeL8BSc`SO#ixC$@QhXxZ=B}L`tP}&k?1oSPS=4%{UOHe0<_XWln zwbl5cn(j-qK`)vGHY5B5C|QZd5)W7c@{bNVXqJ!!n$^ufc?N9C-BF2QK1(kv++h!>$QbAjq)_b$$PcJdV+F7hz0Hu@ zqj+}m0qn{t^tD3DfBb~0B36|Q`bs*xs|$i^G4uNUEBl4g;op-;Wl~iThgga?+dL7s zUP(8lMO?g{GcYpDS{NM!UA8Hco?#}eNEioRBHy4`mq!Pd-9@-97|k$hpEX>xoX+dY zDr$wfm^P&}Wu{!%?)U_(%Mn79$(ywvu*kJ9r4u|MyYLI_67U7%6Gd_vb##Nerf@>& z8W11z$$~xEZt$dPG}+*IZky+os5Ju2eRi;1=rUEeIn>t-AzC_IGM-IXWK3^6QNU+2pe=MBn4I*R@A%-iLDCOHTE-O^wo$sL_h{dcPl=^muAQb`_BRm};=cy{qSkui;`WSsj9%c^+bIDQ z0`_?KX0<-=o!t{u(Ln)v>%VGL z0pC=GB7*AQ?N7N{ut*a%MH-tdtNmNC+Yf$|KS)BW(gQJ*z$d{+{j?(e&hgTy^2|AR9vx1Xre2fagGv0YXWqtNkg*v%40v?BJBt|f9wX5 z{QTlCM}b-0{mV?IG>TW_BdviUKhtosrBqdfq&Frdz>cF~yK{P@(w{Vr7z2qKFwLhc zQuogKO@~YwyS9%+d-zD7mJG~@?EFJLSn!a&mhE5$_4xBl&6QHMzL?CdzEnC~C3$X@ zvY!{_GR06ep5;<#cKCSJ%srxX=+pn?ywDwtJ2{TV;0DKBO2t++B(tIO4)Wh`rD13P z4fE$#%zkd=UzOB74gi=-*CuID&Z3zI^-`4U^S?dHxK8fP*;fE|a(KYMgMUo`THIS1f!*6dOI2 zFjC3O=-AL`6=9pp;`CYPTdVX z8(*?V&%QoipuH0>WKlL8A*zTKckD!paN@~hh zmXzm~qZhMGVdQGd=AG8&20HW0RGV8X{$9LldFZYm zE?}`Q3i?xJRz43S?VFMmqRyvWaS#(~Lempg9nTM$EFDP(Gzx#$r)W&lpFKqcAoJh-AxEw$-bjW>`_+gEi z2w`99#UbFZGiQjS8kj~@PGqpsPX`T{YOj`CaEqTFag;$jY z8_{Wzz>HXx&G*Dx<5skhpETxIdhKH?DtY@b9l8$l?UkM#J-Snmts7bd7xayKTFJ(u zyAT&@6cAYcs{PBfpqZa%sxhJ5nSZBPji?Zlf&}#L?t)vC4X5VLp%~fz2Sx<*oN<7` z?ge=k<=X7r<~F7Tvp9#HB{!mA!QWBOf%EiSJ6KIF8QZNjg&x~-%e*tflL(ji_S^sO ztmib1rp09uon}RcsFi#k)oLs@$?vs(i>5k3YN%$T(5Or(TZ5JW9mA6mIMD08=749$ z!d+l*iu{Il7^Yu}H;lgw=En1sJpCKPSqTCHy4(f&NPelr31^*l%KHq^QE>z>Ks_bH zjbD?({~8Din7IvZeJ>8Ey=e;I?thpzD=zE5UHeO|neioJwG;IyLk?xOz(yO&0DTU~ z^#)xcs|s>Flgmp;SmYJ4g(|HMu3v7#;c*Aa8iF#UZo7CvDq4>8#qLJ|YdZ!AsH%^_7N1IQjCro

K7UpUK$>l@ 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 E2O(~oYXATM diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index aa991fc..0000000 --- a/platform/android/java/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/platform/android/java/gradlew b/platform/android/java/gradlew deleted file mode 100755 index 4f906e0..0000000 --- a/platform/android/java/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# 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 -# -# https://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. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/platform/android/java/gradlew.bat b/platform/android/java/gradlew.bat deleted file mode 100644 index 107acd3..0000000 --- a/platform/android/java/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml deleted file mode 100644 index d354656..0000000 --- a/platform/android/java/lib/AndroidManifest.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/platform/android/java/lib/THIRDPARTY.md b/platform/android/java/lib/THIRDPARTY.md deleted file mode 100644 index 2496b59..0000000 --- a/platform/android/java/lib/THIRDPARTY.md +++ /dev/null @@ -1,39 +0,0 @@ -# Third-party libraries - -This file list third-party libraries used in the Android source folder, -with their provenance and, when relevant, modifications made to those files. - -## com.android.vending.billing - -- Upstream: https://github.com/googlesamples/android-play-billing/tree/master/TrivialDrive/app/src/main -- Version: git (7a94c69, 2019) -- License: Apache 2.0 - -Overwrite the file `aidl/com/android/vending/billing/IInAppBillingService.aidl`. - -## com.google.android.vending.expansion.downloader - -- Upstream: https://github.com/google/play-apk-expansion/tree/master/apkx_library -- Version: git (9ecf54e, 2017) -- License: Apache 2.0 - -Overwrite all files under: - -- `src/com/google/android/vending/expansion/downloader` - -Some files have been modified for yet unclear reasons. -See the `patches/com.google.android.vending.expansion.downloader.patch` file. - -## com.google.android.vending.licensing - -- Upstream: https://github.com/google/play-licensing/tree/master/lvl_library/ -- Version: git (eb57657, 2018) with modifications -- License: Apache 2.0 - -Overwrite all files under: - -- `aidl/com/android/vending/licensing` -- `src/com/google/android/vending/licensing` - -Some files have been modified to silence linter errors or fix downstream issues. -See the `patches/com.google.android.vending.licensing.patch` file. diff --git a/platform/android/java/lib/aidl/com/android/vending/licensing/ILicenseResultListener.aidl b/platform/android/java/lib/aidl/com/android/vending/licensing/ILicenseResultListener.aidl deleted file mode 100644 index 869cb16..0000000 --- a/platform/android/java/lib/aidl/com/android/vending/licensing/ILicenseResultListener.aidl +++ /dev/null @@ -1,21 +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. - */ - -package com.android.vending.licensing; - -oneway interface ILicenseResultListener { - void verifyLicense(int responseCode, String signedData, String signature); -} diff --git a/platform/android/java/lib/aidl/com/android/vending/licensing/ILicensingService.aidl b/platform/android/java/lib/aidl/com/android/vending/licensing/ILicensingService.aidl deleted file mode 100644 index 9541a20..0000000 --- a/platform/android/java/lib/aidl/com/android/vending/licensing/ILicensingService.aidl +++ /dev/null @@ -1,23 +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. - */ - -package com.android.vending.licensing; - -import com.android.vending.licensing.ILicenseResultListener; - -oneway interface ILicensingService { - void checkLicense(long nonce, String packageName, in ILicenseResultListener listener); -} diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle deleted file mode 100644 index 265eeb7..0000000 --- a/platform/android/java/lib/build.gradle +++ /dev/null @@ -1,165 +0,0 @@ -plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' -} - -dependencies { - implementation libraries.kotlinStdLib - implementation libraries.androidxFragment -} - -def pathToRootDir = "../../../../" - -android { - compileSdkVersion versions.compileSdk - buildToolsVersion versions.buildTools - ndkVersion versions.ndkVersion - - defaultConfig { - minSdkVersion versions.minSdk - targetSdkVersion versions.targetSdk - - manifestPlaceholders = [pandemoniumLibraryVersion: getPandemoniumLibraryVersionName()] - } - - compileOptions { - sourceCompatibility versions.javaVersion - targetCompatibility versions.javaVersion - } - - kotlinOptions { - jvmTarget = versions.javaVersion - } - - buildTypes { - dev { - initWith debug - } - } - - flavorDimensions "products" - productFlavors { - editor {} - template {} - } - - lintOptions { - abortOnError false - disable 'MissingTranslation', 'UnusedResources' - } - - packagingOptions { - exclude 'META-INF/LICENSE' - exclude 'META-INF/NOTICE' - - // 'doNotStrip' is enabled for development within Android Studio - if (shouldNotStrip()) { - doNotStrip '**/*.so' - } - } - - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] - res.srcDirs = ['res'] - aidl.srcDirs = ['aidl'] - assets.srcDirs = ['assets'] - } - - debug.jniLibs.srcDirs = ['libs/debug'] - dev.jniLibs.srcDirs = ['libs/dev'] - release.jniLibs.srcDirs = ['libs/release'] - - // Editor jni library - editorDebug.jniLibs.srcDirs = ['libs/tools/debug'] - editorDev.jniLibs.srcDirs = ['libs/tools/dev'] - } - - // Disable 'editorRelease'. - // The editor can't be used with target=release as debugging tools are then not - // included, and it would crash on errors instead of reporting them. - variantFilter { variant -> - if (variant.name == "editorRelease") { - setIgnore(true) - } - } - - libraryVariants.all { variant -> - def flavorName = variant.getFlavorName() - - if (flavorName == null || flavorName == "") { - throw new GradleException("Invalid product flavor: $flavorName") - } - - boolean toolsFlag = flavorName == "editor" - - def buildType = variant.buildType.name - if (buildType == null || buildType == "" || !supportedTargetsMap.containsKey(buildType)) { - throw new GradleException("Invalid build type: $buildType") - } - - def sconsTarget = supportedTargetsMap[buildType] - if (sconsTarget == null || sconsTarget == "") { - throw new GradleException("Invalid scons target: $sconsTarget") - } - - // Update the name of the generated library - def outputSuffix = "${buildType}.aar" - if (toolsFlag) { - outputSuffix = "tools.$outputSuffix" - } - - variant.outputs.all { output -> - output.outputFileName = "pandemonium-lib.${outputSuffix}" - } - - // Find scons' executable path - File sconsExecutableFile = null - def sconsName = "scons" - def sconsExts = (org.gradle.internal.os.OperatingSystem.current().isWindows() - ? [".bat", ".cmd", ".ps1", ".exe"] - : [""]) - logger.lifecycle("Looking for $sconsName executable path") - for (ext in sconsExts) { - String sconsNameExt = sconsName + ext - logger.lifecycle("Checking $sconsNameExt") - - sconsExecutableFile = org.gradle.internal.os.OperatingSystem.current().findInPath(sconsNameExt) - if (sconsExecutableFile != null) { - // We're done! - break - } - - // Check all the options in path - List allOptions = org.gradle.internal.os.OperatingSystem.current().findAllInPath(sconsNameExt) - if (!allOptions.isEmpty()) { - // Pick the first option and we're done! - sconsExecutableFile = allOptions.get(0) - break - } - } - - if (sconsExecutableFile == null) { - throw new GradleException("Unable to find executable path for the '$sconsName' command.") - } else { - logger.lifecycle("Found executable path for $sconsName: ${sconsExecutableFile.absolutePath}") - } - - for (String selectedAbi : selectedAbis) { - if (!supportedAbis.contains(selectedAbi)) { - throw new GradleException("Invalid selected abi: $selectedAbi") - } - - // Creating gradle task to generate the native libraries for the selected abi. - def taskName = getSconsTaskName(flavorName, buildType, selectedAbi) - tasks.create(name: taskName, type: Exec) { - executable sconsExecutableFile.absolutePath - args "--directory=${pathToRootDir}", "platform=android", "tools=${toolsFlag}", "target=${sconsTarget}", "android_arch=${selectedAbi}", "-j" + Runtime.runtime.availableProcessors() - } - - // Schedule the tasks so the generated libs are present before the aar file is packaged. - tasks["merge${flavorName.capitalize()}${buildType.capitalize()}JniLibFolders"].dependsOn taskName - } - } -} diff --git a/platform/android/java/lib/patches/com.google.android.vending.expansion.downloader.patch b/platform/android/java/lib/patches/com.google.android.vending.expansion.downloader.patch deleted file mode 100644 index c0b19ab..0000000 --- a/platform/android/java/lib/patches/com.google.android.vending.expansion.downloader.patch +++ /dev/null @@ -1,300 +0,0 @@ -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java -index ad6ea0de6..452c7d148 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderClientMarshaller.java -@@ -32,6 +32,9 @@ import android.os.Messenger; - import android.os.RemoteException; - import android.util.Log; - -+// -- PANDEMONIUM start -- -+import java.lang.ref.WeakReference; -+// -- PANDEMONIUM end -- - - - /** -@@ -118,29 +121,46 @@ public class DownloaderClientMarshaller { - /** - * Target we publish for clients to send messages to IncomingHandler. - */ -- final Messenger mMessenger = new Messenger(new Handler() { -+ // -- PANDEMONIUM start -- -+ private final MessengerHandlerClient mMsgHandler = new MessengerHandlerClient(this); -+ final Messenger mMessenger = new Messenger(mMsgHandler); -+ -+ private static class MessengerHandlerClient extends Handler { -+ private final WeakReference mDownloader; -+ public MessengerHandlerClient(Stub downloader) { -+ mDownloader = new WeakReference<>(downloader); -+ } -+ - @Override - public void handleMessage(Message msg) { -- switch (msg.what) { -- case MSG_ONDOWNLOADPROGRESS: -- Bundle bun = msg.getData(); -- if ( null != mContext ) { -- bun.setClassLoader(mContext.getClassLoader()); -- DownloadProgressInfo dpi = (DownloadProgressInfo) msg.getData() -- .getParcelable(PARAM_PROGRESS); -- mItf.onDownloadProgress(dpi); -- } -- break; -- case MSG_ONDOWNLOADSTATE_CHANGED: -- mItf.onDownloadStateChanged(msg.getData().getInt(PARAM_NEW_STATE)); -- break; -- case MSG_ONSERVICECONNECTED: -- mItf.onServiceConnected( -- (Messenger) msg.getData().getParcelable(PARAM_MESSENGER)); -- break; -+ Stub downloader = mDownloader.get(); -+ if (downloader != null) { -+ downloader.handleMessage(msg); - } - } -- }); -+ } -+ -+ private void handleMessage(Message msg) { -+ switch (msg.what) { -+ case MSG_ONDOWNLOADPROGRESS: -+ Bundle bun = msg.getData(); -+ if (null != mContext) { -+ bun.setClassLoader(mContext.getClassLoader()); -+ DownloadProgressInfo dpi = (DownloadProgressInfo)msg.getData() -+ .getParcelable(PARAM_PROGRESS); -+ mItf.onDownloadProgress(dpi); -+ } -+ break; -+ case MSG_ONDOWNLOADSTATE_CHANGED: -+ mItf.onDownloadStateChanged(msg.getData().getInt(PARAM_NEW_STATE)); -+ break; -+ case MSG_ONSERVICECONNECTED: -+ mItf.onServiceConnected( -+ (Messenger)msg.getData().getParcelable(PARAM_MESSENGER)); -+ break; -+ } -+ } -+ // -- PANDEMONIUM end -- - - public Stub(IDownloaderClient itf, Class downloaderService) { - mItf = itf; -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java -index 979352299..3771d19c9 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/DownloaderServiceMarshaller.java -@@ -25,6 +25,9 @@ import android.os.Message; - import android.os.Messenger; - import android.os.RemoteException; - -+// -- PANDEMONIUM start -- -+import java.lang.ref.WeakReference; -+// -- PANDEMONIUM end -- - - - /** -@@ -108,32 +111,49 @@ public class DownloaderServiceMarshaller { - - private static class Stub implements IStub { - private IDownloaderService mItf = null; -- final Messenger mMessenger = new Messenger(new Handler() { -+ // -- PANDEMONIUM start -- -+ private final MessengerHandlerServer mMsgHandler = new MessengerHandlerServer(this); -+ final Messenger mMessenger = new Messenger(mMsgHandler); -+ -+ private static class MessengerHandlerServer extends Handler { -+ private final WeakReference mDownloader; -+ public MessengerHandlerServer(Stub downloader) { -+ mDownloader = new WeakReference<>(downloader); -+ } -+ - @Override - public void handleMessage(Message msg) { -- switch (msg.what) { -- case MSG_REQUEST_ABORT_DOWNLOAD: -- mItf.requestAbortDownload(); -- break; -- case MSG_REQUEST_CONTINUE_DOWNLOAD: -- mItf.requestContinueDownload(); -- break; -- case MSG_REQUEST_PAUSE_DOWNLOAD: -- mItf.requestPauseDownload(); -- break; -- case MSG_SET_DOWNLOAD_FLAGS: -- mItf.setDownloadFlags(msg.getData().getInt(PARAMS_FLAGS)); -- break; -- case MSG_REQUEST_DOWNLOAD_STATE: -- mItf.requestDownloadStatus(); -- break; -- case MSG_REQUEST_CLIENT_UPDATE: -- mItf.onClientUpdated((Messenger) msg.getData().getParcelable( -- PARAM_MESSENGER)); -- break; -+ Stub downloader = mDownloader.get(); -+ if (downloader != null) { -+ downloader.handleMessage(msg); - } - } -- }); -+ } -+ -+ private void handleMessage(Message msg) { -+ switch (msg.what) { -+ case MSG_REQUEST_ABORT_DOWNLOAD: -+ mItf.requestAbortDownload(); -+ break; -+ case MSG_REQUEST_CONTINUE_DOWNLOAD: -+ mItf.requestContinueDownload(); -+ break; -+ case MSG_REQUEST_PAUSE_DOWNLOAD: -+ mItf.requestPauseDownload(); -+ break; -+ case MSG_SET_DOWNLOAD_FLAGS: -+ mItf.setDownloadFlags(msg.getData().getInt(PARAMS_FLAGS)); -+ break; -+ case MSG_REQUEST_DOWNLOAD_STATE: -+ mItf.requestDownloadStatus(); -+ break; -+ case MSG_REQUEST_CLIENT_UPDATE: -+ mItf.onClientUpdated((Messenger)msg.getData().getParcelable( -+ PARAM_MESSENGER)); -+ break; -+ } -+ } -+ // -- PANDEMONIUM end -- - - public Stub(IDownloaderService itf) { - mItf = itf; -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java -index e4b1b0f1c..36cd6aacf 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/Helpers.java -@@ -24,7 +24,10 @@ import android.os.StatFs; - import android.os.SystemClock; - import android.util.Log; - --import com.android.vending.expansion.downloader.R; -+// -- PANDEMONIUM start -- -+//import com.android.vending.expansion.downloader.R; -+import org.pandemoniumengine.pandemonium.R; -+// -- PANDEMONIUM end -- - - import java.io.File; - import java.text.SimpleDateFormat; -@@ -146,12 +149,14 @@ public class Helpers { - } - return ""; - } -- return String.format("%.2f", -+ // -- PANDEMONIUM start -- -+ return String.format(Locale.ENGLISH, "%.2f", - (float) overallProgress / (1024.0f * 1024.0f)) - + "MB /" + -- String.format("%.2f", (float) overallTotal / -+ String.format(Locale.ENGLISH, "%.2f", (float) overallTotal / - (1024.0f * 1024.0f)) - + "MB"; -+ // -- PANDEMONIUM end -- - } - - /** -@@ -184,7 +189,9 @@ public class Helpers { - } - - public static String getSpeedString(float bytesPerMillisecond) { -- return String.format("%.2f", bytesPerMillisecond * 1000 / 1024); -+ // -- PANDEMONIUM start -- -+ return String.format(Locale.ENGLISH, "%.2f", bytesPerMillisecond * 1000 / 1024); -+ // -- PANDEMONIUM end -- - } - - public static String getTimeRemaining(long durationInMilliseconds) { -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java -index 12edd97ab..a0e1165cc 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/SystemFacade.java -@@ -26,6 +26,10 @@ import android.net.NetworkInfo; - import android.telephony.TelephonyManager; - import android.util.Log; - -+// -- PANDEMONIUM start -- -+import android.annotation.SuppressLint; -+// -- PANDEMONIUM end -- -+ - /** - * Contains useful helper functions, typically tied to the application context. - */ -@@ -51,6 +55,7 @@ class SystemFacade { - return null; - } - -+ @SuppressLint("MissingPermission") - NetworkInfo activeInfo = connectivity.getActiveNetworkInfo(); - if (activeInfo == null) { - if (Constants.LOGVV) { -@@ -69,6 +74,7 @@ class SystemFacade { - return false; - } - -+ @SuppressLint("MissingPermission") - NetworkInfo info = connectivity.getActiveNetworkInfo(); - boolean isMobile = (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE); - TelephonyManager tm = (TelephonyManager) mContext -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java -index f1536e80e..4b214b22d 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadNotification.java -@@ -16,7 +16,11 @@ - - package com.google.android.vending.expansion.downloader.impl; - --import com.android.vending.expansion.downloader.R; -+// -- PANDEMONIUM start -- -+//import com.android.vending.expansion.downloader.R; -+import org.pandemoniumengine.pandemonium.R; -+// -- PANDEMONIUM end -- -+ - import com.google.android.vending.expansion.downloader.DownloadProgressInfo; - import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller; - import com.google.android.vending.expansion.downloader.Helpers; -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java -index b2e0e7af0..c114b8a64 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloadThread.java -@@ -146,8 +146,12 @@ public class DownloadThread { - - try { - PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); -- wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.TAG); -- wakeLock.acquire(); -+ // -- PANDEMONIUM start -- -+ //wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.TAG); -+ //wakeLock.acquire(); -+ wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "org.pandemonium.game:wakelock"); -+ wakeLock.acquire(20 * 60 * 1000L /*20 minutes*/); -+ // -- PANDEMONIUM end -- - - if (Constants.LOGV) { - Log.v(Constants.TAG, "initiating download for " + mInfo.mFileName); -diff --git a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java -index 4babe476f..8d41a7690 100644 ---- a/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java -+++ b/platform/android/java/src/com/google/android/vending/expansion/downloader/impl/DownloaderService.java -@@ -50,6 +50,10 @@ import android.provider.Settings.Secure; - import android.telephony.TelephonyManager; - import android.util.Log; - -+// -- PANDEMONIUM start -- -+import android.annotation.SuppressLint; -+// -- PANDEMONIUM end -- -+ - import java.io.File; - - /** -@@ -578,6 +582,7 @@ public abstract class DownloaderService extends CustomIntentService implements I - Log.w(Constants.TAG, - "couldn't get connectivity manager to poll network state"); - } else { -+ @SuppressLint("MissingPermission") - NetworkInfo activeInfo = mConnectivityManager - .getActiveNetworkInfo(); - updateNetworkState(activeInfo); diff --git a/platform/android/java/lib/patches/com.google.android.vending.licensing.patch b/platform/android/java/lib/patches/com.google.android.vending.licensing.patch deleted file mode 100644 index 8ae188d..0000000 --- a/platform/android/java/lib/patches/com.google.android.vending.licensing.patch +++ /dev/null @@ -1,42 +0,0 @@ -diff --git a/platform/android/java/src/com/google/android/vending/licensing/PreferenceObfuscator.java b/platform/android/java/src/com/google/android/vending/licensing/PreferenceObfuscator.java -index 7c42bfc28..feb579af0 100644 ---- a/platform/android/java/src/com/google/android/vending/licensing/PreferenceObfuscator.java -+++ b/platform/android/java/src/com/google/android/vending/licensing/PreferenceObfuscator.java -@@ -45,6 +45,9 @@ public class PreferenceObfuscator { - public void putString(String key, String value) { - if (mEditor == null) { - mEditor = mPreferences.edit(); -+ // -- PANDEMONIUM start -- -+ mEditor.apply(); -+ // -- PANDEMONIUM end -- - } - String obfuscatedValue = mObfuscator.obfuscate(value, key); - mEditor.putString(key, obfuscatedValue); -diff --git a/platform/android/java/src/com/google/android/vending/licensing/util/Base64.java b/platform/android/java/src/com/google/android/vending/licensing/util/Base64.java -index a0d2779af..a8bf65f9c 100644 ---- a/platform/android/java/src/com/google/android/vending/licensing/util/Base64.java -+++ b/platform/android/java/src/com/google/android/vending/licensing/util/Base64.java -@@ -31,6 +31,10 @@ package com.google.android.vending.licensing.util; - * @version 1.3 - */ - -+// -- PANDEMONIUM start -- -import org.pandemoniumengine.pandemonium.BuildConfig; -+// -- PANDEMONIUM end -- -+ - /** - * Base64 converter class. This code is not a full-blown MIME encoder; - * it simply converts binary data to base64 data and back. -@@ -341,7 +345,11 @@ public class Base64 { - e += 4; - } - -- assert (e == outBuff.length); -+ // -- PANDEMONIUM start -- -+ //assert (e == outBuff.length); -+ if (BuildConfig.DEBUG && e != outBuff.length) -+ throw new RuntimeException(); -+ // -- PANDEMONIUM end -- - return outBuff; - } - diff --git a/platform/android/java/lib/res/layout/downloading_expansion.xml b/platform/android/java/lib/res/layout/downloading_expansion.xml deleted file mode 100644 index 34c2757..0000000 --- a/platform/android/java/lib/res/layout/downloading_expansion.xml +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - -