Posted on by

One of the two most-requested items in regards to the Storyboard API was the ability to pass custom data between scenes as you switched between them, and also some kind of “pop up” feature, where a scene can be loaded and displayed above another scene, leaving the currently active scene intact.

The documentation for both is available now—parameter passing with storyboard.gotoScene() and scene overlays with storyboard.showOverlay()—but I’ll give you a quick overview right now to get you started.

Parameter Passing

I keep throwing around this term, so for those who don’t know, parameter passing allows you to easily “pass” custom data (such as a single variable or a table with as much data as you want) from one scene to the next when you initiate a transition.

In order to incorporate this, we had to make some changes to the storyboard.gotoScene() syntax (don’t worry, you can still use the old syntax, so none of your current projects will break). Here’s how you use the new syntax to take advantage of parameter passing:

local options =
{
effect = "fade",
time = 400,
params =
{
var1 = "custom data",
sample_var = 123,
}
}
storyboard.gotoScene( "game_scene", options )

The main difference is that now, the second argument in storyboard.gotoScene() is now an optional table with optional keys. The example above shows all the possible options (effect, time, and params). The new addition is the params option, which can be a variable, or a table with anything you want in it (as shown in the example).

If you do decide to pass over custom data, you can access that data from event.params within the “createScene”, “willEnterScene”, and “enterScene” event listeners for the scene that you’re going to (in the example, it would be game_scene).

Here’s a snippet that shows how you would access the custom data from within the “enterFrame” event listener of game_scene.lua:

function scene:enterScene( event )
   local params = event.params

   print( params.var1 ) -- "custom data"
   print( params.sample_var ) -- 123
end

Scene Overlays

A scene overlay is just that: a scene, that also serves as an “overlay” above the currently active scene—sort of like a scene transition (and even supports all current scene transition effects). But unlike a scene transition, the currently active scene stays in place. The only thing that happens to the currently active scene is that it dispatches two more events. One event is dispatched when the scene overlay is displayed, and the other when a scene overlay is hidden/removed.

storyboard.showOverlay()

View Documentation

This function is responsible for showing the overlay. The scene that you specify as the overlay should be structured just like any other scene—you can use any scene you want as an overlay—there is no difference, in fact. Once the overlay is displayed (or after the effect is finished, if specified), an “overlayBegan” event will be dispatched to the currently active non-overlay scene. When the overlay is removed, an “overlayEnded” will be dispatched (more on that in a moment).

So let’s say we called the following while we were in scene1.lua:

local options =
{
effect = "fade",
time = 400,
params = { sample_var=456 }
}
storyboard.showOverlay( "overlay_scene", options )

Somewhere else in the scene1.lua module, you can optionally add listeners for “overlayBegan” and “overlayEnded” events:

function scene:overlayBegan( event )
   print( "The overlay scene is showing: " .. event.sceneName )
   print( "We get custom params too! " .. event.params.sample_var )
end
scene:addEventListener( "overlayBegan" )

--

function scene:overlayEnded( event )
   print( "The following overlay scene was removed: " .. event.sceneName )
end
scene:addEventListener( "overlayEnded" )

There are two things that should stand out in the listeners above. First, is that just as with normal scene transitions, you can now pass parameters (e.g. custom data) to the overlay scene as well via the params option (it’s completely optional though). That custom data can be accessed from the event.params table in your listener function (as shown in the example).

The next not-so-obvious addition is the event.sceneName variable, which represents the name of the overlay scene. This variable is only available from within “overlayBegan” and “overlayEnded” events at the moment.

For more details on usage and syntax, take a moment to view the storyboard.showOverlay() documentation.

storyboard.hideOverlay()

View Documentation

This one’s pretty self-explanatory, but there’s some things you should know about it. This obviously hides the currently shown overlay, but it does a little more than that.

By default, the overlay scene will be completely removed (purged, and the module unloaded form memory—unless the scene was currently loaded as a normal scene prior to being used as an overlay). Optionally, you can have this function simply purge the overlay scene, which is useful if you plan on showing the overlay again in the near-future.

As with storyboard.showOverlay(), this function also supports scene transition effects—the same ones that are available for use with storyboard.gotoScene().

For more details on usage and syntax, take a moment to view the storyboard.hideOverlay() documentation.

Important Notes

There are a few things you should know about overlay scenes.

