I've looked everywhere for this but I'm coming up blank. How do you replicate what Chris Lattner was demonstrating with Playgrounds and SceneKit at WWDC? I want to have a SceneKit scene, animating, in Playgrounds.
I tried cutting and pasting the setup code from the SceneKit project template, thinking it would magically start rendering, but it does not.
I tried watching the keynote and pausing and zooming on on Lattner's screen looking for hints at the source code, but he appeared to be importing all his code from elsewhere in his project, so it gave me no clues. There does not seem to be anything in the documentation, or I'm missing it.
Since Swift doesn't have source compatibility between versions, the code in this answer might not work in either future or previous versions of Swift. Currently is has been updated to work in Xcode 7.0 Playgrounds with Swift 2.0.
The XCPlayground
framework is what you need, and it is documented here.
Here is a very simple scene to get you started with Scene Kit in Swift:
import Cocoa // (or UIKit for iOS) import SceneKit import QuartzCore // for the basic animation import XCPlayground // for the live preview // create a scene view with an empty scene var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 300, height: 300)) var scene = SCNScene() sceneView.scene = scene // start a live preview of that view XCPShowView("The Scene View", view: sceneView) // default lighting sceneView.autoenablesDefaultLighting = true // a camera var cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 0, y: 0, z: 3) scene.rootNode.addChildNode(cameraNode) // a geometry object var torus = SCNTorus(ringRadius: 1, pipeRadius: 0.35) var torusNode = SCNNode(geometry: torus) scene.rootNode.addChildNode(torusNode) // configure the geometry object torus.firstMaterial?.diffuse.contents = NSColor.redColor() // (or UIColor on iOS) torus.firstMaterial?.specular.contents = NSColor.whiteColor() // (or UIColor on iOS) // set a rotation axis (no angle) to be able to // use a nicer keypath below and avoid needing // to wrap it in an NSValue torusNode.rotation = SCNVector4(x: 1.0, y: 1.0, z: 0.0, w: 0.0) // animate the rotation of the torus var spin = CABasicAnimation(keyPath: "rotation.w") // only animate the angle spin.toValue = 2.0*M_PI spin.duration = 3 spin.repeatCount = HUGE // for infinity torusNode.addAnimation(spin, forKey: "spin around")
When I run it, it looks like this:

Note that to run Scene Kit in an iOS playground, you need to check the "Run in Full Simulator" checkbox.

You find the Playground Setting in the Utilities Pane (⌥⌘0 to hide or show)
To get the playground running with iOS as target, and using the latest Xcode 8.1, I got it working with the following modifications to David Rönnqvist's original code.
import UIKit import SceneKit import QuartzCore // for the basic animation import PlaygroundSupport // create a scene view with an empty scene var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 300, height: 300)) var scene = SCNScene() sceneView.scene = scene PlaygroundPage.current.liveView = sceneView // default lighting sceneView.autoenablesDefaultLighting = true // a camera var cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 0, y: 0, z: 3) scene.rootNode.addChildNode(cameraNode) // a geometry object var torus = SCNTorus(ringRadius: 1, pipeRadius: 0.35) var torusNode = SCNNode(geometry: torus) scene.rootNode.addChildNode(torusNode) // configure the geometry object torus.firstMaterial?.diffuse.contents = UIColor.red torus.firstMaterial?.specular.contents = UIColor.white // set a rotation axis (no angle) to be able to // use a nicer keypath below and avoid needing // to wrap it in an NSValue torusNode.rotation = SCNVector4(x: 1.0, y: 1.0, z: 0.0, w: 0.0) // animate the rotation of the torus var spin = CABasicAnimation(keyPath: "rotation.w") // only animate the angle spin.toValue = 2.0*M_PI spin.duration = 3 spin.repeatCount = HUGE // for infinity torusNode.addAnimation(spin, forKey: "spin around")
The main things you have to do different are:
- to assign to the playground's
liveView
and, - also open up Xcode's Assistant Editor (The two intersecting circles icon on the toolbar)
Expanding on Moshe's response.
If that keyboard combination doesn't work for you, try going to the the menu bar and select View > Assistant Editor > Show Assistant.
If the playground is complaining with 'int is not convertible to CGFloat' then you can use this line of code:
spin.toValue = NSValue(SCNVector4: SCNVector4(x: 1, y: 1, z: 0, w: CGFloat(2.0*M_PI)))
Implicit typecasts seem not to be defined in swift.
In Xcode 10.2 there's a PlaygroundSupport
framework. It shares a playground data, manages live views, and controls the execution of a playground.
import PlaygroundSupport
You can use Playground Support from within playgrounds to:
- Access a playground page and manage its execution
- Access and share persistent data
- Assess the progress of the learner, update hints, and show success text
You also can use
PlaygroundSupport
to display and dismiss live views, which show the results of running the code in a playground. You can create live views for your own types by leveraging the built-in live view representations available on many existing types. Traditional live views are available in playgrounds in Xcode and in Swift Playgrounds. They run in the same process as the code in the playground, so you can access their properties and methods as usual; however, they're reset each time you run the playground. The always-on live view in Swift Playgrounds, activated when you add LiveView.swift to a page, executes in its own process so you can persist information and visuals between successive runs. The always-on live view isn't reset until you leave the page.
I slightly modified the code:
import PlaygroundSupport import UIKit import SceneKit import QuartzCore var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 1000, height: 200)) var scene = SCNScene() sceneView.scene = scene sceneView.backgroundColor = .black PlaygroundPage.current.liveView = sceneView var lightNode = SCNNode() lightNode.light = SCNLight() lightNode.light?.type = .directional lightNode.light?.intensity = 3000 lightNode.light?.shadowMode = .deferred lightNode.rotation = SCNVector4(x: 0, y: 0, z: 0.5, w: 1.5 * Float.pi) scene.rootNode.addChildNode(lightNode) var cameraNode = SCNNode() cameraNode.camera = SCNCamera() cameraNode.position = SCNVector3(x: 2.5, y: 0, z: 5) scene.rootNode.addChildNode(cameraNode) var box = SCNBox(width: 3, height: 3, length: 3, chamferRadius: 0.4) var boxNode = SCNNode(geometry: box) scene.rootNode.addChildNode(boxNode) box.firstMaterial?.diffuse.contents = UIColor.blue box.firstMaterial?.specular.contents = UIColor.purple boxNode.rotation = SCNVector4(x: 1.0, y: 1.0, z: 0.0, w: 0.0) boxNode.scale = SCNVector3(x: 1.0, y: 1.0, z: 1.0) var spin = CABasicAnimation(keyPath: "rotation.w") var scale = CABasicAnimation(keyPath: "scale.x") spin.toValue = 3 * -CGFloat.pi spin.duration = 2 spin.repeatCount = .greatestFiniteMagnitude scale.toValue = 1.5 scale.duration = 2 scale.repeatCount = .infinity boxNode.addAnimation(spin, forKey: "spin around") boxNode.addAnimation(scale, forKey: "scale x")
来源:https://stackoverflow.com/questions/24126669/using-scenekit-in-swift-playground