GeometryReader3D always reading 1280x1280x1280 in a volumetric window on VisionOS no matter what I set defaultWindowSize to

179 Views Asked by At

I'm picking Swift development back up for the first time in many years to play w/ VisionOS. SwiftUI is new to me so I'm not sure if I'm missing something or if this is a bug.

The results of running the following code is:

(width: 1280.0, height: 1280.0, depth: 1280.0) (width: 1280.0, height: 1280.0, depth: 1280.0)

I get the same numbers no matter what I set the .defaultSize to. If I switch to a window instead of a volume I get different numbers as expected. Interestingly the actual size of the volume and the red/blue colors does change properly, but the GeometryReader3D doesn't seem to see it properly.

Am I missing something or is this a bug?

Btw, my actual goal is to scale up a model created programmatically using MeshDescriptor to fill the volume. I have model generation working, but I spent most of a day trying to figure out why my transformations weren't working as expected until I finally realized the info I'm getting from the GometryReader3D outside of my RealityView was giving me bad info.

import SwiftUI

@main
struct app: App {
    var body: some Scene {
        WindowGroup {
            GeometryReader3D { outer in
                ZStack {
                    GeometryReader3D { inner in
                        Color.blue.frame(maxDepth: .infinity).onAppear() {
                            print(inner.size, outer.size)
                        }
                    }
                    Color.red
                }
            }
        }
        .windowStyle(.volumetric)
        .defaultSize(width: 2000, height: 1000, depth: 1000)
    }
}

I wrote this yesterday, and then figured out that I can use .frame (like below) with a copy of the window size I set to get the behavior I expected. I still feel like it should work that way without the .frame calls so the question stands. Is it a bug or expected behavior?

import SwiftUI

let windowSize = Size3D(SIMD3(repeating: Double(500)))

@main
struct app: App {
    var body: some Scene {
        WindowGroup {
            ContentView().frame(width: windowSize.width, height: windowSize.height).frame(depth: windowSize.depth)
        }
        .windowStyle(.volumetric)
        .defaultSize(windowSize)
    }
}
1

There are 1 best solutions below

3
Andy Jazz On

Use delay Task.sleep(..) when printing proxy3D.size and remember that a result is in pt.

import SwiftUI
import RealityKit

@main struct YourApp : App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .windowStyle(.volumetric)
        .defaultSize(width: 0.51, height: 0.51, depth: 0.51, in: .meters)
    }
}

struct ContentView : View {
    var body: some View {
        GeometryReader3D { proxy3D in
            RealityView { content in
                let box = ModelEntity(mesh: .generateBox(size: 0.5))
                content.add(box)
            }
            .onAppear {
                Task {
                    try await Task.sleep(nanoseconds: 900_000_000)  // delay
                    print("The size is:", proxy3D.size)
                }
            }
        }
    }
}

// Result:

// The size is: (width: 694.0, height: 694.0, depth: 694.0)

P. S.

In your case it will look like this:

Color.blue.frame(maxDepth: .infinity).onAppear() {
    Task {
        try await Task.sleep(nanoseconds: 900_000_000)
        print(inner.size, outer.size)
    }
}