• Runtimes
  • [objc] Touch event on slots

Related Discussions
...

Hello,

i need to detect touch events on the exported character slots.
What is the best way to achieve that?

I can get the touch location with the touchBegan🙁UITouch *)touch withEvent🙁UIEvent *)event, but how i can get the slot list from the skeleton?

There are different ways to check what part of a skeleton was touched. Just to clear up nomenclature: a slot itself doesn't have a representation you could check against. However, a slot can have an attachment (bounding box attachment, region attachment, mesh attachment) which you might want to test against.

For bounding box attachments, you can check out the SkeletonBounds. You can use it like this (provided you have a reference to spSkeleton* and your skeleton world transforms have been updated):

spSkeletonBounds* bounds = spSkeletonBounds_create();
spSkeletonBounds_update(bounds, skeleton, true);
spBoundingBoxAttachment* hitAttachment = spSkeletonBounds_containsPoint(bounds, touchX, touchY);

The last function will return the bounding box attachment that contains the point (touchX, touchY), or null. You can find out how to create bounding box attachments on your skeleton in the editor here Bounding Boxes - Spine User Guide

If you want to check against other attachment types (region, mesh), you will have to get your hands dirty a little bit and replicate what spSkeletonBounds_containsPoint does. Here's a bit of code that iterates through the slots and the attachments attached to them spine-runtimes/SkeletonRenderer.m at 3.6

Thanks for your fast response!
Bounding boxes also can work for me, i thinked about it yesterday, but the included debugSlot draw was too handy 😃

I will try this tonight!
Thanks!


For the readers who might read this in the future, here is my solution (after 4 hour trying with wrong touch position):

- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {

    CGPoint touchLocation = [[CCDirector sharedDirector] convertTouchToGL:touch];
    CGPoint locationInNode = [skeletonNode convertToNodeSpace:touchLocation];

    spSkeletonBounds* bounds = spSkeletonBounds_create();
    spSkeletonBounds_update(bounds, [skeletonNode skeleton], true);
    
    spBoundingBoxAttachment* hitAttachment = spSkeletonBounds_containsPoint(bounds, locationInNode.x, locationInNode.y);
    if (hitAttachment != NULL) {        
        //hitAttachment->super.super.name contains the boundingbox name
        return;
    }
}

Thanks again for the help!

Ah, yes. Converting points from and to different coordinate spaces is always fickle. Glad you figured it out!