Composer Overlay Transitioning Too Quickly

Hi Rob,

Here’s a video capture of my iPad Air running the OverlayTest app I sent you. It was captured using a Lightning cable and OS X Yosemite.

Thanks!
 

  • David

What version of Corona SDK are you running?

The latest public release, 2511.

  • David

Interesting.  It only happens if the @2x images get loaded even in the Corona Simulator.  If you change the skin to any of the iPhone skins except the 6+ you will see it fade.  As soon as I pick either the iPad Air (an @2x device for you) or the iPhone 6+, it also demonstrates the problem.  When I installed it to my iPad 4, I noticed the problem there.

I did a little research and I forgot about some issues with when we load images.  We currently “lazy load” them for performance reasons (if I understand the issue correctly.)   To get around this we introduce a new API call way back with Graphics 2.0 came out that controls how we load the images. 

Add this line to the top of your main.lua:

display.setDefault( “preloadTextures”, false )

That should fix you up.

Rob

Hi Rob,

Thank you for your time and research! Really great to know that I’m not crazy and there is a real reason for this. :slight_smile: I gave the setDefault call a try, and it did indeed clear up the overlay transition problem. Unfortunately, it also introduced a host of performance issues throughout the game, which is probably why it’s not normally set to ‘false’, so I won’t be able to ship with this fix. I’ll use the workaround of extending the transition length.

I think it would be useful if this information were added to the Graphics 2.0 Migration Guide. This is the second behavior change I’ve run into (the first being a change in “shader precision,” as detailed here), and both have literally cost me many days of time trying to fix/workaround. Others would likely benefit from this information as well.

Really appreciate your help!

  • David

I’ve spent the better part of the morning optimizing the overlay modules that are ‘popping’ on-screen (removing around 50 lines of code!), and while they now works properly in the simulator, they still just ‘pop’ on-screen on my iPad Air and iPhone 4S (both 1x and 2x assets). What continues to be frustrating and perplexing is that other overlay modules display just fine.

Here’s the “create” function of one of the problem modules:

[lua]

function scene:create (e)local group = self.view propGift = display.newGroup() blackBG = display.newRect(propGift, 512, 384, 1024, 768) blackBG:setFillColor(0,0,0, overlayAlpha) giftBox = display.newImageRect(propGift, "images/overlays/gift\_box/ExtPT\_GiftOpen.png", 1024, 768) buttonInactive = display.newRect(propGift, 0, 0, 520, 520) buttonActive = display.newImageRect(propGift, "images/overlays/gift\_box/ExtPT\_GiftActive.png", 512, 512) boxTop = display.newImageRect(propGift, "images/overlays/gift\_box/ExtPT\_GiftClosed.png", 1024, 768) buttonInactive.isVisible = false; buttonInactive.isHitTestable = true buttonActive.isVisible = false local screenMidpointX = \_W \* .5 local screenMidpointY = \_H \* .5 for i=2, propGift.numChildren do propGift[i].x = screenMidpointX; propGift[i].y = screenMidpointY end exitButton = display.newImageRect(propGift, "images/UI/Close\_White.png", 40, 40) exitButton.x = \_W - 50; exitButton.y = 50 + deviceInfo.verticalOffset exitButton\_Touch = display.newCircle(propGift, exitButton.x, exitButton.y, 45) exitButton\_Touch.isVisible = false; exitButton\_Touch.isHitTestable = true boxTop:scale(deviceInfo.reductionFactor, deviceInfo.reductionFactor) giftBox:scale(deviceInfo.reductionFactor, deviceInfo.reductionFactor) buttonInactive:scale(deviceInfo.reductionFactor, deviceInfo.reductionFactor) buttonActive:scale(deviceInfo.reductionFactor, deviceInfo.reductionFactor) group:insert(propGift) end

[/lua]

And here’s the “create” function of a working module:

[lua]function scene:create (e)

local group = self.view

blackBG = display.newRect(group, 512, 384, 1024, 768)

blackBG:setFillColor(0,0,0, overlayAlpha)

