WindowSystem.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import { _decorator, Component, Constructor, find, Node, Prefab, instantiate, EventHandler } from "cc";
  2. import { ResourcesUtils } from "../../resourceManager/ResourcesUtils";
  3. import { Log } from "../../utils/Log";
  4. import { Utils } from "../../utils/Utils";
  5. import { Tips } from "./Tips";
  6. import { Window } from "./Window";
  7. import { WindowOpenMode } from "./WindowOpenMode";
  8. const { ccclass, property } = _decorator;
  9. /**
  10. * 窗口系统,负责管理窗口,底层运行时自动创建,无需在编辑器中绑定
  11. * @author 袁浩
  12. */
  13. @ccclass('WindowSystem')
  14. export class WindowSystem extends Component {
  15. public createBySystem: boolean = false;
  16. public windowList: Window[] = [];
  17. start() {
  18. if (!this.createBySystem) {
  19. Log.warn("WindowSystem组件由底层创建,无需编辑器创建");
  20. }
  21. }
  22. public onWindowOpen(_window: Window) {
  23. this.windowList.push(_window);
  24. }
  25. public onWindowClose(_window: Window) {
  26. Utils.removeArrayItem(this.windowList, _window);
  27. }
  28. /**
  29. * 最近打开的窗口
  30. */
  31. public get currentWindow(): Window {
  32. return this.windowList[this.windowList.length - 1];
  33. }
  34. public destroyWindow(_window: Window) {
  35. _window.openWindowOnClosing && _window.openWindowOnClosing.emit([_window]);
  36. if (_window.onClosing) {
  37. _window.onClosing.emit([() => {
  38. _window.node.destroy();
  39. Utils.removeArrayItem(this.windowList, _window);
  40. }]);
  41. }
  42. else {
  43. _window.node.destroy();
  44. Utils.removeArrayItem(this.windowList, _window);
  45. }
  46. }
  47. private isLoadding: boolean = false;
  48. /**
  49. * 打开窗口
  50. * @param prefabPath 预制体路径
  51. * @param openMode 窗口打开模式
  52. * @param params 给窗口传递的参数
  53. * @returns
  54. */
  55. public async open(prefabPath: string, openMode: WindowOpenMode, params: any[], onOpening: EventHandler = null, onClosing: EventHandler = null) {
  56. var _window: Window;
  57. switch (openMode) {
  58. case WindowOpenMode.NotCloseAndAdd:
  59. _window = await this.doOpen(prefabPath, params, onOpening, onClosing);
  60. break;
  61. case WindowOpenMode.NotCloseAndCover:
  62. if (this.currentWindow && prefabPath == this.currentWindow.prefabPath) {
  63. this.currentWindow.setParams(params);
  64. _window = this.currentWindow;
  65. }
  66. else {
  67. _window = await this.doOpen(prefabPath, params, onOpening, onClosing);
  68. }
  69. break;
  70. case WindowOpenMode.CloseAndAdd:
  71. this.close();
  72. _window = await this.doOpen(prefabPath, params, onOpening, onClosing);
  73. break;
  74. case WindowOpenMode.CloseAndCover:
  75. if (this.currentWindow && prefabPath == this.currentWindow.prefabPath) {
  76. this.currentWindow.setParams(params);
  77. _window = this.currentWindow;
  78. }
  79. else {
  80. this.close();
  81. _window = await this.doOpen(prefabPath, params, onOpening, onClosing);
  82. }
  83. break;
  84. default:
  85. break;
  86. }
  87. return _window;
  88. }
  89. private async doOpen(prefabPath: string, params: any[], onOpening: EventHandler = null, onClosing: EventHandler = null) {
  90. if (this.isLoadding) {
  91. return null;
  92. }
  93. this.isLoadding = true;
  94. var prefab = await ResourcesUtils.load<Prefab>(prefabPath, null, this.node);
  95. var windowNode = instantiate(prefab);
  96. var _window = windowNode.getComponent(Window) || windowNode.addComponent(Window);
  97. _window.node.parent = find("Canvas");
  98. _window.setParams(params);
  99. _window.prefabPath = prefabPath;
  100. onClosing && (_window.openWindowOnClosing = onClosing);
  101. onOpening && onOpening.emit([_window]);
  102. this.isLoadding = false;
  103. return _window;
  104. }
  105. public async showTips(message: string, prefabPath: string = "Prefabs/Tips") {
  106. var _window = await this.open(prefabPath, WindowOpenMode.NotCloseAndAdd, [message]);
  107. if (_window) {
  108. _window.getComponent(Tips) || _window.addComponent(Tips);
  109. }
  110. }
  111. /**
  112. * 关闭窗口
  113. * @param type 指定窗口类型,如果不传则关闭最近打开的窗口
  114. */
  115. public close(type: ui_window | Window | Node = null): void {
  116. if (!this.currentWindow) {
  117. return;
  118. }
  119. if (type) {
  120. var windowList = this.windowList.concat();
  121. for (let i = 0; i < windowList.length; i++) {
  122. const _window = windowList[i];
  123. if (type instanceof Window) {
  124. if (type == _window) {
  125. this.destroyWindow(_window);
  126. }
  127. }
  128. else if (type instanceof Node) {
  129. if (type == _window.node) {
  130. this.destroyWindow(_window);
  131. }
  132. }
  133. else if (_window instanceof type) {
  134. this.destroyWindow(_window);
  135. }
  136. }
  137. }
  138. else {
  139. var _window = this.windowList[this.windowList.length - 1];
  140. this.destroyWindow(_window);
  141. }
  142. }
  143. /**
  144. * 关闭指定路径的窗口
  145. * @param path 路径,例:Canvas/XXWindow
  146. */
  147. public closeByPath(path: string): void {
  148. if (!this.currentWindow) {
  149. return;
  150. }
  151. var _windowNode = find(path);
  152. _windowNode && this.destroyWindow(_windowNode.getComponent(Window));
  153. }
  154. /**
  155. * 关闭所有窗口
  156. */
  157. public closeAll() {
  158. while (this.windowList.length) {
  159. var _window = this.windowList.shift();
  160. this.destroyWindow(_window);
  161. }
  162. }
  163. }
  164. export type ui_window<T = Window> = Constructor<T>;