145 lines
4.2 KiB
JavaScript
145 lines
4.2 KiB
JavaScript
// @ts-check
|
|
|
|
/**
|
|
* Hold the stack of scenes (gdjs.RuntimeScene) being played.
|
|
*
|
|
* @memberof gdjs
|
|
* @param {gdjs.RuntimeGame} runtimeGame The runtime game that is using the scene stack
|
|
* @class SceneStack
|
|
*/
|
|
gdjs.SceneStack = function(runtimeGame) {
|
|
if (!runtimeGame) {
|
|
throw "SceneStack must be constructed with a gdjs.RuntimeGame."
|
|
}
|
|
|
|
this._runtimeGame = runtimeGame;
|
|
|
|
/** @type {gdjs.RuntimeScene[]} */
|
|
this._stack = [];
|
|
|
|
/** @type {boolean} */
|
|
this._wasFirstSceneLoaded = false;
|
|
};
|
|
|
|
/**
|
|
* Called by the RuntimeGame when the game resolution is changed.
|
|
* Useful to notify scene and layers that resolution is changed, as they
|
|
* might be caching it.
|
|
*/
|
|
gdjs.SceneStack.prototype.onGameResolutionResized = function() {
|
|
for(var i = 0;i < this._stack.length; ++i) {
|
|
this._stack[i].onGameResolutionResized();
|
|
}
|
|
};
|
|
|
|
gdjs.SceneStack.prototype.step = function(elapsedTime) {
|
|
if (this._stack.length === 0) return false;
|
|
|
|
var currentScene = this._stack[this._stack.length - 1];
|
|
if (currentScene.renderAndStep(elapsedTime)) {
|
|
var request = currentScene.getRequestedChange();
|
|
//Something special was requested by the current scene.
|
|
if (request === gdjs.RuntimeScene.STOP_GAME) {
|
|
this._runtimeGame.getRenderer().stopGame();
|
|
return true;
|
|
} else if (request === gdjs.RuntimeScene.POP_SCENE) {
|
|
this.pop();
|
|
} else if (request === gdjs.RuntimeScene.PUSH_SCENE) {
|
|
this.push(currentScene.getRequestedScene());
|
|
} else if (request === gdjs.RuntimeScene.REPLACE_SCENE) {
|
|
this.replace(currentScene.getRequestedScene());
|
|
} else if (request === gdjs.RuntimeScene.CLEAR_SCENES) {
|
|
this.replace(currentScene.getRequestedScene(), true);
|
|
} else {
|
|
console.error("Unrecognized change in scene stack.");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
gdjs.SceneStack.prototype.renderWithoutStep = function() {
|
|
if (this._stack.length === 0) return false;
|
|
|
|
var currentScene = this._stack[this._stack.length - 1];
|
|
currentScene.render();
|
|
|
|
return true;
|
|
};
|
|
|
|
gdjs.SceneStack.prototype.pop = function() {
|
|
if (this._stack.length <= 1) return null;
|
|
|
|
// Unload the current scene
|
|
var scene = this._stack.pop();
|
|
if (!scene) return null;
|
|
|
|
scene.unloadScene();
|
|
|
|
// Tell the new current scene it's being resumed
|
|
var currentScene = this._stack[this._stack.length - 1];
|
|
if (currentScene) {
|
|
currentScene.onResume();
|
|
}
|
|
|
|
return scene;
|
|
};
|
|
|
|
gdjs.SceneStack.prototype.push = function(newSceneName, externalLayoutName) {
|
|
// Tell the scene it's being paused
|
|
var currentScene = this._stack[this._stack.length - 1];
|
|
if (currentScene) {
|
|
currentScene.onPause();
|
|
}
|
|
|
|
// Load the new one
|
|
var newScene = new gdjs.RuntimeScene(this._runtimeGame);
|
|
newScene.loadFromScene(this._runtimeGame.getSceneData(newSceneName));
|
|
this._wasFirstSceneLoaded = true;
|
|
|
|
//Optionally create the objects from an external layout.
|
|
if (externalLayoutName) {
|
|
var externalLayoutData = this._runtimeGame.getExternalLayoutData(externalLayoutName);
|
|
if (externalLayoutData)
|
|
newScene.createObjectsFrom(externalLayoutData.instances, 0, 0);
|
|
}
|
|
|
|
this._stack.push(newScene);
|
|
return newScene;
|
|
};
|
|
|
|
gdjs.SceneStack.prototype.replace = function(newSceneName, clear) {
|
|
if (!!clear) {
|
|
// Unload all the scenes
|
|
while (this._stack.length !== 0) {
|
|
var scene = this._stack.pop();
|
|
if (scene) scene.unloadScene();
|
|
}
|
|
} else {
|
|
// Unload the current scene
|
|
if (this._stack.length !== 0) {
|
|
var scene = this._stack.pop();
|
|
if (scene) scene.unloadScene();
|
|
}
|
|
}
|
|
|
|
return this.push(newSceneName);
|
|
};
|
|
|
|
/**
|
|
* Return the current gdjs.RuntimeScene being played, or null if none is run.
|
|
*/
|
|
gdjs.SceneStack.prototype.getCurrentScene = function() {
|
|
if (this._stack.length === 0) return null;
|
|
|
|
return this._stack[this._stack.length - 1];
|
|
};
|
|
|
|
/**
|
|
* Return true if a scene was loaded, false otherwise (i.e: game not yet started).
|
|
*/
|
|
gdjs.SceneStack.prototype.wasFirstSceneLoaded = function() {
|
|
return this._wasFirstSceneLoaded;
|
|
}
|