Search code examples
iosobjective-c3duibuttoncalayer

Create 3D cube with layers, with clickable sides - objective C


I'm now trying to create an application with a '3D cube', and clickable sides.

To create a '3D cube', i found a great article : here It uses some 'layers'.

What i want to do, is done a cube in 3D, but with clickable sides. I found some examples like this :

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if ([touches count] == 1) {
        for (UITouch *touch in touches) {
            CGPoint point = [touch locationInView:[touch view]];
            point = [[touch view] convertPoint:point toView:nil];

            CALayer *layer = [(CALayer *)self.view.layer.presentationLayer hitTest:point];

            layer = layer.modelLayer;
            layer.opacity = 0.5;
        }
    }
}

But this sort of code makes no difference between the different sides. So I try to make some changes to the code from the article. For example, to create the first side, the code was :

CALayer *sideOne = [CALayer layer];
sideOne.borderColor = [UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
sideOne.backgroundColor = [UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:0.4].CGColor;
sideOne.borderWidth = Border_Width;
sideOne.cornerRadius = Corner_Radius;
sideOne.frame = layerRect;
sideOne.position = self.center;

and :

transformLayer = [CATransformLayer layer];
[transformLayer addSublayer:test.layer];
transformLayer.anchorPointZ = Layer_Size/-2;
[rootLayer addSublayer:transformLayer];

So I try to make some modifications and finally add a 'UIButton' on this side. Like this :

UIButton * test = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[test setFrame:CGRectMake(0.0, 0.0, layerSize, layerSize)];
[test addTarget:self action:@selector(ActionTest) forControlEvents:UIControlEventTouchUpInside];
test.layer.borderColor = [UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
test.layer.backgroundColor = [UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:0.4].CGColor;
test.layer.borderWidth = Border_Width;
test.layer.cornerRadius = Corner_Radius;
test.layer.frame = layerRect;
test.layer.position = self.center;

But the problem is, when i want to add it to the side.

When i do :

transformLayer = [CATransformLayer layer];
[self addSubview:test];
[transformLayer addSublayer:test.layer];
transformLayer.anchorPointZ = Layer_Size/-2;
[rootLayer addSublayer:transformLayer];

the button no react

And when i do :

transformLayer = [CATransformLayer layer];
[transformLayer addSublayer:test.layer];
transformLayer.anchorPointZ = Layer_Size/-2;
[self addSubview:test];
[rootLayer addSublayer:transformLayer];

the button react but don't move with the rest of the cube

I understand the problem but don't know how to fix it...

Thanks !


Solution

  • What you're seeing is the difference between a UIButton, which inherits from UIResponder, and CALayer's, which do not make up a part of the responder chain directly.

    Fortunately, there is a simple way to grab events from the responder chain and direct them towards your CALayer of choice, and it looks a little like this:

    - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
    {
        CGPoint p = [(UITouch*)[touches anyObject] locationInView:self.worldView];
        for (CALayer *layer in self.worldView.layer.sublayers) {
            if ([layer containsPoint:[self.worldView.layer convertPoint:p toLayer:layer]]) {
                // do something
            }
        }
    }
    

    It's the containsPoint:convertPoint:toLayer: that's going to hold the essence of what you seek.

    There's a bit more largely relevant discussion around this topic on this post too

    To connect the dots of this to your invocation, when you add the button's layer to your other layers, all the visual aspects perform as expected, but no one is a member of the responder chain, and therefore no one receives touches to handle.