How to get updated scale value in RealityKit in vision pro

Hello, I am doing to load model from bundle and it is loaded successfully. Now I am scaling model using GestureExtension from apple demo code. (https://developer.apple.com/documentation/realitykit/transforming-realitykit-entities-with-gestures?changes=_8)

    
    @State private var selectedEntityName : String = ""
    @State private var modelEntity: ModelEntity?
            
    
    var body: some View {
        contentView
            .task {
                do {
                    modelEntity = try await ModelEntity.loadArcadeMachine()
                } catch {
                    fatalError(error.localizedDescription)
                }
            }
    }

    @ViewBuilder
    private var contentView: some View {
        if let modelEntity {
            RealityView { content, attachments in

                modelEntity.position = SIMD3<Float>(x: 0, y: -0.3, z: -5)
                print(modelEntity.transform.scale)
                modelEntity.transform.scale =  [0.006, 0.006, 0.006] 
                content.add(modelEntity)
                
                if let percentTextAttachment = attachments.entity(for: "percentage") {
                    percentTextAttachment.position = [0, 50, 0]
                    modelEntity.addChild(percentTextAttachment)
                }
                
            } update: { content, attachments in
  
// I want here to get updated scaling value and it is showing in RealityView attachmnt text.

            } attachments: {
                Attachment(id: "percentage") {
                    Text("\(modelEntity.name)  \(modelEntity.scale * 100) %")
                        .font(.system(size: 5000))
                        .background(.red)
                }
            }
        
           // This method am using for gesture support
            .installGestures()

   
            
            
        } else {
            ProgressView()
        }
    }
}

Below code from GestureExtension

        let state = EntityGestureState.shared
        guard canScale, !state.isDragging else { return }
        
        let entity = value.entity
        
        if !state.isScaling {
            state.isScaling = true
            state.startScale = entity.scale
        }
        
        let magnification = Float(value.magnification)
        entity.scale = state.startScale * magnification
        
        
        state.magnifyValue = magnification
        
        magnifyScale = Double(magnification)
        
        print("Entity Name  :::::::  \(entity.name)")
        print("Scale  :::::::  \(entity.scale)")
        print("Magnification  :::::::  \(magnification)")
        print("StartScale  :::::::  \(state.startScale)")
        

> This "magnification" value I need to use in RealityView class. How can i Do it? Could you please guide it.


        
        
        
    }

Accepted Reply

Hello @Sandip_Aura,

I believe you are trying to utilize the current gesture state of the MagnifyGesture to update your UI. For this task, I recommend making use of @GestureState.

It is tricky to implement this in that sample project, but here is how you can do it:

  1. Add @GestureState private var magnification: Double = 1 as a property of ContentView.
  2. Update the RealityView extension that defines magnifyGesture to build a gesture that updates the magnification GestureState:
/// Builds a magnify gesture.
func makeMagnifyGesture(magnification: GestureState<Double>) -> some Gesture {
    MagnifyGesture()
        .updating(magnification) { currentState, gestureState, transaction in
            gestureState = currentState.magnification
        }
        .targetedToAnyEntity()
        .useGestureComponent()
}
  1. Update the installGestures function to use the new magnify gesture, passing through the GestureState:
/// Apply this to a `RealityView` to pass gestures on to the component code.
func installGestures(magnification: GestureState<Double>) -> some View {
    simultaneousGesture(dragGesture)
        .simultaneousGesture(makeMagnifyGesture(magnification: magnification))
        .simultaneousGesture(rotateGesture)
}
  1. Update the ContentView to pass through the GestureState to installGestures:
.installGestures(magnification: $magnification)

// This onChange will print the current magnification value ✅
.onChange(of: magnification) { oldValue, newValue in
    print("Current magnification: \(newValue)")
}

Replies

Hello @Sandip_Aura,

I believe you are trying to utilize the current gesture state of the MagnifyGesture to update your UI. For this task, I recommend making use of @GestureState.

It is tricky to implement this in that sample project, but here is how you can do it:

  1. Add @GestureState private var magnification: Double = 1 as a property of ContentView.
  2. Update the RealityView extension that defines magnifyGesture to build a gesture that updates the magnification GestureState:
/// Builds a magnify gesture.
func makeMagnifyGesture(magnification: GestureState<Double>) -> some Gesture {
    MagnifyGesture()
        .updating(magnification) { currentState, gestureState, transaction in
            gestureState = currentState.magnification
        }
        .targetedToAnyEntity()
        .useGestureComponent()
}
  1. Update the installGestures function to use the new magnify gesture, passing through the GestureState:
/// Apply this to a `RealityView` to pass gestures on to the component code.
func installGestures(magnification: GestureState<Double>) -> some View {
    simultaneousGesture(dragGesture)
        .simultaneousGesture(makeMagnifyGesture(magnification: magnification))
        .simultaneousGesture(rotateGesture)
}
  1. Update the ContentView to pass through the GestureState to installGestures:
.installGestures(magnification: $magnification)

// This onChange will print the current magnification value ✅
.onChange(of: magnification) { oldValue, newValue in
    print("Current magnification: \(newValue)")
}