view_controller.mm 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /**************************************************************************/
  2. /* view_controller.mm */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #import "view_controller.h"
  31. #include "core/project_settings.h"
  32. #import "godot_view.h"
  33. #import "godot_view_renderer.h"
  34. #import "keyboard_input_view.h"
  35. #import "native_video_view.h"
  36. #include "os_iphone.h"
  37. @interface ViewController () <GodotViewDelegate>
  38. @property(strong, nonatomic) GodotViewRenderer *renderer;
  39. @property(strong, nonatomic) GodotNativeVideoView *videoView;
  40. @property(strong, nonatomic) GodotKeyboardInputView *keyboardView;
  41. @property(strong, nonatomic) UIView *godotLoadingOverlay;
  42. @end
  43. @implementation ViewController
  44. - (GodotView *)godotView {
  45. return (GodotView *)self.view;
  46. }
  47. - (void)loadView {
  48. GodotView *view = [[GodotView alloc] init];
  49. [view initializeRendering];
  50. GodotViewRenderer *renderer = [[GodotViewRenderer alloc] init];
  51. self.renderer = renderer;
  52. self.view = view;
  53. view.renderer = self.renderer;
  54. view.delegate = self;
  55. }
  56. - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
  57. self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  58. if (self) {
  59. [self godot_commonInit];
  60. }
  61. return self;
  62. }
  63. - (instancetype)initWithCoder:(NSCoder *)coder {
  64. self = [super initWithCoder:coder];
  65. if (self) {
  66. [self godot_commonInit];
  67. }
  68. return self;
  69. }
  70. - (void)godot_commonInit {
  71. // Initialize view controller values.
  72. }
  73. - (void)didReceiveMemoryWarning {
  74. [super didReceiveMemoryWarning];
  75. printf("*********** did receive memory warning!\n");
  76. };
  77. - (void)viewDidLoad {
  78. [super viewDidLoad];
  79. [self observeKeyboard];
  80. [self displayLoadingOverlay];
  81. if (@available(iOS 11.0, *)) {
  82. [self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
  83. }
  84. }
  85. - (void)observeKeyboard {
  86. printf("******** setting up keyboard input view\n");
  87. self.keyboardView = [GodotKeyboardInputView new];
  88. [self.view addSubview:self.keyboardView];
  89. printf("******** adding observer for keyboard show/hide\n");
  90. [[NSNotificationCenter defaultCenter]
  91. addObserver:self
  92. selector:@selector(keyboardOnScreen:)
  93. name:UIKeyboardDidShowNotification
  94. object:nil];
  95. [[NSNotificationCenter defaultCenter]
  96. addObserver:self
  97. selector:@selector(keyboardHidden:)
  98. name:UIKeyboardDidHideNotification
  99. object:nil];
  100. }
  101. - (void)displayLoadingOverlay {
  102. NSBundle *bundle = [NSBundle mainBundle];
  103. NSString *storyboardName = @"Launch Screen";
  104. if ([bundle pathForResource:storyboardName ofType:@"storyboardc"] == nil) {
  105. return;
  106. }
  107. UIStoryboard *launchStoryboard = [UIStoryboard storyboardWithName:storyboardName bundle:bundle];
  108. UIViewController *controller = [launchStoryboard instantiateInitialViewController];
  109. self.godotLoadingOverlay = controller.view;
  110. self.godotLoadingOverlay.frame = self.view.bounds;
  111. self.godotLoadingOverlay.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
  112. [self.view addSubview:self.godotLoadingOverlay];
  113. }
  114. - (BOOL)godotViewFinishedSetup:(GodotView *)view {
  115. [self.godotLoadingOverlay removeFromSuperview];
  116. self.godotLoadingOverlay = nil;
  117. return YES;
  118. }
  119. - (void)dealloc {
  120. [self.videoView stopVideo];
  121. self.videoView = nil;
  122. self.keyboardView = nil;
  123. self.renderer = nil;
  124. if (self.godotLoadingOverlay) {
  125. [self.godotLoadingOverlay removeFromSuperview];
  126. self.godotLoadingOverlay = nil;
  127. }
  128. [[NSNotificationCenter defaultCenter] removeObserver:self];
  129. }
  130. // MARK: Orientation
  131. - (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
  132. if (GLOBAL_GET("display/window/ios/suppress_ui_gesture")) {
  133. return UIRectEdgeAll;
  134. } else {
  135. return UIRectEdgeNone;
  136. }
  137. }
  138. - (BOOL)shouldAutorotate {
  139. if (!OSIPhone::get_singleton()) {
  140. return NO;
  141. }
  142. switch (OS::get_singleton()->get_screen_orientation()) {
  143. case OS::SCREEN_SENSOR:
  144. case OS::SCREEN_SENSOR_LANDSCAPE:
  145. case OS::SCREEN_SENSOR_PORTRAIT:
  146. return YES;
  147. default:
  148. return NO;
  149. }
  150. }
  151. - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
  152. if (!OSIPhone::get_singleton()) {
  153. return UIInterfaceOrientationMaskAll;
  154. }
  155. switch (OS::get_singleton()->get_screen_orientation()) {
  156. case OS::SCREEN_PORTRAIT:
  157. return UIInterfaceOrientationMaskPortrait;
  158. case OS::SCREEN_REVERSE_LANDSCAPE:
  159. return UIInterfaceOrientationMaskLandscapeRight;
  160. case OS::SCREEN_REVERSE_PORTRAIT:
  161. return UIInterfaceOrientationMaskPortraitUpsideDown;
  162. case OS::SCREEN_SENSOR_LANDSCAPE:
  163. return UIInterfaceOrientationMaskLandscape;
  164. case OS::SCREEN_SENSOR_PORTRAIT:
  165. return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
  166. case OS::SCREEN_SENSOR:
  167. return UIInterfaceOrientationMaskAll;
  168. case OS::SCREEN_LANDSCAPE:
  169. return UIInterfaceOrientationMaskLandscapeLeft;
  170. }
  171. }
  172. - (BOOL)prefersStatusBarHidden {
  173. if (GLOBAL_GET("display/window/ios/hide_status_bar")) {
  174. return YES;
  175. } else {
  176. return NO;
  177. }
  178. }
  179. - (BOOL)prefersHomeIndicatorAutoHidden {
  180. if (GLOBAL_GET("display/window/ios/hide_home_indicator")) {
  181. return YES;
  182. } else {
  183. return NO;
  184. }
  185. }
  186. // MARK: Keyboard
  187. - (void)keyboardOnScreen:(NSNotification *)notification {
  188. NSDictionary *info = notification.userInfo;
  189. NSValue *value = info[UIKeyboardFrameEndUserInfoKey];
  190. CGRect rawFrame = [value CGRectValue];
  191. CGRect keyboardFrame = [self.view convertRect:rawFrame fromView:nil];
  192. if (OSIPhone::get_singleton()) {
  193. OSIPhone::get_singleton()->set_virtual_keyboard_height(keyboardFrame.size.height);
  194. }
  195. }
  196. - (void)keyboardHidden:(NSNotification *)notification {
  197. if (OSIPhone::get_singleton()) {
  198. OSIPhone::get_singleton()->set_virtual_keyboard_height(0);
  199. }
  200. }
  201. // MARK: Native Video Player
  202. - (BOOL)playVideoAtPath:(NSString *)filePath volume:(float)videoVolume audio:(NSString *)audioTrack subtitle:(NSString *)subtitleTrack {
  203. // If we are showing some video already, reuse existing view for new video.
  204. if (self.videoView) {
  205. return [self.videoView playVideoAtPath:filePath volume:videoVolume audio:audioTrack subtitle:subtitleTrack];
  206. } else {
  207. // Create autoresizing view for video playback.
  208. GodotNativeVideoView *videoView = [[GodotNativeVideoView alloc] initWithFrame:self.view.bounds];
  209. videoView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  210. [self.view addSubview:videoView];
  211. self.videoView = videoView;
  212. return [self.videoView playVideoAtPath:filePath volume:videoVolume audio:audioTrack subtitle:subtitleTrack];
  213. }
  214. }
  215. @end