[RESOLVED] events not working on objects inside snapshot

That’s expected behavior. As far as Corona’s hit-testing is concerned, snapshots are no different from normal rectangles.

Also, it’s important to note that snapshots are *not* groups. They have group properties but they use those groups to control how the snapshot’s texture is generated. So those child object are effectively offscreen.

Thanks for the quick response Walter.

It seems several of the filters should logically be applied to the whole screen, like this is what they were designed for? For example the vignette, the radial wipe, linear wipe, bloom, iris and sepia would all be great and very useful full screen effects. If these effects cannot be applied to a group or a container, only to a snapshot then how do we apply them full screen? I think we must have missed some simple G2.0 logic.

I realise for some effects (for example to fade the whole game to black & white via filter.saturate) you could process every image individually but wouldn’t that be much slower than just applying it to the whole screen/frame buffer once in post?

Would it be possible to expose a screen buffer type object that we could apply said filters to? Excluding any distortion objects of course as they would understandably break the touch.

I was given a suggestion of a way to do it (thank you!)… to use “display.captureScreen()”. Worth a shot. I tried this:

local screen local debug = display.newText("Frame Time", \_W \* 0.5, \_H \* 0.15, native.systemFont, 150) debug:setFillColor(0, 0, 1) local tPrev = 0 local function updateGame(e) debug.text = e.time - tPrev tPrev = e.time --[[if screen then screen:removeSelf() screen = nil end screen = display.captureScreen() screen.x = \_W \* 0.5 screen.y = \_H \* 0.5 screen.fill.effect = "filter.vignette" screen.fill.effect.radius = 0.1 --]] end Runtime:addEventListener("enterFrame", updateGame)

Unfortunately the frame times doubles on the simulator - making this approach unusable. I can’t imagine it’s better on a device.

So back to our original problem. How do we implement full screen shader effects? Shaders like vignette, radial wipe, etc. are just crying out to be used full screen.

@spideri:

It’s not necessary to do display.captureScreen() every frame. I suggest you only do it once at the top.

Also, you can apply “filter.vignette” to an empty rectangle (“display.newRect()”) that covers the whole screen.

If you are do display.captureScreen() once only then then how will that apply the effect the animated game?

I like the idea applying “filter.vignette” to an empty rectangle. How do you create an “empty” rectangle? If it has a colour then it overlays the whole image with that colour. If it’s transparent then so it the vignette.

Back to the main problem, and please can we use say “radialWipe”. Image, all I want to do is make a full screen radial wipe for my game (whilst it’s still animating and not static). How do I do this? Is there an example or can Corona provide one?

In the case where you want the game to be animated behind an effect, I would pick an effect that’s not too expensive to execute every frame on an object.
 

If you set opaque white to a vignette, only the opaque part of the vignette will be opaque white.

Sure:

(1) Create a rectangle or an image. (See display.newRect())
(2) Place (1) over the animated scene. (Use the “x” and “y” properties of your object.)
(3) Assign the effect to (1). (my_object.fill.effect = “filter.radialWipe”)
(4) Vary the “progress” parameter between 0 and 1. (my_object.fill.effect.progress = 0.5)

Q:If you are do display.captureScreen() once only then then how will that apply the effect the animated game?

A:In the case where you want the game to be animated behind an effect, I would pick an effect that’s not too expensive to execute every frame on an object.

So in this case, are you saying that we WOULD need to be calling display.captureScreen() every frame, as we originally thought? Otherwise I don’t see how using display.captureScreen() would allow you to apply a filter to a non-static scene.

Q:I like the idea applying “filter.vignette” to an empty rectangle. How do you create an “empty” rectangle? If it has a colour then it overlays the whole image with that colour. If it’s transparent then so it the vignette.

A:If you set opaque white to a vignette, only the opaque part of the vignette will be opaque white.

If we set a rect to opaque white then the rect is coloured white and you can’t see the scene beneath it. Yes, the rest of the vignette will fade out to black, but you cannot see your scene through it. If you try drawing a scene and the putting this on top:

local myVignette = display.newRect(display.contentWidth \* 0.5, display.contentHeight \* 0.5, display.contentWidth, display.contentHeight) myVignette:setFillColor(1, 1, 1, 1) myVignette.fill.effect = "filter.vignette" myVignette.fill.effect.radius = 0.1