if (gameState.currRoom == “rooms.int_1902_cavern”) then

pageFileExt = “_B&W.png”

end

propUninvite = display.newGroup()

propUninvite.isFlipping = false

propUninvite.hasFlipped = false

propUninvite_Back = display.newImageRect(propUninvite, “images/overlays/uninvite/UnInvite_Back” … pageFileExt, 800, 600)

propUninvite_Front = display.newImageRect(propUninvite, “images/overlays/uninvite/UnInvite_Front” … pageFileExt, 800, 600)

exitButton = display.newImageRect(propUninvite, “images/UI/Close_White.png”, 40, 40)

exitButton.x = _W - 50; exitButton.y = 50 + deviceInfo.verticalOffset

exitButton_Touch = display.newCircle(propUninvite, exitButton.x, exitButton.y, 45)

exitButton_Touch.isVisible = false; exitButton_Touch.isHitTestable = true

propUninvite_Front.x = _W / 2; propUninvite_Front.y = _H / 2

propUninvite_Back.x = _W / 2; propUninvite_Back.y = _H / 2

propUninvite_Back.xScale = .1

propUninvite_Back.isVisible = false

group:insert(propUninvite)

end[/lua]

It seems like the scene isn’t created in time before the transition actually begins. Is this possible? Why would this be the case? And why would Composer/Graphics 2.0 have a harder time creating the scene than Storyboard/Graphics 1.0, which was fine with these modules?

Thanks!
 

  • David

One other note on this: if I put print statements in each of the main scene functions (create, show, hide) they all show up in the console after the entire process is complete. For example, I’ll get three print statements at once (one for create, two for show), and they will all appear after the scene has visually finished transitioning onscreen. Shouldn’t the ‘create’ print statement fire, then I should see the transition, followed by the two ‘show’ print statements?

I did a lot more testing, and have reduced the problem module to this simple piece of code:

[lua]-- Load composer and create the scene

local composer = require(“composer”)

local scene = composer.newScene()

– Local variables

local blackBG = nil

local boxTop = nil

function scene:create (e)

local group = self.view

blackBG = display.newRect(group, 512, 384, 1024, 768)

blackBG:setFillColor(0,0,0, overlayAlpha)

boxTop = display.newImageRect(group, “images/Default-Landscape.png”, 1024, 768)

boxTop.x = _W * .5; boxTop.y = _H * .5

end

function scene:show (e)

end

function scene:hide (e)

end

scene:addEventListener(“create”, scene)

scene:addEventListener(“show”, scene)

scene:addEventListener(“hide”, scene)

return scene[/lua]

Even with this simple scene, the transition fails to work properly. However, if I convert the PNG to a JPG file, it works much better. That may be the reason why the ‘good’ module in one of my earlier posts works: it uses JPG images, rather than PNGs.

What’s going on here??

  • David

Hi David,

It could be that you’re loading a very large image. What is the file size of the largest version of “Default-Landscape” you’re loading? What device are you testing on which shows this behavior?

Brent

Thanks for the reply, Brent! The 2x PNG version of Default-Landscape is 1.2 MB, and the problem is apparent on both an iPad Air and an iPhone 4S, both with iOS 8. I also tested on an iPad Mini with iOS 7, and it had the same effect. This was not a problem with the old Storyboard and Graphics 1.0 framework, so I’m not sure why it would be an issue now.

Right now the only workaround I can see is to increase the transition time, but I’d prefer a better solution.

Thanks again!
 

  • David

Hi David,

So what is the pixel dimensions on that largest version? 2048 x 1536? Or otherwise?

Sorry Brent, should have included that info.

Default-Landscape.png [1024x768, 384KB]

Default-Landscape@2x.png [2048x1536, 1.2MB]

The JPG versions are 344KB and 962KB, respectively

The images that worked well, above:

UnInvite_Front.jpg [800x600, 281KB]

UnInvite_Front@2x.jpg [1600x1200, 1.2MB]

