olympus-r
Version:
一个力求简单易用的前端开发框架 #### 开发语言 TypeScript #### 核心架构 MVC #### 模块间通讯和解耦 采用事件机制,利用一个全局唯一的事件派发器进行模块间通讯,解耦模块间依赖 #### 表现层结构 使用桥接模式拆分接口与实现,达到一套核心驱动多套表现层的目的(目前支持DOM、Egret、PixiJS三种表现层),同时支持表现层的未来可扩展性 #### TypeScript装饰器注入 框架提供TypeScript装饰器注入功能,便捷获取托管对象。例如:
249 lines (248 loc) • 9.66 kB
JavaScript
import * as tslib_1 from "tslib";
import { core } from "../../core/Core";
import { Injectable } from "../../core/injector/Injector";
import { notify, wait } from "../../utils/SyncUtil";
import { maskManager } from '../mask/MaskManager';
import none from "./NoneScenePolicy";
import SceneMessage from "./SceneMessage";
/**
* @author Raykid
* @email initial_r@qq.com
* @create date 2017-09-08
* @modify date 2017-09-08
*
* 弹窗管理器,包含切换场景、push场景、pop场景功能
*/
var SYNC_NAME = "SceneManager_sync";
var ChangeType;
(function (ChangeType) {
ChangeType[ChangeType["Switch"] = 0] = "Switch";
ChangeType[ChangeType["Push"] = 1] = "Push";
ChangeType[ChangeType["Pop"] = 2] = "Pop";
})(ChangeType || (ChangeType = {}));
var SceneManager = /** @class */ (function () {
function SceneManager() {
this._sceneStack = [];
}
Object.defineProperty(SceneManager.prototype, "currentScene", {
/**
* 获取当前场景
*
* @readonly
* @type {IScene}
* @memberof SceneManager
*/
get: function () {
return this._sceneStack[0];
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneManager.prototype, "activeCount", {
/**
* 获取活动场景个数
*
* @readonly
* @type {number}
* @memberof SceneManager
*/
get: function () {
return this._sceneStack.length;
},
enumerable: true,
configurable: true
});
/**
* 获取场景是否已经开启
*
* @param {IScene} scene 场景对象
* @returns {boolean} 是否已经开启
* @memberof SceneManager
*/
SceneManager.prototype.isOpened = function (scene) {
return (this._sceneStack.indexOf(scene) >= 0);
};
/**
* 切换场景,替换当前场景,当前场景会被销毁
*
* @param {IScene} scene 要切换到的场景
* @param {*} [data] 要携带给下一个场景的数据
* @returns {IScene} 场景本体
* @memberof SceneManager
*/
SceneManager.prototype.switch = function (scene, data) {
var _this = this;
// 非空判断
if (scene == null)
return;
// 如果切入的是第一个场景,则改用push操作
if (this.activeCount == 0)
return this.push(scene, data);
// 同步执行
wait(SYNC_NAME, this.doChange, this, this.currentScene, scene, data, this.getScenePolicy(scene), ChangeType.Switch, function () {
// 数据先行
_this._sceneStack[0] = scene;
// 派发消息
core.dispatch(SceneMessage.SCENE_STACK_CHANGE);
});
return scene;
};
/**
* 推入场景,当前场景不会销毁,而是进入场景栈保存,以后可以通过popScene重新展现
*
* @param {IScene} scene 要推入的场景
* @param {*} [data] 要携带给下一个场景的数据
* @returns {IScene} 场景本体
* @memberof SceneManager
*/
SceneManager.prototype.push = function (scene, data) {
var _this = this;
// 非空判断
if (scene == null)
return scene;
// 同步执行
wait(SYNC_NAME, this.doChange, this, this.currentScene, scene, data, this.getScenePolicy(scene), ChangeType.Push, function () {
// 数据先行
_this._sceneStack.unshift(scene);
// 派发消息
core.dispatch(SceneMessage.SCENE_STACK_CHANGE);
});
return scene;
};
/**
* 弹出场景,当前场景会被销毁,当前位于栈顶的场景会重新显示
*
* @param {IScene} scene 要切换出的场景,如果传入的场景不是当前场景则仅移除指定场景,不会进行切换操作
* @param {*} [data] 要携带给下一个场景的数据
* @returns {IScene} 场景本体
* @memberof SceneManager
*/
SceneManager.prototype.pop = function (scene, data) {
// 非空判断
if (scene == null)
return scene;
// 同步执行
wait(SYNC_NAME, this.doPop, this, scene, data);
return scene;
};
SceneManager.prototype.doPop = function (scene, data) {
var _this = this;
// 如果没有足够的场景储备则什么都不做
if (this.activeCount <= 1) {
console.log("场景栈中的场景数量不足,无法执行pop操作");
// 完成步骤
notify(SYNC_NAME);
return;
}
// 验证是否是当前场景,不是则直接移除,不使用Policy
var to = this._sceneStack[1];
var policy = this.getScenePolicy(scene);
if (this._sceneStack.indexOf(scene) != 0) {
to = null;
policy = none;
}
// 执行切换
this.doChange(scene, to, data, policy, ChangeType.Pop, function () {
// 数据先行
_this._sceneStack.splice(_this._sceneStack.indexOf(scene), 1);
// 派发消息
core.dispatch(SceneMessage.SCENE_STACK_CHANGE);
});
};
SceneManager.prototype.getScenePolicy = function (scene) {
return scene.policy || scene.bridge.defaultScenePolicy || none;
};
SceneManager.prototype.getPolicyFuncs = function (policy, type) {
var prepareFunc;
var doFunc;
switch (type) {
case ChangeType.Switch:
prepareFunc = policy.prepareSwitch;
doFunc = policy.switch;
break;
case ChangeType.Push:
prepareFunc = policy.preparePush || policy.prepareSwitch;
doFunc = policy.push || policy.switch;
break;
case ChangeType.Pop:
prepareFunc = policy.preparePop || policy.prepareSwitch;
doFunc = policy.pop || policy.switch;
break;
}
return [prepareFunc, doFunc];
};
SceneManager.prototype.doChange = function (from, to, data, policy, type, begin, complete) {
// 添加遮罩
maskManager.showMask(0);
// 调用回调
begin && begin();
// 前置处理
if (to) {
to.bridge.htmlWrapper.style.display = "";
from && from.onBeforeOut(to, data);
to.onBeforeIn(from, data);
// 派发事件
core.dispatch(SceneMessage.SCENE_BEFORE_CHANGE, to, from);
}
// 判断是否是两个不同类型场景切换
var changePromises = [];
if (from && to && to.bridge.type != from.bridge.type) {
// 是两个不同类型的场景切换,则应各个场景执行各个policy操作
if (from) {
// from处理,不传递to
var fromPolicy = this.getScenePolicy(from);
var _a = this.getPolicyFuncs(fromPolicy, type), fromPrepareFunc = _a[0], fromDoFunc = _a[1];
// 调用准备接口
fromPrepareFunc && fromPrepareFunc.call(fromPolicy, from, null);
// 调用切换接口
fromDoFunc && changePromises.push(fromDoFunc.call(fromPolicy, from, null).then(function () {
from.bridge.htmlWrapper.style.display = "none";
}));
}
if (to) {
// to处理,不传递from
var toPolicy = this.getScenePolicy(to);
var _b = this.getPolicyFuncs(toPolicy, type), toPrepareFunc = _b[0], toDoFunc = _b[1];
// 调用准备接口
toPrepareFunc && toPrepareFunc.call(toPolicy, null, to);
// 添加显示
to.bridge.addChild(to.bridge.sceneLayer, to.skin);
// 调用切换接口
toDoFunc && changePromises.push(toDoFunc.call(toPolicy, null, to));
}
}
else {
// 场景类型相同,常规处理
var _c = this.getPolicyFuncs(policy, type), prepareFunc = _c[0], doFunc = _c[1];
// 调用准备接口
prepareFunc && prepareFunc.call(policy, from, to);
// 添加显示
to && to.bridge.addChild(to.bridge.sceneLayer, to.skin);
// 调用切换接口
doFunc && changePromises.push(doFunc.call(policy, from, to));
}
// 等待所有切换动画结束后执行后续步骤
Promise.all(changePromises).then(function () {
// 完成步骤
notify(SYNC_NAME);
// 移除显示
to && from && from.bridge.removeChild(from.bridge.sceneLayer, from.skin);
// 后置处理
to && from && from.onAfterOut(to, data);
to && to.onAfterIn(from, data);
// 派发事件
to && core.dispatch(SceneMessage.SCENE_AFTER_CHANGE, to, from);
// 调用回调
complete && complete();
// 移除遮罩
maskManager.hideMask();
});
};
SceneManager = tslib_1.__decorate([
Injectable
], SceneManager);
return SceneManager;
}());
export default SceneManager;
/** 再额外导出一个单例 */
export var sceneManager = core.getInject(SceneManager);