ViewManager.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. import { BaseView } from "../base/BaseView";
  2. import BaseMediator from "../base/BaseMediator";
  3. import BaseScene from "../base/BaseScene";
  4. import { OPEN_VIEW_OPTION } from "../Constants";
  5. import Canvas = cc.Canvas;
  6. import FrameworkCfg from "../FrameworkCfg";
  7. /**
  8. * mvc框架控制类
  9. * @author ituuz
  10. * @description 负责控制和维护框架各个节点和结构间的跳转和关联。
  11. */
  12. export class ViewManager {
  13. // 实例
  14. private static _instance: ViewManager = new ViewManager();
  15. /** 上一场景类 */
  16. private _preSceneMediatorCls: { new(): BaseMediator } = null;
  17. private _preSceneViewCls: { new(): BaseScene } = null;
  18. /** 当前场景类 */
  19. private _curSceneMediatorCls: { new(): BaseMediator } = null;
  20. private _curSceneViewCls: { new(): BaseScene } = null;
  21. /** 当前场景 */
  22. private _curScene: BaseMediator;
  23. /** 当前显示的pop view列表 */
  24. private _popViewList: BaseMediator[];
  25. /** 当前显示的layer view列表 */
  26. private _layerViewList: BaseMediator[];
  27. /***是否有黑色背景 */
  28. private _hasblackBg: boolean = false
  29. /**
  30. * @constructor
  31. * @private
  32. */
  33. private constructor() {
  34. this._popViewList = [];
  35. this._layerViewList = [];
  36. }
  37. /**
  38. * 单例获取类
  39. */
  40. public static getInstance(): ViewManager {
  41. return this._instance;
  42. }
  43. /**
  44. * 运行场景
  45. * @param {{new(): BaseMediator}} mediator 场景mediator类型,类类型。
  46. * @param {{new(): BaseScene}} view 场景mediator类型,类类型。
  47. * @param {Object} data 自定义的任意类型透传数据。(可选)
  48. * @param {()=>void} cb 加载完成回调.
  49. * @private
  50. */
  51. public __runScene__(mediator: { new(): BaseMediator }, view: { new(): BaseScene }, data?: any, cb?: () => void): void {
  52. // 创建并绑定场景
  53. let sceneMediator: BaseMediator = new mediator();
  54. sceneMediator["__init__"]();
  55. sceneMediator.init(data);
  56. // 如果前一场景不为空则进行清理
  57. if (this._curScene) {
  58. this._curScene.destroy();
  59. }
  60. // 保存当前场景
  61. this._curScene = sceneMediator;
  62. if (this._curSceneMediatorCls != null && this._curSceneViewCls != null) {
  63. this._preSceneMediatorCls = this._curSceneMediatorCls;
  64. this._preSceneViewCls = this._curSceneViewCls;
  65. }
  66. this._curSceneMediatorCls = mediator;
  67. this._curSceneViewCls = view;
  68. // 处理场景显示逻辑
  69. let scenePath: string = (<any>(view)).path();
  70. if (scenePath === "") {
  71. let ccs = new cc.Scene();
  72. ccs.name = "Scene";
  73. let canvasNode = new cc.Node();
  74. canvasNode.name = "Canvas";
  75. let canvas = canvasNode.addComponent(cc.Canvas);
  76. canvas.designResolution = FrameworkCfg.DESIGN_RESOLUTION;
  77. canvas.fitHeight = FrameworkCfg.FIT_HEIGHT;
  78. canvas.fitWidth = FrameworkCfg.FIT_WIDTH;
  79. sceneMediator.view = canvasNode.addComponent(view);
  80. sceneMediator.view.__init__();
  81. ccs.addChild(canvasNode);
  82. // 这里延迟1ms是为了让场景在下一帧加载
  83. setTimeout(() => {
  84. this.__closeAllView__();
  85. cc.director.runSceneImmediate(ccs);
  86. sceneMediator.viewDidAppear();
  87. cb && cb();
  88. }, 1);
  89. } else {
  90. cc.director.loadScene(scenePath, () => {
  91. this.__closeAllView__();
  92. let canvas = cc.director.getScene().getChildByName('Canvas');
  93. if (canvas) {
  94. sceneMediator.view = canvas.addComponent(view);
  95. sceneMediator.view.__init__();
  96. sceneMediator.viewDidAppear();
  97. cb && cb();
  98. } else {
  99. console.log("场景中必须包含默认的Canvas节点!");
  100. }
  101. });
  102. }
  103. }
  104. /**
  105. * 返回上一场景
  106. * @returns {boolean}是否存在上一个场景
  107. */
  108. public __backScene__(): boolean {
  109. if (this._preSceneMediatorCls && this._preSceneViewCls) {
  110. this.__runScene__(this._preSceneMediatorCls, this._preSceneViewCls);
  111. return true;
  112. }
  113. return false;
  114. }
  115. /**
  116. * 打开view界面
  117. * @param {{new(): BaseMediator}} mediator 界面mediator类型,类类型。
  118. * @param {{new(): BaseView}} view view 场景mediator类型,类类型。
  119. * @param {boolean} hasShowBlackBg 是否有黑色背景图
  120. * @param {Object} data 自定义的任意类型透传数据。(可选)
  121. * @param {OPEN_VIEW_OPTION} option 打开ui的操作选项,枚举类型。
  122. * @param {number} zOrder 层级。
  123. * @param {()=>void} cb 加载完成回调.
  124. */
  125. public __showView__(mediator: { new(): BaseMediator }, view: { new(): BaseView },
  126. data?: any, option?: OPEN_VIEW_OPTION, zOrder?: number, cb?: () => void, hasShowBlackBg: boolean = false): void {
  127. // 处理打开UI的其他操作
  128. this.openViewOptionHandler(option);
  129. // 创建并绑定view
  130. let viewMediator: BaseMediator = new mediator();
  131. viewMediator["__init__"]();
  132. //设置是否有黑色背景
  133. this._hasblackBg = hasShowBlackBg;
  134. // 处理场景显示逻辑
  135. let viewPath: string = (<any>(view)).path();
  136. let viewPathList = viewPath.split('/');
  137. let bundle : string = viewPathList[0];
  138. viewPath = "";
  139. for(let i = 1;i<viewPathList.length;i++){
  140. if(i<viewPathList.length-1){
  141. viewPath+=viewPathList[i]+"/";
  142. }else{
  143. viewPath+=viewPathList[i];
  144. }
  145. }
  146. // console.log("bundle: ",bundle," viewPath: ",viewPath);
  147. if (viewPath === "") {
  148. let viewNode = new cc.Node();
  149. this.initViewMediator(viewMediator, viewNode, view, option);
  150. viewMediator.init(data);
  151. viewMediator.viewDidAppear();
  152. cb && cb();
  153. } else {
  154. if(bundle===""||bundle===null){
  155. cc.loader.loadRes(viewPath, cc.Prefab, (err, prefab) => {
  156. if (err) {
  157. console.error(err);
  158. return;
  159. }
  160. let viewNode = cc.instantiate(prefab);
  161. this.initViewMediator(viewMediator, viewNode, view, option);
  162. viewMediator.init(data);
  163. viewMediator.viewDidAppear();
  164. cb && cb();
  165. });
  166. }else{
  167. cc.assetManager.loadBundle(bundle,(err,bundle)=>{
  168. bundle.load(viewPath, cc.Prefab, (err, prefab: cc.Prefab) => {
  169. if (err) {
  170. console.error(err);
  171. return;
  172. }
  173. let viewNode = cc.instantiate(prefab);
  174. this.initViewMediator(viewMediator, viewNode, view, option);
  175. viewMediator.init(data);
  176. viewMediator.viewDidAppear();
  177. cb && cb();
  178. });
  179. });
  180. }
  181. }
  182. }
  183. /**
  184. * 初始化ViewMediator
  185. * @param {BaseMediator} mediator ViewMediator
  186. * @param {cc.Node} viewNode view显示节点
  187. * @param {{new(): BaseView}} view view显示组件类
  188. * @param {OPEN_VIEW_OPTION} option 打开选项
  189. * @param {number} zOrder 层级排序
  190. */
  191. private initViewMediator(mediator: BaseMediator, viewNode: cc.Node, view: { new(): BaseView },
  192. option?: OPEN_VIEW_OPTION, zOrder?: number): void {
  193. viewNode.zIndex = zOrder;
  194. mediator.view = viewNode.addComponent(view);
  195. //出现黑色背景图
  196. this.blackBg(viewNode);
  197. mediator.view.__init__();
  198. // 根据不同打开类型,存储到不同队列中。
  199. if (option === OPEN_VIEW_OPTION.OVERLAY || option === OPEN_VIEW_OPTION.SINGLE) {
  200. this._popViewList.push(mediator);
  201. } else if (option === OPEN_VIEW_OPTION.LAYER) {
  202. this._layerViewList.push(mediator);
  203. }
  204. }
  205. /**
  206. *
  207. * 是否显示黑色背景
  208. */
  209. private blackBg(viewNode) {
  210. if (this._hasblackBg) {
  211. this._hasblackBg = false;
  212. var node = new cc.Node('myNode');
  213. node.name = "blackBg" + viewNode.name;
  214. const sprite = node.addComponent(cc.Sprite);
  215. node.addComponent(cc.BlockInputEvents);
  216. cc.loader.loadRes("blackBg", cc.SpriteFrame, (err, spriteFrame) => {
  217. if (err) {
  218. console.error(err);
  219. return;
  220. }
  221. sprite.spriteFrame = spriteFrame;
  222. cc.director.getScene().getChildByName('Canvas').addChild(node);
  223. node.width = FrameworkCfg.DESIGN_RESOLUTION.width;
  224. node.height = FrameworkCfg.DESIGN_RESOLUTION.height;
  225. node.x = 0;
  226. node.y = 0;
  227. cc.director.getScene().getChildByName('Canvas').addChild(viewNode);
  228. });
  229. } else {
  230. cc.director.getScene().getChildByName('Canvas').addChild(viewNode);
  231. }
  232. }
  233. /**
  234. * 关闭指定View
  235. * @param view
  236. * @private
  237. */
  238. public __closeView__(view: BaseView): void {
  239. for (let i = 0; i < this._popViewList.length; i++) {
  240. if (this._popViewList[i].view === view) {
  241. this._popViewList.splice(i, 1);
  242. return;
  243. }
  244. }
  245. for (let i = 0; i < this._layerViewList.length; i++) {
  246. if (this._layerViewList[i].view === view) {
  247. this._layerViewList.splice(i, 1);
  248. return;
  249. }
  250. }
  251. }
  252. /**
  253. * 关闭所有弹出窗口
  254. * @private
  255. */
  256. public __closeAllPopView__(): void {
  257. for (let i = 0; i < this._popViewList.length; i++) {
  258. this._popViewList[i].view["__onClose__"]();
  259. }
  260. this._popViewList = [];
  261. }
  262. /**
  263. * 关闭所有添加层级
  264. * @private
  265. */
  266. public __closeAllAddLayer__(): void {
  267. for (let i = 0; i < this._layerViewList.length; i++) {
  268. this._layerViewList[i].view["__onClose__"]();
  269. }
  270. this._layerViewList = [];
  271. }
  272. /**
  273. * 关闭所有view
  274. * @private
  275. */
  276. public __closeAllView__(): void {
  277. this.__closeAllPopView__();
  278. this.__closeAllAddLayer__();
  279. }
  280. /**
  281. * 根据参数处理ui的打开方式
  282. * @param option
  283. * @private
  284. */
  285. private openViewOptionHandler(option: OPEN_VIEW_OPTION): void {
  286. // 设置默认值
  287. if (!option) {
  288. option = OPEN_VIEW_OPTION.OVERLAY;
  289. }
  290. // 根据不同操作做不同处理
  291. if (option === OPEN_VIEW_OPTION.SINGLE) {
  292. // TODO:暂时不提供这种关闭其他view的打开方式,可以通过BaseView.closeAllPopView()来实现。
  293. }
  294. }
  295. /**************************** getter and setter ******************************/
  296. get popViewList(): BaseMediator[] {
  297. return this._popViewList;
  298. }
  299. get layerViewList(): BaseMediator[] {
  300. return this._layerViewList;
  301. }
  302. get curScene(): BaseMediator {
  303. return this._curScene;
  304. }
  305. public pushLayerList(mediator: BaseMediator) {
  306. this._layerViewList.push(mediator);
  307. }
  308. }