我过去能够在 SceneKit 上做到这一点,无论出于何种原因,这在 RealityKit 上都无法做到。这是我在添加到我正在开发的应用程序之前用来测试的一些代码。
所以我有一个标题视图,当我输入新文本时,标题视图会更新文本。问题是,它无法更新 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 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
}
当我在文本字段中输入文本时,ARtext 就会更新
@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
}
}
实现起来并不容易,虽然代码很简单。由于我现在完全没有时间,我只是复制粘贴我的代码版本。这里一切正常。
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)
}
}