The first is that only ONE overlay scene can be shown at a time. If you call storyboard.gotoScene(), storyboard.removeAll(), storyboard.purgeAll(), or attempt to show a different overlay scene, the current overlay scene will be removed—it is completely dependent on the scene that was active when the overlay was originally shown.

Another important note is that you should be careful with how you call overlay scenes, and what you have them do. For example, if you have an overlay show after a time delay, you should probably make sure that scene transitions don’t occur before the delay duration has been reached (or just be sure to cancel the timer). You should also remove an overlay before attempting to change currently active scenes via display.gotoScene().


Posted by . Thanks for reading...

17 Responses to “Scene Overlays and Parameter Passing”

  1. Andy Hadlington

    Loving the overlays, was just about to code something similar myself so I’ll give it a try!

    Reply
  2. FreeDevz

    Hi, when I am trying to access params in the createScene.

    local params = event.params

    I keep getting “attempt to index field ‘params’ (a nil value)” error.
    I am using trial version, build 2011.704, is this only for latest build?

    Reply
  3. Taruga

    @FreeDevz

    “So for those waiting for those things to finally get here—your wait is over. As of daily build 2012.797, both of those are in place, in the form of “parameter passing” and “scene overlays” (build 2012.785 for parameter passing).”

    Reply
  4. David James

    Jonathan, what is the advantage of passing a variable through storyboard’s new params option versus just using a _G.variable or global variable?

    Reply
  5. Jonathan Beebe

    @David: The benefit is that the data you pass will be local in scope to the three different event listeners of the next scene, via event.params in “createScene”, “willEnterScene”, and “enterScene”.

    Reply
  6. Emanouel

    jonathan,

    i used the example code from here in my storyboard and got the following error

    Copyright (C) 2009-2012 A n s c a , I n c .
    Version: 2.0.0
    Build: 2012.797
    The file sandbox for this project is located at the following folder:
    (/Users/emanouel1979/Library/Application Support/Corona Simulator/Haunted House-9C5596D8D2694A3F5472DC3989A7B207)
    WARNING: Cannot transition to a scene that does not exist. If you called storyboard.removeScene() on a scene that is NOT represented by a module, the scene must be recreated before transitioning back to it.

    here’s my code

    -----------------------------------------------------------------------------------------
    -- main.lua
    -----------------------------------------------------------------------------------------
    display.setStatusBar( display.HiddenStatusBar )

    -- require controller module
    local storyboard = require "storyboard"
    --local health = require( "health" )

    -- comment out below four lines to remove FPS status
    --local fps = require("fps")
    --local performance = fps.PerformanceOutput.new();
    --performance.group.x, performance.group.y = 50, 0;
    --performance.alpha = 0.2; -- So it doesn't get in the way of the rest of the scene

    -- load first screen

    local options =
    {
    effect = "fade",
    time = 400,
    params =
    {
    var1 = "custom data",
    sample_var = 123,
    }
    }
    storyboard.gotoScene( "scene1", options )


    ---------------------------------------------------------------------------------
    -- scene1.lua Room 1
    ---------------------------------------------------------------------------------
    local storyboard = require( "storyboard" )
    local scene = storyboard.newScene()
    local lastScene = storyboard.getPrevious()
    --local health = require( "health" )
    ---------------------------------------------------------------------------------
    -- BEGINNING OF YOUR IMPLEMENTATION
    ---------------------------------------------------------------------------------
    local background, room2, blackKey, blackdoorlocked, text1

    -- Touch event listener for background image
    local function gotoRoom2( self, event )
    if event.phase == "began" then

    storyboard.gotoScene( "scene2", "fade", 400 )

    return true
    end
    end

    local function doorlocked( self, event )
    if event.phase == "began" then
    -- storyboard.gotoScene( "scene20", "fade", 400 )
    text1 = display.newText( "Door is Locked, the key should be near by", 0, 245, native.systemFontBold, 20 )
    text1:setTextColor( 255 )
    transition.to(text1, {time=1000, onComplete = function() display.remove(text1) end})
    return true

    elseif(event.phase == "moved") then
    -- Do Something During the "moved" phase
    transition.to(self, {x = event.x, y = event.y, time=0});
    end
    end

    local function onSceneTouchx( self, event )
    if event.phase == "began" then

    storyboard.gotoScene( "scene3", "fade", 400 )

    return true
    end
    end

    -- Called when the scene's view does not exist:
    function scene:createScene( event )
    local screenGroup = self.view

    background = display.newImage( "assets/graphics/Room1.png", 0, 0 )
    screenGroup:insert( background )

    blackdoorlocked = display.newImage( "assets/graphics/BlackLock2.png", 175, 0 )
    screenGroup:insert( blackdoorlocked )

    blackdoorlocked.touch = doorlocked

    room2 = display.newImage( "assets/graphics/gotoRoom2.png", 175, 0 )
    screenGroup:insert( room2 )

    room2.touch = gotoRoom2

    -- blackKey = display.newImage( "assets/graphics/BlackKey.png", 100, 200 )
    -- screenGroup:insert( blackKey )

    -- blackKey.touch = onSceneTouchx

    print( "n1: createScene event")
    end

    -- Called immediately after scene has moved onscreen:
    function scene:enterScene( event )

    local params = event.params

    print( params.var1 ) -- "custom data"
    print( params.sample_var ) -- 123
    end

    print( "1: enterScene event" )

    -- remove previous scene's view
    storyboard.purgeScene( lastScene )
    print( "last scene was:", lastScene ) -- output: last scene name

    -- Update Lua memory text display
    -- blackKey:addEventListener( "touch", blackKey )
    room2:addEventListener( "touch", room2 )
    blackdoorlocked:addEventListener( "touch", blackdoorlocked )

    end

    -- Called when scene is about to move offscreen:
    function scene:exitScene( event )

    print( "1: exitScene event" )

    -- remove touch listener for image
    -- blackKey:removeEventListener( "touch", blackKey )
    room2:removeEventListener( "touch", room2 )
    blackdoorlocked:removeEventListener( "touch", blackdoorlocked )
    end

    -- Called prior to the removal of scene's "view" (display group)
    function scene:destroyScene( event )

    print( "((destroying scene 1's view))" )
    end

    ---------------------------------------------------------------------------------
    -- END OF YOUR IMPLEMENTATION
    ---------------------------------------------------------------------------------

    -- "createScene" event is dispatched if scene's view does not exist
    scene:addEventListener( "createScene", scene )

    -- "enterScene" event is dispatched whenever scene transition has finished
    scene:addEventListener( "enterScene", scene )

    -- "exitScene" event is dispatched before next scene's transition begins
    scene:addEventListener( "exitScene", scene )

    -- "destroyScene" event is dispatched before view is unloaded, which can be
    -- automatically unloaded in low memory situations, or explicitly via a call to
    -- storyboard.purgeScene() or storyboard.removeScene().
    scene:addEventListener( "destroyScene", scene )

    ---------------------------------------------------------------------------------

    return scene

    im not sure what i did wrong, any advice ???

    Reply
  7. Emanouel

    jonathan,

    found the error, i had a extra end statement in the code.

    i now see in the terminal
    custom data
    123

    how would i implement a text health bar. that starts at 100.

    should i create the health bar via a external module or just load the code into main.lua and have it run from there ?

    Reply
  8. maxlight

    Does poping up a scene block the button listeners in scene that initiated the popup scene for example if I have some buttons in the background scene that I do not wish to accidentally press while popup scene is showing and I’m interacting with it. If this are still enabled, could you add an option to block them as long as popup is showing and user is interacting with it.

    It would save me from having to disable everything on background scene and enable it again, I currently have to do that, I’m not using a storyboard but just implemented my own popup and stuff that is behind it still registeres, I had to disable it and enable it afterwards.

    Reply
  9. Michael

    Hmmm after storyboard.hideOverlay() I see that the function scene:overlayEnded( event ) will execute and the overlay is hide, but the screen object are still visible. What Im doinng wrong. is there a download of a example for the right use of the storyboard.showOverlay()

    Reply
  10. Eli Marko

    When will all these important storyboard features be available to trial users?

    Reply
  11. dellos

    first . I use overlay scene like o popup. from current active scene i pass params to overlay scene to user. then how to get back user data from overlay scene ? because storyboard.hideOverlay() don’t pass any params to overlayEnded event.

    second . I call “storyboard.showOverlay()” in a module .
    call “storyboard.hideOverlay() ” in overlay scene.
    then call “storyboard.gotoScene(“prScene”)” in “overlayEnded” listener function of current active scene.

    But and error ?? it call may time before and runtime error ????

    any suggest??

    Reply

Leave a Reply

  • (Will Not Be Published)