Can anyone explain what is going on (and how to stop it?)

Here’s a snippet:

display.newRect( 300, 300, 200, 200 ).fill = {0,0,1} local parent = display.newGroup() local laser = display.newSnapshot( parent, 500, 500 ) timer.performWithDelay( 1000, function() display.newCircle( laser.group, 0, 0, 50 ).fill = {0,0,0} laser.x, laser.y = display.contentCenterX, display.contentCenterY laser:invalidate() transition.to( laser, { delay=500, time=1000, x=100 } ) end, 1 )

The intention is for a blue square to get rendered to a background group, then a black circle to get rendered to a snapshot and for the snapshot to get moved across the screen.

For some reason, the blue square, which is not in the snapshot, is getting copied (and scaled!) to the snapshot and moves with it.

I clearly do not understand snapshots. Could someone please explain what is going on and how to stop it. I would like to use the snapshot to apply effects (blurs, etc) to the circle and not involve the blue square at all, except in the background.

I’ve run into problems with manipulating snapshots before. I’m not sure if it’s what you’re experiencing (I haven’t run your above code) but in case it helps:

  1. Capture with display.captureBounds

  2. Use display.save to save the result

  3. Nil the result

  4. Load result with display.newImageRect

  5. Delete temp file when possible

It’s been a while since I did this, so my memory is a bit fuzzy on the details, but snapshots act in ways that are unintuitive. You may be able to work around it via the above method, albeit in a kludgy manner. Whether such a kludge should be required is, of course, a different question!

Thank you - I really don’t think the kludge should be required.

I’m currently seeing the problem above, but I’m also creating 25 squares, each with their own snapshot. The squares are quite small (128x128) and centred on the screen. If I create a snapshot for each one, and put a red circle in the top left corner before doing so, only the first square using a snapshot has that little red circle added to it - all the others are just fine.

This is really weird, unintuitive and counter-productive. I’d love to figure this one out, but all the samples and docs use demos which don’t have anything in the background to get in the way.

I’m convinced, however, that it is something basic that I’m missing. Anyone able to fill me in, please?

Hi Matt,

I just tested your code, and the blue square is definitely not becoming part of the snapshot, scaling with it, moving with it, or anything like that. Everything actually looks fine in this implementation… well, meaning that the intended behavior that you describe with the squares and circle is actually happening with your code, and properly so. Now, perhaps there’s some other surrounding code which is mucking things up, but in its pure form, this does exactly what you think it should.

One thing which may be helpful to you is using the “clearColor” property of snapshots to see the bounds of the snapshot and what’s going on with it. Consider this just like you’re filling the snapshot with a color, except that it’s not a separate display object.

[lua]

laser.clearColor = { 1, 0, 0, 1 }

[/lua]

Take care,

Brent

Here’s what I see with the basic code and your line added:

http://screencast.com/t/cufPMQqv2p

As you can see, the snapshot is initially created at 0,0 and covers the blue square. When it is moved, it appears to be instantiated with a capture of the screen at 0,0 of the area it is defined with, in this case 500x500.

Here’s my code with your line added:

display.newRect( 100, 100, 200, 200 ).fill = {0,0,1} local parent = display.newGroup() local laser timer.performWithDelay( 1000, function() laser = display.newSnapshot( parent, 500, 500 ) laser.clearColor = { 1, 0, 0, 1 } end ) timer.performWithDelay( 2000, function() display.newCircle( laser.group, 0, 0, 50 ) laser.x, laser.y = display.contentCenterX, display.contentCenterY laser:invalidate() transition.to( laser, { delay=500, time=1000, x=100 } ) end, 1 )

I should say that I am running today’s latest build 2015.2576 on a mid-2010 MacBook Pro with OS X 10.7.6 Mavericks. However, I also see this on a 2014 MacBook Pro running build 2015.2571 and the same Mavericks. The code you see above is everything in my main.lua and I’m not using a config.lua or build.settings file.

Just to make sure I’m not going crazy, I created a new directory with one main.lua, no other files at all, and put the following code into the main.lua:

