@curiousmedia/createjs-scene-container
Version:
A scene manager for CreateJS
356 lines (287 loc) • 7 kB
JavaScript
class Scene extends createjs.Container
{
constructor( name, options )
{
super();
// console.log( "Scene Created: ", name, options );
this.name = name;
this.options = options;
this.active = false;
}
static preload()
{
return Promise.resolve();
}
setup()
{
// console.log("Set up....", this.name);
return Promise.resolve();
}
reset()
{
// console.log("Resetting....", this.name);
return Promise.resolve();
}
start()
{
this.setActive( true );
return Promise.resolve();
}
end()
{
this.setActive( false );
return Promise.resolve();
}
setActive( active )
{
// console.log("Set Active", active);
this.active = active;
}
animateIn()
{
// console.log("Animating in....", this.name);
return Promise.resolve();
}
animateOut()
{
// console.log("Animating out....", this.name);
return Promise.resolve();
}
resize( width, height )
{
}
update()
{
}
destroy()
{
this.setActive( false );
}
}
const _scenes = {};
const _transitions = {};
let instance;
class SceneContainer extends createjs.Container
{
constructor()
{
super();
if ( instance ) throw new Error( "Only one instance of SceneContainer allowed" );
this.anchorX = 0.5;
this.anchorY = 0.5;
this._last = null;
this.lastID = "";
this.current = null;
this.currentID = "";
}
static get scenes()
{
return _scenes;
}
static get currentScene()
{
return SceneContainer.getCurrentScene();
}
static getInstance()
{
if ( !instance ) instance = new SceneContainer();
return instance;
}
static getCurrentScene()
{
return instance && instance.current;
}
static registerScene( sceneId, SceneClass )
{
// console.log( "Registering Scene: ", sceneId );
_scenes[sceneId] = { id: sceneId, sceneClass: SceneClass };
}
static registerTransition( transitionId, TransitionClass )
{
// console.log( "Registering Transition/Loader Scene: ", transitionId );
_transitions[transitionId] = { id: transitionId, instance: new TransitionClass( transitionId ) };
}
static registerDefaultTransition( TransitionClass )
{
this.registerTransition( "default", TransitionClass);
}
static getSceneDefinition( sceneId )
{
return _scenes[sceneId] || false;
}
static getTransitionDefinition( transitionId )
{
return _transitions[transitionId] || false;
}
static gotoScene( sceneId, options, transitionId, transitionOptions )
{
instance.gotoScene( sceneId, options, transitionId, transitionOptions );
}
gotoScene( sceneId, options, transitionId = "default", transitionOptions = {} )
{
const current = this.current;
const nextSceneDef = SceneContainer.getSceneDefinition( sceneId );
if ( !nextSceneDef )
{
throw new Error( "No Scene with id: " + sceneId );
}
_log(" ------ ");
_log("Starting Scene Change");
// Start promise chain
let promiseChain = Promise.resolve();
let transition;
// If there's a current scene
if ( current )
{
_log("Removing Current Scene");
promiseChain = promiseChain.then( () => current.end() ); // end it
promiseChain = promiseChain.then( () => current.animateOut() ); // animate out
// Transition
const transitionDef = SceneContainer.getTransitionDefinition( transitionId );
transition = transitionDef.instance;
if ( transition )
{
_log("Adding Transition");
promiseChain = promiseChain.then( () => this.addTransition( transition ) );
promiseChain = promiseChain.then( () => transition.setup( transitionOptions ) );
promiseChain = promiseChain.then( () => transition.animateIn() );
promiseChain = promiseChain.then( () => transition.loadAssets() );
}
}
_log("Next Scene: " + nextSceneDef.id);
// Start prepping next scene
const NextSceneClass = nextSceneDef.sceneClass;
_log("Loading Next Scene");
promiseChain = promiseChain.then( () => NextSceneClass.preload() );
_log("Creating Next Scene");
// Now make the next scene
let next;
promiseChain = promiseChain.then( () =>
{
next = new NextSceneClass( nextSceneDef.id, options );
return Promise.resolve();
} );
// swap scenes
promiseChain = promiseChain.then( () => this.swapScenes( current, next ) );
promiseChain = promiseChain.then( () => next.setup( options ) );
promiseChain = promiseChain.then( () => next.reset() );
if ( transition )
{
_log("Removing Transition");
promiseChain = promiseChain.then( () => transition.animateOut() );
promiseChain = promiseChain.then( () =>
{
this.removeChild( transition );
return Promise.resolve();
} );
}
promiseChain = promiseChain.then( () => next.animateIn() );
promiseChain.then( () => next.start() );
}
setScreenAnchors( anchorX = 0.5, anchorY = 0.5 )
{
this.anchorX = anchorX;
this.anchorY = anchorY;
}
swapScenes( current, next )
{
if ( current )
{
current.destroy();
this.removeChild( current );
}
this.addChildAt( next, 0 );
this.current = next;
const event = new Event( "change" );
event.current = this.current;
event.previous = current;
this.dispatchEvent( event );
return Promise.resolve();
}
addTransition( loaderOfTransition )
{
this.addChild( loaderOfTransition );
return Promise.resolve();
}
transitOut()
{
return this.transitionOverlay.transitOut();
}
transitIn()
{
return this.transitionOverlay.transitIn();
}
_tick( evt )
{
super._tick( evt );
const stage = this.stage;
if ( stage && this.parent === stage )
{
this.x = Math.floor( stage.canvas.width * this.anchorX );
this.y = Math.floor( stage.canvas.height * this.anchorY );
}
if ( this.current )
{
this.current.update( evt.delta / 1000 );
}
}
}
function _log( message )
{
const promise = new Promise( resolve =>
{
console.log(message);
resolve();
});
return promise;
}
class SceneTransition extends Scene
{
constructor( name, options )
{
super( name, options );
}
loadAssets()
{
return Promise.resolve();
}
}
class DefaultSceneTransition extends SceneTransition
{
constructor( name, options, color = "#000" )
{
super( name, options );
// TODO: Reference app settings
const width = 1664;
const height = 768;
this.regX = width / 2;
this.regY = height / 2;
this.overlay = new createjs.Shape();
this.overlay.graphics.f( color ).dr( 0, 0, width, height );
this.overlay.set( { alpha: 0, visible: false } );
this.addChild( this.overlay );
}
animateIn()
{
// console.log("Animating in....", this.name);
return new Promise( resolve =>
{
createjs.Tween.get( this.overlay )
.set( { visible: true } )
.to( { alpha: 1 }, 250, createjs.Ease.quadInOut )
.call( resolve );
} );
}
animateOut()
{
// console.log("Animating in....", this.name);
return new Promise( resolve =>
{
createjs.Tween.get( this.overlay )
.to( { alpha: 0 }, 250, createjs.Ease.quadInOut )
.set( { visible: false } )
.call( resolve );
} );
}
}
export { DefaultSceneTransition, Scene, SceneContainer, SceneTransition };