简体   繁体   English

如何使用 SwiftUI 中的“*.scnp”文件进行按钮单击(iOS)?

[英]How to use "*.scnp" file in SwiftUI for button click (iOS)?

I have "Explode.scnp" SceneKit file.我有"Explode.scnp" SceneKit文件。 It's already configured, the texture has been set.它已经配置好了,纹理已经设置好了。

How we can use it in SwiftUI?我们如何在 SwiftUI 中使用它? For example, after the button clicks the background will be animated once.例如,单击按钮后,背景将动画一次。

var body: some View {
    ZStack {
            VStack {
                Button(action: {
                  Particles()
                }) { 
                  Text("Animate")
                }
            }
     }
}

This code works for scn.此代码适用于 scn。 but how to use it with scnp?但是如何将它与 scnp 一起使用?

import SwiftUI
import SceneKit

struct ScenekitView : UIViewRepresentable {
    let scene = SCNScene(named: "art.scnassets/ship.scn")!

    func makeUIView(context: Context) -> SCNView {
        // create and add a camera to the scene
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)

        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)

        // create and add an ambient light to the scene
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = UIColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)

        // retrieve the ship node
        let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!

        // animate the 3d object
        ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1)))

        // retrieve the SCNView
        let scnView = SCNView()
        return scnView
    }

    func updateUIView(_ scnView: SCNView, context: Context) {
        scnView.scene = scene

        // allows the user to manipulate the camera
        scnView.allowsCameraControl = true

        // show statistics such as fps and timing information
        scnView.showsStatistics = true

        // configure the view
        scnView.backgroundColor = UIColor.black
    }
}

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

Moreover, Xcode version is 11.3.1.此外,Xcode 版本是 11.3.1。 When I try to create a new file I have this:当我尝试创建一个新文件时,我有这个: 在此处输入图像描述

And the extension is SKS... any ideas?扩展名是SKS ...有什么想法吗?

Reworked the code according to @Asperi version:根据@Asperi 版本重新编写代码:

import SwiftUI
import SceneKit

struct ScenekitView : UIViewRepresentable {
    @Binding var exploding: Bool
    //let scene = SCNScene(named: "SceneKit.scnassets/Explode.scnp")!
    let scene = SCNScene(named: "SceneKit.scnassets/scene.scn")!

    func makeUIView(context: Context) -> SCNView {
        // create and add a camera to the scene
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)

        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)

        // create and add an ambient light to the scene
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = UIColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)

        // retrieve the ship node
        let ship = scene.rootNode.childNode(withName: "blow", recursively: true)!

        // animate the 3d object
        ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1)))

        // retrieve the SCNView
        let scnView = SCNView()
        return scnView
    }

    func updateUIView(_ scnView: SCNView, context: Context) {
        scnView.scene = scene

        // allows the user to manipulate the camera
        scnView.allowsCameraControl = true

        // show statistics such as fps and timing information
        scnView.showsStatistics = true

        // configure the view
        scnView.backgroundColor = UIColor.black

        if exploding {
            if let scene = scene.rootNode.childNode(withName: "SceneKit.scnassets/scene", recursively: false),
                let particles = SCNParticleSystem(named: "SceneKit.scnassets/Explode", inDirectory: nil) {

                let node = SCNNode()
                node.addParticleSystem(particles)
                node.position = scene.position
                scnView.scene?.rootNode.addChildNode(node)
                scene.removeFromParentNode()
            }
        }
    }
}

Errors related to the path names...与路径名相关的错误...

// retrieve the ship node

here.这里。 Tried.sks, .scnp... any ideas? Tried.sks、.scnp ......有什么想法吗?

Here is modified code with demo.这是带有演示的修改代码。 Tested with Xcode 11.4 / macOS 10.15.4使用 Xcode 11.4 / macOS 10.15.4 测试

演示

Note: as I don't know your project structure, all dependent resource files were added as Resources (not in Assets).注意:由于我不知道您的项目结构,所有依赖的资源文件都作为资源添加(而不是在资产中)。 Just in case.以防万一。

资源

struct DemoSceneKitParticles: View {
    @State private var exploding = false
    var body: some View {
        VStack {
            ScenekitView(exploding: $exploding)
            Button("BOOM") { self.exploding = true }
        }
    }
}

struct ScenekitView : NSViewRepresentable {
    @Binding var exploding: Bool
    let scene = SCNScene(named: "ship.scn")!

    func makeNSView(context: NSViewRepresentableContext<ScenekitView>) -> SCNView {
        // create and add a camera to the scene
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)

        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)

        // create and add an ambient light to the scene
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = NSColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)

        // retrieve the ship node
        let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!

        // animate the 3d object
        ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1)))

        // retrieve the SCNView
        let scnView = SCNView()
        return scnView
    }

    func updateNSView(_ scnView: SCNView, context: Context) {
        scnView.scene = scene

        // allows the user to manipulate the camera
        scnView.allowsCameraControl = true

        // show statistics such as fps and timing information
        scnView.showsStatistics = true

        // configure the view
        scnView.backgroundColor = NSColor.black

        if exploding {
            if let ship = scene.rootNode.childNode(withName: "ship", recursively: true),
                let particles = SCNParticleSystem(named: "Explosion", inDirectory: nil) {

                let node = SCNNode()
                node.addParticleSystem(particles)
                node.position = ship.position
                scnView.scene?.rootNode.addChildNode(node)
                ship.removeFromParentNode()
            }
        }
    }
}

Update: variant for iOS更新:iOS 的变体

Tested with Xcode 11.4 / iOS 13.4使用 Xcode 11.4 / iOS 13.4 测试

演示3

Full module code (resource files as before at top level)完整的模块代码(资源文件和以前一样在顶层)

import SwiftUI
import SceneKit

struct DemoSceneKitParticles: View {
    @State private var exploding = false
    var body: some View {
        VStack {
            ScenekitView(exploding: $exploding)
            Button("BOOM") { self.exploding = true }
        }
    }
}

struct ScenekitView : UIViewRepresentable {
    @Binding var exploding: Bool
    let scene = SCNScene(named: "ship.scn")!

    func makeUIView(context: Context) -> SCNView {
        // create and add a camera to the scene
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)

        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)

        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)

        // create and add an ambient light to the scene
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = UIColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)

        // retrieve the ship node
        let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!

        // animate the 3d object
        ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1)))

        // retrieve the SCNView
        let scnView = SCNView()
        return scnView
    }

    func updateUIView(_ scnView: SCNView, context: Context) {
        scnView.scene = scene

        // allows the user to manipulate the camera
        scnView.allowsCameraControl = true

        // show statistics such as fps and timing information
        scnView.showsStatistics = true

        // configure the view
        scnView.backgroundColor = UIColor.black

        if exploding {
            if let ship = scene.rootNode.childNode(withName: "ship", recursively: true),
                let particles = SCNParticleSystem(named: "Explosion", inDirectory: nil) {

                let node = SCNNode()
                node.addParticleSystem(particles)
                node.position = ship.position
                scnView.scene?.rootNode.addChildNode(node)
                ship.removeFromParentNode()
            }
        }
    }
}

struct DemeSKParticles_Previews: PreviewProvider {
    static var previews: some View {
        DemoSceneKitParticles()
    }
}

backup 备份

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM