From 614f70137312686a4e22c827f554b2aa31005e3b Mon Sep 17 00:00:00 2001 From: Sergey Minakov Date: Thu, 13 Aug 2020 18:24:39 +0300 Subject: [PATCH 1/5] iOS Modules: separate main platform code from modules Moved previously builtin modules 'GameCenter', 'AppStore', 'iCloud' to separate modules to be represented as plugin. Modified 'ARKit' and 'Camera' to not be builtin into engine and work as plugin. Changed platform code so it's not affected by the move. Modified Xcode project file to remove parameters that doesn't make any effect. Added basic '.gdip' plugin config file. --- .../godot_ios.xcodeproj/project.pbxproj | 75 ------------------- modules/arkit/arkit.gdip | 18 +++++ .../{register_types.cpp => arkit_module.cpp} | 4 +- .../{register_types.h => arkit_module.h} | 2 +- modules/camera/SCsub | 12 +-- modules/camera/config.py | 2 +- modules/camera/register_types.cpp | 6 -- modules/camera_iphone/SCsub | 15 ++++ modules/camera_iphone/camera.gdip | 18 +++++ .../{camera => camera_iphone}/camera_ios.h | 0 .../{camera => camera_iphone}/camera_ios.mm | 0 modules/camera_iphone/camera_module.cpp | 40 ++++++++++ modules/camera_iphone/camera_module.h | 32 ++++++++ modules/camera_iphone/config.py | 6 ++ modules/gamecenter/SCsub | 15 ++++ modules/gamecenter/config.py | 6 ++ .../gamecenter}/game_center.h | 4 - .../gamecenter}/game_center.mm | 25 ++++--- modules/gamecenter/game_center_delegate.h | 35 +++++++++ modules/gamecenter/game_center_delegate.mm | 45 +++++++++++ modules/gamecenter/game_center_module.cpp | 48 ++++++++++++ modules/gamecenter/game_center_module.h | 32 ++++++++ modules/gamecenter/gamecenter.gdip | 17 +++++ modules/icloud/SCsub | 15 ++++ modules/icloud/config.py | 6 ++ modules/icloud/icloud.gdip | 17 +++++ {platform/iphone => modules/icloud}/icloud.h | 4 - {platform/iphone => modules/icloud}/icloud.mm | 8 +- modules/icloud/icloud_module.cpp | 48 ++++++++++++ modules/icloud/icloud_module.h | 32 ++++++++ modules/inappstore/SCsub | 15 ++++ modules/inappstore/config.py | 6 ++ .../inappstore}/in_app_store.h | 4 - .../inappstore}/in_app_store.mm | 4 - modules/inappstore/in_app_store_module.cpp | 48 ++++++++++++ modules/inappstore/in_app_store_module.h | 32 ++++++++ modules/inappstore/inappstore.gdip | 17 +++++ platform/iphone/SCsub | 3 - platform/iphone/detect.py | 15 ---- platform/iphone/os_iphone.h | 12 --- platform/iphone/os_iphone.mm | 33 -------- platform/iphone/view_controller.h | 3 +- platform/iphone/view_controller.mm | 8 -- 43 files changed, 586 insertions(+), 201 deletions(-) create mode 100644 modules/arkit/arkit.gdip rename modules/arkit/{register_types.cpp => arkit_module.cpp} (96%) rename modules/arkit/{register_types.h => arkit_module.h} (97%) create mode 100644 modules/camera_iphone/SCsub create mode 100644 modules/camera_iphone/camera.gdip rename modules/{camera => camera_iphone}/camera_ios.h (100%) rename modules/{camera => camera_iphone}/camera_ios.mm (100%) create mode 100644 modules/camera_iphone/camera_module.cpp create mode 100644 modules/camera_iphone/camera_module.h create mode 100644 modules/camera_iphone/config.py create mode 100644 modules/gamecenter/SCsub create mode 100644 modules/gamecenter/config.py rename {platform/iphone => modules/gamecenter}/game_center.h (98%) rename {platform/iphone => modules/gamecenter}/game_center.mm (95%) create mode 100644 modules/gamecenter/game_center_delegate.h create mode 100644 modules/gamecenter/game_center_delegate.mm create mode 100644 modules/gamecenter/game_center_module.cpp create mode 100644 modules/gamecenter/game_center_module.h create mode 100644 modules/gamecenter/gamecenter.gdip create mode 100644 modules/icloud/SCsub create mode 100644 modules/icloud/config.py create mode 100644 modules/icloud/icloud.gdip rename {platform/iphone => modules/icloud}/icloud.h (98%) rename {platform/iphone => modules/icloud}/icloud.mm (99%) create mode 100644 modules/icloud/icloud_module.cpp create mode 100644 modules/icloud/icloud_module.h create mode 100644 modules/inappstore/SCsub create mode 100644 modules/inappstore/config.py rename {platform/iphone => modules/inappstore}/in_app_store.h (99%) rename {platform/iphone => modules/inappstore}/in_app_store.mm (99%) create mode 100644 modules/inappstore/in_app_store_module.cpp create mode 100644 modules/inappstore/in_app_store_module.h create mode 100644 modules/inappstore/inappstore.gdip diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj index 19ed60c5f69..42d51b87b65 100644 --- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj +++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj @@ -146,81 +146,6 @@ DevelopmentTeam = $team_id; ProvisioningStyle = Automatic; SystemCapabilities = { - com.apple.AccessWiFi = { - enabled = $access_wifi; - }; - com.apple.ApplePay = { - enabled = 0; - }; - com.apple.ApplicationGroups.iOS = { - enabled = 0; - }; - com.apple.AutoFillCredentialProvider = { - enabled = 0; - }; - com.apple.BackgroundModes = { - enabled = 0; - }; - com.apple.ClassKit = { - enabled = 0; - }; - com.apple.DataProtection = { - enabled = 0; - }; - com.apple.GameCenter.iOS = { - enabled = $game_center; - }; - com.apple.HealthKit = { - enabled = 0; - }; - com.apple.HomeKit = { - enabled = 0; - }; - com.apple.HotspotConfiguration = { - enabled = 0; - }; - com.apple.InAppPurchase = { - enabled = $in_app_purchases; - }; - com.apple.InterAppAudio = { - enabled = 0; - }; - com.apple.Keychain = { - enabled = 0; - }; - com.apple.Maps.iOS = { - enabled = 0; - }; - com.apple.Multipath = { - enabled = 0; - }; - com.apple.NearFieldCommunicationTagReading = { - enabled = 0; - }; - com.apple.NetworkExtensions.iOS = { - enabled = 0; - }; - com.apple.Push = { - enabled = $push_notifications; - }; - com.apple.SafariKeychain = { - enabled = 0; - }; - com.apple.Siri = { - enabled = 0; - }; - com.apple.VPNLite = { - enabled = 0; - }; - com.apple.WAC = { - enabled = 0; - }; - com.apple.Wallet = { - enabled = 0; - }; - com.apple.iCloud = { - enabled = 0; - }; }; }; }; diff --git a/modules/arkit/arkit.gdip b/modules/arkit/arkit.gdip new file mode 100644 index 00000000000..22c0a07e264 --- /dev/null +++ b/modules/arkit/arkit.gdip @@ -0,0 +1,18 @@ +[config] +name="ARKit" +binary="arkit_lib.a" + +initialization="register_arkit_types" +deinitialization="unregister_arkit_types" + +[dependencies] +linked=[] +embedded=[] +system=["AVFoundation.framework", "ARKit.framework"] + +capabilities=["arkit"] + +files=[] + +[plist] +NSCameraUsageDescription="Device camera is used for some functionality" diff --git a/modules/arkit/register_types.cpp b/modules/arkit/arkit_module.cpp similarity index 96% rename from modules/arkit/register_types.cpp rename to modules/arkit/arkit_module.cpp index 59730d2416b..0bfdb3866ff 100644 --- a/modules/arkit/register_types.cpp +++ b/modules/arkit/arkit_module.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* register_types.cpp */ +/* arkit_module.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "register_types.h" +#include "arkit_module.h" #include "arkit_interface.h" diff --git a/modules/arkit/register_types.h b/modules/arkit/arkit_module.h similarity index 97% rename from modules/arkit/register_types.h rename to modules/arkit/arkit_module.h index 7f96bc933fb..ed40f91d747 100644 --- a/modules/arkit/register_types.h +++ b/modules/arkit/arkit_module.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* register_types.h */ +/* arkit_module.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ diff --git a/modules/camera/SCsub b/modules/camera/SCsub index 631a65bde2b..de97724d09d 100644 --- a/modules/camera/SCsub +++ b/modules/camera/SCsub @@ -5,17 +5,7 @@ Import("env_modules") env_camera = env_modules.Clone() -if env["platform"] == "iphone": - # (iOS) Enable module support - env_camera.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) - - # (iOS) Build as separate static library - modules_sources = [] - env_camera.add_source_files(modules_sources, "register_types.cpp") - env_camera.add_source_files(modules_sources, "camera_ios.mm") - mod_lib = env_modules.add_library("#bin/libgodot_camera_module" + env["LIBSUFFIX"], modules_sources) - -elif env["platform"] == "windows": +if env["platform"] == "windows": env_camera.add_source_files(env.modules_sources, "register_types.cpp") env_camera.add_source_files(env.modules_sources, "camera_win.cpp") diff --git a/modules/camera/config.py b/modules/camera/config.py index 87d75427419..8a22751aa7b 100644 --- a/modules/camera/config.py +++ b/modules/camera/config.py @@ -1,5 +1,5 @@ def can_build(env, platform): - return platform == "iphone" or platform == "osx" or platform == "windows" + return platform == "osx" or platform == "windows" def configure(env): diff --git a/modules/camera/register_types.cpp b/modules/camera/register_types.cpp index 8e7de1048b3..0d33ff9ddca 100644 --- a/modules/camera/register_types.cpp +++ b/modules/camera/register_types.cpp @@ -33,9 +33,6 @@ #if defined(WINDOWS_ENABLED) #include "camera_win.h" #endif -#if defined(IPHONE_ENABLED) -#include "camera_ios.h" -#endif #if defined(OSX_ENABLED) #include "camera_osx.h" #endif @@ -44,9 +41,6 @@ void register_camera_types() { #if defined(WINDOWS_ENABLED) CameraServer::make_default(); #endif -#if defined(IPHONE_ENABLED) - CameraServer::make_default(); -#endif #if defined(OSX_ENABLED) CameraServer::make_default(); #endif diff --git a/modules/camera_iphone/SCsub b/modules/camera_iphone/SCsub new file mode 100644 index 00000000000..0a37d9a6f53 --- /dev/null +++ b/modules/camera_iphone/SCsub @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +Import("env") +Import("env_modules") + +env_camera = env_modules.Clone() + +# (iOS) Enable module support +env_camera.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) + +# (iOS) Build as separate static library +modules_sources = [] +env_camera.add_source_files(modules_sources, "*.cpp") +env_camera.add_source_files(modules_sources, "*.mm") +mod_lib = env_modules.add_library("#bin/libgodot_camera_module" + env["LIBSUFFIX"], modules_sources) diff --git a/modules/camera_iphone/camera.gdip b/modules/camera_iphone/camera.gdip new file mode 100644 index 00000000000..09017b8d27d --- /dev/null +++ b/modules/camera_iphone/camera.gdip @@ -0,0 +1,18 @@ +[config] +name="Camera" +binary="camera_lib.a" + +initialization="register_camera_types" +deinitialization="unregister_camera_types" + +[dependencies] +linked=[] +embedded=[] +system=["AVFoundation.framework"] + +capabilities=[] + +files=[] + +[plist] +NSCameraUsageDescription="Device camera is used for some functionality" diff --git a/modules/camera/camera_ios.h b/modules/camera_iphone/camera_ios.h similarity index 100% rename from modules/camera/camera_ios.h rename to modules/camera_iphone/camera_ios.h diff --git a/modules/camera/camera_ios.mm b/modules/camera_iphone/camera_ios.mm similarity index 100% rename from modules/camera/camera_ios.mm rename to modules/camera_iphone/camera_ios.mm diff --git a/modules/camera_iphone/camera_module.cpp b/modules/camera_iphone/camera_module.cpp new file mode 100644 index 00000000000..7ea035892e1 --- /dev/null +++ b/modules/camera_iphone/camera_module.cpp @@ -0,0 +1,40 @@ +/*************************************************************************/ +/* camera_module.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 "camera_module.h" + +#include "camera_ios.h" + +void register_camera_types() { + CameraServer::make_default(); +} + +void unregister_camera_types() { +} diff --git a/modules/camera_iphone/camera_module.h b/modules/camera_iphone/camera_module.h new file mode 100644 index 00000000000..5a94d8b529b --- /dev/null +++ b/modules/camera_iphone/camera_module.h @@ -0,0 +1,32 @@ +/*************************************************************************/ +/* camera_module.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_camera_types(); +void unregister_camera_types(); diff --git a/modules/camera_iphone/config.py b/modules/camera_iphone/config.py new file mode 100644 index 00000000000..e68603fc93b --- /dev/null +++ b/modules/camera_iphone/config.py @@ -0,0 +1,6 @@ +def can_build(env, platform): + return platform == "iphone" + + +def configure(env): + pass diff --git a/modules/gamecenter/SCsub b/modules/gamecenter/SCsub new file mode 100644 index 00000000000..72fbf7ab0e5 --- /dev/null +++ b/modules/gamecenter/SCsub @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +Import("env") +Import("env_modules") + +env_gamecenter = env_modules.Clone() + +# (iOS) Enable module support +env_gamecenter.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) + +# (iOS) Build as separate static library +modules_sources = [] +env_gamecenter.add_source_files(modules_sources, "*.cpp") +env_gamecenter.add_source_files(modules_sources, "*.mm") +mod_lib = env_modules.add_library("#bin/libgodot_gamecenter_module" + env["LIBSUFFIX"], modules_sources) diff --git a/modules/gamecenter/config.py b/modules/gamecenter/config.py new file mode 100644 index 00000000000..e68603fc93b --- /dev/null +++ b/modules/gamecenter/config.py @@ -0,0 +1,6 @@ +def can_build(env, platform): + return platform == "iphone" + + +def configure(env): + pass diff --git a/platform/iphone/game_center.h b/modules/gamecenter/game_center.h similarity index 98% rename from platform/iphone/game_center.h rename to modules/gamecenter/game_center.h index e718ae103af..74d8cc26e3d 100644 --- a/platform/iphone/game_center.h +++ b/modules/gamecenter/game_center.h @@ -28,8 +28,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef GAME_CENTER_ENABLED - #ifndef GAME_CENTER_H #define GAME_CENTER_H @@ -72,5 +70,3 @@ public: }; #endif - -#endif diff --git a/platform/iphone/game_center.mm b/modules/gamecenter/game_center.mm similarity index 95% rename from platform/iphone/game_center.mm rename to modules/gamecenter/game_center.mm index 6b4f4c8145d..3802b5ca748 100644 --- a/platform/iphone/game_center.mm +++ b/modules/gamecenter/game_center.mm @@ -28,15 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef GAME_CENTER_ENABLED - #include "game_center.h" -#import "app_delegate.h" -#import "view_controller.h" +#import "game_center_delegate.h" +#import "platform/iphone/app_delegate.h" +#import "platform/iphone/view_controller.h" + #import GameCenter *GameCenter::instance = NULL; +GodotGameCenterDelegate *gameCenterDelegate = nil; void GameCenter::_bind_methods() { ClassDB::bind_method(D_METHOD("authenticate"), &GameCenter::authenticate); @@ -64,7 +65,7 @@ Error GameCenter::authenticate() { GKLocalPlayer *player = [GKLocalPlayer localPlayer]; ERR_FAIL_COND_V(![player respondsToSelector:@selector(authenticateHandler)], ERR_UNAVAILABLE); - ViewController *root_controller = (ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController; + UIViewController *root_controller = [[UIApplication sharedApplication] delegate].window.rootViewController; ERR_FAIL_COND_V(!root_controller, FAILED); // This handler is called several times. First when the view needs to be shown, then again @@ -298,10 +299,10 @@ Error GameCenter::show_game_center(Variant p_params) { GKGameCenterViewController *controller = [[GKGameCenterViewController alloc] init]; ERR_FAIL_COND_V(!controller, FAILED); - ViewController *root_controller = (ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController; + UIViewController *root_controller = [[UIApplication sharedApplication] delegate].window.rootViewController; ERR_FAIL_COND_V(!root_controller, FAILED); - controller.gameCenterDelegate = root_controller; + controller.gameCenterDelegate = gameCenterDelegate; controller.viewState = view_state; if (view_state == GKGameCenterViewControllerStateLeaderboards) { controller.leaderboardIdentifier = nil; @@ -373,8 +374,12 @@ GameCenter::GameCenter() { ERR_FAIL_COND(instance != NULL); instance = this; authenticated = false; + + gameCenterDelegate = [[GodotGameCenterDelegate alloc] init]; }; -GameCenter::~GameCenter(){}; - -#endif +GameCenter::~GameCenter() { + if (gameCenterDelegate) { + gameCenterDelegate = nil; + } +} diff --git a/modules/gamecenter/game_center_delegate.h b/modules/gamecenter/game_center_delegate.h new file mode 100644 index 00000000000..ef1d2ae93d1 --- /dev/null +++ b/modules/gamecenter/game_center_delegate.h @@ -0,0 +1,35 @@ +/*************************************************************************/ +/* game_center_delegate.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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. */ +/*************************************************************************/ + +#import + +@interface GodotGameCenterDelegate : NSObject + +@end diff --git a/modules/gamecenter/game_center_delegate.mm b/modules/gamecenter/game_center_delegate.mm new file mode 100644 index 00000000000..6e20db572b4 --- /dev/null +++ b/modules/gamecenter/game_center_delegate.mm @@ -0,0 +1,45 @@ +/*************************************************************************/ +/* game_center_delegate.mm */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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. */ +/*************************************************************************/ + +#import "game_center_delegate.h" + +#include "game_center.h" + +@implementation GodotGameCenterDelegate + +- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController { + //[gameCenterViewController dismissViewControllerAnimated:YES completion:^{GameCenter::get_singleton()->game_center_closed();}];//version for signaling when overlay is completely gone + if (GameCenter::get_singleton()) { + GameCenter::get_singleton()->game_center_closed(); + } + [gameCenterViewController dismissViewControllerAnimated:YES completion:nil]; +} + +@end diff --git a/modules/gamecenter/game_center_module.cpp b/modules/gamecenter/game_center_module.cpp new file mode 100644 index 00000000000..fba8f84f408 --- /dev/null +++ b/modules/gamecenter/game_center_module.cpp @@ -0,0 +1,48 @@ +/*************************************************************************/ +/* game_center_module.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 "game_center_module.h" + +#include "core/engine.h" + +#include "game_center.h" + +GameCenter *game_center; + +void register_gamecenter_types() { + game_center = memnew(GameCenter); + Engine::get_singleton()->add_singleton(Engine::Singleton("GameCenter", game_center)); +} + +void unregister_gamecenter_types() { + if (game_center) { + memdelete(game_center); + } +} diff --git a/modules/gamecenter/game_center_module.h b/modules/gamecenter/game_center_module.h new file mode 100644 index 00000000000..5df3645b1cf --- /dev/null +++ b/modules/gamecenter/game_center_module.h @@ -0,0 +1,32 @@ +/*************************************************************************/ +/* game_center_module.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_gamecenter_types(); +void unregister_gamecenter_types(); diff --git a/modules/gamecenter/gamecenter.gdip b/modules/gamecenter/gamecenter.gdip new file mode 100644 index 00000000000..eb44effbddd --- /dev/null +++ b/modules/gamecenter/gamecenter.gdip @@ -0,0 +1,17 @@ +[config] +name="GameCenter" +binary="gamecenter_lib.a" + +initialization="register_gamecenter_types" +deinitialization="unregister_gamecenter_types" + +[dependencies] +linked=[] +embedded=[] +system=["GameKit.framework"] + +capabilities=["gamekit"] + +files=[] + +[plist] diff --git a/modules/icloud/SCsub b/modules/icloud/SCsub new file mode 100644 index 00000000000..805a4846003 --- /dev/null +++ b/modules/icloud/SCsub @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +Import("env") +Import("env_modules") + +env_icloud = env_modules.Clone() + +# (iOS) Enable module support +env_icloud.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) + +# (iOS) Build as separate static library +modules_sources = [] +env_icloud.add_source_files(modules_sources, "*.cpp") +env_icloud.add_source_files(modules_sources, "*.mm") +mod_lib = env_modules.add_library("#bin/libgodot_icloud_module" + env["LIBSUFFIX"], modules_sources) diff --git a/modules/icloud/config.py b/modules/icloud/config.py new file mode 100644 index 00000000000..e68603fc93b --- /dev/null +++ b/modules/icloud/config.py @@ -0,0 +1,6 @@ +def can_build(env, platform): + return platform == "iphone" + + +def configure(env): + pass diff --git a/modules/icloud/icloud.gdip b/modules/icloud/icloud.gdip new file mode 100644 index 00000000000..9f81be8a346 --- /dev/null +++ b/modules/icloud/icloud.gdip @@ -0,0 +1,17 @@ +[config] +name="iCloud" +binary="icloud_lib.a" + +initialization="register_icloud_types" +deinitialization="unregister_icloud_types" + +[dependencies] +linked=[] +embedded=[] +system=[] + +capabilities=[] + +files=[] + +[plist] diff --git a/platform/iphone/icloud.h b/modules/icloud/icloud.h similarity index 98% rename from platform/iphone/icloud.h rename to modules/icloud/icloud.h index 88546529141..f639c9b0ba0 100644 --- a/platform/iphone/icloud.h +++ b/modules/icloud/icloud.h @@ -28,8 +28,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef ICLOUD_ENABLED - #ifndef ICLOUD_H #define ICLOUD_H @@ -61,5 +59,3 @@ public: }; #endif - -#endif diff --git a/platform/iphone/icloud.mm b/modules/icloud/icloud.mm similarity index 99% rename from platform/iphone/icloud.mm rename to modules/icloud/icloud.mm index 610fe6183ff..ef45094da51 100644 --- a/platform/iphone/icloud.mm +++ b/modules/icloud/icloud.mm @@ -28,11 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef ICLOUD_ENABLED - #include "icloud.h" -#import "app_delegate.h" +#import "platform/iphone/app_delegate.h" #import @@ -346,6 +344,4 @@ ICloud::ICloud() { }]; } -ICloud::~ICloud(){}; - -#endif +ICloud::~ICloud() {} diff --git a/modules/icloud/icloud_module.cpp b/modules/icloud/icloud_module.cpp new file mode 100644 index 00000000000..b1a2f58dafe --- /dev/null +++ b/modules/icloud/icloud_module.cpp @@ -0,0 +1,48 @@ +/*************************************************************************/ +/* icloud_module.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 "icloud_module.h" + +#include "core/engine.h" + +#include "icloud.h" + +ICloud *icloud; + +void register_icloud_types() { + icloud = memnew(ICloud); + Engine::get_singleton()->add_singleton(Engine::Singleton("ICloud", icloud)); +} + +void unregister_icloud_types() { + if (icloud) { + memdelete(icloud); + } +} diff --git a/modules/icloud/icloud_module.h b/modules/icloud/icloud_module.h new file mode 100644 index 00000000000..fb8b5fe66e5 --- /dev/null +++ b/modules/icloud/icloud_module.h @@ -0,0 +1,32 @@ +/*************************************************************************/ +/* icloud_module.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_icloud_types(); +void unregister_icloud_types(); diff --git a/modules/inappstore/SCsub b/modules/inappstore/SCsub new file mode 100644 index 00000000000..cee6a256d5e --- /dev/null +++ b/modules/inappstore/SCsub @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +Import("env") +Import("env_modules") + +env_inappstore = env_modules.Clone() + +# (iOS) Enable module support +env_inappstore.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) + +# (iOS) Build as separate static library +modules_sources = [] +env_inappstore.add_source_files(modules_sources, "*.cpp") +env_inappstore.add_source_files(modules_sources, "*.mm") +mod_lib = env_modules.add_library("#bin/libgodot_inappstore_module" + env["LIBSUFFIX"], modules_sources) diff --git a/modules/inappstore/config.py b/modules/inappstore/config.py new file mode 100644 index 00000000000..e68603fc93b --- /dev/null +++ b/modules/inappstore/config.py @@ -0,0 +1,6 @@ +def can_build(env, platform): + return platform == "iphone" + + +def configure(env): + pass diff --git a/platform/iphone/in_app_store.h b/modules/inappstore/in_app_store.h similarity index 99% rename from platform/iphone/in_app_store.h rename to modules/inappstore/in_app_store.h index b601af57b43..227d727aa59 100644 --- a/platform/iphone/in_app_store.h +++ b/modules/inappstore/in_app_store.h @@ -28,8 +28,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef STOREKIT_ENABLED - #ifndef IN_APP_STORE_H #define IN_APP_STORE_H @@ -78,5 +76,3 @@ public: }; #endif - -#endif diff --git a/platform/iphone/in_app_store.mm b/modules/inappstore/in_app_store.mm similarity index 99% rename from platform/iphone/in_app_store.mm rename to modules/inappstore/in_app_store.mm index c7e67d769f9..3030bcd0962 100644 --- a/platform/iphone/in_app_store.mm +++ b/modules/inappstore/in_app_store.mm @@ -28,8 +28,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef STOREKIT_ENABLED - #include "in_app_store.h" #import @@ -414,5 +412,3 @@ InAppStore::~InAppStore() { [[SKPaymentQueue defaultQueue] removeTransactionObserver:transactions_observer]; transactions_observer = nil; } - -#endif diff --git a/modules/inappstore/in_app_store_module.cpp b/modules/inappstore/in_app_store_module.cpp new file mode 100644 index 00000000000..42673f7278d --- /dev/null +++ b/modules/inappstore/in_app_store_module.cpp @@ -0,0 +1,48 @@ +/*************************************************************************/ +/* in_app_store_module.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 "in_app_store_module.h" + +#include "core/engine.h" + +#include "in_app_store.h" + +InAppStore *store_kit; + +void register_inappstore_types() { + store_kit = memnew(InAppStore); + Engine::get_singleton()->add_singleton(Engine::Singleton("InAppStore", store_kit)); +} + +void unregister_inappstore_types() { + if (store_kit) { + memdelete(store_kit); + } +} diff --git a/modules/inappstore/in_app_store_module.h b/modules/inappstore/in_app_store_module.h new file mode 100644 index 00000000000..dc389698254 --- /dev/null +++ b/modules/inappstore/in_app_store_module.h @@ -0,0 +1,32 @@ +/*************************************************************************/ +/* in_app_store_module.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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_inappstore_types(); +void unregister_inappstore_types(); diff --git a/modules/inappstore/inappstore.gdip b/modules/inappstore/inappstore.gdip new file mode 100644 index 00000000000..7a5efb8ad39 --- /dev/null +++ b/modules/inappstore/inappstore.gdip @@ -0,0 +1,17 @@ +[config] +name="InAppStore" +binary="inappstore_lib.a" + +initialization="register_inappstore_types" +deinitialization="unregister_inappstore_types" + +[dependencies] +linked=[] +embedded=[] +system=["StoreKit.framework"] + +capabilities=[] + +files=[] + +[plist] diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index c5c459ab98f..6e0e62407a2 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -9,9 +9,6 @@ iphone_lib = [ "main.m", "app_delegate.mm", "view_controller.mm", - "game_center.mm", - "in_app_store.mm", - "icloud.mm", "ios.mm", "joypad_iphone.mm", "godot_view.mm", diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index e48fd83a2a7..b4985343355 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -33,9 +33,6 @@ def get_opts(): "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain", ), ("IPHONESDK", "Path to the iPhone SDK", ""), - BoolVariable("game_center", "Support for game center", True), - BoolVariable("store_kit", "Support for in-app store", True), - BoolVariable("icloud", "Support for iCloud", True), BoolVariable("ios_exceptions", "Enable exceptions", False), ("ios_triple", "Triple for ios toolchain", ""), ] @@ -205,18 +202,6 @@ def configure(env): ] ) - # Feature options - if env["game_center"]: - env.Append(CPPDEFINES=["GAME_CENTER_ENABLED"]) - env.Append(LINKFLAGS=["-framework", "GameKit"]) - - if env["store_kit"]: - env.Append(CPPDEFINES=["STOREKIT_ENABLED"]) - env.Append(LINKFLAGS=["-framework", "StoreKit"]) - - if env["icloud"]: - env.Append(CPPDEFINES=["ICLOUD_ENABLED"]) - env.Prepend( CPPPATH=[ "$IPHONESDK/usr/include", diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 21141ef6239..633864b11f5 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -38,9 +38,6 @@ #include "drivers/unix/os_unix.h" #include "joypad_iphone.h" -#include "game_center.h" -#include "icloud.h" -#include "in_app_store.h" #include "ios.h" #include "main/input_default.h" #include "servers/audio_server.h" @@ -57,15 +54,6 @@ private: AudioDriverCoreAudio audio_driver; -#ifdef GAME_CENTER_ENABLED - GameCenter *game_center; -#endif -#ifdef STOREKIT_ENABLED - InAppStore *store_kit; -#endif -#ifdef ICLOUD_ENABLED - ICloud *icloud; -#endif iOS *ios; JoypadIPhone *joypad_iphone; diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm index 54cdd21540b..63810d33e99 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/iphone/os_iphone.mm @@ -181,21 +181,6 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p input = memnew(InputDefault); -#ifdef GAME_CENTER_ENABLED - game_center = memnew(GameCenter); - Engine::get_singleton()->add_singleton(Engine::Singleton("GameCenter", game_center)); -#endif - -#ifdef STOREKIT_ENABLED - store_kit = memnew(InAppStore); - Engine::get_singleton()->add_singleton(Engine::Singleton("InAppStore", store_kit)); -#endif - -#ifdef ICLOUD_ENABLED - icloud = memnew(ICloud); - Engine::get_singleton()->add_singleton(Engine::Singleton("ICloud", icloud)); - //icloud->connect(); -#endif ios = memnew(iOS); Engine::get_singleton()->add_singleton(Engine::Singleton("iOS", ios)); @@ -334,24 +319,6 @@ void OSIPhone::finalize() { memdelete(ios); } -#ifdef GAME_CENTER_ENABLED - if (game_center) { - memdelete(game_center); - } -#endif - -#ifdef STOREKIT_ENABLED - if (store_kit) { - memdelete(store_kit); - } -#endif - -#ifdef ICLOUD_ENABLED - if (icloud) { - memdelete(icloud); - } -#endif - visual_server->finish(); memdelete(visual_server); // memdelete(rasterizer); diff --git a/platform/iphone/view_controller.h b/platform/iphone/view_controller.h index 6cea8df3409..52fb6fbbf2a 100644 --- a/platform/iphone/view_controller.h +++ b/platform/iphone/view_controller.h @@ -28,14 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#import #import @class GodotView; @class GodotNativeVideoView; @class GodotKeyboardInputView; -@interface ViewController : UIViewController +@interface ViewController : UIViewController @property(nonatomic, readonly, strong) GodotView *godotView; @property(nonatomic, readonly, strong) GodotNativeVideoView *videoView; diff --git a/platform/iphone/view_controller.mm b/platform/iphone/view_controller.mm index 9e6b00d84fc..c047579a17b 100644 --- a/platform/iphone/view_controller.mm +++ b/platform/iphone/view_controller.mm @@ -225,12 +225,4 @@ } } -#ifdef GAME_CENTER_ENABLED -- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController { - //[gameCenterViewController dismissViewControllerAnimated:YES completion:^{GameCenter::get_singleton()->game_center_closed();}];//version for signaling when overlay is completely gone - GameCenter::get_singleton()->game_center_closed(); - [gameCenterViewController dismissViewControllerAnimated:YES completion:nil]; -} -#endif - @end From 03cf3d5d4b4db2428f8c1d85e3a21ef2ac3d86a6 Mon Sep 17 00:00:00 2001 From: Sergey Minakov Date: Thu, 13 Aug 2020 18:30:54 +0300 Subject: [PATCH 2/5] iOS: change platform code to support plugins --- platform/iphone/os_iphone.h | 3 +++ platform/iphone/os_iphone.mm | 3 +++ 2 files changed, 6 insertions(+) diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 633864b11f5..054f2ed68dc 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -44,6 +44,9 @@ #include "servers/visual/rasterizer.h" #include "servers/visual_server.h" +extern void godot_ios_plugins_initialize(); +extern void godot_ios_plugins_deinitialize(); + class OSIPhone : public OS_Unix { private: diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm index 63810d33e99..20215e7a7cf 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/iphone/os_iphone.mm @@ -195,6 +195,7 @@ MainLoop *OSIPhone::get_main_loop() const { }; void OSIPhone::set_main_loop(MainLoop *p_main_loop) { + godot_ios_plugins_initialize(); main_loop = p_main_loop; @@ -319,6 +320,8 @@ void OSIPhone::finalize() { memdelete(ios); } + godot_ios_plugins_deinitialize(); + visual_server->finish(); memdelete(visual_server); // memdelete(rasterizer); From d5047603a3064a11f29e9c646cc8a83ffd748481 Mon Sep 17 00:00:00 2001 From: Sergey Minakov Date: Thu, 13 Aug 2020 18:33:41 +0300 Subject: [PATCH 3/5] iOS Export: export modification to support plugins Added plugin configuration. Export options now use plugins that could be enabled/disabled. Plugin changes are observed at runtime. --- .../godot_ios.xcodeproj/project.pbxproj | 4 +- platform/iphone/export/export.cpp | 401 ++++++++++++++---- platform/iphone/plugin/godot_plugin_config.h | 238 +++++++++++ 3 files changed, 565 insertions(+), 78 deletions(-) create mode 100644 platform/iphone/plugin/godot_plugin_config.h diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj index 42d51b87b65..5e397dbdba7 100644 --- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj +++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj @@ -310,7 +310,7 @@ ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)", + "$(PROJECT_DIR)/**", ); PRODUCT_BUNDLE_IDENTIFIER = $identifier; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -340,7 +340,7 @@ ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)", + "$(PROJECT_DIR)/**", ); PRODUCT_BUNDLE_IDENTIFIER = $identifier; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 319cdd1621a..2a9dba3f613 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -41,6 +41,7 @@ #include "editor/editor_settings.h" #include "main/splash.gen.h" #include "platform/iphone/logo.gen.h" +#include "platform/iphone/plugin/godot_plugin_config.h" #include "string.h" #include @@ -53,6 +54,13 @@ class EditorExportPlatformIOS : public EditorExportPlatform { Ref logo; + // Plugins + volatile bool plugins_changed; + Thread *check_for_changes_thread; + volatile bool quit_request; + Mutex *plugins_lock; + Vector plugins; + typedef Error (*FileHandler)(String p_file, void *p_userdata); static Error _walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata); static Error _codesign(String p_file, void *p_userdata); @@ -68,6 +76,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform { String modules_fileref; String modules_buildphase; String modules_buildgrp; + Vector capabilities; }; struct ExportArchitecture { @@ -105,6 +114,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform { void _add_assets_to_project(const Ref &p_preset, Vector &p_project_data, const Vector &p_additional_assets); Error _export_additional_assets(const String &p_out_dir, const Vector &p_assets, bool p_is_framework, bool p_should_embed, Vector &r_exported_assets); Error _export_additional_assets(const String &p_out_dir, const Vector &p_libraries, Vector &r_exported_assets); + Error _export_plugins(const Ref &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector &r_exported_assets); bool is_package_name_valid(const String &p_package, String *r_error = NULL) const { @@ -130,6 +140,43 @@ class EditorExportPlatformIOS : public EditorExportPlatform { return true; } + static void _check_for_changes_poll_thread(void *ud) { + EditorExportPlatformIOS *ea = (EditorExportPlatformIOS *)ud; + + while (!ea->quit_request) { + // Nothing to do if we already know the plugins have changed. + if (!ea->plugins_changed) { + + ea->plugins_lock->lock(); + + Vector loaded_plugins = get_plugins(); + + if (ea->plugins.size() != loaded_plugins.size()) { + ea->plugins_changed = true; + } else { + for (int i = 0; i < ea->plugins.size(); i++) { + if (ea->plugins[i].name != loaded_plugins[i].name || ea->plugins[i].last_updated != loaded_plugins[i].last_updated) { + ea->plugins_changed = true; + break; + } + } + } + + ea->plugins_lock->unlock(); + } + + uint64_t wait = 3000000; + uint64_t time = OS::get_singleton()->get_ticks_usec(); + while (OS::get_singleton()->get_ticks_usec() - time < wait) { + OS::get_singleton()->delay_usec(300000); + + if (ea->quit_request) { + break; + } + } + } + } + protected: virtual void get_preset_features(const Ref &p_preset, List *r_features); virtual void get_export_options(List *r_options); @@ -139,13 +186,22 @@ public: virtual String get_os_name() const { return "iOS"; } virtual Ref get_logo() const { return logo; } + virtual bool should_update_export_options() { + bool export_options_changed = plugins_changed; + if (export_options_changed) { + // don't clear unless we're reporting true, to avoid race + plugins_changed = false; + } + return export_options_changed; + } + virtual List get_binary_extensions(const Ref &p_preset) const { List list; list.push_back("ipa"); return list; } + virtual Error export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags = 0); - virtual void add_module_code(const Ref &p_preset, IOSConfigData &p_config_data, const String &p_name, const String &p_fid, const String &p_gid); virtual bool can_export(const Ref &p_preset, String &r_error, bool &r_missing_templates) const; @@ -160,6 +216,85 @@ public: EditorExportPlatformIOS(); ~EditorExportPlatformIOS(); + + /// List the gdip files in the directory specified by the p_path parameter. + static Vector list_plugin_config_files(const String &p_path, bool p_check_directories) { + Vector dir_files; + DirAccessRef da = DirAccess::open(p_path); + if (da) { + da->list_dir_begin(); + while (true) { + String file = da->get_next(); + if (file.empty()) { + break; + } + + if (file == "." || file == "..") { + continue; + } + + if (da->current_is_hidden()) { + continue; + } + + if (da->current_is_dir()) { + if (p_check_directories) { + Vector directory_files = list_plugin_config_files(p_path.plus_file(file), false); + for (int i = 0; i < directory_files.size(); ++i) { + dir_files.push_back(file.plus_file(directory_files[i])); + } + } + + continue; + } + + if (file.ends_with(PLUGIN_CONFIG_EXT)) { + dir_files.push_back(file); + } + } + da->list_dir_end(); + } + + return dir_files; + } + + static Vector get_plugins() { + Vector loaded_plugins; + + String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("ios/plugins"); + + if (DirAccess::exists(plugins_dir)) { + Vector plugins_filenames = list_plugin_config_files(plugins_dir, true); + + if (!plugins_filenames.empty()) { + Ref config_file = memnew(ConfigFile); + for (int i = 0; i < plugins_filenames.size(); i++) { + PluginConfig config = 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; + } + + static Vector get_enabled_plugins(const Ref &p_presets) { + Vector enabled_plugins; + Vector all_plugins = get_plugins(); + for (int i = 0; i < all_plugins.size(); i++) { + PluginConfig plugin = all_plugins[i]; + bool enabled = p_presets->get("plugins/" + plugin.name); + if (enabled) { + enabled_plugins.push_back(plugin); + } + } + + return enabled_plugins; + } }; void EditorExportPlatformIOS::get_preset_features(const Ref &p_preset, List *r_features) { @@ -230,11 +365,16 @@ void EditorExportPlatformIOS::get_export_options(List *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/arkit"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/camera"), false)); + Vector found_plugins = get_plugins(); + + for (int i = 0; i < found_plugins.size(); i++) { + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + found_plugins[i].name), false)); + } + + plugins_changed = false; + plugins = found_plugins; + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/access_wifi"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/game_center"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/in_app_purchases"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "capabilities/push_notifications"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_files_app"), false)); @@ -341,18 +481,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ strnew += lines[i].replace("$docs_in_place", ((bool)p_preset->get("user_data/accessible_from_files_app")) ? "" : "") + "\n"; } else if (lines[i].find("$docs_sharing") != -1) { strnew += lines[i].replace("$docs_sharing", ((bool)p_preset->get("user_data/accessible_from_itunes_sharing")) ? "" : "") + "\n"; - } else if (lines[i].find("$access_wifi") != -1) { - bool is_on = p_preset->get("capabilities/access_wifi"); - strnew += lines[i].replace("$access_wifi", is_on ? "1" : "0") + "\n"; - } else if (lines[i].find("$game_center") != -1) { - bool is_on = p_preset->get("capabilities/game_center"); - strnew += lines[i].replace("$game_center", is_on ? "1" : "0") + "\n"; - } else if (lines[i].find("$in_app_purchases") != -1) { - bool is_on = p_preset->get("capabilities/in_app_purchases"); - strnew += lines[i].replace("$in_app_purchases", is_on ? "1" : "0") + "\n"; - } else if (lines[i].find("$push_notifications") != -1) { - bool is_on = p_preset->get("capabilities/push_notifications"); - strnew += lines[i].replace("$push_notifications", is_on ? "1" : "0") + "\n"; } else if (lines[i].find("$entitlements_push_notifications") != -1) { bool is_on = p_preset->get("capabilities/push_notifications"); strnew += lines[i].replace("$entitlements_push_notifications", is_on ? "aps-environmentdevelopment" : "") + "\n"; @@ -362,15 +490,14 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ // I've removed armv7 as we can run on 64bit only devices // Note that capabilities listed here are requirements for the app to be installed. // They don't enable anything. + Vector capabilities_list = p_config.capabilities; - if ((bool)p_preset->get("capabilities/arkit")) { - capabilities += "arkit\n"; + if ((bool)p_preset->get("capabilities/access_wifi") && capabilities_list.find("wifi") != -1) { + capabilities_list.push_back("wifi"); } - if ((bool)p_preset->get("capabilities/game_center")) { - capabilities += "gamekit\n"; - } - if ((bool)p_preset->get("capabilities/access_wifi")) { - capabilities += "wifi\n"; + + for (int idx = 0; idx < capabilities_list.size(); idx++) { + capabilities += "" + capabilities_list[idx] + "\n"; } strnew += lines[i].replace("$required_device_capabilities", capabilities); @@ -850,28 +977,6 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Refget("capabilities/arkit")) { - String build_id = (++current_id).str(); - String ref_id = (++current_id).str(); - - if (pbx_frameworks_build.length() > 0) { - pbx_frameworks_build += ",\n"; - pbx_frameworks_refs += ",\n"; - } - - pbx_frameworks_build += build_id; - pbx_frameworks_refs += ref_id; - - Dictionary format_dict; - format_dict["build_id"] = build_id; - format_dict["ref_id"] = ref_id; - format_dict["name"] = "ARKit.framework"; - format_dict["file_path"] = "System/Library/Frameworks/ARKit.framework"; - format_dict["file_type"] = "wrapper.framework"; - pbx_files += file_info_format.format(format_dict, "$_"); - } - String str = String::utf8((const char *)p_project_data.ptr(), p_project_data.size()); str = str.replace("$additional_pbx_files", pbx_files); str = str.replace("$additional_pbx_frameworks_build", pbx_frameworks_build); @@ -1067,20 +1172,165 @@ Vector EditorExportPlatformIOS::_get_preset_architectures(const Ref &p_preset, EditorExportPlatformIOS::IOSConfigData &p_config_data, const String &p_name, const String &p_fid, const String &p_gid) { - if ((bool)p_preset->get("capabilities/" + p_name)) { - //add module static library - print_line("ADDING MODULE: " + p_name); +Error EditorExportPlatformIOS::_export_plugins(const Ref &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector &r_exported_assets) { + String plugin_definition_cpp_code; + String plugin_initialization_cpp_code; + String plugin_deinitialization_cpp_code; - p_config_data.modules_buildfile += p_gid + " /* libgodot_" + p_name + "_module.a in Frameworks */ = {isa = PBXBuildFile; fileRef = " + p_fid + " /* libgodot_" + p_name + "_module.a */; };\n\t\t"; - p_config_data.modules_fileref += p_fid + " /* libgodot_" + p_name + "_module.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = godot_" + p_name + "_module ; path = \"libgodot_" + p_name + "_module.a\"; sourceTree = \"\"; };\n\t\t"; - p_config_data.modules_buildphase += p_gid + " /* libgodot_" + p_name + "_module.a */,\n\t\t\t\t"; - p_config_data.modules_buildgrp += p_fid + " /* libgodot_" + p_name + "_module.a */,\n\t\t\t\t"; - } else { - //add stub function for disabled module - p_config_data.cpp_code += "void register_" + p_name + "_types() { /*stub*/ };\n"; - p_config_data.cpp_code += "void unregister_" + p_name + "_types() { /*stub*/ };\n"; + Vector plugin_libraries; + Vector plugin_linked_dependencies; + Vector plugin_embedded_dependencies; + Vector plugin_files; + + Vector enabled_plugins = get_enabled_plugins(p_preset); + + Vector added_linked_dependenciy_names; + Vector added_embedded_dependenciy_names; + HashMap plist_values; + + for (int i = 0; i < enabled_plugins.size(); i++) { + PluginConfig plugin = enabled_plugins[i]; + + // Adding plugin binary. + plugin_libraries.push_back(plugin.binary); + + // Adding dependencies. + // Use separate container for names to check for duplicates. + for (int j = 0; j < plugin.linked_dependencies.size(); j++) { + String dependency = plugin.linked_dependencies[j]; + String name = dependency.get_file(); + + if (added_linked_dependenciy_names.find(name) != -1) { + continue; + } + + added_linked_dependenciy_names.push_back(name); + plugin_linked_dependencies.push_back(dependency); + } + + for (int j = 0; j < plugin.system_dependencies.size(); j++) { + String dependency = plugin.system_dependencies[j]; + String name = dependency.get_file(); + + if (added_linked_dependenciy_names.find(name) != -1) { + continue; + } + + added_linked_dependenciy_names.push_back(name); + plugin_linked_dependencies.push_back(dependency); + } + + for (int j = 0; j < plugin.embedded_dependencies.size(); j++) { + String dependency = plugin.embedded_dependencies[j]; + String name = dependency.get_file(); + + if (added_embedded_dependenciy_names.find(name) != -1) { + continue; + } + + added_embedded_dependenciy_names.push_back(name); + plugin_embedded_dependencies.push_back(dependency); + } + + plugin_files.append_array(plugin.files_to_copy); + + // Capabilities + // Also checking for duplicates. + for (int j = 0; j < plugin.capabilities.size(); j++) { + String capability = plugin.capabilities[j]; + + if (p_config_data.capabilities.find(capability) != -1) { + continue; + } + + p_config_data.capabilities.push_back(capability); + } + + // Plist + // Using hash map container to remove duplicates + const String *K = nullptr; + + while ((K = plugin.plist.next(K))) { + String key = *K; + String value = plugin.plist[key]; + + if (key.empty() || value.empty()) { + continue; + } + + plist_values[key] = value; + } + + // CPP Code + String definition_comment = "// Plugin: " + plugin.name + "\n"; + String initialization_method = plugin.initialization_method + "();\n"; + String deinitialization_method = plugin.deinitialization_method + "();\n"; + + plugin_definition_cpp_code += definition_comment + + "extern void " + initialization_method + + "extern void " + deinitialization_method + "\n"; + + plugin_initialization_cpp_code += "\t" + initialization_method; + plugin_deinitialization_cpp_code += "\t" + deinitialization_method; } + + // Updating `Info.plist` + { + const String *K = nullptr; + while ((K = plist_values.next(K))) { + String key = *K; + String value = plist_values[key]; + + if (key.empty() || value.empty()) { + continue; + } + + p_config_data.plist_content += "" + key + "" + value + "\n"; + } + } + + // Export files + { + // Export plugin libraries + Error err = _export_additional_assets(dest_dir, plugin_libraries, true, true, r_exported_assets); + ERR_FAIL_COND_V(err, err); + + // Export linked plugin dependency + err = _export_additional_assets(dest_dir, plugin_linked_dependencies, true, false, r_exported_assets); + ERR_FAIL_COND_V(err, err); + + // Export embedded plugin dependency + err = _export_additional_assets(dest_dir, plugin_embedded_dependencies, true, true, r_exported_assets); + ERR_FAIL_COND_V(err, err); + + // Export plugin files + err = _export_additional_assets(dest_dir, plugin_files, false, false, r_exported_assets); + ERR_FAIL_COND_V(err, err); + } + + // Update CPP + { + Dictionary plugin_format; + plugin_format["definition"] = plugin_definition_cpp_code; + plugin_format["initialization"] = plugin_initialization_cpp_code; + plugin_format["deinitialization"] = plugin_deinitialization_cpp_code; + + String plugin_cpp_code = "\n// Godot Plugins\n" + "void godot_ios_plugins_initialize();\n" + "void godot_ios_plugins_deinitialize();\n" + "// Exported Plugins\n\n" + "$definition" + "// Use Plugins\n" + "void godot_ios_plugins_initialize() {\n" + "$initialization" + "}\n\n" + "void godot_ios_plugins_deinitialize() {\n" + "$deinitialization" + "}\n"; + + p_config_data.cpp_code += plugin_cpp_code.format(plugin_format, "$_"); + } + return OK; } Error EditorExportPlatformIOS::export_project(const Ref &p_preset, bool p_debug, const String &p_path, int p_flags) { @@ -1186,9 +1436,12 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p "", "", "", - "" + "", + Vector() }; + Vector assets; + DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir); ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE); @@ -1201,8 +1454,8 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p return ERR_CANT_OPEN; } - add_module_code(p_preset, config_data, "arkit", "F9B95E6E2391205500AF0000", "F9C95E812391205C00BF0000"); - add_module_code(p_preset, config_data, "camera", "F9B95E6E2391205500AF0001", "F9C95E812391205C00BF0001"); + err = _export_plugins(p_preset, config_data, dest_dir + binary_name, assets); + ERR_FAIL_COND_V(err, err); //export rest of the files int ret = unzGoToFirstFile(src_pkg_zip); @@ -1244,21 +1497,8 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p is_execute = true; #endif file = "godot_ios.a"; - } else if (file.begins_with("libgodot_arkit")) { - if ((bool)p_preset->get("capabilities/arkit") && file.ends_with(String(p_debug ? "debug" : "release") + ".fat.a")) { - file = "libgodot_arkit_module.a"; - } else { - ret = unzGoToNextFile(src_pkg_zip); - continue; //ignore! - } - } else if (file.begins_with("libgodot_camera")) { - if ((bool)p_preset->get("capabilities/camera") && file.ends_with(String(p_debug ? "debug" : "release") + ".fat.a")) { - file = "libgodot_camera_module.a"; - } else { - ret = unzGoToNextFile(src_pkg_zip); - continue; //ignore! - } } + if (file == project_file) { project_file_data = data; } @@ -1390,7 +1630,6 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p } print_line("Exporting additional assets"); - Vector assets; _export_additional_assets(dest_dir + binary_name, libraries, assets); _add_assets_to_project(p_preset, project_file_data, assets); String project_file_name = dest_dir + binary_name + ".xcodeproj/project.pbxproj"; @@ -1526,9 +1765,19 @@ EditorExportPlatformIOS::EditorExportPlatformIOS() { Ref img = memnew(Image(_iphone_logo)); logo.instance(); logo->create_from_image(img); + + plugins_changed = true; + quit_request = false; + plugins_lock = Mutex::create(); + + check_for_changes_thread = Thread::create(_check_for_changes_poll_thread, this); } EditorExportPlatformIOS::~EditorExportPlatformIOS() { + quit_request = true; + Thread::wait_to_finish(check_for_changes_thread); + memdelete(plugins_lock); + memdelete(check_for_changes_thread); } void register_iphone_exporter() { diff --git a/platform/iphone/plugin/godot_plugin_config.h b/platform/iphone/plugin/godot_plugin_config.h new file mode 100644 index 00000000000..fec9ba339fe --- /dev/null +++ b/platform/iphone/plugin/godot_plugin_config.h @@ -0,0 +1,238 @@ +/*************************************************************************/ +/* godot_plugin_config.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 GODOT_PLUGIN_CONFIG_H +#define GODOT_PLUGIN_CONFIG_H + +#include "core/error_list.h" +#include "core/io/config_file.h" +#include "core/ustring.h" + +static const char *PLUGIN_CONFIG_EXT = ".gdip"; + +static const char *CONFIG_SECTION = "config"; +static const char *CONFIG_NAME_KEY = "name"; +static const char *CONFIG_BINARY_KEY = "binary"; +static const char *CONFIG_INITIALIZE_KEY = "initialization"; +static const char *CONFIG_DEINITIALIZE_KEY = "deinitialization"; + +static const char *DEPENDENCIES_SECTION = "dependencies"; +static const char *DEPENDENCIES_LINKED_KEY = "linked"; +static const char *DEPENDENCIES_EMBEDDED_KEY = "embedded"; +static const char *DEPENDENCIES_SYSTEM_KEY = "system"; +static const char *DEPENDENCIES_CAPABILITIES_KEY = "capabilities"; +static const char *DEPENDENCIES_FILES_KEY = "files"; + +static const char *PLIST_SECTION = "plist"; + +/* + The `config` section and fields are required and defined as follow: +- **name**: name of the plugin +- **binary**: path to static `.a` library + +The `dependencies` and fields are optional. +- **linked**: dependencies that should only be linked. +- **embedded**: dependencies that should be linked and embedded into application. +- **system**: system dependencies that should be linked. +- **capabilities**: capabilities that would be used for `UIRequiredDeviceCapabilities` options in Info.plist file. +- **files**: files that would be copied into application + +The `plist` section are optional. +- **key**: key and value that would be added in Info.plist file. + */ + +struct PluginConfig { + // 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; + String initialization_method; + String deinitialization_method; + + // Optional dependencies section + Vector linked_dependencies; + Vector embedded_dependencies; + Vector system_dependencies; + + Vector files_to_copy; + Vector capabilities; + + // Optional plist section + // Supports only string types for now + HashMap plist; +}; + +static inline String resolve_local_dependency_path(String plugin_config_dir, String dependency_path) { + String absolute_path; + + if (dependency_path.empty()) { + return absolute_path; + } + + if (dependency_path.is_abs_path()) { + return dependency_path; + } + + String res_path = ProjectSettings::get_singleton()->globalize_path("res://"); + absolute_path = plugin_config_dir.plus_file(dependency_path); + + return absolute_path.replace(res_path, "res://"); +} + +static inline String resolve_system_dependency_path(String dependency_path) { + String absolute_path; + + if (dependency_path.empty()) { + return absolute_path; + } + + if (dependency_path.is_abs_path()) { + return dependency_path; + } + + String system_path = "/System/Library/Frameworks"; + + return system_path.plus_file(dependency_path); +} + +static inline Vector resolve_local_dependencies(String plugin_config_dir, Vector p_paths) { + Vector paths; + + for (int i = 0; i < p_paths.size(); i++) { + String path = resolve_local_dependency_path(plugin_config_dir, p_paths[i]); + + if (path.empty()) { + continue; + } + + paths.push_back(path); + } + + return paths; +} + +static inline Vector resolve_system_dependencies(Vector p_paths) { + Vector paths; + + for (int i = 0; i < p_paths.size(); i++) { + String path = resolve_system_dependency_path(p_paths[i]); + + if (path.empty()) { + continue; + } + + paths.push_back(path); + } + + return paths; +} + +static inline bool is_plugin_config_valid(PluginConfig plugin_config) { + bool valid_name = !plugin_config.name.empty(); + bool valid_binary = !plugin_config.binary.empty() && FileAccess::exists(plugin_config.binary); + bool valid_initialize = !plugin_config.initialization_method.empty(); + bool valid_deinitialize = !plugin_config.deinitialization_method.empty(); + + return valid_name && valid_binary && valid_initialize && valid_deinitialize; +} + +static inline uint64_t get_plugin_modification_time(const PluginConfig &plugin_config, const String &config_path) { + uint64_t last_updated = FileAccess::get_modified_time(config_path); + last_updated = MAX(last_updated, FileAccess::get_modified_time(plugin_config.binary)); + + return last_updated; +} + +static inline PluginConfig load_plugin_config(Ref config_file, const String &path) { + PluginConfig plugin_config = {}; + + if (!config_file.is_valid()) { + return plugin_config; + } + + Error err = config_file->load(path); + + if (err != OK) { + return plugin_config; + } + + String config_base_dir = path.get_base_dir(); + + plugin_config.name = config_file->get_value(CONFIG_SECTION, CONFIG_NAME_KEY, String()); + plugin_config.initialization_method = config_file->get_value(CONFIG_SECTION, CONFIG_INITIALIZE_KEY, String()); + plugin_config.deinitialization_method = config_file->get_value(CONFIG_SECTION, CONFIG_DEINITIALIZE_KEY, String()); + + String binary_path = config_file->get_value(CONFIG_SECTION, CONFIG_BINARY_KEY, String()); + plugin_config.binary = resolve_local_dependency_path(config_base_dir, binary_path); + + if (config_file->has_section(DEPENDENCIES_SECTION)) { + Vector linked_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_LINKED_KEY, Vector()); + Vector embedded_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_EMBEDDED_KEY, Vector()); + Vector system_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_SYSTEM_KEY, Vector()); + Vector files = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_FILES_KEY, Vector()); + + plugin_config.linked_dependencies = resolve_local_dependencies(config_base_dir, linked_dependencies); + plugin_config.embedded_dependencies = resolve_local_dependencies(config_base_dir, embedded_dependencies); + plugin_config.system_dependencies = resolve_system_dependencies(system_dependencies); + + plugin_config.files_to_copy = resolve_local_dependencies(config_base_dir, files); + + plugin_config.capabilities = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_CAPABILITIES_KEY, Vector()); + } + + if (config_file->has_section(PLIST_SECTION)) { + List keys; + config_file->get_section_keys(PLIST_SECTION, &keys); + + for (int i = 0; i < keys.size(); i++) { + String value = config_file->get_value(PLIST_SECTION, keys[i], String()); + + if (value.empty()) { + continue; + } + + plugin_config.plist[keys[i]] = value; + } + } + + plugin_config.valid_config = is_plugin_config_valid(plugin_config); + + if (plugin_config.valid_config) { + plugin_config.last_updated = get_plugin_modification_time(plugin_config, path); + } + + return plugin_config; +} + +#endif // GODOT_PLUGIN_CONFIG_H From cb15abda29fe5ec8f25ce19e19c9c8000964e1ec Mon Sep 17 00:00:00 2001 From: Sergey Minakov Date: Mon, 17 Aug 2020 21:47:37 +0300 Subject: [PATCH 4/5] iOS Export: support multi-target plugin Plugins can use 'binary_name.a' or 'binary_name.release.a' and 'binary_name.debug.a' for plugin library. --- platform/iphone/export/export.cpp | 306 +++++++++++-------- platform/iphone/plugin/godot_plugin_config.h | 41 ++- 2 files changed, 210 insertions(+), 137 deletions(-) diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 2a9dba3f613..da50801c596 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -112,9 +112,10 @@ class EditorExportPlatformIOS : public EditorExportPlatform { Vector _get_preset_architectures(const Ref &p_preset); void _add_assets_to_project(const Ref &p_preset, Vector &p_project_data, const Vector &p_additional_assets); + Error _copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector &r_exported_assets); Error _export_additional_assets(const String &p_out_dir, const Vector &p_assets, bool p_is_framework, bool p_should_embed, Vector &r_exported_assets); Error _export_additional_assets(const String &p_out_dir, const Vector &p_libraries, Vector &r_exported_assets); - Error _export_plugins(const Ref &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector &r_exported_assets); + Error _export_ios_plugins(const Ref &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector &r_exported_assets, bool p_debug); bool is_package_name_valid(const String &p_package, String *r_error = NULL) const { @@ -992,11 +993,164 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref &p_assets, bool p_is_framework, bool p_should_embed, Vector &r_exported_assets) { +Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector &r_exported_assets) { DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'."); + String binary_name = p_out_dir.get_file().get_basename(); - ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'."); + DirAccess *da = DirAccess::create_for_path(p_asset); + if (!da) { + memdelete(filesystem_da); + ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't create directory: " + p_asset + "."); + } + bool file_exists = da->file_exists(p_asset); + bool dir_exists = da->dir_exists(p_asset); + if (!file_exists && !dir_exists) { + memdelete(da); + memdelete(filesystem_da); + return ERR_FILE_NOT_FOUND; + } + + String base_dir = p_asset.get_base_dir().replace("res://", ""); + String destination_dir; + String destination; + String asset_path; + + bool create_framework = false; + + if (p_is_framework && p_asset.ends_with(".dylib")) { + // For iOS we need to turn .dylib into .framework + // to be able to send application to AppStore + asset_path = String("dylibs").plus_file(base_dir); + + String file_name; + + if (!p_custom_file_name) { + file_name = p_asset.get_basename().get_file(); + } else { + file_name = *p_custom_file_name; + } + + String framework_name = file_name + ".framework"; + + asset_path = asset_path.plus_file(framework_name); + destination_dir = p_out_dir.plus_file(asset_path); + destination = destination_dir.plus_file(file_name); + create_framework = true; + } else if (p_is_framework && (p_asset.ends_with(".framework") || p_asset.ends_with(".xcframework"))) { + asset_path = String("dylibs").plus_file(base_dir); + + String file_name; + + if (!p_custom_file_name) { + file_name = p_asset.get_file(); + } else { + file_name = *p_custom_file_name; + } + + asset_path = asset_path.plus_file(file_name); + destination_dir = p_out_dir.plus_file(asset_path); + destination = destination_dir; + } else { + asset_path = base_dir; + + String file_name; + + if (!p_custom_file_name) { + file_name = p_asset.get_file(); + } else { + file_name = *p_custom_file_name; + } + + destination_dir = p_out_dir.plus_file(asset_path); + asset_path = asset_path.plus_file(file_name); + destination = p_out_dir.plus_file(asset_path); + } + + if (!filesystem_da->dir_exists(destination_dir)) { + Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir); + if (make_dir_err) { + memdelete(da); + memdelete(filesystem_da); + return make_dir_err; + } + } + + Error err = dir_exists ? da->copy_dir(p_asset, destination) : da->copy(p_asset, destination); + memdelete(da); + if (err) { + memdelete(filesystem_da); + return err; + } + IOSExportAsset exported_asset = { binary_name.plus_file(asset_path), p_is_framework, p_should_embed }; + r_exported_assets.push_back(exported_asset); + + if (create_framework) { + String file_name; + + if (!p_custom_file_name) { + file_name = p_asset.get_basename().get_file(); + } else { + file_name = *p_custom_file_name; + } + + String framework_name = file_name + ".framework"; + + // Performing `install_name_tool -id @rpath/{name}.framework/{name} ./{name}` on dylib + { + List install_name_args; + install_name_args.push_back("-id"); + install_name_args.push_back(String("@rpath").plus_file(framework_name).plus_file(file_name)); + install_name_args.push_back(destination); + + OS::get_singleton()->execute("install_name_tool", install_name_args, true); + } + + // Creating Info.plist + { + String info_plist_format = "\n" + "\n" + "\n" + "\n" + "CFBundleShortVersionString\n" + "1.0\n" + "CFBundleIdentifier\n" + "com.gdnative.framework.$name\n" + "CFBundleName\n" + "$name\n" + "CFBundleExecutable\n" + "$name\n" + "DTPlatformName\n" + "iphoneos\n" + "CFBundleInfoDictionaryVersion\n" + "6.0\n" + "CFBundleVersion\n" + "1\n" + "CFBundlePackageType\n" + "FMWK\n" + "MinimumOSVersion\n" + "10.0\n" + "\n" + ""; + + String info_plist = info_plist_format.replace("$name", file_name); + + FileAccess *f = FileAccess::open(destination_dir.plus_file("Info.plist"), FileAccess::WRITE); + if (f) { + f->store_string(info_plist); + f->close(); + memdelete(f); + } + } + } + + memdelete(filesystem_da); + + return OK; +} + +Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir, const Vector &p_assets, bool p_is_framework, bool p_should_embed, Vector &r_exported_assets) { for (int f_idx = 0; f_idx < p_assets.size(); ++f_idx) { String asset = p_assets[f_idx]; if (!asset.begins_with("res://")) { @@ -1004,126 +1158,10 @@ Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir IOSExportAsset exported_asset = { asset, p_is_framework, p_should_embed }; r_exported_assets.push_back(exported_asset); } else { - DirAccess *da = DirAccess::create_for_path(asset); - if (!da) { - memdelete(filesystem_da); - ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't create directory: " + asset + "."); - } - bool file_exists = da->file_exists(asset); - bool dir_exists = da->dir_exists(asset); - if (!file_exists && !dir_exists) { - memdelete(da); - memdelete(filesystem_da); - return ERR_FILE_NOT_FOUND; - } - - String base_dir = asset.get_base_dir().replace("res://", ""); - String destination_dir; - String destination; - String asset_path; - - bool create_framework = false; - - if (p_is_framework && asset.ends_with(".dylib")) { - // For iOS we need to turn .dylib into .framework - // to be able to send application to AppStore - asset_path = String("dylibs").plus_file(base_dir); - - String file_name = asset.get_basename().get_file(); - String framework_name = file_name + ".framework"; - - asset_path = asset_path.plus_file(framework_name); - destination_dir = p_out_dir.plus_file(asset_path); - destination = destination_dir.plus_file(file_name); - create_framework = true; - } else if (p_is_framework && (asset.ends_with(".framework") || asset.ends_with(".xcframework"))) { - asset_path = String("dylibs").plus_file(base_dir); - - String file_name = asset.get_file(); - asset_path = asset_path.plus_file(file_name); - destination_dir = p_out_dir.plus_file(asset_path); - destination = destination_dir; - } else { - asset_path = base_dir; - - String file_name = asset.get_file(); - destination_dir = p_out_dir.plus_file(asset_path); - asset_path = asset_path.plus_file(file_name); - destination = p_out_dir.plus_file(asset_path); - } - - if (!filesystem_da->dir_exists(destination_dir)) { - Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir); - if (make_dir_err) { - memdelete(da); - memdelete(filesystem_da); - return make_dir_err; - } - } - - Error err = dir_exists ? da->copy_dir(asset, destination) : da->copy(asset, destination); - memdelete(da); - if (err) { - memdelete(filesystem_da); - return err; - } - IOSExportAsset exported_asset = { binary_name.plus_file(asset_path), p_is_framework, p_should_embed }; - r_exported_assets.push_back(exported_asset); - - if (create_framework) { - String file_name = asset.get_basename().get_file(); - String framework_name = file_name + ".framework"; - - // Performing `install_name_tool -id @rpath/{name}.framework/{name} ./{name}` on dylib - { - List install_name_args; - install_name_args.push_back("-id"); - install_name_args.push_back(String("@rpath").plus_file(framework_name).plus_file(file_name)); - install_name_args.push_back(destination); - - OS::get_singleton()->execute("install_name_tool", install_name_args, true); - } - - // Creating Info.plist - { - String info_plist_format = "\n" - "\n" - "\n" - "\n" - "CFBundleShortVersionString\n" - "1.0\n" - "CFBundleIdentifier\n" - "com.gdnative.framework.$name\n" - "CFBundleName\n" - "$name\n" - "CFBundleExecutable\n" - "$name\n" - "DTPlatformName\n" - "iphoneos\n" - "CFBundleInfoDictionaryVersion\n" - "6.0\n" - "CFBundleVersion\n" - "1\n" - "CFBundlePackageType\n" - "FMWK\n" - "MinimumOSVersion\n" - "10.0\n" - "\n" - ""; - - String info_plist = info_plist_format.replace("$name", file_name); - - FileAccess *f = FileAccess::open(destination_dir.plus_file("Info.plist"), FileAccess::WRITE); - if (f) { - f->store_string(info_plist); - f->close(); - memdelete(f); - } - } - } + Error err = _copy_asset(p_out_dir, asset, nullptr, p_is_framework, p_should_embed, r_exported_assets); + ERR_FAIL_COND_V(err, err); } } - memdelete(filesystem_da); return OK; } @@ -1172,12 +1210,11 @@ Vector EditorExportPlatformIOS::_get_preset_architectures(const Ref &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector &r_exported_assets) { +Error EditorExportPlatformIOS::_export_ios_plugins(const Ref &p_preset, IOSConfigData &p_config_data, const String &dest_dir, Vector &r_exported_assets, bool p_debug) { String plugin_definition_cpp_code; String plugin_initialization_cpp_code; String plugin_deinitialization_cpp_code; - Vector plugin_libraries; Vector plugin_linked_dependencies; Vector plugin_embedded_dependencies; Vector plugin_files; @@ -1188,11 +1225,24 @@ Error EditorExportPlatformIOS::_export_plugins(const Ref &p_ Vector added_embedded_dependenciy_names; HashMap plist_values; + Error err; + for (int i = 0; i < enabled_plugins.size(); i++) { PluginConfig plugin = enabled_plugins[i]; - // Adding plugin binary. - plugin_libraries.push_back(plugin.binary); + // Export plugin binary. + if (!plugin.supports_targets) { + err = _copy_asset(dest_dir, plugin.binary, nullptr, true, true, r_exported_assets); + } else { + String plugin_binary_dir = plugin.binary.get_base_dir(); + String plugin_name_prefix = plugin.binary.get_basename().get_file(); + String plugin_file = plugin_name_prefix + "." + (p_debug ? "debug" : "release") + ".a"; + String result_file_name = plugin.binary.get_file(); + + err = _copy_asset(dest_dir, plugin_binary_dir.plus_file(plugin_file), &result_file_name, true, true, r_exported_assets); + } + + ERR_FAIL_COND_V(err, err); // Adding dependencies. // Use separate container for names to check for duplicates. @@ -1291,10 +1341,6 @@ Error EditorExportPlatformIOS::_export_plugins(const Ref &p_ // Export files { - // Export plugin libraries - Error err = _export_additional_assets(dest_dir, plugin_libraries, true, true, r_exported_assets); - ERR_FAIL_COND_V(err, err); - // Export linked plugin dependency err = _export_additional_assets(dest_dir, plugin_linked_dependencies, true, false, r_exported_assets); ERR_FAIL_COND_V(err, err); @@ -1454,7 +1500,7 @@ Error EditorExportPlatformIOS::export_project(const Ref &p_p return ERR_CANT_OPEN; } - err = _export_plugins(p_preset, config_data, dest_dir + binary_name, assets); + err = _export_ios_plugins(p_preset, config_data, dest_dir + binary_name, assets, p_debug); ERR_FAIL_COND_V(err, err); //export rest of the files diff --git a/platform/iphone/plugin/godot_plugin_config.h b/platform/iphone/plugin/godot_plugin_config.h index fec9ba339fe..ab25688ac60 100644 --- a/platform/iphone/plugin/godot_plugin_config.h +++ b/platform/iphone/plugin/godot_plugin_config.h @@ -71,6 +71,7 @@ The `plist` section are optional. struct PluginConfig { // Set to true when the config file is properly loaded. bool valid_config = false; + bool supports_targets = false; // Unix timestamp of last change to this plugin. uint64_t last_updated = 0; @@ -158,18 +159,46 @@ static inline Vector resolve_system_dependencies(Vector p_paths) return paths; } -static inline bool is_plugin_config_valid(PluginConfig plugin_config) { +static inline bool validate_plugin(PluginConfig &plugin_config) { bool valid_name = !plugin_config.name.empty(); - bool valid_binary = !plugin_config.binary.empty() && FileAccess::exists(plugin_config.binary); + bool valid_binary_name = !plugin_config.binary.empty(); bool valid_initialize = !plugin_config.initialization_method.empty(); bool valid_deinitialize = !plugin_config.deinitialization_method.empty(); - return valid_name && valid_binary && valid_initialize && valid_deinitialize; + bool fields_value = valid_name && valid_binary_name && valid_initialize && valid_deinitialize; + + if (fields_value && FileAccess::exists(plugin_config.binary)) { + plugin_config.valid_config = true; + plugin_config.supports_targets = false; + } else if (fields_value) { + String file_path = plugin_config.binary.get_base_dir(); + String file_name = plugin_config.binary.get_basename().get_file(); + String release_file_name = file_path.plus_file(file_name + ".release.a"); + String debug_file_name = file_path.plus_file(file_name + ".debug.a"); + + if (FileAccess::exists(release_file_name) && FileAccess::exists(debug_file_name)) { + plugin_config.valid_config = true; + plugin_config.supports_targets = true; + } + } + + return plugin_config.valid_config; } static inline uint64_t get_plugin_modification_time(const PluginConfig &plugin_config, const String &config_path) { uint64_t last_updated = FileAccess::get_modified_time(config_path); - last_updated = MAX(last_updated, FileAccess::get_modified_time(plugin_config.binary)); + + if (!plugin_config.supports_targets) { + last_updated = MAX(last_updated, FileAccess::get_modified_time(plugin_config.binary)); + } else { + String file_path = plugin_config.binary.get_base_dir(); + String file_name = plugin_config.binary.get_basename().get_file(); + String release_file_name = file_path.plus_file(file_name + ".release.a"); + String debug_file_name = file_path.plus_file(file_name + ".debug.a"); + + last_updated = MAX(last_updated, FileAccess::get_modified_time(release_file_name)); + last_updated = MAX(last_updated, FileAccess::get_modified_time(debug_file_name)); + } return last_updated; } @@ -226,9 +255,7 @@ static inline PluginConfig load_plugin_config(Ref config_file, const } } - plugin_config.valid_config = is_plugin_config_valid(plugin_config); - - if (plugin_config.valid_config) { + if (validate_plugin(plugin_config)) { plugin_config.last_updated = get_plugin_modification_time(plugin_config, path); } From 64923945b3324cb833845468283459474f5e8607 Mon Sep 17 00:00:00 2001 From: Sergey Minakov Date: Thu, 14 Jan 2021 15:05:42 +0300 Subject: [PATCH 5/5] [Plugins] Rename 'PluginConfig' struct to platform specific name --- platform/android/export/export.cpp | 30 ++--- platform/android/plugin/godot_plugin_config.h | 118 ++++++++++-------- platform/iphone/export/export.cpp | 27 ++-- platform/iphone/plugin/godot_plugin_config.h | 88 +++++++------ 4 files changed, 149 insertions(+), 114 deletions(-) diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 8ec3f963579..5c269bfff37 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -264,7 +264,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { EditorProgress *ep; }; - Vector plugins; + Vector plugins; String last_plugin_names; uint64_t last_custom_build_time = 0; volatile bool plugins_changed; @@ -283,7 +283,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { { // Nothing to do if we already know the plugins have changed. if (!ea->plugins_changed) { - Vector loaded_plugins = get_plugins(); + Vector loaded_plugins = get_plugins(); ea->plugins_lock->lock(); @@ -640,7 +640,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { continue; } - if (file.ends_with(PLUGIN_CONFIG_EXT)) { + if (file.ends_with(PluginConfigAndroid::PLUGIN_CONFIG_EXT)) { dir_files.push_back(file); } } @@ -650,8 +650,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { return dir_files; } - static Vector get_plugins() { - Vector loaded_plugins; + static Vector get_plugins() { + Vector loaded_plugins; String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("android/plugins"); @@ -664,7 +664,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { if (!plugins_filenames.empty()) { Ref config_file = memnew(ConfigFile); for (int i = 0; i < plugins_filenames.size(); i++) { - PluginConfig config = load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i])); + PluginConfigAndroid config = load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i])); if (config.valid_config) { loaded_plugins.push_back(config); } else { @@ -677,11 +677,11 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { return loaded_plugins; } - static Vector get_enabled_plugins(const Ref &p_presets) { - Vector enabled_plugins; - Vector all_plugins = get_plugins(); + static Vector get_enabled_plugins(const Ref &p_presets) { + Vector enabled_plugins; + Vector all_plugins = get_plugins(); for (int i = 0; i < all_plugins.size(); i++) { - PluginConfig plugin = all_plugins[i]; + PluginConfigAndroid plugin = all_plugins[i]; bool enabled = p_presets->get("plugins/" + plugin.name); if (enabled) { enabled_plugins.push_back(plugin); @@ -1655,7 +1655,7 @@ public: 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(); + 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)); @@ -2487,7 +2487,7 @@ public: } } - inline bool is_clean_build_required(Vector enabled_plugins) { + inline bool is_clean_build_required(Vector enabled_plugins) { String plugin_names = get_plugins_names(enabled_plugins); bool first_build = last_custom_build_time == 0; bool have_plugins_changed = false; @@ -2797,9 +2797,9 @@ public: String sign_flag = should_sign ? "true" : "false"; String zipalign_flag = "true"; - Vector enabled_plugins = get_enabled_plugins(p_preset); - String local_plugins_binaries = get_plugins_binaries(BINARY_TYPE_LOCAL, enabled_plugins); - String remote_plugins_binaries = get_plugins_binaries(BINARY_TYPE_REMOTE, enabled_plugins); + Vector enabled_plugins = get_enabled_plugins(p_preset); + String local_plugins_binaries = get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_LOCAL, enabled_plugins); + String remote_plugins_binaries = get_plugins_binaries(PluginConfigAndroid::BINARY_TYPE_REMOTE, enabled_plugins); String custom_maven_repos = get_plugins_custom_maven_repos(enabled_plugins); bool clean_build_required = is_clean_build_required(enabled_plugins); diff --git a/platform/android/plugin/godot_plugin_config.h b/platform/android/plugin/godot_plugin_config.h index 7f71547b951..782fba47493 100644 --- a/platform/android/plugin/godot_plugin_config.h +++ b/platform/android/plugin/godot_plugin_config.h @@ -35,23 +35,6 @@ #include "core/io/config_file.h" #include "core/ustring.h" -static const char *PLUGIN_CONFIG_EXT = ".gdap"; - -static const char *CONFIG_SECTION = "config"; -static const char *CONFIG_NAME_KEY = "name"; -static const char *CONFIG_BINARY_TYPE_KEY = "binary_type"; -static const char *CONFIG_BINARY_KEY = "binary"; - -static const char *DEPENDENCIES_SECTION = "dependencies"; -static const char *DEPENDENCIES_LOCAL_KEY = "local"; -static const char *DEPENDENCIES_REMOTE_KEY = "remote"; -static const char *DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY = "custom_maven_repos"; - -static const char *BINARY_TYPE_LOCAL = "local"; -static const char *BINARY_TYPE_REMOTE = "remote"; - -static const char *PLUGIN_VALUE_SEPARATOR = "|"; - /* The `config` section and fields are required and defined as follow: - **name**: name of the plugin @@ -67,7 +50,25 @@ The `dependencies` section and fields are optional and defined as follow: See https://github.com/godotengine/godot/issues/38157#issuecomment-618773871 */ -struct PluginConfig { +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. @@ -84,11 +85,28 @@ struct PluginConfig { Vector custom_maven_repos; }; +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 PluginConfig MY_PREBUILT_PLUGIN = { +// static const PluginConfigAndroid MY_PREBUILT_PLUGIN = { // /*.valid_config =*/true, // /*.last_updated =*/0, // /*.name =*/"GodotPayment", @@ -112,9 +130,9 @@ static inline String resolve_local_dependency_path(String plugin_config_dir, Str return absolute_path; } -static inline PluginConfig resolve_prebuilt_plugin(PluginConfig prebuilt_plugin, String plugin_config_dir) { - PluginConfig resolved = prebuilt_plugin; - resolved.binary = resolved.binary_type == BINARY_TYPE_LOCAL ? resolve_local_dependency_path(plugin_config_dir, prebuilt_plugin.binary) : prebuilt_plugin.binary; +static inline 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++) { @@ -124,21 +142,21 @@ static inline PluginConfig resolve_prebuilt_plugin(PluginConfig prebuilt_plugin, return resolved; } -static inline Vector get_prebuilt_plugins(String plugins_base_dir) { - Vector prebuilt_plugins; +static inline Vector 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; } -static inline bool is_plugin_config_valid(PluginConfig plugin_config) { +static inline bool is_plugin_config_valid(PluginConfigAndroid plugin_config) { bool valid_name = !plugin_config.name.empty(); - bool valid_binary_type = plugin_config.binary_type == BINARY_TYPE_LOCAL || - plugin_config.binary_type == BINARY_TYPE_REMOTE; + 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 == BINARY_TYPE_REMOTE || + (plugin_config.binary_type == PluginConfigAndroid::BINARY_TYPE_REMOTE || FileAccess::exists(plugin_config.binary)); } @@ -154,7 +172,7 @@ static inline bool is_plugin_config_valid(PluginConfig plugin_config) { return valid_name && valid_binary && valid_binary_type && valid_local_dependencies; } -static inline uint64_t get_plugin_modification_time(const PluginConfig &plugin_config, const String &config_path) { +static inline uint64_t get_plugin_modification_time(const PluginConfigAndroid &plugin_config, const String &config_path) { uint64_t last_updated = FileAccess::get_modified_time(config_path); last_updated = MAX(last_updated, FileAccess::get_modified_time(plugin_config.binary)); @@ -166,30 +184,30 @@ static inline uint64_t get_plugin_modification_time(const PluginConfig &plugin_c return last_updated; } -static inline PluginConfig load_plugin_config(Ref config_file, const String &path) { - PluginConfig plugin_config = {}; +static inline 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(CONFIG_SECTION, CONFIG_NAME_KEY, String()); - plugin_config.binary_type = config_file->get_value(CONFIG_SECTION, CONFIG_BINARY_TYPE_KEY, String()); + 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(CONFIG_SECTION, CONFIG_BINARY_KEY, String()); - plugin_config.binary = plugin_config.binary_type == BINARY_TYPE_LOCAL ? resolve_local_dependency_path(config_base_dir, binary_path) : binary_path; + 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(DEPENDENCIES_SECTION)) { - Vector local_dependencies_paths = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_LOCAL_KEY, Vector()); + 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(DEPENDENCIES_SECTION, DEPENDENCIES_REMOTE_KEY, Vector()); - plugin_config.custom_maven_repos = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_CUSTOM_MAVEN_REPOS_KEY, Vector()); + 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); @@ -200,12 +218,12 @@ static inline PluginConfig load_plugin_config(Ref config_file, const return plugin_config; } -static inline String get_plugins_binaries(String binary_type, Vector plugins_configs) { +static inline String get_plugins_binaries(String binary_type, Vector plugins_configs) { String plugins_binaries; if (!plugins_configs.empty()) { Vector binaries; for (int i = 0; i < plugins_configs.size(); i++) { - PluginConfig config = plugins_configs[i]; + PluginConfigAndroid config = plugins_configs[i]; if (!config.valid_config) { continue; } @@ -214,27 +232,27 @@ static inline String get_plugins_binaries(String binary_type, Vector plugins_configs) { +static inline String get_plugins_custom_maven_repos(Vector plugins_configs) { String custom_maven_repos; if (!plugins_configs.empty()) { Vector repos_urls; for (int i = 0; i < plugins_configs.size(); i++) { - PluginConfig config = plugins_configs[i]; + PluginConfigAndroid config = plugins_configs[i]; if (!config.valid_config) { continue; } @@ -242,24 +260,24 @@ static inline String get_plugins_custom_maven_repos(Vector plugins repos_urls.append_array(config.custom_maven_repos); } - custom_maven_repos = String(PLUGIN_VALUE_SEPARATOR).join(repos_urls); + custom_maven_repos = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(repos_urls); } return custom_maven_repos; } -static inline String get_plugins_names(Vector plugins_configs) { +static inline String get_plugins_names(Vector plugins_configs) { String plugins_names; if (!plugins_configs.empty()) { Vector names; for (int i = 0; i < plugins_configs.size(); i++) { - PluginConfig config = plugins_configs[i]; + PluginConfigAndroid config = plugins_configs[i]; if (!config.valid_config) { continue; } names.push_back(config.name); } - plugins_names = String(PLUGIN_VALUE_SEPARATOR).join(names); + plugins_names = String(PluginConfigAndroid::PLUGIN_VALUE_SEPARATOR).join(names); } return plugins_names; diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index da50801c596..a62f019c01a 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -59,7 +59,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform { Thread *check_for_changes_thread; volatile bool quit_request; Mutex *plugins_lock; - Vector plugins; + Vector plugins; typedef Error (*FileHandler)(String p_file, void *p_userdata); static Error _walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata); @@ -150,7 +150,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform { ea->plugins_lock->lock(); - Vector loaded_plugins = get_plugins(); + Vector loaded_plugins = get_plugins(); if (ea->plugins.size() != loaded_plugins.size()) { ea->plugins_changed = true; @@ -249,7 +249,7 @@ public: continue; } - if (file.ends_with(PLUGIN_CONFIG_EXT)) { + if (file.ends_with(PluginConfigIOS::PLUGIN_CONFIG_EXT)) { dir_files.push_back(file); } } @@ -259,8 +259,8 @@ public: return dir_files; } - static Vector get_plugins() { - Vector loaded_plugins; + static Vector get_plugins() { + Vector loaded_plugins; String plugins_dir = ProjectSettings::get_singleton()->get_resource_path().plus_file("ios/plugins"); @@ -270,7 +270,7 @@ public: if (!plugins_filenames.empty()) { Ref config_file = memnew(ConfigFile); for (int i = 0; i < plugins_filenames.size(); i++) { - PluginConfig config = load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i])); + PluginConfigIOS config = load_plugin_config(config_file, plugins_dir.plus_file(plugins_filenames[i])); if (config.valid_config) { loaded_plugins.push_back(config); } else { @@ -283,11 +283,11 @@ public: return loaded_plugins; } - static Vector get_enabled_plugins(const Ref &p_presets) { - Vector enabled_plugins; - Vector all_plugins = get_plugins(); + static Vector get_enabled_plugins(const Ref &p_presets) { + Vector enabled_plugins; + Vector all_plugins = get_plugins(); for (int i = 0; i < all_plugins.size(); i++) { - PluginConfig plugin = all_plugins[i]; + PluginConfigIOS plugin = all_plugins[i]; bool enabled = p_presets->get("plugins/" + plugin.name); if (enabled) { enabled_plugins.push_back(plugin); @@ -366,8 +366,7 @@ void EditorExportPlatformIOS::get_export_options(List *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); - Vector found_plugins = get_plugins(); - + Vector found_plugins = get_plugins(); for (int i = 0; i < found_plugins.size(); i++) { r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "plugins/" + found_plugins[i].name), false)); } @@ -1219,7 +1218,7 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref Vector plugin_embedded_dependencies; Vector plugin_files; - Vector enabled_plugins = get_enabled_plugins(p_preset); + Vector enabled_plugins = get_enabled_plugins(p_preset); Vector added_linked_dependenciy_names; Vector added_embedded_dependenciy_names; @@ -1228,7 +1227,7 @@ Error EditorExportPlatformIOS::_export_ios_plugins(const Ref Error err; for (int i = 0; i < enabled_plugins.size(); i++) { - PluginConfig plugin = enabled_plugins[i]; + PluginConfigIOS plugin = enabled_plugins[i]; // Export plugin binary. if (!plugin.supports_targets) { diff --git a/platform/iphone/plugin/godot_plugin_config.h b/platform/iphone/plugin/godot_plugin_config.h index ab25688ac60..ab712e491dc 100644 --- a/platform/iphone/plugin/godot_plugin_config.h +++ b/platform/iphone/plugin/godot_plugin_config.h @@ -35,23 +35,6 @@ #include "core/io/config_file.h" #include "core/ustring.h" -static const char *PLUGIN_CONFIG_EXT = ".gdip"; - -static const char *CONFIG_SECTION = "config"; -static const char *CONFIG_NAME_KEY = "name"; -static const char *CONFIG_BINARY_KEY = "binary"; -static const char *CONFIG_INITIALIZE_KEY = "initialization"; -static const char *CONFIG_DEINITIALIZE_KEY = "deinitialization"; - -static const char *DEPENDENCIES_SECTION = "dependencies"; -static const char *DEPENDENCIES_LINKED_KEY = "linked"; -static const char *DEPENDENCIES_EMBEDDED_KEY = "embedded"; -static const char *DEPENDENCIES_SYSTEM_KEY = "system"; -static const char *DEPENDENCIES_CAPABILITIES_KEY = "capabilities"; -static const char *DEPENDENCIES_FILES_KEY = "files"; - -static const char *PLIST_SECTION = "plist"; - /* The `config` section and fields are required and defined as follow: - **name**: name of the plugin @@ -68,7 +51,25 @@ The `plist` section are optional. - **key**: key and value that would be added in Info.plist file. */ -struct PluginConfig { +struct PluginConfigIOS { + + static const char *PLUGIN_CONFIG_EXT; + + static const char *CONFIG_SECTION; + static const char *CONFIG_NAME_KEY; + static const char *CONFIG_BINARY_KEY; + static const char *CONFIG_INITIALIZE_KEY; + static const char *CONFIG_DEINITIALIZE_KEY; + + static const char *DEPENDENCIES_SECTION; + static const char *DEPENDENCIES_LINKED_KEY; + static const char *DEPENDENCIES_EMBEDDED_KEY; + static const char *DEPENDENCIES_SYSTEM_KEY; + static const char *DEPENDENCIES_CAPABILITIES_KEY; + static const char *DEPENDENCIES_FILES_KEY; + + static const char *PLIST_SECTION; + // Set to true when the config file is properly loaded. bool valid_config = false; bool supports_targets = false; @@ -94,6 +95,23 @@ struct PluginConfig { HashMap plist; }; +const char *PluginConfigIOS::PLUGIN_CONFIG_EXT = ".gdip"; + +const char *PluginConfigIOS::CONFIG_SECTION = "config"; +const char *PluginConfigIOS::CONFIG_NAME_KEY = "name"; +const char *PluginConfigIOS::CONFIG_BINARY_KEY = "binary"; +const char *PluginConfigIOS::CONFIG_INITIALIZE_KEY = "initialization"; +const char *PluginConfigIOS::CONFIG_DEINITIALIZE_KEY = "deinitialization"; + +const char *PluginConfigIOS::DEPENDENCIES_SECTION = "dependencies"; +const char *PluginConfigIOS::DEPENDENCIES_LINKED_KEY = "linked"; +const char *PluginConfigIOS::DEPENDENCIES_EMBEDDED_KEY = "embedded"; +const char *PluginConfigIOS::DEPENDENCIES_SYSTEM_KEY = "system"; +const char *PluginConfigIOS::DEPENDENCIES_CAPABILITIES_KEY = "capabilities"; +const char *PluginConfigIOS::DEPENDENCIES_FILES_KEY = "files"; + +const char *PluginConfigIOS::PLIST_SECTION = "plist"; + static inline String resolve_local_dependency_path(String plugin_config_dir, String dependency_path) { String absolute_path; @@ -159,7 +177,7 @@ static inline Vector resolve_system_dependencies(Vector p_paths) return paths; } -static inline bool validate_plugin(PluginConfig &plugin_config) { +static inline bool validate_plugin(PluginConfigIOS &plugin_config) { bool valid_name = !plugin_config.name.empty(); bool valid_binary_name = !plugin_config.binary.empty(); bool valid_initialize = !plugin_config.initialization_method.empty(); @@ -185,7 +203,7 @@ static inline bool validate_plugin(PluginConfig &plugin_config) { return plugin_config.valid_config; } -static inline uint64_t get_plugin_modification_time(const PluginConfig &plugin_config, const String &config_path) { +static inline uint64_t get_plugin_modification_time(const PluginConfigIOS &plugin_config, const String &config_path) { uint64_t last_updated = FileAccess::get_modified_time(config_path); if (!plugin_config.supports_targets) { @@ -203,8 +221,8 @@ static inline uint64_t get_plugin_modification_time(const PluginConfig &plugin_c return last_updated; } -static inline PluginConfig load_plugin_config(Ref config_file, const String &path) { - PluginConfig plugin_config = {}; +static inline PluginConfigIOS load_plugin_config(Ref config_file, const String &path) { + PluginConfigIOS plugin_config = {}; if (!config_file.is_valid()) { return plugin_config; @@ -218,18 +236,18 @@ static inline PluginConfig load_plugin_config(Ref config_file, const String config_base_dir = path.get_base_dir(); - plugin_config.name = config_file->get_value(CONFIG_SECTION, CONFIG_NAME_KEY, String()); - plugin_config.initialization_method = config_file->get_value(CONFIG_SECTION, CONFIG_INITIALIZE_KEY, String()); - plugin_config.deinitialization_method = config_file->get_value(CONFIG_SECTION, CONFIG_DEINITIALIZE_KEY, String()); + plugin_config.name = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_NAME_KEY, String()); + plugin_config.initialization_method = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_INITIALIZE_KEY, String()); + plugin_config.deinitialization_method = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_DEINITIALIZE_KEY, String()); - String binary_path = config_file->get_value(CONFIG_SECTION, CONFIG_BINARY_KEY, String()); + String binary_path = config_file->get_value(PluginConfigIOS::CONFIG_SECTION, PluginConfigIOS::CONFIG_BINARY_KEY, String()); plugin_config.binary = resolve_local_dependency_path(config_base_dir, binary_path); - if (config_file->has_section(DEPENDENCIES_SECTION)) { - Vector linked_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_LINKED_KEY, Vector()); - Vector embedded_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_EMBEDDED_KEY, Vector()); - Vector system_dependencies = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_SYSTEM_KEY, Vector()); - Vector files = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_FILES_KEY, Vector()); + if (config_file->has_section(PluginConfigIOS::DEPENDENCIES_SECTION)) { + Vector linked_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_LINKED_KEY, Vector()); + Vector embedded_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_EMBEDDED_KEY, Vector()); + Vector system_dependencies = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_SYSTEM_KEY, Vector()); + Vector files = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_FILES_KEY, Vector()); plugin_config.linked_dependencies = resolve_local_dependencies(config_base_dir, linked_dependencies); plugin_config.embedded_dependencies = resolve_local_dependencies(config_base_dir, embedded_dependencies); @@ -237,15 +255,15 @@ static inline PluginConfig load_plugin_config(Ref config_file, const plugin_config.files_to_copy = resolve_local_dependencies(config_base_dir, files); - plugin_config.capabilities = config_file->get_value(DEPENDENCIES_SECTION, DEPENDENCIES_CAPABILITIES_KEY, Vector()); + plugin_config.capabilities = config_file->get_value(PluginConfigIOS::DEPENDENCIES_SECTION, PluginConfigIOS::DEPENDENCIES_CAPABILITIES_KEY, Vector()); } - if (config_file->has_section(PLIST_SECTION)) { + if (config_file->has_section(PluginConfigIOS::PLIST_SECTION)) { List keys; - config_file->get_section_keys(PLIST_SECTION, &keys); + config_file->get_section_keys(PluginConfigIOS::PLIST_SECTION, &keys); for (int i = 0; i < keys.size(); i++) { - String value = config_file->get_value(PLIST_SECTION, keys[i], String()); + String value = config_file->get_value(PluginConfigIOS::PLIST_SECTION, keys[i], String()); if (value.empty()) { continue;