diff --git a/src/video/uikit/SDL_CurvedContentHosting.swift b/src/video/uikit/SDL_CurvedContentHosting.swift index 3648c391e8..88d95499ed 100644 --- a/src/video/uikit/SDL_CurvedContentHosting.swift +++ b/src/video/uikit/SDL_CurvedContentHosting.swift @@ -151,6 +151,16 @@ internal class SDL_CurvedContentHosting: NSObject { //NSLog("SDL_CurvedContentHosting: Bootstrapping RealityView as hidden child") } + @objc public func dismiss() { + guard let hc = self.hostingController else { return } + + settings.dimmingReady = false + + hc.dismiss(animated: false) + + hostingController = nil + } + private func updateOrnaments() { guard let hostingController else { return } let settings = self.settings @@ -263,8 +273,8 @@ internal class SDL_CurvedContentSettings { var inputType: InputType = .eyes var showHover: Bool = true - var enableDimming: Bool = false // Doesn't seem to be reliable at the moment var isDimmed: Bool = false + var dimmingReady: Bool = false var curvatureRadius: Float = 0.0 var sceneState: SceneState = .interactive var isSnapped: Bool = false @@ -320,10 +330,8 @@ struct SDL_SettingsPanelView: View { HStack(spacing: 12) { Image(systemName: settings.showHover ? "eye" : "eye.slash") - if settings.enableDimming { - Image(systemName: settings.isDimmed ? "moon.fill" : "sun.max") - .foregroundStyle(settings.isDimmed ? .primary : .secondary) - } + Image(systemName: settings.isDimmed ? "moon.fill" : "sun.max") + .foregroundStyle(settings.isDimmed ? .primary : .secondary) Divider().frame(height: 8) @@ -344,10 +352,8 @@ struct SDL_SettingsPanelView: View { VStack(spacing: 12) { Image(systemName: settings.showHover ? "eye" : "eye.slash") - if settings.enableDimming { - Image(systemName: settings.isDimmed ? "moon.fill" : "sun.max") - .foregroundStyle(settings.isDimmed ? .primary : .secondary) - } + Image(systemName: settings.isDimmed ? "moon.fill" : "sun.max") + .foregroundStyle(settings.isDimmed ? .primary : .secondary) Divider().frame(height: 8) @@ -394,21 +400,19 @@ struct SDL_SettingsPanelView: View { Image(systemName: "eye") Spacer() - if settings.enableDimming { - Spacer() - Image(systemName: "sun.max") + Spacer() + Image(systemName: "sun.max") - Toggle(isOn: $settings.isDimmed) { - } - .onChange(of: settings.isDimmed) { - settings.save() - } - .labelsHidden() - .tint(.secondary) - - Image(systemName: "moon.fill") - Spacer() + Toggle(isOn: $settings.isDimmed) { } + .onChange(of: settings.isDimmed) { + settings.save() + } + .labelsHidden() + .tint(.secondary) + + Image(systemName: "moon.fill") + Spacer() } // Curvature slider diff --git a/src/video/uikit/SDL_CurvedContentView.swift b/src/video/uikit/SDL_CurvedContentView.swift index 275a85f562..d7c0abdac6 100644 --- a/src/video/uikit/SDL_CurvedContentView.swift +++ b/src/video/uikit/SDL_CurvedContentView.swift @@ -71,6 +71,10 @@ internal struct SDL_CurvedContentView: View { return curvedUIEntity != nil && helper.collisionShape != nil && !mouseInputEnabled } + private var shouldEnableDimming: Bool { + return settings.isDimmed && settings.dimmingReady + } + /// Value use to animate the screen radius @State private var animatedScreenRadius: Float = 1010 @@ -265,6 +269,13 @@ internal struct SDL_CurvedContentView: View { guard let curvedUIEntity else { return } if let shape = helper.collisionShape, shouldPopulateCollisionShape { curvedUIEntity.components.set(CollisionComponent(shapes: [shape])) + + // Dimming is possible now that we have a collision component + Task { + try await Task.sleep(nanoseconds: 1_000_000_000 / 4) + + settings.dimmingReady = true + } } else { curvedUIEntity.components.set(CollisionComponent(shapes: [])) } @@ -273,7 +284,7 @@ internal struct SDL_CurvedContentView: View { settings.isSnapped = snappedStatus.isSnapped helper.updateSnappedStatus(snapped: snappedStatus.isSnapped) } - .preferredSurroundingsEffect(settings.enableDimming && settings.isDimmed ? .dark : nil) + .preferredSurroundingsEffect(shouldEnableDimming ? .dark : nil) .frame(depth: 0) .ignoresSafeArea() .persistentSystemOverlays(settings.sceneState == .cinematic ? .hidden : .automatic) diff --git a/src/video/uikit/SDL_UIKitBridge-objc.h b/src/video/uikit/SDL_UIKitBridge-objc.h index db80a8cb5d..676e19a6bc 100644 --- a/src/video/uikit/SDL_UIKitBridge-objc.h +++ b/src/video/uikit/SDL_UIKitBridge-objc.h @@ -42,6 +42,11 @@ bool SDL_UIKit_HasCurvedWindow(); */ bool SDL_UIKit_IsCurvedWindow(SDL_Window *window); +/** + * Dismiss the curved content view + */ +void SDL_UIKit_HideCurvedWindow(SDL_Window *window); + /** * Get the curved content display texture. */ diff --git a/src/video/uikit/SDL_UIKitBridge.m b/src/video/uikit/SDL_UIKitBridge.m index e869d4b22c..a7f30aa30c 100644 --- a/src/video/uikit/SDL_UIKitBridge.m +++ b/src/video/uikit/SDL_UIKitBridge.m @@ -152,6 +152,28 @@ bool SDL_UIKit_IsCurvedWindow(SDL_Window *window) return data && data.curvedContentHosting; } +void SDL_UIKit_HideCurvedWindow(SDL_Window *window) +{ + SDL_UIKitWindowData *data = (__bridge SDL_UIKitWindowData *)window->internal; + if (!data || !data.curvedContentHosting) { + return nil; + } + + id hosting = data.curvedContentHosting; + SEL dismissSelector = NSSelectorFromString(@"dismiss"); + if (![hosting respondsToSelector:dismissSelector]) { + return nil; + } + + NSMethodSignature *signature = [hosting methodSignatureForSelector:dismissSelector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setSelector:dismissSelector]; + [invocation setTarget:hosting]; + [invocation invoke]; + + data.curvedContentHosting = nil; +} + id SDL_UIKit_GetCurvedDisplayTexture(SDL_Window *window, id commandBuffer, int width, int height, MTLPixelFormat pixelFormat) { SDL_UIKitWindowData *data = (__bridge SDL_UIKitWindowData *)window->internal; diff --git a/src/video/uikit/SDL_uikitwindow.m b/src/video/uikit/SDL_uikitwindow.m index 5523d6c55f..43076e8a40 100644 --- a/src/video/uikit/SDL_uikitwindow.m +++ b/src/video/uikit/SDL_uikitwindow.m @@ -33,6 +33,7 @@ #include "SDL_uikitappdelegate.h" #include "SDL_uikitview.h" #include "SDL_uikitopenglview.h" +#include "SDL_UIKitBridge-objc.h" #include @@ -386,6 +387,9 @@ void UIKit_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) [data.viewcontroller stopAnimation]; +#ifdef SDL_PLATFORM_VISIONOS + SDL_UIKit_HideCurvedWindow(window); +#endif /* Detach all views from this window. We use a copy of the array * because setSDLWindow will remove the object from the original * array, which would be undesirable if we were iterating over it. */