UnInvite_Back.jpg [800x600, 313KB]

UnInvite_Back@2x.jpg [1600x1200, 1.3MB]

Let me know if you’d like any more info. Thanks!
 

  • David

Hi David,

I don’t know the internal technical explanation for this. It’s a large image, which might be hurting the overall performance. Is there any way you can pre-load this image into the cache and keep it hidden, so when the scene shows, it’s already in memory?

Brent

Hi Brent, I just tried pre-loading the scene with composer.loadScene(), and it had no effect. I don’t really understand why a large image would matter, as it shouldn’t start transitioning until create() was finished. If the image was taking a long time to load, I would expect a pause before the transition starts, not a truncation of the transition. Also puzzling is that this is fine in the simulator, but not on any of my iOS devices.

Thanks again,

  • David

First of all… your print statements… Corona SDK has buffering turned on for the output for performance reasons.  You might find adding:

io.output():setvbuf(‘no’)

to the top of your main.lua.

As for why PNG’s could be slower to load than JPEG’s, well it’s about file size.  A 300K JPEG will load faster than a 1.3MB PNG just due to the file size.  However if you are trying to call composer.loadScene() in advance, this is very likely not the issue.

Does this happen in the Simulator or just on Device?

Can you zip up a sample to look at?  It would need to be complete with build.settings, config.lua and any images that display the issuel

Rob

Hi Rob,

Thanks for weighing in! The issue only happens on device (tested on iPad Air, iPhone 4S, iPad Mini 1G). I tried including [lua]io.output():setvbuf(‘no’)[/lua], but the output in my console is the same: all three print statements appear simultaneously, after the overlay is done transitioning (in both Xcode and the Corona Simulator console).

As to filesize, I would agree, but then these images should be giving me trouble, even though they’re not (overlay code posted above):

UnInvite_Front.jpg [800x600, 281KB]

UnInvite_Front@2x.jpg [1600x1200, 1.2MB]

UnInvite_Back.jpg [800x600, 313KB]

UnInvite_Back@2x.jpg [1600x1200, 1.3MB]

 

Also, I still don’t understand why the transition would start before the scene is finished being created, no matter how long it takes to load.

 

I’ll zip something up and post it here soon. Thanks!

 

  • David

Hi Rob,

 
Here is a ZIP file containing a small project that demonstrates this issue. I tested it on both my iPad Air and iPhone 4S, and both exhibited the problem. The app will load, and after two seconds, display the overlay. None of the overlay’s functionality will work, but you will see that it ‘pops’ on, with no visible transition.
 
Thanks for checking into it!
 

  • David

Before I dig to far into this, you are generating an error when click on the gift box:

    /Users/rmiracle/Downloads/OverlayTest/props/gift.lua:170: attempt to index field ‘ext_party_tree’ (a nil value)
    stack traceback:
        /Users/rmiracle/Downloads/OverlayTest/props/gift.lua:170: in function </Users/rmiracle/Downloads/OverlayTest/props/gift.lua:168>
        (tail call): ?
        ?: in function <?:498>
        ?: in function <?:221>

Next, you are trying to call showOverlay()  but you don’t have a parent scene to overlay.  Your main.lua should be calling composer.gotoScene() to go to your first scene.  Once there you can have an overlay.

Rob

Hi Rob,

No worries on the error; the entire overlay will be functionally broken. I just wanted to give you the most ‘real-world’ example I could without sending the entire game. In the actual game, once the overlay is on screen, everything works perfectly. The problem lies solely with the transition.

As for calling showOverlay without a parent scene, that was done just to make the example simpler, and it seems to work regardless: the overlay shows properly in the simulator, and shows (but without a transition) on device. I can fashion an updated example with a parent scene if you need it, just let me know.

Thanks!
 

  • David

We can’t support 3rd party libraries which you appear to be using with the Luna library.  Please put together a demo that shows this issue without using Luna and I’ll take another look.   If you find that you can’t produce this issue without Luna, then you should contact it’s author to see if they can isolate the issue in their code.