首页 > 其他分享 >vision pro拖拽和旋转模型

vision pro拖拽和旋转模型

时间:2024-12-30 16:56:53浏览次数:1  
标签:target parent pro value entity let var 拖拽 vision

如果在苹果vision pro开发时,想要实现拖拽和旋转模型时,可以用以下方法实现

import SwiftUI
import RealityKit
import RealityKitContent

struct DeviceAnimationView: View {

    var viewModel: AppStateModel
    static let markersQuery = EntityQuery(where: .has(PointComponent.self))
    static let runtimeQuery = EntityQuery(where: .has(PointOfInterestRuntimeComponent.self))
    
    @State private var subscriptions = [EventSubscription]()
    @State private var attachmentsProvider = AttachmentsProvider()
    @State internal var rotatedEntity: Entity? = nil
    @State internal var rotationParent: Entity? = nil
    @State private var lastRotation: Rotation3D = .identity
    @State private var lastScale: CGFloat = 1.0
    @State private var lastTransform: SIMD3<Float> = [0,0,0]
    @State private var isPinching = false
    @State private var startPinchAll = false
    @GestureState private var magnifyBy:CGFloat = 1.0
    
    var body: some View {
        
        RealityView { content in
            do {

                if let entity = try?await Entity(named: "Scene",in: realityKitContentBundle){
                    viewModel.rootEntity = entity
                    entity.scale=SIMD3<Float>(repeating: 1.8)
                    entity.position=SIMD3(x:0,y:0,z:-1)
                    
                    content.add(entity)
//                    subscriptions.append(content.subscribe(to: ComponentEvents.DidAdd.self, componentType: PointComponent.self, { event in
//                        createLearnMoreView(for: event.entity)
//                    }))
                    viewModel.rootEntity!.children.forEach { entity in
                            entity.components.set(InputTargetComponent(allowedInputTypes: .direct));
                            //entity.components.set(HoverEffectComponent());
                            entity.generateCollisionShapes(recursive: true)
                    }
                }
            }
.simultaneousGesture( // 拖拽
            DragGesture(minimumDistance: 0.0, coordinateSpace: .local)
                .targetedToAnyEntity()
                .handActivationBehavior(.pinch)
                .onChanged { gestureValue in
                    var target = gestureValue.entity
                    //print(target.parent!.name)
                    let newTarget = target
                    if isPinching {
                        if let entity = viewModel.rootEntity {
                            startPinchAll = true
                            while (!target.name.hasPrefix("Root") && target.parent != nil ) {
                                target = target.parent!
                            }
                            
                            let convertedTranslation = gestureValue.convert(gestureValue.translation3D, from: .local, to: target.parent!)
                            target.transform.translation = lastTransform + limitTranslation(convertedTranslation)
                        }
                    } else {
                        while (!target.name.hasPrefix("sigenstor_") && target.parent != nil ) {
                            target = target.parent!
                        }
                        
                        if target.name.hasPrefix("sigenstor_") {
                            if target.sourceTransform == nil {
                                target.sourceTransform = target.transform
                            }
                            
                            let translation = gestureValue.translation3D
                            let convertedTranslation = gestureValue.convert(translation, from: .local, to: target.parent!)
                            target.transform.translation = target.sourceTransform!.translation + convertedTranslation
                            
                        }
                    }
                }
                .onEnded{ gestureValue in
                    var target = gestureValue.entity
                    if startPinchAll {
                        startPinchAll = false
                        while (!target.name.hasPrefix("Root") && target.parent != nil ) {
                            target = target.parent!
                        }
                        if target.name.hasPrefix("Root") {
                            let convertedTranslation = gestureValue.convert(gestureValue.translation3D, from: .local, to: target.parent!)
                            print(target.transform.translation)
                            lastTransform = target.transform.translation
                        }
                    } else {
                        while (!target.name.hasPrefix("sigenstor_") && target.parent != nil ) {
                            target = target.parent!
                        }
                        
                        if target.name.hasPrefix("sigenstor_") {
                            target.sourceTransform = nil
                        }
                    }
                }
        )
        .simultaneousGesture( // 旋转
            SimultaneousGesture(
                RotateGesture3D(constrainedToAxis: .y, minimumAngleDelta: Angle(degrees: 10))
                    .targetedToAnyEntity()
                    .onChanged { value in
                        if let entity = viewModel.rootEntity {
                            entity.orientation = value.convert(
                                value.rotation * lastRotation,
                                from: .local,
                                to: entity.parent!)
                        }
                    }
                    .onEnded { value in
                        lastRotation *= value.rotation
                    },
                MagnifyGesture()
                    .targetedToAnyEntity()
                    .updating($magnifyBy){ value, gestureState, transaction in
                        let newScale = getCuttentScale(magnification:value.magnification)
                        viewModel.rootEntity?.setScale(SIMD3<Float>(repeating: Float(newScale)), relativeTo: nil)
                    }
                    .onChanged { value in
                        isPinching = true
                    }
                    .onEnded { value in
                        isPinching=false
                        let scale = value.magnification
                        lastScale = getCuttentScale(magnification:scale)
                    }
                )
    )
        
//        .onReceive(NotificationCenter.default.publisher(for: .showAnimationNotification)) { _ in
//            // 显示
//            viewModel.rootEntity?.isEnabled = true
//        }.onReceive(NotificationCenter.default.publisher(for: .hideAnimationNotification)) { _ in
//            // 隐藏
//            viewModel.rootEntity?.anchor?.removeFromParent()
//        }
    }
    func limitTranslation(_ translation: SIMD3<Float>) -> SIMD3<Float> {
            // 设置拖动手势的范围限制条件
            let maxX: Float = 100
            let minX: Float = -100
            let maxY: Float = 100
            let minY: Float = -100
            let maxZ: Float = 100
            let minZ: Float = -100
            
            // 处理拖动手势的范围限制
            var limitedTranslation = translation
            limitedTranslation.x = min(max(limitedTranslation.x, minX), maxX)
            limitedTranslation.y = min(max(limitedTranslation.y, minY), maxY)
            limitedTranslation.z = min(max(limitedTranslation.z, minZ), maxZ)
            
            return limitedTranslation
        }
    
    func getCuttentScale(magnification:CGFloat)->CGFloat {
        let minScale: CGFloat = 0.3
        let maxScale: CGFloat = 5.0
        
        var current = lastScale*magnification
        current = max(min(current,maxScale),minScale)
        return current
    }
}

#Preview {


    DeviceAnimationView(viewModel: AppStateModel())

        .environment(AppStateModel())

}

 

 

标签:target,parent,pro,value,entity,let,var,拖拽,vision
From: https://www.cnblogs.com/wxcbg/p/18641731

相关文章