如何在RealityKit上使用键盘更改并持续更新AR文本?这适用于 SceneKit,找不到 realKit 解决方案

问题描述 投票:0回答:1

我过去能够在 SceneKit 上做到这一点,无论出于何种原因,这在 RealityKit 上都无法做到。这是我在添加到我正在开发的应用程序之前用来测试的一些代码。

从标题视图文本更新 AR 文本

所以我有一个标题视图,当我输入新文本时,标题视图会更新文本。问题是,它无法更新 ARView 内的 AR 文本。 在下图中,您可以在左侧看到标题视图与 ARText 匹配。这就是您最初在屏幕上看到的内容。

问题是数据没有持续更新。该代码在运行后已经将原始文本更新为标题文本,但一旦使用键盘更改了标题文本,它就不会更新。

但是,一旦我使用键盘更改标题文本(右图),文本不会在 AR 视图上更新

我知道问题是我无法像其他地方那样添加美元符号 $title 或 $title 输入。

例如在内容视图下, 单击标题文本可以成功更改文本(仅在标题视图上)。

内容视图 - 更改标题文本有效

import SwiftUI
import RealityKit


struct ContentView : View {
    
    @State var title: String = "Default Title"
    @State private var titleInput: String = ""
  
    var body: some View {
        // Button on top of the screen
        
        VStack { HeaderView(title: $title)
            
            TextField("Insert Title", text: $titleInput)
                .textFieldStyle(.roundedBorder)
            Button(action: {
                title = titleInput
                titleInput = ""
            }, label: { Text("Change Title")})
            //Spacer()
        }//.padding()
        
        // AR screen space
        
        
        ARViewContainer(title: $title, titleInput: $titleInput).edgesIgnoringSafeArea(.all)
        
        
    }
    
    
}
//end of content view struct


//another view here as the header view
struct HeaderView: View {
    @Binding var title: String
    
    var body: some View {
        Text(title)
        //.padding(10)
    }
}

AR视图:

文本从初始标题视图文本成功更新,按照下面的初始代码,这很好,但不是我寻求的最终解决方案,其中 AR 文本通过键盘不断更新。

也许你们中的一些人可能知道解决方法。 我将稍后使用场景套件添加对我有用的内容。


//AR View Container
struct ARViewContainer: UIViewRepresentable {
    @Binding var title: String
    @Binding var titleInput: String
    
