Creating Composer scenes programmatically.

It would be nice to do this :slight_smile: AFAICS the only way you can create a named scene is through gotoScene() which involves a separate code file for every scene.

So you could write something like this (would not be disposable I suppose !) :-

local scene = composer.newScene() -- attach various bits and bobs to it composer.addScene("demoscene",scene) -- then, later composer.gotoScene("demoscene")

or even if you could just provide a factory routine, something like :-

composer.gotoScene("scenename",function(composerInstance)     -- code to programatically create scene  end)

so the code would do the same as the code in the scene file does.

Have you considered a DIY on the legacy storyboard?: https://github.com/coronalabs/framework-storyboard-legacy

Seems a shame not to use the new system, especially if it Storyboard is going to be removed. I don’t think this change would be difficult ; at the moment gotoScene() et al. access their scenes through the require mechanism, it is only an issue of providing an alternate.

storyboard vs composer - your choice. but this doesn’t sound like the type of feature they’d ever add.

fwiw, if you really think about it, you don’t REALLY need more than two scenes (or maybe three, if you want one dedicated as an overlay). then just ping-pong between them.

in that scenario, your “factory” wouldn’t be creating entire scenes, rather it’d be creating CONTENT for the two “template” ping-pong scenes. your scenes then are just “wrappers” for composer’s/storyboard’s use.

pseudo-code OTTOMH example:

-- load/precreate two empty "template" scenes: local composer = require("composer") composer.loadScene("ping") local ping = composer.getScene("ping") composer.loadScene("pong") local pong = composer.getScene("pong") -- contentFactory:createContentForScene(ping,"someModuleThatResemblesASceneButIsnt") composer:gotoScene("ping") -- inside your template scenes you'd do something like this: local scene = composer.newScene() scene.content = nil -- to be populated by content factory function scene:show(event) -- and similarly for others.. if (self.content) then self.content:show(event) end end

We want this as well. If you want to use the Composer for business apps you are going to end up with the same scene (file) used to populate different things.

Consider for example a blog app. You may have a “posts-list.lua” and a “single-post.lua”. If you want to move directly from a single-post to another single-post, you need to duplicate your single-post.lua. Not cool. Not DRY.

The implementation should be quite easy anyway. If you pass a string to the composer.gotoScene() function, it does a require. If you pass it a table, it uses that table instead. Something as simple as this:

[lua]

function composer:gotoScene( scene, options )

local scene_table

if type(scene) == “string” then

scene_table = require( scene )

elseif type(scene) == “table” then

scene_table = scene

end

…

end

[/lua]

 

Of course you need to check if you have previously loaded the same table before (so you don’t call create, etc) but I bet the composer is already doing that in some way.

Then you can do a composer.newScene() outside a .lua file, organise the code to be reusable and don’t repeat yourself.

Today I have read this on the Daily Builds:

  • Composer: Fixing a error when defining multiple scenes inside the same lua file. Casenum #32231, #32168

I wonder if there is already a way to do this.

Could somebody from Corona explain it? I couldn’t find any more information about it.

Composer can create multiple scenes in one file.

local composer = require "composer" local scene1 = composer.newScene( "scene1" ) local scene2 = composer.newScene( "scene2" ) function scene1:create( event ) --do stuff end scene1:addEventListener( "create", scene1 ) function scene2:create( event ) -- do stuff end scene2:addEventListener( "create", scene2 ) composer.gotoScene( "scene1" )

Does this help?

Thanks,

alex

Thanks for that - missed that optional parameter. Will make my OOP Wrapper somewhat more coherent I think :slight_smile:

http://docs.coronalabs.com/api/library/composer/newScene.html has this useful API feature missing, which is why I missed it. Presumably if you create it programmatically you cannot have the scene recycling on, as when it recycles it the next gotoScene() will try to load it in as code.

Yes, @alexf, many thanks. As @paulscottrobson said, it would be great to add that to the documentation.

Have you considered a DIY on the legacy storyboard?: https://github.com/coronalabs/framework-storyboard-legacy