display.setStatusBar( display.HiddenStatusBar ) display.newCircle( 50, 50, 25 ) local s = display.newSnapshot( 100, 100 ) s.x, s.y = 200, 200 s:invalidate() local r = display.newRect( 10, 10, 20, 20 ) timer.performWithDelay( 1000, function() s.group:insert( r ) s:invalidate() end, 1 )

This is the result:

http://screencast.com/t/GNAWQHe33

As you can see, once the rectangle is inserted into the snapshot’s group, the snapshot seems to copy a piece of the circle, where the snapshot overlaps the circle.

Here it is with the clear colour turned on:

http://screencast.com/t/0wZwSMAMQxpr

And the code:

display.setStatusBar( display.HiddenStatusBar ) display.newCircle( 50, 50, 25 ) local s = display.newSnapshot( 100, 100 ) s.x, s.y = 200, 200 s.clearColor = { 1, 0, 0, 1 } s:invalidate() local r = display.newRect( 10, 10, 20, 20 ) timer.performWithDelay( 1000, function() s.group:insert( r ) s:invalidate() end, 1 )

I really don’t understand why this is happening. Can someone explain the canvas to me please?

Right, it seems that I have some sort of solution, though I really don’t think this is ideal and that there is a bug involved.

When I put all my screen content into a display group, which is above the display group used when constructing the snapshot object, the snapshot does not gain/copy/clone any of the screen content.

This code works, unless you comment out the marked line:

display.setStatusBar( display.HiddenStatusBar ) local lower, upper = display.newGroup(), display.newGroup() upper:toBack() -- comment out to see snapshot() clone the lower group display.newCircle( lower, 50, 50, 25 ) local s = display.newSnapshot( upper, 100, 100 ) s.x, s.y = 200, 200 s.clearColor = { 1, 0, 0, 1 } s.canvasMode = "discard" local r = display.newRect( 10, 10, 20, 20 ) timer.performWithDelay( 1000, function() s.group:insert( r ) s:invalidate() end, 1 )

Is the intended functionality of snapshots really to take the content of the display below them in the stack?

[…] As you can see, once the rectangle is inserted into the snapshot’s group, the snapshot seems to copy a piece of the circle, where the snapshot overlaps the circle. […]

That must be a bug!?

I would have assumed that the snapshot’s contents should only render its group’s children.

Hi Matt,

OK, this definitely seems like a system issue. I tested your identical code on OS X 10.10 Yosemite, using Corona build #2576, and the snapshot works exactly how the code indicates it should. The circle is never “copied over” to the snapshot.

A more revealing test will be on devices. As you know, the Simulator is not 100% perfect in representing what will happen on real devices.

Thanks,

Brent

I’ve run into problems with manipulating snapshots before. I’m not sure if it’s what you’re experiencing (I haven’t run your above code) but in case it helps:

  1. Capture with display.captureBounds

  2. Use display.save to save the result

  3. Nil the result

  4. Load result with display.newImageRect

  5. Delete temp file when possible

It’s been a while since I did this, so my memory is a bit fuzzy on the details, but snapshots act in ways that are unintuitive. You may be able to work around it via the above method, albeit in a kludgy manner. Whether such a kludge should be required is, of course, a different question!

Thank you - I really don’t think the kludge should be required.

I’m currently seeing the problem above, but I’m also creating 25 squares, each with their own snapshot. The squares are quite small (128x128) and centred on the screen. If I create a snapshot for each one, and put a red circle in the top left corner before doing so, only the first square using a snapshot has that little red circle added to it - all the others are just fine.

This is really weird, unintuitive and counter-productive. I’d love to figure this one out, but all the samples and docs use demos which don’t have anything in the background to get in the way.

I’m convinced, however, that it is something basic that I’m missing. Anyone able to fill me in, please?

Hi Matt,

I just tested your code, and the blue square is definitely not becoming part of the snapshot, scaling with it, moving with it, or anything like that. Everything actually looks fine in this implementation… well, meaning that the intended behavior that you describe with the squares and circle is actually happening with your code, and properly so. Now, perhaps there’s some other surrounding code which is mucking things up, but in its pure form, this does exactly what you think it should.

One thing which may be helpful to you is using the “clearColor” property of snapshots to see the bounds of the snapshot and what’s going on with it. Consider this just like you’re filling the snapshot with a color, except that it’s not a separate display object.