    func makeUIView(context: Context) -> ARView {
        //AR View Begins
        let arView = ARView(frame: .zero)
        
        //AR Content
        // Load the "Box" scene from the "Experience" Reality File
        let boxAnchor = try! Experience.loadBox()
        
        // Add the box anchor to the scene
        arView.scene.anchors.append(boxAnchor)
        
        
        let boxImg = ModelEntity(mesh: .generateBox(size: simd_make_float3(0.03, 0.01, 0.02)))
        if let texture = try? TextureResource.load(named: "texture") {
            var imageMaterial = UnlitMaterial()
            imageMaterial.baseColor = MaterialColorParameter.texture(texture)
            boxImg.model?.materials = [imageMaterial]
        }
        
        
        
        
        //end here what to bring to texture app starting above
        
        let text = MeshResource.generateText(title,
                                             extrusionDepth: 0.1,
                                             font: .systemFont(ofSize: 0.1),
                                             containerFrame: .zero,
                                             alignment: .center,
                                             lineBreakMode: .byWordWrapping)
        
        let shader = UnlitMaterial(color: .yellow)
        let textYellowEntity = ModelEntity(mesh: text, materials: [shader])
        textYellowEntity.position = simd_make_float3(-0.1, 0, -0.7)
        
        
        let textEntity = Entity()
        textEntity.setText("Please Update")
        
        //textYellowEntity.setText(title)
        let anchor = AnchorEntity()
        anchor.addChild(boxImg)
        anchor.addChild(textYellowEntity)
        anchor.addChild(textEntity)
        arView.scene.anchors.append(anchor)
        //End of AR Content
        
        return arView
        //AR View Ends
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {}
    
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

扩展

extension Entity{
    
    /// Changes The Text Of An Entity
    /// - Parameters:
    ///   - content: String
    func setText(_ content: String){ self.components[ModelComponent] = self.generatedModelComponent(text: content) }
    
    /// Generates A Model Component With The Specified Text
    /// - Parameter text: String
    func generatedModelComponent(text: String) -> ModelComponent{
        
        let modelComponent: ModelComponent = ModelComponent(
            
            mesh: .generateText(text, extrusionDepth: TextElements().extrusionDepth, font: TextElements().font,
                                containerFrame: .zero, alignment: .center, lineBreakMode: .byTruncatingTail),
            
            materials: [SimpleMaterial(color: TextElements().colour, isMetallic: true)]
            
        )
        
        return modelComponent
    }
    
}

//--------------------
//MARK:- Text Elements
//--------------------

/// The Base Setup Of The MeshResource
struct TextElements{
   
    
    let initialText: String = "cube"
    let extrusionDepth: Float = 0.01
    let font: MeshResource.Font = MeshResource.Font.systemFont(ofSize: 0.05, weight: .bold)
    let colour: UIColor = .white
    
}

仅供参考,过去使用 SceneKit 对我有用的方法

当我在屏幕上使用 inputText 时,SceneKit 更新了 ARtext,如下所示。

当我在文本字段中输入文本时,ARtext 就会更新

[SceneKit screenshot3

  @IBOutlet weak var inputText: UITextField!
   @IBAction func updateAct(_ sender: Any) {
        sceneView.removeNodeByName(nodeName: "flyingText")
        sceneView.add3DText(showText: self.inputText!.text! ,nodeName: "flyingText")

        
        }
    
    
       // Set a delegate to track the number of plane anchors for providing UI feedback.
        sceneView.session.delegate = self
        sceneView.add3DText(showText: self.inputText!.text! )
        

扩展

import UIKit
import ARKit
import SceneKit

extension ARSCNView {
    
    func removeNodeByName(nodeName: String)  {
        self.scene.rootNode.enumerateChildNodes { (node, _) in
            if node.name == nodeName {
                node.removeFromParentNode()
            }
        }
    }
    
    
    func add3DText(showText: String, nodeName: String = "flyingText")  {
        let inText = showText.isEmpty ? "Text not Avaiable!" : showText
        let text = SCNText(string: inText, extrusionDepth: 0.9)
        let material = SCNMaterial()
        //material.diffuse.contents = UIImage(named: randomMaterial())
        text.materials = [material]
        
        let node = SCNNode()
        let xpos = randomPosition(lowerBound: -0.5, upperBound: 0.5)
        let ypos = randomPosition(lowerBound: -0.5, upperBound: 0.5)
        node.position = SCNVector3(x: -0.5, y: -0.5, z: -0.3)
        //referenceNode.rotation = SCNVector4Make(0.01,0,0,.pi/2)
        node.rotation = SCNVector4Make(0.01,0,0,0)
        node.scale = SCNVector3(x: 0.01, y: 0.01, z: 0.01)
        node.geometry = text
        //node.name = nodeName
        node.name = nodeName
        
        self.scene.rootNode.addChildNode(node)
        //self.allowsCameraControl = true
        self.automaticallyUpdatesLighting = true
    
    }
    
    
    
    func randomPosition ( lowerBound lower:Float, upperBound upper:Float) -> Float {
        return Float(arc4random()) / Float(UInt32.max) * (lower - upper) + upper
    }
    
    
    
}




swiftui scenekit arkit realitykit arview
1个回答
0
投票

实现起来并不容易,虽然代码很简单。由于我现在完全没有时间,我只是复制粘贴我的代码版本。这里一切正常。

import SwiftUI
import RealityKit

struct ContentView : View {
    @State var arView = ARView(frame: .zero)
    @State var title: String = "Default Title"
    @State var text: String = ""
    @State var entity = ModelEntity()
    @State var mesh = MeshResource.generateText("")
    @State var bool: Bool = false
    
    var body: some View {
        VStack {
            Text(title)
                .frame(alignment: .center)
                .font(.title)
            
            TextField("Enter text here:", text: $text)
                .padding([.horizontal], 20)
            
            Button("Change title") {
                if text != "" {
                    bool.toggle()
                    title = text
                    mesh = MeshResource.generateText(title,
                                      extrusionDepth: 0.01,
                                                font: .systemFont(ofSize: 0.12))
                    entity = ModelEntity(mesh: mesh,
                                    materials: [UnlitMaterial(color: .cyan)])
                    let xHalf = mesh.bounds.extents.x / 2
                    entity.position.x -= xHalf
                    text = ""
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                    bool.toggle()
                }
            }

            ARViewContainer(arView: $arView, title: $title,
                                            entity: $entity, bool: $bool)
                .ignoresSafeArea()
                .onAppear {
                    bool.toggle()
                    mesh = MeshResource.generateText(title,
                                      extrusionDepth: 0.01,
                                                font: .systemFont(ofSize: 0.12))
                    entity = ModelEntity(mesh: mesh,
                                    materials: [UnlitMaterial(color: .yellow)])
                    let xHalf = mesh.bounds.extents.x / 2
                    entity.position.x -= xHalf
                    
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                        bool.toggle()
                    }
                }
        }
    }
}

struct ARViewContainer: UIViewRepresentable {
    @Binding var arView: ARView
    @Binding var title: String
    @Binding var entity: ModelEntity
    @Binding var bool: Bool
    var anchor = AnchorEntity()
    
    func makeUIView(context: Context) -> ARView {
        if bool {
            anchor.addChild(entity)
            anchor.position.z = -1.0
            arView.scene.anchors.append(anchor)
        }
        return arView
    }
    func updateUIView(_ arView: ARView, context: Context) {
        if bool {
            arView.scene.anchors.first?.removeFromParent()
            anchor.addChild(entity)
            anchor.position.z = -1.0
            arView.scene.anchors.append(anchor)
        }
        print("Anchors:", arView.scene.anchors.count)
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.