Seems a shame not to use the new system, especially if it Storyboard is going to be removed. I don’t think this change would be difficult ; at the moment gotoScene() et al. access their scenes through the require mechanism, it is only an issue of providing an alternate.

storyboard vs composer - your choice. but this doesn’t sound like the type of feature they’d ever add.

fwiw, if you really think about it, you don’t REALLY need more than two scenes (or maybe three, if you want one dedicated as an overlay). then just ping-pong between them.

in that scenario, your “factory” wouldn’t be creating entire scenes, rather it’d be creating CONTENT for the two “template” ping-pong scenes. your scenes then are just “wrappers” for composer’s/storyboard’s use.

pseudo-code OTTOMH example:

-- load/precreate two empty "template" scenes: local composer = require("composer") composer.loadScene("ping") local ping = composer.getScene("ping") composer.loadScene("pong") local pong = composer.getScene("pong") -- contentFactory:createContentForScene(ping,"someModuleThatResemblesASceneButIsnt") composer:gotoScene("ping") -- inside your template scenes you'd do something like this: local scene = composer.newScene() scene.content = nil -- to be populated by content factory function scene:show(event) -- and similarly for others.. if (self.content) then self.content:show(event) end end

We want this as well. If you want to use the Composer for business apps you are going to end up with the same scene (file) used to populate different things.

Consider for example a blog app. You may have a “posts-list.lua” and a “single-post.lua”. If you want to move directly from a single-post to another single-post, you need to duplicate your single-post.lua. Not cool. Not DRY.

The implementation should be quite easy anyway. If you pass a string to the composer.gotoScene() function, it does a require. If you pass it a table, it uses that table instead. Something as simple as this:

[lua]

function composer:gotoScene( scene, options )

local scene_table

if type(scene) == “string” then

scene_table = require( scene )

elseif type(scene) == “table” then

scene_table = scene

end

…

end

[/lua]

 

Of course you need to check if you have previously loaded the same table before (so you don’t call create, etc) but I bet the composer is already doing that in some way.

Then you can do a composer.newScene() outside a .lua file, organise the code to be reusable and don’t repeat yourself.

Today I have read this on the Daily Builds:

  • Composer: Fixing a error when defining multiple scenes inside the same lua file. Casenum #32231, #32168

I wonder if there is already a way to do this.

Could somebody from Corona explain it? I couldn’t find any more information about it.

Composer can create multiple scenes in one file.

local composer = require "composer" local scene1 = composer.newScene( "scene1" ) local scene2 = composer.newScene( "scene2" ) function scene1:create( event ) --do stuff end scene1:addEventListener( "create", scene1 ) function scene2:create( event ) -- do stuff end scene2:addEventListener( "create", scene2 ) composer.gotoScene( "scene1" )

Does this help?

Thanks,

alex

Thanks for that - missed that optional parameter. Will make my OOP Wrapper somewhat more coherent I think :slight_smile:

http://docs.coronalabs.com/api/library/composer/newScene.html has this useful API feature missing, which is why I missed it. Presumably if you create it programmatically you cannot have the scene recycling on, as when it recycles it the next gotoScene() will try to load it in as code.

Hi guys, please help to find solutions how to create and load dynamically scenes. So, for example. we have only one template .lua file with general scene code. And need to create 3 scenes with different names but same structure from template .lua file

Well, you can use alexf’s idea and pre-create it. Or my OOP Composer, which would allow you to declare it as an class and create instances for the various scenes. My Bitmap Font demo app does something like this, creating different scenes using the same basic template with small differences.

If this is a level scene you could have it data driven, so everything uses the same scene, but the things that go in the scene are (say) pulled from an XML file.

Paul, thank you for answer. Where I can find your OOP Composer to check out?

It’s at https://github.com/autismuk/Scene-Manager - there’s a simple demo showing a couple of scenes and an overlay. The Font Demo program at https://github.com/autismuk/Font-Demo does something similar to what you want to do and uses it.

It has one main scene (the menu) and six sub scenes, which are very similar but slightly different (the font effect changes) and it creates a scene class which can be modified via the constructor, and it then creates six instances of the scene to add to the composer equivalent.

It’s a bit beta but I think it works :slight_smile: