diff options
Diffstat (limited to 'platform/iphone/view_controller.mm')
| -rw-r--r-- | platform/iphone/view_controller.mm | 250 |
1 files changed, 41 insertions, 209 deletions
diff --git a/platform/iphone/view_controller.mm b/platform/iphone/view_controller.mm index 31597f7856..2723ac4706 100644 --- a/platform/iphone/view_controller.mm +++ b/platform/iphone/view_controller.mm @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* 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 */ @@ -29,27 +29,22 @@ /*************************************************************************/ #import "view_controller.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" #include "display_server_iphone.h" #import "godot_view.h" #import "godot_view_renderer.h" +#import "keyboard_input_view.h" #include "os_iphone.h" +#import <AVFoundation/AVFoundation.h> #import <GameController/GameController.h> -@interface ViewController () +@interface ViewController () <GodotViewDelegate> @property(strong, nonatomic) GodotViewRenderer *renderer; +@property(strong, nonatomic) GodotKeyboardInputView *keyboardView; -// TODO: separate view to handle video -// AVPlayer-related properties -@property(strong, nonatomic) AVAsset *avAsset; -@property(strong, nonatomic) AVPlayerItem *avPlayerItem; -@property(strong, nonatomic) AVPlayer *avPlayer; -@property(strong, nonatomic) AVPlayerLayer *avPlayerLayer; -@property(assign, nonatomic) CMTime videoCurrentTime; -@property(assign, nonatomic) BOOL isVideoCurrentlyPlaying; -@property(assign, nonatomic) BOOL videoHasFoundError; +@property(strong, nonatomic) UIView *godotLoadingOverlay; @end @@ -67,9 +62,7 @@ self.view = view; view.renderer = self.renderer; - - [renderer release]; - [view release]; + view.delegate = self; } - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { @@ -93,9 +86,7 @@ } - (void)godot_commonInit { - self.isVideoCurrentlyPlaying = NO; - self.videoCurrentTime = kCMTimeZero; - self.videoHasFoundError = false; + // Initialize view controller values. } - (void)didReceiveMemoryWarning { @@ -107,7 +98,7 @@ [super viewDidLoad]; [self observeKeyboard]; - [self observeAudio]; + [self displayLoadingOverlay]; if (@available(iOS 11.0, *)) { [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; @@ -115,6 +106,10 @@ } - (void)observeKeyboard { + printf("******** setting up keyboard input view\n"); + self.keyboardView = [GodotKeyboardInputView new]; + [self.view addSubview:self.keyboardView]; + printf("******** adding observer for keyboard show/hide\n"); [[NSNotificationCenter defaultCenter] addObserver:self @@ -128,33 +123,42 @@ object:nil]; } -- (void)observeAudio { - printf("******** adding observer for sound routing changes\n"); - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(audioRouteChangeListenerCallback:) - name:AVAudioSessionRouteChangeNotification - object:nil]; -} +- (void)displayLoadingOverlay { + NSBundle *bundle = [NSBundle mainBundle]; + NSString *storyboardName = @"Launch Screen"; -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - if (object == self.avPlayerItem && [keyPath isEqualToString:@"status"]) { - [self handleVideoOrPlayerStatus]; + if ([bundle pathForResource:storyboardName ofType:@"storyboardc"] == nil) { + return; } - if (object == self.avPlayer && [keyPath isEqualToString:@"rate"]) { - [self handleVideoPlayRate]; - } + UIStoryboard *launchStoryboard = [UIStoryboard storyboardWithName:storyboardName bundle:bundle]; + + UIViewController *controller = [launchStoryboard instantiateInitialViewController]; + self.godotLoadingOverlay = controller.view; + self.godotLoadingOverlay.frame = self.view.bounds; + self.godotLoadingOverlay.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + [self.view addSubview:self.godotLoadingOverlay]; +} + +- (BOOL)godotViewFinishedSetup:(GodotView *)view { + [self.godotLoadingOverlay removeFromSuperview]; + self.godotLoadingOverlay = nil; + + return YES; } - (void)dealloc { - [self stopVideo]; + self.keyboardView = nil; self.renderer = nil; - [[NSNotificationCenter defaultCenter] removeObserver:self]; + if (self.godotLoadingOverlay) { + [self.godotLoadingOverlay removeFromSuperview]; + self.godotLoadingOverlay = nil; + } - [super dealloc]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; } // MARK: Orientation @@ -233,176 +237,4 @@ } } -// MARK: Audio - -- (void)audioRouteChangeListenerCallback:(NSNotification *)notification { - printf("*********** route changed!\n"); - NSDictionary *interuptionDict = notification.userInfo; - - NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue]; - - switch (routeChangeReason) { - case AVAudioSessionRouteChangeReasonNewDeviceAvailable: { - NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable"); - NSLog(@"Headphone/Line plugged in"); - } break; - case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: { - NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable"); - NSLog(@"Headphone/Line was pulled. Resuming video play...."); - if ([self isVideoPlaying]) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - [self.avPlayer play]; // NOTE: change this line according your current player implementation - NSLog(@"resumed play"); - }); - } - } break; - case AVAudioSessionRouteChangeReasonCategoryChange: { - // called at start - also when other audio wants to play - NSLog(@"AVAudioSessionRouteChangeReasonCategoryChange"); - } break; - } -} - -// MARK: Native Video Player - -- (void)handleVideoOrPlayerStatus { - if (self.avPlayerItem.status == AVPlayerItemStatusFailed || self.avPlayer.status == AVPlayerStatusFailed) { - [self stopVideo]; - self.videoHasFoundError = true; - } - - if (self.avPlayer.status == AVPlayerStatusReadyToPlay && self.avPlayerItem.status == AVPlayerItemStatusReadyToPlay && CMTimeCompare(self.videoCurrentTime, kCMTimeZero) == 0) { - // NSLog(@"time: %@", self.video_current_time); - [self.avPlayer seekToTime:self.videoCurrentTime]; - self.videoCurrentTime = kCMTimeZero; - } -} - -- (void)handleVideoPlayRate { - NSLog(@"Player playback rate changed: %.5f", self.avPlayer.rate); - if ([self isVideoPlaying] && self.avPlayer.rate == 0.0 && !self.avPlayer.error) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - [self.avPlayer play]; // NOTE: change this line according your current player implementation - NSLog(@"resumed play"); - }); - - NSLog(@" . . . PAUSED (or just started)"); - } -} - -- (BOOL)playVideoAtPath:(NSString *)filePath volume:(float)videoVolume audio:(NSString *)audioTrack subtitle:(NSString *)subtitleTrack { - self.avAsset = [AVAsset assetWithURL:[NSURL fileURLWithPath:filePath]]; - - self.avPlayerItem = [AVPlayerItem playerItemWithAsset:self.avAsset]; - [self.avPlayerItem addObserver:self forKeyPath:@"status" options:0 context:nil]; - - self.avPlayer = [AVPlayer playerWithPlayerItem:self.avPlayerItem]; - self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer]; - - [self.avPlayer addObserver:self forKeyPath:@"status" options:0 context:nil]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(playerItemDidReachEnd:) - name:AVPlayerItemDidPlayToEndTimeNotification - object:[self.avPlayer currentItem]]; - - [self.avPlayer addObserver:self forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:0]; - - [self.avPlayerLayer setFrame:self.view.bounds]; - [self.view.layer addSublayer:self.avPlayerLayer]; - [self.avPlayer play]; - - AVMediaSelectionGroup *audioGroup = [self.avAsset mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicAudible]; - - NSMutableArray *allAudioParams = [NSMutableArray array]; - for (id track in audioGroup.options) { - NSString *language = [[track locale] localeIdentifier]; - NSLog(@"subtitle lang: %@", language); - - if ([language isEqualToString:audioTrack]) { - AVMutableAudioMixInputParameters *audioInputParams = [AVMutableAudioMixInputParameters audioMixInputParameters]; - [audioInputParams setVolume:videoVolume atTime:kCMTimeZero]; - [audioInputParams setTrackID:[track trackID]]; - [allAudioParams addObject:audioInputParams]; - - AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix]; - [audioMix setInputParameters:allAudioParams]; - - [self.avPlayer.currentItem selectMediaOption:track inMediaSelectionGroup:audioGroup]; - [self.avPlayer.currentItem setAudioMix:audioMix]; - - break; - } - } - - AVMediaSelectionGroup *subtitlesGroup = [self.avAsset mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicLegible]; - NSArray *useableTracks = [AVMediaSelectionGroup mediaSelectionOptionsFromArray:subtitlesGroup.options withoutMediaCharacteristics:[NSArray arrayWithObject:AVMediaCharacteristicContainsOnlyForcedSubtitles]]; - - for (id track in useableTracks) { - NSString *language = [[track locale] localeIdentifier]; - NSLog(@"subtitle lang: %@", language); - - if ([language isEqualToString:subtitleTrack]) { - [self.avPlayer.currentItem selectMediaOption:track inMediaSelectionGroup:subtitlesGroup]; - break; - } - } - - self.isVideoCurrentlyPlaying = YES; - - return true; -} - -- (BOOL)isVideoPlaying { - if (self.avPlayer.error) { - printf("Error during playback\n"); - } - return (self.avPlayer.rate > 0 && !self.avPlayer.error); -} - -- (void)pauseVideo { - self.videoCurrentTime = self.avPlayer.currentTime; - [self.avPlayer pause]; - self.isVideoCurrentlyPlaying = NO; -} - -- (void)unpauseVideo { - [self.avPlayer play]; - self.isVideoCurrentlyPlaying = YES; -} - -- (void)playerItemDidReachEnd:(NSNotification *)notification { - [self stopVideo]; -} - -- (void)stopVideo { - [self.avPlayer pause]; - [self.avPlayerLayer removeFromSuperlayer]; - self.avPlayerLayer = nil; - - if (self.avPlayerItem) { - [self.avPlayerItem removeObserver:self forKeyPath:@"status"]; - self.avPlayerItem = nil; - } - - if (self.avPlayer) { - [self.avPlayer removeObserver:self forKeyPath:@"status"]; - self.avPlayer = nil; - } - - self.avAsset = nil; - - self.isVideoCurrentlyPlaying = NO; -} - -// 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 |