[lua]

laser.clearColor = { 1, 0, 0, 1 }

[/lua]

Take care,

Brent

Here’s what I see with the basic code and your line added:

http://screencast.com/t/cufPMQqv2p

As you can see, the snapshot is initially created at 0,0 and covers the blue square. When it is moved, it appears to be instantiated with a capture of the screen at 0,0 of the area it is defined with, in this case 500x500.

Here’s my code with your line added:

display.newRect( 100, 100, 200, 200 ).fill = {0,0,1} local parent = display.newGroup() local laser timer.performWithDelay( 1000, function() laser = display.newSnapshot( parent, 500, 500 ) laser.clearColor = { 1, 0, 0, 1 } end ) timer.performWithDelay( 2000, function() display.newCircle( laser.group, 0, 0, 50 ) laser.x, laser.y = display.contentCenterX, display.contentCenterY laser:invalidate() transition.to( laser, { delay=500, time=1000, x=100 } ) end, 1 )

I should say that I am running today’s latest build 2015.2576 on a mid-2010 MacBook Pro with OS X 10.7.6 Mavericks. However, I also see this on a 2014 MacBook Pro running build 2015.2571 and the same Mavericks. The code you see above is everything in my main.lua and I’m not using a config.lua or build.settings file.

Just to make sure I’m not going crazy, I created a new directory with one main.lua, no other files at all, and put the following code into the main.lua:

display.setStatusBar( display.HiddenStatusBar ) display.newCircle( 50, 50, 25 ) local s = display.newSnapshot( 100, 100 ) s.x, s.y = 200, 200 s:invalidate() local r = display.newRect( 10, 10, 20, 20 ) timer.performWithDelay( 1000, function() s.group:insert( r ) s:invalidate() end, 1 )

This is the result:

http://screencast.com/t/GNAWQHe33

As you can see, once the rectangle is inserted into the snapshot’s group, the snapshot seems to copy a piece of the circle, where the snapshot overlaps the circle.

Here it is with the clear colour turned on:

http://screencast.com/t/0wZwSMAMQxpr

And the code:

display.setStatusBar( display.HiddenStatusBar ) display.newCircle( 50, 50, 25 ) local s = display.newSnapshot( 100, 100 ) s.x, s.y = 200, 200 s.clearColor = { 1, 0, 0, 1 } s:invalidate() local r = display.newRect( 10, 10, 20, 20 ) timer.performWithDelay( 1000, function() s.group:insert( r ) s:invalidate() end, 1 )

I really don’t understand why this is happening. Can someone explain the canvas to me please?

Right, it seems that I have some sort of solution, though I really don’t think this is ideal and that there is a bug involved.

When I put all my screen content into a display group, which is above the display group used when constructing the snapshot object, the snapshot does not gain/copy/clone any of the screen content.

This code works, unless you comment out the marked line:

display.setStatusBar( display.HiddenStatusBar ) local lower, upper = display.newGroup(), display.newGroup() upper:toBack() -- comment out to see snapshot() clone the lower group display.newCircle( lower, 50, 50, 25 ) local s = display.newSnapshot( upper, 100, 100 ) s.x, s.y = 200, 200 s.clearColor = { 1, 0, 0, 1 } s.canvasMode = "discard" local r = display.newRect( 10, 10, 20, 20 ) timer.performWithDelay( 1000, function() s.group:insert( r ) s:invalidate() end, 1 )

Is the intended functionality of snapshots really to take the content of the display below them in the stack?

[…] As you can see, once the rectangle is inserted into the snapshot’s group, the snapshot seems to copy a piece of the circle, where the snapshot overlaps the circle. […]

That must be a bug!?

I would have assumed that the snapshot’s contents should only render its group’s children.

Hi Matt,

OK, this definitely seems like a system issue. I tested your identical code on OS X 10.10 Yosemite, using Corona build #2576, and the snapshot works exactly how the code indicates it should. The circle is never “copied over” to the snapshot.

A more revealing test will be on devices. As you know, the Simulator is not 100% perfect in representing what will happen on real devices.

Thanks,

Brent