diff --git a/Engine/system/api/iosapi.h b/Engine/system/api/iosapi.h index c9f837dc..440917bc 100644 --- a/Engine/system/api/iosapi.h +++ b/Engine/system/api/iosapi.h @@ -28,6 +28,7 @@ class iOSApi final: SystemApi { void implProcessEvents(AppCallBack& cb) override; void implSetWindowTitle(SystemApi::Window *w, const char* utf8) override; + void implSetAllowedOrientations(SystemApi::Window *w, Orientation orientations) override; friend class SystemApi; }; diff --git a/Engine/system/api/iosapi.mm b/Engine/system/api/iosapi.mm index 0f78f751..8539dbd0 100644 --- a/Engine/system/api/iosapi.mm +++ b/Engine/system/api/iosapi.mm @@ -15,6 +15,19 @@ using namespace Tempest; +static UIInterfaceOrientationMask nativeFormat(SystemApi::Orientation orientations) { + UIInterfaceOrientationMask mask = 0; + if(orientations & SystemApi::Portrait) + mask |= UIInterfaceOrientationMaskPortrait; + if(orientations & SystemApi::PortraitUpsideDown) + mask |= UIInterfaceOrientationMaskPortraitUpsideDown; + if(orientations & SystemApi::LandscapeLeft) + mask |= UIInterfaceOrientationMaskLandscapeLeft; + if(orientations & SystemApi::LandscapeRight) + mask |= UIInterfaceOrientationMaskLandscapeRight; + return mask; + } + #if TARGET_CPU_X86_64 # define FUNCTION_CALL_ALIGNMENT 16 # define SET_STACK_POINTER "movq %0, %%rsp" @@ -238,16 +251,20 @@ static void discardPendingEvent(TempestWindow* window) { @interface ViewController:UIViewController{} -(id)init; +-(void)setAllowedOrientations:(UIInterfaceOrientationMask)mask; @end @implementation ViewController { bool fullScreen; + UIInterfaceOrientationMask allowedOrientations; } -(id)init { self = [super init]; - if(self!=nil) + if(self!=nil) { fullScreen = true; + allowedOrientations = UIInterfaceOrientationMaskAll; + } return self; } @@ -274,7 +291,19 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface } -(UIInterfaceOrientationMask)supportedInterfaceOrientations { - return UIInterfaceOrientationMaskAll; + return allowedOrientations; + } + +-(void)setAllowedOrientations:(UIInterfaceOrientationMask)mask { + if(allowedOrientations==mask) + return; + allowedOrientations = mask; + // Reevaluate on UIKit's stack after the engine yields. + dispatch_async(dispatch_get_main_queue(), ^{ + if(@available(iOS 16.0, *)) + [self setNeedsUpdateOfSupportedInterfaceOrientations]; else + [UIViewController attemptRotationToDeviceOrientation]; + }); } -(bool)setAsFullscreen: (bool)value { @@ -386,11 +415,6 @@ - (UISceneConfiguration *)application:(UIApplication *)application return configuration; } -- (UIInterfaceOrientationMask)application:(UIApplication *)application - supportedInterfaceOrientationsForWindow:(UIWindow *)window { - return UIInterfaceOrientationMaskAll; - } - - (void)applicationWillTerminate:(UIApplication *)application { (void)application; } @@ -492,6 +516,8 @@ static void appleMain(void*) { auto delegate = (TempestSceneDelegate*)windowScene.delegate; delegate.window = window; + auto controller = (ViewController*)window.rootViewController; + [controller setAllowedOrientations:UIInterfaceOrientationMaskAll]; [window makeKeyAndVisible]; window->owner = owner; @@ -549,6 +575,16 @@ static void appleMain(void*) { return [ctrl isFullscreen]; } +void iOSApi::implSetAllowedOrientations(Window* w, Orientation orientations) { + const auto mask = nativeFormat(orientations); + if(mask==0) + return; + + auto wx = reinterpret_cast(w); + auto ctrl = (ViewController*)wx.rootViewController; + [ctrl setAllowedOrientations:mask]; + } + void iOSApi::implSetCursorPosition(Window* w, int x, int y) { } diff --git a/Engine/system/systemapi.cpp b/Engine/system/systemapi.cpp index 04e3d1dd..217b241a 100644 --- a/Engine/system/systemapi.cpp +++ b/Engine/system/systemapi.cpp @@ -33,6 +33,9 @@ void SystemApi::implSetWindowTitle(Window *w, const char *utf8) { // TODO } +void SystemApi::implSetAllowedOrientations(Window*, Orientation) { + } + void SystemApi::setupKeyTranslate(const TranslateKeyPair k[], uint16_t funcCount ) { m.keys.clear(); m.a. clear(); @@ -200,6 +203,10 @@ void SystemApi::setWindowTitle(Window *w, const char *utf8) { return inst().implSetWindowTitle(w, utf8); } +void SystemApi::setAllowedOrientations(Window *w, Orientation orientations) { + return inst().implSetAllowedOrientations(w, orientations); + } + void SystemApi::setCursorPosition(SystemApi::Window *w, int x, int y) { return inst().implSetCursorPosition(w,x,y); } diff --git a/Engine/system/systemapi.h b/Engine/system/systemapi.h index 31482d0f..6234b226 100644 --- a/Engine/system/systemapi.h +++ b/Engine/system/systemapi.h @@ -34,6 +34,15 @@ class SystemApi { Hidden, //internal }; + enum Orientation : uint8_t { + Portrait = 1 << 0, + PortraitUpsideDown = 1 << 1, + LandscapeLeft = 1 << 2, + LandscapeRight = 1 << 3, + Landscape = LandscapeLeft | LandscapeRight, + AllOrientations = Portrait | PortraitUpsideDown | Landscape, + }; + struct TranslateKeyPair final { uint16_t src; uint16_t result; @@ -51,6 +60,7 @@ class SystemApi { static bool isFullscreen(SystemApi::Window *w); static void setWindowTitle(SystemApi::Window *w, const char* utf8); + static void setAllowedOrientations(SystemApi::Window *w, Orientation orientations); static float uiScale(SystemApi::Window *w); static uint16_t translateKey(uint64_t scancode); @@ -86,6 +96,7 @@ class SystemApi { virtual void implProcessEvents(AppCallBack& cb) = 0; virtual void implSetWindowTitle(SystemApi::Window *w, const char* utf8) = 0; + virtual void implSetAllowedOrientations(SystemApi::Window *w, Orientation orientations); static void setCursorPosition(SystemApi::Window *w, int x, int y); static void showCursor(SystemApi::Window *w, CursorShape c); diff --git a/Engine/ui/window.cpp b/Engine/ui/window.cpp index de00eb2c..255fd8d7 100644 --- a/Engine/ui/window.cpp +++ b/Engine/ui/window.cpp @@ -31,6 +31,10 @@ void Window::setWindowTitle(const char* utf8) { Tempest::SystemApi::setWindowTitle(hwnd(), utf8); } +void Window::setAllowedOrientations(Orientation orientations) { + Tempest::SystemApi::setAllowedOrientations(hwnd(), SystemApi::Orientation(orientations)); + } + void Window::render() { } diff --git a/Engine/ui/window.h b/Engine/ui/window.h index 9217073e..2b030565 100644 --- a/Engine/ui/window.h +++ b/Engine/ui/window.h @@ -17,12 +17,25 @@ class Window : public Widget { FullScreen, }; + enum Orientation : uint8_t { + Portrait = 1 << 0, + PortraitUpsideDown = 1 << 1, + LandscapeLeft = 1 << 2, + LandscapeRight = 1 << 3, + Landscape = LandscapeLeft | LandscapeRight, + AllOrientations = Portrait | PortraitUpsideDown | Landscape, + }; + Window(); Window( ShowMode sm ); ~Window() override; void setWindowTitle(const char* utf8); + // App and platform restrictions still apply. AllOrientations restores the + // app defaults. Has no effect on platforms without orientation support. + void setAllowedOrientations(Orientation orientations); + protected: virtual void render(); using Widget::dispatchPaintEvent; @@ -46,4 +59,12 @@ class Window : public Widget { friend class SystemApi; }; +inline Window::Orientation operator | (Window::Orientation a, const Window::Orientation& b) { + return Window::Orientation(uint8_t(a)|uint8_t(b)); + } + +inline Window::Orientation operator & (Window::Orientation a, const Window::Orientation& b) { + return Window::Orientation(uint8_t(a)&uint8_t(b)); + } + }