you’ll see what we mean. The whole scene become white with a black vignette. If you change it to:

myVignette:setFillColor(1, 1, 1, 0)

then none of the vignette is visible at all.

Q: Back to the main problem, and please can we use say “radialWipe”. Image, all I want to do is make a full screen radial wipe for my game (whilst it’s still animating and not static). How do I do this? Is there an example or can Corona provide one?

A: Sure:

(1) Create a rectangle or an image. (See display.newRect())

(2) Place (1) over the animated scene. (Use the “x” and “y” properties of your object.)

(3) Assign the effect to (1). (my_object.fill.effect = “filter.radialWipe”)

(4) Vary the “progress” parameter between 0 and 1. (my_object.fill.effect.progress = 0.5)

I think we have a misunderstanding here. The question is suggesting that you have an animating scene, and you want the whole scene to have a radial wipe applied on it. If you put an image on top then the effect is only applied to that object. If you use display.captureScreen() to create the object, then your effect is applied to something that looks like your scene at a single moment in time, but is no longer animated you are putting the filter onto a static object. This doesn’t allow you to for example, use an effect to transition between 2 running scenes, and see them both animating at the same time.

Let’s say we have 10 rects bouncing around the screen, and another “scene” hidden underneath with 10 circles bouncing around. As the radial wipe begins at 0 I can still see the squares bouncing and that’s all. When it reached 0.25 I would want to see the circles bouncing around in 1/4 of the screen, and the squares in the remaining 3/4…and so on until the screen is entirely circles. That might not be the exact effect that spideri was looking for, but I think it explains the problem in more detail. I guess that what we would be looking to do is have the effect applied to a group/snapshot/container/whatever as a whole, as suggested in the original post.

@AlanPlantPot: You have a good point, you can’t use the current output of “filter.vignette” as a mask.

I’ve added a “filter.vignetteMask” to the next daily build. This new filter outputs a vignette that will be transparent in the middle, and allow you to overlay it over an animated scene, without having to capture the scene every single frame.

Let me know if it help.

Cool, can’t wait to see how it looks!

That’s expected behavior. As far as Corona’s hit-testing is concerned, snapshots are no different from normal rectangles.

Also, it’s important to note that snapshots are *not* groups. They have group properties but they use those groups to control how the snapshot’s texture is generated. So those child object are effectively offscreen.

Thanks for the quick response Walter.

It seems several of the filters should logically be applied to the whole screen, like this is what they were designed for? For example the vignette, the radial wipe, linear wipe, bloom, iris and sepia would all be great and very useful full screen effects. If these effects cannot be applied to a group or a container, only to a snapshot then how do we apply them full screen? I think we must have missed some simple G2.0 logic.

I realise for some effects (for example to fade the whole game to black & white via filter.saturate) you could process every image individually but wouldn’t that be much slower than just applying it to the whole screen/frame buffer once in post?

Would it be possible to expose a screen buffer type object that we could apply said filters to? Excluding any distortion objects of course as they would understandably break the touch.

I was given a suggestion of a way to do it (thank you!)… to use “display.captureScreen()”. Worth a shot. I tried this:

local screen local debug = display.newText("Frame Time", \_W \* 0.5, \_H \* 0.15, native.systemFont, 150) debug:setFillColor(0, 0, 1) local tPrev = 0 local function updateGame(e) debug.text = e.time - tPrev tPrev = e.time --[[if screen then screen:removeSelf() screen = nil end screen = display.captureScreen() screen.x = \_W \* 0.5 screen.y = \_H \* 0.5 screen.fill.effect = "filter.vignette" screen.fill.effect.radius = 0.1 --]] end Runtime:addEventListener("enterFrame", updateGame)

Unfortunately the frame times doubles on the simulator - making this approach unusable. I can’t imagine it’s better on a device.

So back to our original problem. How do we implement full screen shader effects? Shaders like vignette, radial wipe, etc. are just crying out to be used full screen.

@spideri:

It’s not necessary to do display.captureScreen() every frame. I suggest you only do it once at the top.

Also, you can apply “filter.vignette” to an empty rectangle (“display.newRect()”) that covers the whole screen.

