Touch Event on Masked Group doesn't work

Hi Corona programmers, 

I’m having a really strange problem which could probably be a bug, but I need some help to make that clear.

I have a group object (shapeGroup) that contains n groups (middleGroup) with an image inside. The middleGroups are then masked, mainly to prevent touch listener to register events when you click outside the actual image itself (isHitTestMasked is set to true).

The problem is that, when adding a touchListener to middleGroups, some of it will behave correctly, registering events normally, other will register event just in some portions of the image itself (even if you tap on visible portions of the image).

Here is a sample code to make you better understand what I do:

local composer = require("composer") local scene = composer.newScene() local shapeGroup local shape = "snowman" local function onTouch(event) if event.phase == "began" then print(event.phase) local circle = display.newCircle(shapeGroup,event.x-shapeGroup.x,event.y-shapeGroup.y,5) circle:setFillColor(1,0,0) elseif event.phase == "moved" then print(event.phase) elseif event.phase == "ended" then print(event.phase) end return true end function scene:create(event) shapeGroup = display.newGroup() shapeGroup.x = \_viewW\*0.5 shapeGroup.y = \_viewH\*0.5 local sheetInfo = require ("Grafica.ColorGame."..shape) local imageSheet = graphics.newImageSheet("Grafica/ColorGame/"..shape..".png", sheetInfo:getSheet()) local frameNo = #sheetInfo.sheet.frames local sheetFrames = sheetInfo.sheet.frames for i = 1, frameNo\*0.5 do local group = display.newGroup() local shapePart = display.newImageRect( group ,imageSheet, i, sheetFrames[i].width , sheetFrames[i].height ) shapePart.maskFile = "Grafica/ColorGame/"..shape.."Mask"..i..".png" shapePart.name = shape..i shapeGroup:insert(group) local mask = graphics.newMask(shapePart.maskFile) group:setMask(mask) end end function scene:show(event) local sceneGroup = self.view local phase = event.phase if (phase == "will") then print(shapeGroup.numChildren) for i = 1, shapeGroup.numChildren do shapeGroup[i]:addEventListener("touch",onTouch) end end end

(edited the code removing useless chunks, like composer events, for better reading)

Please note that my images are inside an ImageSheet (created with Texture Packer) and are as big as my content area.

Same with the masks, which are as big as the screen (1280,800) but unfortunately not inside an ImageSheet (because you can’t create a mask from an ImageSheet… yet)

In my touch listener I draw a circle if the event is started… but when I run the code only the second image gets all the touches… 

What is really strange is that the touch is invoked if you touch a very specific area of one of the two malfunctioning images…

I don’t know if you need to run the code to better understand the situation, in case let me know and I’ll provide all graphics required! :wink:

Here’s a screenshots of what I’m getting: 

Screenshot_1.png

 

The red area represents where the event get’s called correctly. Please note the top and bottom portions, and also the left part of the middle segment which is not “touchable”.

I doesn’t seem to be a problem of mask misplacement as the images are showed exactly as I want and where I want… really clueless about this…

@Q-tro,

  1. I’m pretty sure isHitTestMaskedis only heeded if the touch listener is attached to the object, not the group.

  2. I don’t suggest applying touch listeners to groups.  Instead, you should attach them to objects.

Here is an easy way to achieve this with minimal code:

-- 1. Write a single listener like this local function onTouch( self, event ) if(event.phase == "ended" ) then print("You touched: ", self.myName ) end return true end --2. Create as many objects as you want and have them all use the same listener -- local tmp = display.newCircle( 100, 100, 10 ) tmp.touch = onTouch tmp.myName = "Bob" tmp:addEventListener( "touch" ) local tmp = display.newCircle( 100, 150, 10 ) tmp.touch = onTouch -- uses same code as "Bob" tmp.myName = "Bill" tmp:addEventListener( "touch" ) local tmp = display.newCircle( 150, 150, 10 ) tmp.touch = onTouch -- uses same code as "Bob" and "Bill" tmp.myName = "Sue" tmp:addEventListener( "touch" ) -- ...

Note: I realize you’re trying to achieve something somewhat complex w/ your masking of the group, any my answer may not help entirely.  I do wonder though, if the listeners are attached to the objects, but the group is masked, will the objects treat the transparent regions as being masked.  

Now I have to go try this.

@Q-Tro,

OK.  I’ve got a solution that should work for  you:

https://www.youtube.com/watch?v=JkV1i6z7xUg&feature=youtu.be&hd=1

You can get the code here:

https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2015/02/isHitMaskedHelp.zip

@roaminggamer

First af all, thanks for your commitment, it really raises hopes for the future of humanity!!

Going on… I tried your method, and, infact, I can create a masked group that registers touch events on its children with the correct boundaries limit. 

What I’ve found out is that the touch listeners works properly if you use “standard” ImageRects, BUT if you try to initialize your DisplayObjects using an Image Sheet (as I need to do), things start to get a lot less smooth.

The most notable consequence is that the touch event will not always be triggered, instead in some areas of my ImageRects the event wont get trigged, until you touch a someway “magical” area which triggers the event, unlocking the event propagation for the whole surface of my Image for all next touches.

I don’t know if I’ve managed to explain this behaviour correctly, maybe it’s better to just try your example using an imageSheet and see the results…

Thank you again and hope to read you soon!

@Q-tro,

  1. I’m pretty sure isHitTestMaskedis only heeded if the touch listener is attached to the object, not the group.

  2. I don’t suggest applying touch listeners to groups.  Instead, you should attach them to objects.

Here is an easy way to achieve this with minimal code:

-- 1. Write a single listener like this local function onTouch( self, event ) if(event.phase == "ended" ) then print("You touched: ", self.myName ) end return true end --2. Create as many objects as you want and have them all use the same listener -- local tmp = display.newCircle( 100, 100, 10 ) tmp.touch = onTouch tmp.myName = "Bob" tmp:addEventListener( "touch" ) local tmp = display.newCircle( 100, 150, 10 ) tmp.touch = onTouch -- uses same code as "Bob" tmp.myName = "Bill" tmp:addEventListener( "touch" ) local tmp = display.newCircle( 150, 150, 10 ) tmp.touch = onTouch -- uses same code as "Bob" and "Bill" tmp.myName = "Sue" tmp:addEventListener( "touch" ) -- ...

Note: I realize you’re trying to achieve something somewhat complex w/ your masking of the group, any my answer may not help entirely.  I do wonder though, if the listeners are attached to the objects, but the group is masked, will the objects treat the transparent regions as being masked.  

Now I have to go try this.

@Q-Tro,

OK.  I’ve got a solution that should work for  you:

https://www.youtube.com/watch?v=JkV1i6z7xUg&feature=youtu.be&hd=1

You can get the code here:

https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2015/02/isHitMaskedHelp.zip

@roaminggamer

First af all, thanks for your commitment, it really raises hopes for the future of humanity!!

Going on… I tried your method, and, infact, I can create a masked group that registers touch events on its children with the correct boundaries limit. 

What I’ve found out is that the touch listeners works properly if you use “standard” ImageRects, BUT if you try to initialize your DisplayObjects using an Image Sheet (as I need to do), things start to get a lot less smooth.

The most notable consequence is that the touch event will not always be triggered, instead in some areas of my ImageRects the event wont get trigged, until you touch a someway “magical” area which triggers the event, unlocking the event propagation for the whole surface of my Image for all next touches.

I don’t know if I’ve managed to explain this behaviour correctly, maybe it’s better to just try your example using an imageSheet and see the results…

Thank you again and hope to read you soon!