From 14bca227e8b3e3ea62644ed18fc8f3338bd4919a Mon Sep 17 00:00:00 2001 From: James Chen Date: Thu, 23 Nov 2017 09:34:23 +0800 Subject: [PATCH] fixed #18474: Provides an interface for getting SafeArea (#18489) * fixed #18474: Provides an interface for getting SafeArea * Adds getSafeAreaRect test demo in cpp-empty-test. * @available(iOS 11.0, *) isn't supported in Xcode8. So we use the old way. --- cocos/base/CCDirector.cpp | 14 +++++- cocos/base/CCDirector.h | 7 ++- cocos/platform/CCGLView.cpp | 5 ++ cocos/platform/CCGLView.h | 5 ++ cocos/platform/ios/CCEAGLView-ios.h | 11 +++-- cocos/platform/ios/CCGLViewImpl-ios.h | 2 + cocos/platform/ios/CCGLViewImpl-ios.mm | 48 +++++++++++++++++++ .../Classes/HelloWorldScene.cpp | 17 +++++-- 8 files changed, 97 insertions(+), 12 deletions(-) diff --git a/cocos/base/CCDirector.cpp b/cocos/base/CCDirector.cpp index aa8e5a9d40..c2fc054791 100644 --- a/cocos/base/CCDirector.cpp +++ b/cocos/base/CCDirector.cpp @@ -1,4 +1,4 @@ -/**************************************************************************** +/**************************************************************************** Copyright (c) 2008-2010 Ricardo Quesada Copyright (c) 2010-2013 cocos2d-x.org Copyright (c) 2011 Zynga Inc. @@ -866,6 +866,18 @@ Vec2 Director::getVisibleOrigin() const } } +Rect Director::getSafeAreaRect() const +{ + if (_openGLView) + { + return _openGLView->getSafeAreaRect(); + } + else + { + return Rect::ZERO; + } +} + // scene management void Director::runWithScene(Scene *scene) diff --git a/cocos/base/CCDirector.h b/cocos/base/CCDirector.h index 4512cabd9c..d6c484a1d9 100644 --- a/cocos/base/CCDirector.h +++ b/cocos/base/CCDirector.h @@ -256,7 +256,12 @@ public: /** Returns visible origin coordinate of the OpenGL view in points. */ Vec2 getVisibleOrigin() const; - /** + /** + * Returns safe area rectangle of the OpenGL view in points. + */ + Rect getSafeAreaRect() const; + + /** * Converts a screen coordinate to an OpenGL coordinate. * Useful to convert (multi) touch coordinates to the current layout (portrait or landscape). */ diff --git a/cocos/platform/CCGLView.cpp b/cocos/platform/CCGLView.cpp index a4fd4355e7..52b4173966 100644 --- a/cocos/platform/CCGLView.cpp +++ b/cocos/platform/CCGLView.cpp @@ -219,6 +219,11 @@ Rect GLView::getVisibleRect() const return ret; } +Rect GLView::getSafeAreaRect() const +{ + return getVisibleRect(); +} + Size GLView::getVisibleSize() const { if (_resolutionPolicy == ResolutionPolicy::NO_BORDER) diff --git a/cocos/platform/CCGLView.h b/cocos/platform/CCGLView.h index 878bd44df6..6c24f4454c 100644 --- a/cocos/platform/CCGLView.h +++ b/cocos/platform/CCGLView.h @@ -239,6 +239,11 @@ public: */ virtual Rect getVisibleRect() const; + /** + * Gets safe area rectangle + */ + virtual Rect getSafeAreaRect() const; + /** * Set the design resolution size. * @param width Design resolution width. diff --git a/cocos/platform/ios/CCEAGLView-ios.h b/cocos/platform/ios/CCEAGLView-ios.h index cd47c86522..bce94c3eb7 100644 --- a/cocos/platform/ios/CCEAGLView-ios.h +++ b/cocos/platform/ios/CCEAGLView-ios.h @@ -82,19 +82,20 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. */ @interface CCEAGLView : UIView { - id renderer_; - EAGLContext *context_; // weak ref + id renderer_; + EAGLContext *context_; // weak ref NSString *pixelformat_; - GLuint depthFormat_; + GLuint depthFormat_; BOOL preserveBackbuffer_; - CGSize size_; + CGSize size_; + CGRect safeArea_; BOOL discardFramebufferSupported_; //fsaa addition BOOL multisampling_; - unsigned int requestedSamples_; + unsigned int requestedSamples_; BOOL isUseUITextField; @private NSString * markedText_; diff --git a/cocos/platform/ios/CCGLViewImpl-ios.h b/cocos/platform/ios/CCGLViewImpl-ios.h index fed793370f..051a1abbd1 100644 --- a/cocos/platform/ios/CCGLViewImpl-ios.h +++ b/cocos/platform/ios/CCGLViewImpl-ios.h @@ -75,6 +75,8 @@ public: virtual void swapBuffers() override; virtual void setIMEKeyboardState(bool bOpen) override; + virtual Rect getSafeAreaRect() const override; + protected: GLViewImpl(); virtual ~GLViewImpl(); diff --git a/cocos/platform/ios/CCGLViewImpl-ios.mm b/cocos/platform/ios/CCGLViewImpl-ios.mm index cd65d60908..a58a7afa00 100644 --- a/cocos/platform/ios/CCGLViewImpl-ios.mm +++ b/cocos/platform/ios/CCGLViewImpl-ios.mm @@ -32,6 +32,7 @@ #include "platform/ios/CCDirectorCaller-ios.h" #include "platform/ios/CCGLViewImpl-ios.h" #include "base/CCTouch.h" +#include "base/CCDirector.h" NS_CC_BEGIN @@ -227,6 +228,53 @@ void GLViewImpl::setIMEKeyboardState(bool open) } } +Rect GLViewImpl::getSafeAreaRect() const +{ + CCEAGLView *eaglview = (CCEAGLView*) _eaglview; + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 + float version = [[UIDevice currentDevice].systemVersion floatValue]; + if (version >= 11.0f) + { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpartial-availability" + UIEdgeInsets safeAreaInsets = eaglview.safeAreaInsets; +#pragma clang diagnostic pop + + // Multiply contentScaleFactor since safeAreaInsets return points. + safeAreaInsets.left *= eaglview.contentScaleFactor; + safeAreaInsets.right *= eaglview.contentScaleFactor; + safeAreaInsets.top *= eaglview.contentScaleFactor; + safeAreaInsets.bottom *= eaglview.contentScaleFactor; + + // Get leftBottom and rightTop point in UI coordinates + Vec2 leftBottom = Vec2(safeAreaInsets.left, _screenSize.height - safeAreaInsets.bottom); + Vec2 rightTop = Vec2(_screenSize.width - safeAreaInsets.right, safeAreaInsets.top); + + // Convert a point from UI coordinates to which in design resolution coordinate. + leftBottom.x = (leftBottom.x - _viewPortRect.origin.x) / _scaleX, + leftBottom.y = (leftBottom.y - _viewPortRect.origin.y) / _scaleY; + rightTop.x = (rightTop.x - _viewPortRect.origin.x) / _scaleX, + rightTop.y = (rightTop.y - _viewPortRect.origin.y) / _scaleY; + + // Adjust points to make them inside design resolution + leftBottom.x = MAX(leftBottom.x, 0); + leftBottom.y = MIN(leftBottom.y, _designResolutionSize.height); + rightTop.x = MIN(rightTop.x, _designResolutionSize.width); + rightTop.y = MAX(rightTop.y, 0); + + // Convert to GL coordinates + leftBottom = Director::getInstance()->convertToGL(leftBottom); + rightTop = Director::getInstance()->convertToGL(rightTop); + + return Rect(leftBottom.x, leftBottom.y, rightTop.x - leftBottom.x, rightTop.y - leftBottom.y); + } +#endif + + // If running on iOS devices lower than 11.0, return visiable rect instead. + return GLView::getSafeAreaRect(); +} + NS_CC_END #endif // CC_PLATFORM_IOS diff --git a/tests/cpp-empty-test/Classes/HelloWorldScene.cpp b/tests/cpp-empty-test/Classes/HelloWorldScene.cpp index 598b5117ad..99a2ce3df9 100644 --- a/tests/cpp-empty-test/Classes/HelloWorldScene.cpp +++ b/tests/cpp-empty-test/Classes/HelloWorldScene.cpp @@ -31,22 +31,22 @@ bool HelloWorld::init() "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback,this)); - + closeItem->setPosition(origin + Vec2(visibleSize) - Vec2(closeItem->getContentSize() / 2)); // create menu, it's an autorelease object auto menu = Menu::create(closeItem, nullptr); menu->setPosition(Vec2::ZERO); this->addChild(menu, 1); - + ///////////////////////////// // 3. add your codes below... // add a label shows "Hello World" // create and initialize a label - + auto label = Label::createWithTTF("Hello World", "fonts/arial.ttf", TITLE_FONT_SIZE); - + // position the label on the center of the screen label->setPosition(origin.x + visibleSize.width/2, origin.y + visibleSize.height - label->getContentSize().height); @@ -62,7 +62,14 @@ bool HelloWorld::init() // add the sprite as a child to this layer this->addChild(sprite); - + + auto drawNode = DrawNode::create(); + drawNode->setPosition(Vec2(0, 0)); + addChild(drawNode); + + Rect safeArea = Director::getInstance()->getSafeAreaRect(); + drawNode->drawRect(safeArea.origin, safeArea.origin + safeArea.size, Color4F::BLUE); + return true; }