If you are do display.captureScreen() once only then then how will that apply the effect the animated game?

I like the idea applying “filter.vignette” to an empty rectangle. How do you create an “empty” rectangle? If it has a colour then it overlays the whole image with that colour. If it’s transparent then so it the vignette.

Back to the main problem, and please can we use say “radialWipe”. Image, all I want to do is make a full screen radial wipe for my game (whilst it’s still animating and not static). How do I do this? Is there an example or can Corona provide one?

In the case where you want the game to be animated behind an effect, I would pick an effect that’s not too expensive to execute every frame on an object.
 

If you set opaque white to a vignette, only the opaque part of the vignette will be opaque white.

Sure:

(1) Create a rectangle or an image. (See display.newRect())
(2) Place (1) over the animated scene. (Use the “x” and “y” properties of your object.)
(3) Assign the effect to (1). (my_object.fill.effect = “filter.radialWipe”)
(4) Vary the “progress” parameter between 0 and 1. (my_object.fill.effect.progress = 0.5)

Q:If you are do display.captureScreen() once only then then how will that apply the effect the animated game?

A:In the case where you want the game to be animated behind an effect, I would pick an effect that’s not too expensive to execute every frame on an object.

So in this case, are you saying that we WOULD need to be calling display.captureScreen() every frame, as we originally thought? Otherwise I don’t see how using display.captureScreen() would allow you to apply a filter to a non-static scene.

Q:I like the idea applying “filter.vignette” to an empty rectangle. How do you create an “empty” rectangle? If it has a colour then it overlays the whole image with that colour. If it’s transparent then so it the vignette.

A:If you set opaque white to a vignette, only the opaque part of the vignette will be opaque white.

If we set a rect to opaque white then the rect is coloured white and you can’t see the scene beneath it. Yes, the rest of the vignette will fade out to black, but you cannot see your scene through it. If you try drawing a scene and the putting this on top:

local myVignette = display.newRect(display.contentWidth \* 0.5, display.contentHeight \* 0.5, display.contentWidth, display.contentHeight) myVignette:setFillColor(1, 1, 1, 1) myVignette.fill.effect = "filter.vignette" myVignette.fill.effect.radius = 0.1

you’ll see what we mean. The whole scene become white with a black vignette. If you change it to:

myVignette:setFillColor(1, 1, 1, 0)

then none of the vignette is visible at all.

Q: Back to the main problem, and please can we use say “radialWipe”. Image, all I want to do is make a full screen radial wipe for my game (whilst it’s still animating and not static). How do I do this? Is there an example or can Corona provide one?

A: Sure:

(1) Create a rectangle or an image. (See display.newRect())

(2) Place (1) over the animated scene. (Use the “x” and “y” properties of your object.)

(3) Assign the effect to (1). (my_object.fill.effect = “filter.radialWipe”)

(4) Vary the “progress” parameter between 0 and 1. (my_object.fill.effect.progress = 0.5)

I think we have a misunderstanding here. The question is suggesting that you have an animating scene, and you want the whole scene to have a radial wipe applied on it. If you put an image on top then the effect is only applied to that object. If you use display.captureScreen() to create the object, then your effect is applied to something that looks like your scene at a single moment in time, but is no longer animated you are putting the filter onto a static object. This doesn’t allow you to for example, use an effect to transition between 2 running scenes, and see them both animating at the same time.

Let’s say we have 10 rects bouncing around the screen, and another “scene” hidden underneath with 10 circles bouncing around. As the radial wipe begins at 0 I can still see the squares bouncing and that’s all. When it reached 0.25 I would want to see the circles bouncing around in 1/4 of the screen, and the squares in the remaining 3/4…and so on until the screen is entirely circles. That might not be the exact effect that spideri was looking for, but I think it explains the problem in more detail. I guess that what we would be looking to do is have the effect applied to a group/snapshot/container/whatever as a whole, as suggested in the original post.

@AlanPlantPot: You have a good point, you can’t use the current output of “filter.vignette” as a mask.

I’ve added a “filter.vignetteMask” to the next daily build. This new filter outputs a vignette that will be transparent in the middle, and allow you to overlay it over an animated scene, without having to capture the scene every single frame.

Let me know if it help.

Cool, can’t wait to see how it looks!