Reputation: 405
I am trying to create a sphere with selectable grid tiles. The sphere should be able to rotate and zoom in, while still allowing grid tiles to be selectable. From what I understand this can be accomplished by using a SceneKit Sphere and setting the diffuse.contents equal to a Sprite Kit Scene.
Currently, I have the Sphere present with the Sprite Kit Scene as a texture overlay. I am able to create hit tests that recognize x,y coordinates on the sphere, but I am not actually selecting any tiles. "node has no name" is printing, I assume nodes selected would be part of SceneKit, not the Sprite Kit texture.
I created this project as a platform view for a Flutter app, if that changes anything. Also the Sprite Kit Scene was created in a .scn file.
Any suggestions?
public class SceneKitViewFactory: NSObject, FlutterPlatformViewFactory {
public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
print("returning scene kit view")
return SceneKitView(frame, viewId: viewId, args: args)
}
}
public class SceneKitView: NSObject, FlutterPlatformView {
let frame: CGRect
let viewId: Int64
let myScene: SCNScene
let scnView: SCNView
var cameraNode: SCNNode!
init(_ frame: CGRect, viewId: Int64, args: Any?) {
self.frame = frame
self.viewId = viewId
self.scnView = SCNView()
self.myScene = SCNScene()
scnView.scene = myScene
scnView.backgroundColor = .green
super.init()
createSphere()
createSceneHelpers()
createCamera()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
tapGesture.cancelsTouchesInView = false
scnView.addGestureRecognizer(tapGesture)
}
public func view() -> UIView {
return scnView
}
private func createSphere() {
let sphere = SCNSphere(radius: 1.0)
let imageMaterial = SCNMaterial()
let spriteKitScene = SKScene(fileNamed: "GameScene")!
spriteKitScene.isUserInteractionEnabled = true
imageMaterial.diffuse.contents = spriteKitScene
let sphereNode = SCNNode(geometry: sphere)
sphereNode.geometry!.firstMaterial = imageMaterial
myScene.rootNode.addChildNode(sphereNode)
}
private func createSceneHelpers() {
scnView.showsStatistics = true
scnView.allowsCameraControl = true
scnView.autoenablesDefaultLighting = true
}
private func createCamera() {
cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(x: 0, y: 0, z: 5)
myScene.rootNode.addChildNode(cameraNode)
}
@objc func handleTap(_ gestureRecognize: UIGestureRecognizer) {
let p = gestureRecognize.location(in: scnView)
let hitResults = scnView.hitTest(p, options: [:])
if hitResults.count > 0 {
let result: SCNHitTestResult = hitResults[0]
print(result.node.name ?? "node has no name")
print(result.textureCoordinates(withMappingChannel: 0)) // This line is added here.
print("x: \(p.x) y: \(p.y)") // <--- THIS IS WHERE I PRINT THE COORDINATES
}
}
}
Upvotes: 1
Views: 250
Reputation: 1213
Name your node(s) when you create them -> node.name = "x". Depending on a few things, but generally a good practice to name your nodes uniquely (cameras, etc.) in case you have to iterate through a bunch of nodes to see what they are. Not sure that gets you all of the way home, but that could be the first issue. "Looks" like you are reading these posts: 35023170 so it seems you're heading in the right direction.
Might want to iterate for multiple results just to be sure you get the hit you want:
let hitResults = gameScene.hitTest(location, options: hitTestOptions)
for vHit in hitResults
{
if(vHit.node.name?.prefix(5) == "Panel")
{
...
}
}
Upvotes: 0