visionOS: re-enable dimming mode

This commit is contained in:
Sam Lantinga
2026-05-18 16:13:41 -07:00
parent 7f7c1628cb
commit 0e480bee30
5 changed files with 69 additions and 23 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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.
*/

View File

@@ -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<MTLTexture> SDL_UIKit_GetCurvedDisplayTexture(SDL_Window *window, id<MTLCommandBuffer> commandBuffer, int width, int height, MTLPixelFormat pixelFormat)
{
SDL_UIKitWindowData *data = (__bridge SDL_UIKitWindowData *)window->internal;

View File

@@ -33,6 +33,7 @@
#include "SDL_uikitappdelegate.h"
#include "SDL_uikitview.h"
#include "SDL_uikitopenglview.h"
#include "SDL_UIKitBridge-objc.h"
#include <Foundation/Foundation.h>
@@ -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. */