diff options
Diffstat (limited to 'platform/iphone')
-rw-r--r-- | platform/iphone/SCsub | 3 | ||||
-rw-r--r-- | platform/iphone/app_delegate.mm | 1 | ||||
-rw-r--r-- | platform/iphone/detect.py | 15 | ||||
-rw-r--r-- | platform/iphone/game_center.h | 75 | ||||
-rw-r--r-- | platform/iphone/game_center.mm | 389 | ||||
-rw-r--r-- | platform/iphone/icloud.h | 64 | ||||
-rw-r--r-- | platform/iphone/icloud.mm | 357 | ||||
-rw-r--r-- | platform/iphone/in_app_store.h | 81 | ||||
-rw-r--r-- | platform/iphone/in_app_store.mm | 415 | ||||
-rw-r--r-- | platform/iphone/os_iphone.h | 12 | ||||
-rw-r--r-- | platform/iphone/os_iphone.mm | 33 | ||||
-rw-r--r-- | platform/iphone/view_controller.h | 3 | ||||
-rw-r--r-- | platform/iphone/view_controller.mm | 11 |
13 files changed, 3 insertions, 1456 deletions
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index 1dd37dabe5..0a558f8e3d 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -8,9 +8,6 @@ iphone_lib = [ "main.m", "app_delegate.mm", "view_controller.mm", - "game_center.mm", - "in_app_store.mm", - "icloud.mm", "ios.mm", "vulkan_context_iphone.mm", "display_server_iphone.mm", diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm index c9891309fe..c1942e77dd 100644 --- a/platform/iphone/app_delegate.mm +++ b/platform/iphone/app_delegate.mm @@ -36,6 +36,7 @@ #include "os_iphone.h" #import "view_controller.h" +#import <AVFoundation/AVFoundation.h> #import <AudioToolbox/AudioServices.h> #define kRenderingFrequency 60 diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index ab453c353f..0456458326 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -35,9 +35,6 @@ def get_opts(): " validation layers)", False, ), - 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", ""), ] @@ -222,18 +219,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/game_center.h b/platform/iphone/game_center.h deleted file mode 100644 index cbfd616e56..0000000000 --- a/platform/iphone/game_center.h +++ /dev/null @@ -1,75 +0,0 @@ -/*************************************************************************/ -/* game_center.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef GAME_CENTER_ENABLED - -#ifndef GAME_CENTER_H -#define GAME_CENTER_H - -#include "core/object/class_db.h" - -class GameCenter : public Object { - GDCLASS(GameCenter, Object); - - static GameCenter *instance; - static void _bind_methods(); - - List<Variant> pending_events; - - bool authenticated; - - void return_connect_error(const char *p_error_description); - -public: - Error authenticate(); - bool is_authenticated(); - - Error post_score(Dictionary p_score); - Error award_achievement(Dictionary p_params); - void reset_achievements(); - void request_achievements(); - void request_achievement_descriptions(); - Error show_game_center(Dictionary p_params); - Error request_identity_verification_signature(); - - void game_center_closed(); - - int get_pending_event_count(); - Variant pop_pending_event(); - - static GameCenter *get_singleton(); - - GameCenter(); - ~GameCenter(); -}; - -#endif - -#endif diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm deleted file mode 100644 index 0f8c0100c3..0000000000 --- a/platform/iphone/game_center.mm +++ /dev/null @@ -1,389 +0,0 @@ -/*************************************************************************/ -/* game_center.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef GAME_CENTER_ENABLED - -#include "game_center.h" - -#ifdef __IPHONE_9_0 - -#import <GameKit/GameKit.h> -extern "C" { - -#else - -extern "C" { -#import <GameKit/GameKit.h> - -#endif - -#import "app_delegate.h" -}; - -#import "view_controller.h" - -GameCenter *GameCenter::instance = NULL; - -void GameCenter::_bind_methods() { - ClassDB::bind_method(D_METHOD("authenticate"), &GameCenter::authenticate); - ClassDB::bind_method(D_METHOD("is_authenticated"), &GameCenter::is_authenticated); - - ClassDB::bind_method(D_METHOD("post_score"), &GameCenter::post_score); - ClassDB::bind_method(D_METHOD("award_achievement", "achievement"), &GameCenter::award_achievement); - ClassDB::bind_method(D_METHOD("reset_achievements"), &GameCenter::reset_achievements); - ClassDB::bind_method(D_METHOD("request_achievements"), &GameCenter::request_achievements); - ClassDB::bind_method(D_METHOD("request_achievement_descriptions"), &GameCenter::request_achievement_descriptions); - ClassDB::bind_method(D_METHOD("show_game_center"), &GameCenter::show_game_center); - ClassDB::bind_method(D_METHOD("request_identity_verification_signature"), &GameCenter::request_identity_verification_signature); - - ClassDB::bind_method(D_METHOD("get_pending_event_count"), &GameCenter::get_pending_event_count); - ClassDB::bind_method(D_METHOD("pop_pending_event"), &GameCenter::pop_pending_event); -}; - -Error GameCenter::authenticate() { - //if this class isn't available, game center isn't implemented - if ((NSClassFromString(@"GKLocalPlayer")) == nil) { - return ERR_UNAVAILABLE; - } - - GKLocalPlayer *player = [GKLocalPlayer localPlayer]; - ERR_FAIL_COND_V(![player respondsToSelector:@selector(authenticateHandler)], ERR_UNAVAILABLE); - - ViewController *root_controller = (ViewController *)((AppDelegate *)[[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 - // after the view is cancelled or the user logs in. Or if the user's already logged in, it's - // called just once to confirm they're authenticated. This is why no result needs to be specified - // in the presentViewController phase. In this case, more calls to this function will follow. - _weakify(root_controller); - _weakify(player); - player.authenticateHandler = (^(UIViewController *controller, NSError *error) { - _strongify(root_controller); - _strongify(player); - - if (controller) { - [root_controller presentViewController:controller animated:YES completion:nil]; - } else { - Dictionary ret; - ret["type"] = "authentication"; - if (player.isAuthenticated) { - ret["result"] = "ok"; - if (@available(iOS 13, *)) { - ret["player_id"] = [player.teamPlayerID UTF8String]; -#if !defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR - } else { - ret["player_id"] = [player.playerID UTF8String]; -#endif - } - - GameCenter::get_singleton()->authenticated = true; - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - ret["error_description"] = [error.localizedDescription UTF8String]; - GameCenter::get_singleton()->authenticated = false; - }; - - pending_events.push_back(ret); - }; - }); - - return OK; -}; - -bool GameCenter::is_authenticated() { - return authenticated; -}; - -Error GameCenter::post_score(Dictionary p_score) { - ERR_FAIL_COND_V(!p_score.has("score") || !p_score.has("category"), ERR_INVALID_PARAMETER); - float score = p_score["score"]; - String category = p_score["category"]; - - NSString *cat_str = [[NSString alloc] initWithUTF8String:category.utf8().get_data()]; - GKScore *reporter = [[GKScore alloc] initWithLeaderboardIdentifier:cat_str]; - reporter.value = score; - - ERR_FAIL_COND_V([GKScore respondsToSelector:@selector(reportScores)], ERR_UNAVAILABLE); - - [GKScore reportScores:@[ reporter ] - withCompletionHandler:^(NSError *error) { - Dictionary ret; - ret["type"] = "post_score"; - if (error == nil) { - ret["result"] = "ok"; - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - ret["error_description"] = [error.localizedDescription UTF8String]; - }; - - pending_events.push_back(ret); - }]; - - return OK; -}; - -Error GameCenter::award_achievement(Dictionary p_params) { - ERR_FAIL_COND_V(!p_params.has("name") || !p_params.has("progress"), ERR_INVALID_PARAMETER); - String name = p_params["name"]; - float progress = p_params["progress"]; - - NSString *name_str = [[NSString alloc] initWithUTF8String:name.utf8().get_data()]; - GKAchievement *achievement = [[GKAchievement alloc] initWithIdentifier:name_str]; - ERR_FAIL_COND_V(!achievement, FAILED); - - ERR_FAIL_COND_V([GKAchievement respondsToSelector:@selector(reportAchievements)], ERR_UNAVAILABLE); - - achievement.percentComplete = progress; - achievement.showsCompletionBanner = NO; - if (p_params.has("show_completion_banner")) { - achievement.showsCompletionBanner = p_params["show_completion_banner"] ? YES : NO; - } - - [GKAchievement reportAchievements:@[ achievement ] - withCompletionHandler:^(NSError *error) { - Dictionary ret; - ret["type"] = "award_achievement"; - if (error == nil) { - ret["result"] = "ok"; - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - }; - - pending_events.push_back(ret); - }]; - - return OK; -}; - -void GameCenter::request_achievement_descriptions() { - [GKAchievementDescription loadAchievementDescriptionsWithCompletionHandler:^(NSArray *descriptions, NSError *error) { - Dictionary ret; - ret["type"] = "achievement_descriptions"; - if (error == nil) { - ret["result"] = "ok"; - PackedStringArray names; - PackedStringArray titles; - PackedStringArray unachieved_descriptions; - PackedStringArray achieved_descriptions; - PackedInt32Array maximum_points; - Array hidden; - Array replayable; - - for (NSUInteger i = 0; i < [descriptions count]; i++) { - GKAchievementDescription *description = [descriptions objectAtIndex:i]; - - const char *str = [description.identifier UTF8String]; - names.push_back(String::utf8(str != NULL ? str : "")); - - str = [description.title UTF8String]; - titles.push_back(String::utf8(str != NULL ? str : "")); - - str = [description.unachievedDescription UTF8String]; - unachieved_descriptions.push_back(String::utf8(str != NULL ? str : "")); - - str = [description.achievedDescription UTF8String]; - achieved_descriptions.push_back(String::utf8(str != NULL ? str : "")); - - maximum_points.push_back(description.maximumPoints); - - hidden.push_back(description.hidden == YES); - - replayable.push_back(description.replayable == YES); - } - - ret["names"] = names; - ret["titles"] = titles; - ret["unachieved_descriptions"] = unachieved_descriptions; - ret["achieved_descriptions"] = achieved_descriptions; - ret["maximum_points"] = maximum_points; - ret["hidden"] = hidden; - ret["replayable"] = replayable; - - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - }; - - pending_events.push_back(ret); - }]; -}; - -void GameCenter::request_achievements() { - [GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error) { - Dictionary ret; - ret["type"] = "achievements"; - if (error == nil) { - ret["result"] = "ok"; - PackedStringArray names; - PackedFloat32Array percentages; - - for (NSUInteger i = 0; i < [achievements count]; i++) { - GKAchievement *achievement = [achievements objectAtIndex:i]; - const char *str = [achievement.identifier UTF8String]; - names.push_back(String::utf8(str != NULL ? str : "")); - - percentages.push_back(achievement.percentComplete); - } - - ret["names"] = names; - ret["progress"] = percentages; - - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - }; - - pending_events.push_back(ret); - }]; -}; - -void GameCenter::reset_achievements() { - [GKAchievement resetAchievementsWithCompletionHandler:^(NSError *error) { - Dictionary ret; - ret["type"] = "reset_achievements"; - if (error == nil) { - ret["result"] = "ok"; - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - }; - - pending_events.push_back(ret); - }]; -}; - -Error GameCenter::show_game_center(Dictionary p_params) { - ERR_FAIL_COND_V(!NSProtocolFromString(@"GKGameCenterControllerDelegate"), FAILED); - - GKGameCenterViewControllerState view_state = GKGameCenterViewControllerStateDefault; - if (p_params.has("view")) { - String view_name = p_params["view"]; - if (view_name == "default") { - view_state = GKGameCenterViewControllerStateDefault; - } else if (view_name == "leaderboards") { - view_state = GKGameCenterViewControllerStateLeaderboards; - } else if (view_name == "achievements") { - view_state = GKGameCenterViewControllerStateAchievements; - } else if (view_name == "challenges") { - view_state = GKGameCenterViewControllerStateChallenges; - } else { - return ERR_INVALID_PARAMETER; - } - } - - GKGameCenterViewController *controller = [[GKGameCenterViewController alloc] init]; - ERR_FAIL_COND_V(!controller, FAILED); - - ViewController *root_controller = (ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController; - ERR_FAIL_COND_V(!root_controller, FAILED); - - controller.gameCenterDelegate = root_controller; - controller.viewState = view_state; - if (view_state == GKGameCenterViewControllerStateLeaderboards) { - controller.leaderboardIdentifier = nil; - if (p_params.has("leaderboard_name")) { - String name = p_params["leaderboard_name"]; - NSString *name_str = [[NSString alloc] initWithUTF8String:name.utf8().get_data()]; - controller.leaderboardIdentifier = name_str; - } - } - - [root_controller presentViewController:controller animated:YES completion:nil]; - - return OK; -}; - -Error GameCenter::request_identity_verification_signature() { - ERR_FAIL_COND_V(!is_authenticated(), ERR_UNAUTHORIZED); - - GKLocalPlayer *player = [GKLocalPlayer localPlayer]; - [player generateIdentityVerificationSignatureWithCompletionHandler:^(NSURL *publicKeyUrl, NSData *signature, NSData *salt, uint64_t timestamp, NSError *error) { - Dictionary ret; - ret["type"] = "identity_verification_signature"; - if (error == nil) { - ret["result"] = "ok"; - ret["public_key_url"] = [publicKeyUrl.absoluteString UTF8String]; - ret["signature"] = [[signature base64EncodedStringWithOptions:0] UTF8String]; - ret["salt"] = [[salt base64EncodedStringWithOptions:0] UTF8String]; - ret["timestamp"] = timestamp; - if (@available(iOS 13, *)) { - ret["player_id"] = [player.teamPlayerID UTF8String]; -#if !defined(TARGET_OS_SIMULATOR) || !TARGET_OS_SIMULATOR - } else { - ret["player_id"] = [player.playerID UTF8String]; -#endif - } - } else { - ret["result"] = "error"; - ret["error_code"] = (int64_t)error.code; - ret["error_description"] = [error.localizedDescription UTF8String]; - }; - - pending_events.push_back(ret); - }]; - - return OK; -}; - -void GameCenter::game_center_closed() { - Dictionary ret; - ret["type"] = "show_game_center"; - ret["result"] = "ok"; - pending_events.push_back(ret); -} - -int GameCenter::get_pending_event_count() { - return pending_events.size(); -}; - -Variant GameCenter::pop_pending_event() { - Variant front = pending_events.front()->get(); - pending_events.pop_front(); - - return front; -}; - -GameCenter *GameCenter::get_singleton() { - return instance; -}; - -GameCenter::GameCenter() { - ERR_FAIL_COND(instance != NULL); - instance = this; - authenticated = false; -}; - -GameCenter::~GameCenter() {} - -#endif diff --git a/platform/iphone/icloud.h b/platform/iphone/icloud.h deleted file mode 100644 index 5f59abdfc0..0000000000 --- a/platform/iphone/icloud.h +++ /dev/null @@ -1,64 +0,0 @@ -/*************************************************************************/ -/* icloud.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef ICLOUD_ENABLED - -#ifndef ICLOUD_H -#define ICLOUD_H - -#include "core/object/class_db.h" - -class ICloud : public Object { - GDCLASS(ICloud, Object); - - static ICloud *instance; - static void _bind_methods(); - - List<Variant> pending_events; - -public: - Error remove_key(String p_param); - Array set_key_values(Dictionary p_params); - Variant get_key_value(String p_param); - Error synchronize_key_values(); - Variant get_all_key_values(); - - int get_pending_event_count(); - Variant pop_pending_event(); - - static ICloud *get_singleton(); - - ICloud(); - ~ICloud(); -}; - -#endif - -#endif diff --git a/platform/iphone/icloud.mm b/platform/iphone/icloud.mm deleted file mode 100644 index 3d81349883..0000000000 --- a/platform/iphone/icloud.mm +++ /dev/null @@ -1,357 +0,0 @@ -/*************************************************************************/ -/* icloud.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef ICLOUD_ENABLED - -#include "icloud.h" - -#ifndef __IPHONE_9_0 -extern "C" { -#endif - -#import "app_delegate.h" - -#import <Foundation/Foundation.h> - -#ifndef __IPHONE_9_0 -}; -#endif - -ICloud *ICloud::instance = NULL; - -void ICloud::_bind_methods() { - ClassDB::bind_method(D_METHOD("remove_key"), &ICloud::remove_key); - - ClassDB::bind_method(D_METHOD("set_key_values"), &ICloud::set_key_values); - ClassDB::bind_method(D_METHOD("get_key_value"), &ICloud::get_key_value); - - ClassDB::bind_method(D_METHOD("synchronize_key_values"), &ICloud::synchronize_key_values); - ClassDB::bind_method(D_METHOD("get_all_key_values"), &ICloud::get_all_key_values); - - ClassDB::bind_method(D_METHOD("get_pending_event_count"), &ICloud::get_pending_event_count); - ClassDB::bind_method(D_METHOD("pop_pending_event"), &ICloud::pop_pending_event); -}; - -int ICloud::get_pending_event_count() { - return pending_events.size(); -}; - -Variant ICloud::pop_pending_event() { - Variant front = pending_events.front()->get(); - pending_events.pop_front(); - - return front; -}; - -ICloud *ICloud::get_singleton() { - return instance; -}; - -//convert from apple's abstract type to godot's abstract type.... -Variant nsobject_to_variant(NSObject *object) { - if ([object isKindOfClass:[NSString class]]) { - const char *str = [(NSString *)object UTF8String]; - return String::utf8(str != NULL ? str : ""); - } else if ([object isKindOfClass:[NSData class]]) { - PackedByteArray ret; - NSData *data = (NSData *)object; - if ([data length] > 0) { - ret.resize([data length]); - { - // PackedByteArray::Write w = ret.write(); - copymem((void *)ret.ptr(), [data bytes], [data length]); - } - } - return ret; - } else if ([object isKindOfClass:[NSArray class]]) { - Array result; - NSArray *array = (NSArray *)object; - for (NSUInteger i = 0; i < [array count]; ++i) { - NSObject *value = [array objectAtIndex:i]; - result.push_back(nsobject_to_variant(value)); - } - return result; - } else if ([object isKindOfClass:[NSDictionary class]]) { - Dictionary result; - NSDictionary *dic = (NSDictionary *)object; - - NSArray *keys = [dic allKeys]; - int count = [keys count]; - for (int i = 0; i < count; ++i) { - NSObject *k = [keys objectAtIndex:i]; - NSObject *v = [dic objectForKey:k]; - - result[nsobject_to_variant(k)] = nsobject_to_variant(v); - } - return result; - } else if ([object isKindOfClass:[NSNumber class]]) { - //Every type except numbers can reliably identify its type. The following is comparing to the *internal* representation, which isn't guaranteed to match the type that was used to create it, and is not advised, particularly when dealing with potential platform differences (ie, 32/64 bit) - //To avoid errors, we'll cast as broadly as possible, and only return int or float. - //bool, char, int, uint, longlong -> int - //float, double -> float - NSNumber *num = (NSNumber *)object; - if (strcmp([num objCType], @encode(BOOL)) == 0) { - return Variant((int)[num boolValue]); - } else if (strcmp([num objCType], @encode(char)) == 0) { - return Variant((int)[num charValue]); - } else if (strcmp([num objCType], @encode(int)) == 0) { - return Variant([num intValue]); - } else if (strcmp([num objCType], @encode(unsigned int)) == 0) { - return Variant((int)[num unsignedIntValue]); - } else if (strcmp([num objCType], @encode(long long)) == 0) { - return Variant((int)[num longValue]); - } else if (strcmp([num objCType], @encode(float)) == 0) { - return Variant([num floatValue]); - } else if (strcmp([num objCType], @encode(double)) == 0) { - return Variant((float)[num doubleValue]); - } else { - return Variant(); - } - } else if ([object isKindOfClass:[NSDate class]]) { - //this is a type that icloud supports...but how did you submit it in the first place? - //I guess this is a type that *might* show up, if you were, say, trying to make your game - //compatible with existing cloud data written by another engine's version of your game - WARN_PRINT("NSDate unsupported, returning null Variant"); - return Variant(); - } else if ([object isKindOfClass:[NSNull class]] or object == nil) { - return Variant(); - } else { - WARN_PRINT("Trying to convert unknown NSObject type to Variant"); - return Variant(); - } -} - -NSObject *variant_to_nsobject(Variant v) { - if (v.get_type() == Variant::STRING) { - return [[NSString alloc] initWithUTF8String:((String)v).utf8().get_data()]; - } else if (v.get_type() == Variant::FLOAT) { - return [NSNumber numberWithDouble:(double)v]; - } else if (v.get_type() == Variant::INT) { - return [NSNumber numberWithLongLong:(long)(int)v]; - } else if (v.get_type() == Variant::BOOL) { - return [NSNumber numberWithBool:BOOL((bool)v)]; - } else if (v.get_type() == Variant::DICTIONARY) { - NSMutableDictionary *result = [[NSMutableDictionary alloc] init]; - Dictionary dic = v; - Array keys = dic.keys(); - for (int i = 0; i < keys.size(); ++i) { - NSString *key = [[NSString alloc] initWithUTF8String:((String)(keys[i])).utf8().get_data()]; - NSObject *value = variant_to_nsobject(dic[keys[i]]); - - if (key == NULL || value == NULL) { - return NULL; - } - - [result setObject:value forKey:key]; - } - return result; - } else if (v.get_type() == Variant::ARRAY) { - NSMutableArray *result = [[NSMutableArray alloc] init]; - Array arr = v; - for (int i = 0; i < arr.size(); ++i) { - NSObject *value = variant_to_nsobject(arr[i]); - if (value == NULL) { - //trying to add something unsupported to the array. cancel the whole array - return NULL; - } - [result addObject:value]; - } - return result; - } else if (v.get_type() == Variant::PACKED_BYTE_ARRAY) { - PackedByteArray arr = v; - // PackedByteArray::Read r = arr.read(); - NSData *result = [NSData dataWithBytes:arr.ptr() length:arr.size()]; - return result; - } - WARN_PRINT(String("Could not add unsupported type to iCloud: '" + Variant::get_type_name(v.get_type()) + "'").utf8().get_data()); - return NULL; -} - -Error ICloud::remove_key(String p_param) { - NSString *key = [[NSString alloc] initWithUTF8String:p_param.utf8().get_data()]; - - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - - if (![[store dictionaryRepresentation] objectForKey:key]) { - return ERR_INVALID_PARAMETER; - } - - [store removeObjectForKey:key]; - return OK; -} - -//return an array of the keys that could not be set -Array ICloud::set_key_values(Dictionary p_params) { - Array keys = p_params.keys(); - - Array error_keys; - - for (int i = 0; i < keys.size(); ++i) { - String variant_key = keys[i]; - Variant variant_value = p_params[variant_key]; - - NSString *key = [[NSString alloc] initWithUTF8String:variant_key.utf8().get_data()]; - if (key == NULL) { - error_keys.push_back(variant_key); - continue; - } - - NSObject *value = variant_to_nsobject(variant_value); - - if (value == NULL) { - error_keys.push_back(variant_key); - continue; - } - - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - [store setObject:value forKey:key]; - } - - return error_keys; -} - -Variant ICloud::get_key_value(String p_param) { - NSString *key = [[NSString alloc] initWithUTF8String:p_param.utf8().get_data()]; - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - - if (![[store dictionaryRepresentation] objectForKey:key]) { - return Variant(); - } - - Variant result = nsobject_to_variant([[store dictionaryRepresentation] objectForKey:key]); - - return result; -} - -Variant ICloud::get_all_key_values() { - Dictionary result; - - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - NSDictionary *store_dictionary = [store dictionaryRepresentation]; - - NSArray *keys = [store_dictionary allKeys]; - int count = [keys count]; - for (int i = 0; i < count; ++i) { - NSString *k = [keys objectAtIndex:i]; - NSObject *v = [store_dictionary objectForKey:k]; - - const char *str = [k UTF8String]; - if (str != NULL) { - result[String::utf8(str)] = nsobject_to_variant(v); - } - } - - return result; -} - -Error ICloud::synchronize_key_values() { - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - BOOL result = [store synchronize]; - if (result == YES) { - return OK; - } else { - return FAILED; - } -} - -/* -Error ICloud::initial_sync() { - //you sometimes have to write something to the store to get it to download new data. go apple! - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - if ([store boolForKey:@"isb"]) - { - [store setBool:NO forKey:@"isb"]; - } - else - { - [store setBool:YES forKey:@"isb"]; - } - return synchronize(); -} - -*/ -ICloud::ICloud() { - ERR_FAIL_COND(instance != NULL); - instance = this; - //connected = false; - - [[NSNotificationCenter defaultCenter] - addObserverForName:NSUbiquitousKeyValueStoreDidChangeExternallyNotification - object:[NSUbiquitousKeyValueStore defaultStore] - queue:nil - usingBlock:^(NSNotification *notification) { - NSDictionary *userInfo = [notification userInfo]; - NSInteger change = [[userInfo objectForKey:NSUbiquitousKeyValueStoreChangeReasonKey] integerValue]; - - Dictionary ret; - ret["type"] = "key_value_changed"; - - //PackedStringArray result_keys; - //Array result_values; - Dictionary keyValues; - String reason = ""; - - if (change == NSUbiquitousKeyValueStoreServerChange) { - reason = "server"; - } else if (change == NSUbiquitousKeyValueStoreInitialSyncChange) { - reason = "initial_sync"; - } else if (change == NSUbiquitousKeyValueStoreQuotaViolationChange) { - reason = "quota_violation"; - } else if (change == NSUbiquitousKeyValueStoreAccountChange) { - reason = "account"; - } - - ret["reason"] = reason; - - NSUbiquitousKeyValueStore *store = [NSUbiquitousKeyValueStore defaultStore]; - - NSArray *keys = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangedKeysKey]; - for (NSString *key in keys) { - const char *str = [key UTF8String]; - if (str == NULL) { - continue; - } - - NSObject *object = [store objectForKey:key]; - - //figure out what kind of object it is - Variant value = nsobject_to_variant(object); - - keyValues[String::utf8(str)] = value; - } - - ret["changed_values"] = keyValues; - pending_events.push_back(ret); - }]; -} - -ICloud::~ICloud() {} - -#endif diff --git a/platform/iphone/in_app_store.h b/platform/iphone/in_app_store.h deleted file mode 100644 index 85075e4e20..0000000000 --- a/platform/iphone/in_app_store.h +++ /dev/null @@ -1,81 +0,0 @@ -/*************************************************************************/ -/* in_app_store.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef STOREKIT_ENABLED - -#ifndef IN_APP_STORE_H -#define IN_APP_STORE_H - -#include "core/object/class_db.h" - -#ifdef __OBJC__ -@class GodotProductsDelegate; -@class GodotTransactionsObserver; - -typedef GodotProductsDelegate InAppStoreProductDelegate; -typedef GodotTransactionsObserver InAppStoreTransactionObserver; -#else -typedef void InAppStoreProductDelegate; -typedef void InAppStoreTransactionObserver; -#endif - -class InAppStore : public Object { - GDCLASS(InAppStore, Object); - - static InAppStore *instance; - static void _bind_methods(); - - List<Variant> pending_events; - - InAppStoreProductDelegate *products_request_delegate; - InAppStoreTransactionObserver *transactions_observer; - -public: - Error request_product_info(Dictionary p_params); - Error restore_purchases(); - Error purchase(Dictionary p_params); - - int get_pending_event_count(); - Variant pop_pending_event(); - void finish_transaction(String product_id); - void set_auto_finish_transaction(bool b); - - void _post_event(Variant p_event); - void _record_purchase(String product_id); - - static InAppStore *get_singleton(); - - InAppStore(); - ~InAppStore(); -}; - -#endif - -#endif diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm deleted file mode 100644 index 3eec9dae69..0000000000 --- a/platform/iphone/in_app_store.mm +++ /dev/null @@ -1,415 +0,0 @@ -/*************************************************************************/ -/* in_app_store.mm */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifdef STOREKIT_ENABLED - -#include "in_app_store.h" - -#import <Foundation/Foundation.h> -#import <StoreKit/StoreKit.h> - -InAppStore *InAppStore::instance = NULL; - -@interface SKProduct (LocalizedPrice) - -@property(nonatomic, readonly) NSString *localizedPrice; - -@end - -//----------------------------------// -// SKProduct extension -//----------------------------------// -@implementation SKProduct (LocalizedPrice) - -- (NSString *)localizedPrice { - NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; - [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; - [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; - [numberFormatter setLocale:self.priceLocale]; - NSString *formattedString = [numberFormatter stringFromNumber:self.price]; - return formattedString; -} - -@end - -@interface GodotProductsDelegate : NSObject <SKProductsRequestDelegate> - -@property(nonatomic, strong) NSMutableArray *loadedProducts; -@property(nonatomic, strong) NSMutableArray *pendingRequests; - -- (void)performRequestWithProductIDs:(NSSet *)productIDs; -- (Error)purchaseProductWithProductID:(NSString *)productID; -- (void)reset; - -@end - -@implementation GodotProductsDelegate - -- (instancetype)init { - self = [super init]; - - if (self) { - [self godot_commonInit]; - } - - return self; -} - -- (void)godot_commonInit { - self.loadedProducts = [NSMutableArray new]; - self.pendingRequests = [NSMutableArray new]; -} - -- (void)performRequestWithProductIDs:(NSSet *)productIDs { - SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:productIDs]; - - request.delegate = self; - [self.pendingRequests addObject:request]; - [request start]; -} - -- (Error)purchaseProductWithProductID:(NSString *)productID { - SKProduct *product = nil; - - NSLog(@"searching for product!"); - - if (self.loadedProducts) { - for (SKProduct *storedProduct in self.loadedProducts) { - if ([storedProduct.productIdentifier isEqualToString:productID]) { - product = storedProduct; - break; - } - } - } - - if (!product) { - return ERR_INVALID_PARAMETER; - } - - NSLog(@"product found!"); - - SKPayment *payment = [SKPayment paymentWithProduct:product]; - [[SKPaymentQueue defaultQueue] addPayment:payment]; - - NSLog(@"purchase sent!"); - - return OK; -} - -- (void)reset { - [self.loadedProducts removeAllObjects]; - [self.pendingRequests removeAllObjects]; -} - -- (void)request:(SKRequest *)request didFailWithError:(NSError *)error { - [self.pendingRequests removeObject:request]; - - Dictionary ret; - ret["type"] = "product_info"; - ret["result"] = "error"; - ret["error"] = String::utf8([error.localizedDescription UTF8String]); - - InAppStore::get_singleton()->_post_event(ret); -} - -- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { - [self.pendingRequests removeObject:request]; - - NSArray *products = response.products; - [self.loadedProducts addObjectsFromArray:products]; - - Dictionary ret; - ret["type"] = "product_info"; - ret["result"] = "ok"; - PackedStringArray titles; - PackedStringArray descriptions; - PackedFloat32Array prices; - PackedStringArray ids; - PackedStringArray localized_prices; - PackedStringArray currency_codes; - - for (NSUInteger i = 0; i < [products count]; i++) { - SKProduct *product = [products objectAtIndex:i]; - - const char *str = [product.localizedTitle UTF8String]; - titles.push_back(String::utf8(str != NULL ? str : "")); - - str = [product.localizedDescription UTF8String]; - descriptions.push_back(String::utf8(str != NULL ? str : "")); - prices.push_back([product.price doubleValue]); - ids.push_back(String::utf8([product.productIdentifier UTF8String])); - localized_prices.push_back(String::utf8([product.localizedPrice UTF8String])); - currency_codes.push_back(String::utf8([[[product priceLocale] objectForKey:NSLocaleCurrencyCode] UTF8String])); - } - - ret["titles"] = titles; - ret["descriptions"] = descriptions; - ret["prices"] = prices; - ret["ids"] = ids; - ret["localized_prices"] = localized_prices; - ret["currency_codes"] = currency_codes; - - PackedStringArray invalid_ids; - - for (NSString *ipid in response.invalidProductIdentifiers) { - invalid_ids.push_back(String::utf8([ipid UTF8String])); - } - - ret["invalid_ids"] = invalid_ids; - - InAppStore::get_singleton()->_post_event(ret); -} - -@end - -@interface GodotTransactionsObserver : NSObject <SKPaymentTransactionObserver> - -@property(nonatomic, assign) BOOL shouldAutoFinishTransactions; -@property(nonatomic, strong) NSMutableDictionary *pendingTransactions; - -- (void)finishTransactionWithProductID:(NSString *)productID; -- (void)reset; - -@end - -@implementation GodotTransactionsObserver - -- (instancetype)init { - self = [super init]; - - if (self) { - [self godot_commonInit]; - } - - return self; -} - -- (void)godot_commonInit { - self.pendingTransactions = [NSMutableDictionary new]; -} - -- (void)finishTransactionWithProductID:(NSString *)productID { - SKPaymentTransaction *transaction = self.pendingTransactions[productID]; - - if (transaction) { - [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; - } - - self.pendingTransactions[productID] = nil; -} - -- (void)reset { - [self.pendingTransactions removeAllObjects]; -} - -- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { - printf("transactions updated!\n"); - for (SKPaymentTransaction *transaction in transactions) { - switch (transaction.transactionState) { - case SKPaymentTransactionStatePurchased: { - printf("status purchased!\n"); - String pid = String::utf8([transaction.payment.productIdentifier UTF8String]); - String transactionId = String::utf8([transaction.transactionIdentifier UTF8String]); - InAppStore::get_singleton()->_record_purchase(pid); - Dictionary ret; - ret["type"] = "purchase"; - ret["result"] = "ok"; - ret["product_id"] = pid; - ret["transaction_id"] = transactionId; - - NSData *receipt = nil; - int sdk_version = [[[UIDevice currentDevice] systemVersion] intValue]; - - NSBundle *bundle = [NSBundle mainBundle]; - // Get the transaction receipt file path location in the app bundle. - NSURL *receiptFileURL = [bundle appStoreReceiptURL]; - - // Read in the contents of the transaction file. - receipt = [NSData dataWithContentsOfURL:receiptFileURL]; - - NSString *receipt_to_send = nil; - - if (receipt != nil) { - receipt_to_send = [receipt base64EncodedStringWithOptions:0]; - } - Dictionary receipt_ret; - receipt_ret["receipt"] = String::utf8(receipt_to_send != nil ? [receipt_to_send UTF8String] : ""); - receipt_ret["sdk"] = sdk_version; - ret["receipt"] = receipt_ret; - - InAppStore::get_singleton()->_post_event(ret); - - if (self.shouldAutoFinishTransactions) { - [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; - } else { - self.pendingTransactions[transaction.payment.productIdentifier] = transaction; - } - - } break; - case SKPaymentTransactionStateFailed: { - printf("status transaction failed!\n"); - String pid = String::utf8([transaction.payment.productIdentifier UTF8String]); - Dictionary ret; - ret["type"] = "purchase"; - ret["result"] = "error"; - ret["product_id"] = pid; - ret["error"] = String::utf8([transaction.error.localizedDescription UTF8String]); - InAppStore::get_singleton()->_post_event(ret); - [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; - } break; - case SKPaymentTransactionStateRestored: { - printf("status transaction restored!\n"); - String pid = String::utf8([transaction.originalTransaction.payment.productIdentifier UTF8String]); - InAppStore::get_singleton()->_record_purchase(pid); - Dictionary ret; - ret["type"] = "restore"; - ret["result"] = "ok"; - ret["product_id"] = pid; - InAppStore::get_singleton()->_post_event(ret); - [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; - } break; - default: { - printf("status default %i!\n", (int)transaction.transactionState); - } break; - } - } -} - -@end - -void InAppStore::_bind_methods() { - ClassDB::bind_method(D_METHOD("request_product_info"), &InAppStore::request_product_info); - ClassDB::bind_method(D_METHOD("restore_purchases"), &InAppStore::restore_purchases); - ClassDB::bind_method(D_METHOD("purchase"), &InAppStore::purchase); - - ClassDB::bind_method(D_METHOD("get_pending_event_count"), &InAppStore::get_pending_event_count); - ClassDB::bind_method(D_METHOD("pop_pending_event"), &InAppStore::pop_pending_event); - ClassDB::bind_method(D_METHOD("finish_transaction"), &InAppStore::finish_transaction); - ClassDB::bind_method(D_METHOD("set_auto_finish_transaction"), &InAppStore::set_auto_finish_transaction); -} - -Error InAppStore::request_product_info(Dictionary p_params) { - ERR_FAIL_COND_V(!p_params.has("product_ids"), ERR_INVALID_PARAMETER); - - PackedStringArray pids = p_params["product_ids"]; - printf("************ request product info! %i\n", pids.size()); - - NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:pids.size()]; - for (int i = 0; i < pids.size(); i++) { - printf("******** adding %s to product list\n", pids[i].utf8().get_data()); - NSString *pid = [[NSString alloc] initWithUTF8String:pids[i].utf8().get_data()]; - [array addObject:pid]; - }; - - NSSet *products = [[NSSet alloc] initWithArray:array]; - - [products_request_delegate performRequestWithProductIDs:products]; - - return OK; -} - -Error InAppStore::restore_purchases() { - printf("restoring purchases!\n"); - [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]; - - return OK; -} - -Error InAppStore::purchase(Dictionary p_params) { - ERR_FAIL_COND_V(![SKPaymentQueue canMakePayments], ERR_UNAVAILABLE); - if (![SKPaymentQueue canMakePayments]) { - return ERR_UNAVAILABLE; - } - - printf("purchasing!\n"); - Dictionary params = p_params; - ERR_FAIL_COND_V(!params.has("product_id"), ERR_INVALID_PARAMETER); - - NSString *pid = [[NSString alloc] initWithUTF8String:String(params["product_id"]).utf8().get_data()]; - - return [products_request_delegate purchaseProductWithProductID:pid]; -} - -int InAppStore::get_pending_event_count() { - return pending_events.size(); -} - -Variant InAppStore::pop_pending_event() { - Variant front = pending_events.front()->get(); - pending_events.pop_front(); - - return front; -} - -void InAppStore::_post_event(Variant p_event) { - pending_events.push_back(p_event); -} - -void InAppStore::_record_purchase(String product_id) { - String skey = "purchased/" + product_id; - NSString *key = [[NSString alloc] initWithUTF8String:skey.utf8().get_data()]; - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:key]; - [[NSUserDefaults standardUserDefaults] synchronize]; -} - -InAppStore *InAppStore::get_singleton() { - return instance; -} - -InAppStore::InAppStore() { - ERR_FAIL_COND(instance != NULL); - instance = this; - - products_request_delegate = [[GodotProductsDelegate alloc] init]; - transactions_observer = [[GodotTransactionsObserver alloc] init]; - - [[SKPaymentQueue defaultQueue] addTransactionObserver:transactions_observer]; -} - -void InAppStore::finish_transaction(String product_id) { - NSString *prod_id = [NSString stringWithCString:product_id.utf8().get_data() encoding:NSUTF8StringEncoding]; - - [transactions_observer finishTransactionWithProductID:prod_id]; -} - -void InAppStore::set_auto_finish_transaction(bool b) { - transactions_observer.shouldAutoFinishTransactions = b; -} - -InAppStore::~InAppStore() { - [products_request_delegate reset]; - [transactions_observer reset]; - - products_request_delegate = nil; - [[SKPaymentQueue defaultQueue] removeTransactionObserver:transactions_observer]; - transactions_observer = nil; -} - -#endif diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index c6f95869ee..f0854cf98b 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -35,9 +35,6 @@ #include "drivers/coreaudio/audio_driver_coreaudio.h" #include "drivers/unix/os_unix.h" -#include "game_center.h" -#include "icloud.h" -#include "in_app_store.h" #include "ios.h" #include "joypad_iphone.h" #include "servers/audio_server.h" @@ -55,15 +52,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 32e9dda92b..a749ac7e06 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/iphone/os_iphone.mm @@ -125,21 +125,6 @@ void OSIPhone::initialize() { } void OSIPhone::initialize_modules() { -#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)); -#endif - ios = memnew(iOS); Engine::get_singleton()->add_singleton(Engine::Singleton("iOS", ios)); @@ -154,24 +139,6 @@ void OSIPhone::deinitialize_modules() { if (ios) { 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 } void OSIPhone::set_main_loop(MainLoop *p_main_loop) { diff --git a/platform/iphone/view_controller.h b/platform/iphone/view_controller.h index b0b31ae377..2cc4e4c388 100644 --- a/platform/iphone/view_controller.h +++ b/platform/iphone/view_controller.h @@ -28,13 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#import <GameKit/GameKit.h> #import <UIKit/UIKit.h> @class GodotView; @class GodotNativeVideoView; -@interface ViewController : UIViewController <GKGameCenterControllerDelegate> +@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 e11eff423b..5d18a72be1 100644 --- a/platform/iphone/view_controller.mm +++ b/platform/iphone/view_controller.mm @@ -36,6 +36,7 @@ #import "native_video_view.h" #include "os_iphone.h" +#import <AVFoundation/AVFoundation.h> #import <GameController/GameController.h> @interface ViewController () @@ -214,14 +215,4 @@ } } -// MARK: Delegates - -#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 |