Как использовать файл "* .scnp" в SwiftUI для нажатия кнопки (iOS)? - PullRequest
2 голосов
/ 27 мая 2020

У меня есть "Explode.scnp" SceneKit файл. Он уже настроен, текстура установлена.

Как мы можем использовать это в SwiftUI? Например, после нажатия кнопки фон будет анимирован один раз.

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

Этот код работает для scn. но как использовать его с 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

Более того, версия Xcode - 11.3.1. Когда я пытаюсь создать новый файл, я получаю следующее: enter image description here

А расширение - SKS ... есть идеи?

Код переделан в соответствии с @ Версия 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()
            }
        }
    }
}

Ошибки, связанные с именами путей ...

// retrieve the ship node

здесь. Пробовал .sks, .scnp ... есть идеи?

1 Ответ

1 голос
/ 08 июня 2020

Вот модифицированный код с демо. Протестировано с Xcode 11.4 / macOS 10.15.4

demo

Примечание: поскольку я не знаю структуру вашего проекта, все зависимые файлы ресурсов были добавлены как ресурсы (не в активы). На всякий случай.

resources

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()
            }
        }
    }
}

Обновление: вариант для iOS

Протестировано с Xcode 11.4 / iOS 13.4

demo3

Полный код модуля (файлы ресурсов, как и раньше, на верхнем уровне)

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()
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...