1

It looks like UIResponder is interwoven with UIView. Yet, Sprite Kit has the SKNode class which inherits from UIResponder so it can handle touch events.

If you create a node-based game engine yourself: Can you create your own UIResponder subclass so your objects rendered by OpenGL can respond to touch events similar to a UIView hierarchy could?

And how are the touch events coming into the UIResponder subclass?

openfrog
  • 40,201
  • 65
  • 225
  • 373

2 Answers2

3

There's nothing special about UIResponder -- it's indeed possible to do what you suggest. (Though maybe not as easy as you think.)

In effect, UIResponder is an abstract superclass. It doesn't (AFAIK) implement event dispatching itself; rather, it defines an interface for classes that handle events. How events get handled is up to the subclass implementation. UIApplication, UIWindow, and UIView implement responder methods to pass touch events along to the view under the touch -- presumably, UIView calls its own hitTest:withEvent: method to find the subview under the touch and forward the event to it. Sprite Kit extends the responder pattern into its node-tree model, so SKView likely implements UIResponder methods by calling its scene's convertPointFromView: and nodeAtPoint: methods to find the node under a touch before passing the event to that node.

If you implement your own UIView (or GLKView or whatever kind of view) subclass, you can extend the responder pattern to include your custom objects as well. If you're drawing a 3D scene with OpenGL ES and have Objective-C classes for representing the elements of that scene, feel free to have those classes inherit from UIResponder.

Just doing that won't magically forward touch events to those objects, though -- just like UIView does hit testing to forward events to subviews and SKView does hit testing to forward events to nodes, your view will need to do hit testing to determine which of your custom objects should receive a touch event (and then call the appropriate responder method on that object).

How to do hit testing in your OpenGL ES view is up to you... you'll have to find a method that works well for the needs of your app. Hit testing (aka selection or picking) is one of the big problem areas in 3D programming, so there's a lot written about it -- do some searching and you'll find plenty of recommendations. Here's a quick overview of the two most common approaches:

  • Re-render your scene to an offscreen framebuffer using a special fragment shader (or reconfigured GLKBaseEffect) that outputs object IDs instead of pixel colors, then use glReadPixels to find the pixel under the touch. (Multiple render targets in OpenGL ES 3.0 might help with performance.) Reading from GPU memory using glReadPixels is slow, so read only the point under the touch (or a small area around it if you want to allows some error margin) to keep performance up.

  • If you know where the elements of your scene are in its 3D coordinate space , you can use the GLKMathUnproject function to convert the touch location -- a point in 2D screen space -- to a line in your scene's 3D world space, then see where that line intersects your scene geometry (or the bounding boxes for your scene geometry) to figure out which object got touched. (This approach is called ray casting.)

If you extend the responder pattern into your own custom object architecture, you'll want to make sure your classes forward events up the responder chain appropriately. Read Event Handling Guide for iOS for details.

rickster
  • 124,678
  • 26
  • 272
  • 326
0

I don't believe this is possible in the way that SKNode has been implemented. There is no public API for inserting custom UIResponder subclasses into the responder chain.

See ricksters answer on details how to insert a UIResponder subclass into the responder chain correctly. Be sure to override - (UIResponder *)nextResponder in the child nodes to return your custom view class, so that the responder chain is still correct.

One possibility is to create a UIControl for each of your GL objects, and keep its position in sync. By adding these controls as subviews of your top level GL view, they will be inserted into the responder chain and receive touches. Another possibility is to handle touches in your top level view, and perform hit testing there to decide which GL node intersects with the touch.

Tark
  • 5,153
  • 3
  • 24
  • 23