123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- #include "UnityView.h"
- #include "UnityAppController.h"
- #include "UnityAppController+Rendering.h"
- #include "OrientationSupport.h"
- #include "Unity/DisplayManager.h"
- #include "Unity/UnityMetalSupport.h"
- #include "Unity/ObjCRuntime.h"
- extern bool _renderingInited;
- extern bool _unityAppReady;
- extern bool _skipPresent;
- extern bool _supportsMSAA;
- @implementation UnityView
- {
- CGSize _surfaceSize;
- }
- @synthesize contentOrientation = _curOrientation;
- - (void)onUpdateSurfaceSize:(CGSize)size
- {
- _surfaceSize = size;
- CGSize systemRenderSize = CGSizeMake(size.width * self.contentScaleFactor, size.height * self.contentScaleFactor);
- _curOrientation = (ScreenOrientation)UnityReportResizeView(systemRenderSize.width, systemRenderSize.height, _curOrientation);
- ReportSafeAreaChangeForView(self);
- }
- - (void)initImpl:(CGRect)frame scaleFactor:(CGFloat)scale
- {
- #if !PLATFORM_TVOS
- self.multipleTouchEnabled = YES;
- self.exclusiveTouch = YES;
- #endif
- self.contentScaleFactor = scale;
- self.isAccessibilityElement = TRUE;
- self.accessibilityTraits = UIAccessibilityTraitAllowsDirectInteraction;
- #if UNITY_TVOS
- _curOrientation = UNITY_TVOS_ORIENTATION;
- #endif
- [self onUpdateSurfaceSize: frame.size];
- }
- - (id)initWithFrame:(CGRect)frame scaleFactor:(CGFloat)scale;
- {
- if ((self = [super initWithFrame: frame]))
- [self initImpl: frame scaleFactor: scale];
- return self;
- }
- - (id)initWithFrame:(CGRect)frame
- {
- if ((self = [super initWithFrame: frame]))
- [self initImpl: frame scaleFactor: 1.0f];
- return self;
- }
- - (id)initFromMainScreen
- {
- CGRect frame = [UIScreen mainScreen].bounds;
- CGFloat scale = UnityScreenScaleFactor([UIScreen mainScreen]);
- if ((self = [super initWithFrame: frame]))
- [self initImpl: frame scaleFactor: scale];
- return self;
- }
- - (void)layoutSubviews
- {
- if (_surfaceSize.width != self.bounds.size.width || _surfaceSize.height != self.bounds.size.height)
- _shouldRecreateView = YES;
- [self onUpdateSurfaceSize: self.bounds.size];
- for (UIView* subView in self.subviews)
- {
- if ([subView respondsToSelector: @selector(onUnityUpdateViewLayout)])
- [subView performSelector: @selector(onUnityUpdateViewLayout)];
- }
- [super layoutSubviews];
- }
- - (void)safeAreaInsetsDidChange
- {
- ReportSafeAreaChangeForView(self);
- }
- - (void)recreateRenderingSurfaceIfNeeded
- {
- unsigned requestedW, requestedH; UnityGetRenderingResolution(&requestedW, &requestedH);
- int requestedMSAA = UnityGetDesiredMSAASampleCount(MSAA_DEFAULT_SAMPLE_COUNT);
- int requestedSRGB = UnityGetSRGBRequested();
- int requestedWideColor = UnityGetWideColorRequested();
- int requestedMemorylessDepth = UnityMetalMemorylessDepth();
- UnityDisplaySurfaceBase* surf = GetMainDisplaySurface();
- if (_shouldRecreateView == YES
- || surf->targetW != requestedW || surf->targetH != requestedH
- || surf->disableDepthAndStencil != UnityDisableDepthAndStencilBuffers()
- || (_supportsMSAA && surf->msaaSamples != requestedMSAA)
- || surf->srgb != requestedSRGB
- || surf->wideColor != requestedWideColor
- || surf->memorylessDepth != requestedMemorylessDepth
- )
- {
- [self recreateRenderingSurface];
- }
- }
- - (void)recreateRenderingSurface
- {
- if (_renderingInited)
- {
- unsigned requestedW, requestedH;
- UnityGetRenderingResolution(&requestedW, &requestedH);
- RenderingSurfaceParams params =
- {
- .msaaSampleCount = UnityGetDesiredMSAASampleCount(MSAA_DEFAULT_SAMPLE_COUNT),
- .renderW = (int)requestedW,
- .renderH = (int)requestedH,
- .srgb = UnityGetSRGBRequested(),
- .wideColor = UnityGetWideColorRequested(),
- .metalFramebufferOnly = UnityMetalFramebufferOnly(),
- .metalMemorylessDepth = UnityMetalMemorylessDepth(),
- .disableDepthAndStencil = UnityDisableDepthAndStencilBuffers(),
- .useCVTextureCache = 0,
- };
- APP_CONTROLLER_RENDER_PLUGIN_METHOD_ARG(onBeforeMainDisplaySurfaceRecreate, ¶ms);
- [GetMainDisplay() recreateSurface: params];
- // actually poke unity about updated back buffer and notify that extents were changed
- UnityReportBackbufferChange(GetMainDisplaySurface()->unityColorBuffer, GetMainDisplaySurface()->unityDepthBuffer);
- APP_CONTROLLER_RENDER_PLUGIN_METHOD(onAfterMainDisplaySurfaceRecreate);
- if (_unityAppReady)
- {
- // seems like ios sometimes got confused about abrupt swap chain destroy
- // draw 2 times to fill both buffers
- // present only once to make sure correct image goes to CA
- // if we are calling this from inside repaint, second draw and present will be done automatically
- _skipPresent = true;
- if (!UnityIsPaused())
- {
- UnityRepaint();
- // we are not inside repaint so we need to draw second time ourselves
- if (_viewIsRotating)
- UnityRepaint();
- }
- _skipPresent = false;
- }
- }
- _shouldRecreateView = NO;
- }
- @end
- @implementation UnityView (Deprecated)
- - (void)recreateGLESSurfaceIfNeeded { [self recreateRenderingSurfaceIfNeeded]; }
- - (void)recreateGLESSurface { [self recreateRenderingSurface]; }
- @end
- static Class UnityRenderingView_LayerClassGLES(id self_, SEL _cmd)
- {
- return [CAEAGLLayer class];
- }
- static Class UnityRenderingView_LayerClassMTL(id self_, SEL _cmd)
- {
- return [[NSBundle bundleWithPath: @"/System/Library/Frameworks/QuartzCore.framework"] classNamed: @"CAMetalLayer"];
- }
- @implementation UnityRenderingView
- + (Class)layerClass
- {
- return nil;
- }
- + (void)InitializeForAPI:(UnityRenderingAPI)api
- {
- IMP layerClassImpl = 0;
- if (api == apiOpenGLES2 || api == apiOpenGLES3)
- layerClassImpl = (IMP)UnityRenderingView_LayerClassGLES;
- else if (api == apiMetal)
- layerClassImpl = (IMP)UnityRenderingView_LayerClassMTL;
- class_replaceMethod(object_getClass([UnityRenderingView class]), @selector(layerClass), layerClassImpl, UIView_LayerClass_Enc);
- }
- @end
- void ReportSafeAreaChangeForView(UIView* view)
- {
- CGRect safeArea = ComputeSafeArea(view);
- UnityReportSafeAreaChange(safeArea.origin.x, safeArea.origin.y,
- safeArea.size.width, safeArea.size.height);
- switch (UnityDeviceGeneration())
- {
- case deviceiPhoneXR:
- {
- const float x = 184, y = 1726, w = 460, h = 66;
- UnityReportDisplayCutouts(&x, &y, &w, &h, 1);
- break;
- }
- case deviceiPhoneX:
- case deviceiPhoneXS:
- {
- const float x = 250, y = 2346, w = 625, h = 90;
- UnityReportDisplayCutouts(&x, &y, &w, &h, 1);
- break;
- }
- case deviceiPhoneXSMax:
- {
- const float x = 308, y = 2598, w = 626, h = 90;
- UnityReportDisplayCutouts(&x, &y, &w, &h, 1);
- break;
- }
- default:
- UnityReportDisplayCutouts(nullptr, nullptr, nullptr, nullptr, 0);
- }
- }
- CGRect ComputeSafeArea(UIView* view)
- {
- CGSize screenSize = view.bounds.size;
- CGRect screenRect = CGRectMake(0, 0, screenSize.width, screenSize.height);
- UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, 0, 0);
- if (@available(iOS 11.0, tvOS 11.0, *))
- insets = [view safeAreaInsets];
- screenRect.origin.x += insets.left;
- screenRect.origin.y += insets.bottom; // Unity uses bottom left as the origin
- screenRect.size.width -= insets.left + insets.right;
- screenRect.size.height -= insets.top + insets.bottom;
- float scale = view.contentScaleFactor;
- // Truncate safe area size because in some cases (for example when Display zoom is turned on)
- // it might become larger than Screen.width/height which are returned as ints.
- screenRect.origin.x = (unsigned)(screenRect.origin.x * scale);
- screenRect.origin.y = (unsigned)(screenRect.origin.y * scale);
- screenRect.size.width = (unsigned)(screenRect.size.width * scale);
- screenRect.size.height = (unsigned)(screenRect.size.height * scale);
- return screenRect;
- }
|