ui.origin.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { Button, Canvas, Component, EventHandler, EventTouch, Node, SpriteFrame, _decorator, warn } from "cc";
  2. // import GlobalDC from "../common/data.global.center";
  3. const { ccclass, property } = _decorator;
  4. @ccclass
  5. export class UI extends Component {
  6. /** 获取节点深度 */
  7. public static getDepth(node: Node) {
  8. let d: number;
  9. if (node.getComponent(Canvas)) d = 0;
  10. else d = this.getDepth(node.parent) + 1;
  11. return d;
  12. }
  13. /** 节点层级深度 */
  14. protected get depth() {
  15. return UI.getDepth(this.node);
  16. }
  17. /** 组件名称 */
  18. get comp_name() {
  19. let reg = new RegExp('(?<=<)(?<comp_name>[\\w, \\W]+)(?=>)', 'g');
  20. return reg.exec(this.name).groups.comp_name;
  21. }
  22. /** 给按钮绑定点击事件 */
  23. private __ButtonBindCall() {
  24. this.__handle = mtec.cc.creatEventHandle({
  25. target: this.node,
  26. component: this.comp_name,
  27. handler: '__ClickButton',
  28. });
  29. this.node.getComponentsInChildren(Button)
  30. .filter(btn => {
  31. let pass = false;
  32. // 如果btn的事件列表是空的,则直接无脑把自己的中继事件放进去
  33. if (btn.clickEvents.length === 0) pass = true;
  34. else {
  35. // 分别收集手动绑定事件和自动绑定事件
  36. let [hand_event, auto_event] = [[], []] as EventHandler[][];
  37. btn.clickEvents.forEach(hdl => {
  38. if (hdl.handler === '__ClickButton') auto_event.push(hdl);
  39. else hand_event.push(hdl);
  40. });
  41. // 如果脚本中初始化了按钮事件,并且按钮事件列表中没有其它初始化事件,则直接添加
  42. if (auto_event.length === 0 && this._click_event_[btn.node.name]) pass = true;
  43. // 如果存在其它初始化事件,则以组件的深度优先(即距离按钮最近的组件为准)覆盖,相同深度则以当前为准覆盖
  44. else if (auto_event.length > 0) {
  45. let power = this.depth;
  46. if (this._click_event_[btn.node.name]) power += 10000;
  47. let el = auto_event.map(h => {
  48. let comp = h.target.getComponent(UI);
  49. let p = comp.depth;
  50. if (comp._click_event_[btn.node.name]) p += 10000;
  51. return { h, p };
  52. }).sort((a, b) => a.p - b.p).pop();
  53. if (el.p <= power) pass = true;
  54. else auto_event.splice(auto_event.indexOf(el.h), 1);
  55. auto_event.forEach(h => btn.clickEvents.splice(btn.clickEvents.indexOf(h), 1));
  56. }
  57. }
  58. return pass;
  59. }).forEach(btn => {
  60. btn.clickEvents.push(this.__handle);
  61. this.__btn_map__.set(btn.node.name, btn);
  62. });
  63. }
  64. /** 按钮点击事件中继 */
  65. protected __ClickButton(event: EventTouch) {
  66. let node = event.currentTarget as Node;
  67. let btn = node.getComponent(Button);
  68. let call = Reflect.get(this._click_event_, node.name);
  69. if (node.name in this._click_event_) {
  70. Reflect.apply(call, this, [btn]);
  71. // 发送点击事件,只对初始化的按钮发送事件
  72. // GlobalDC.Trigger.CLICK = {
  73. // component: this.comp_name,
  74. // button: node.name
  75. // };
  76. } else this.ClickBtn(btn);
  77. }
  78. /** 没有被初始化的按钮 */
  79. protected ClickBtn(btn: Button) {
  80. btn.interactable
  81. warn(`<${this.comp_name}> 按钮[${btn.node.name}]未被初始化`);
  82. }
  83. /** ui交互控制 */
  84. protected interactable(able: boolean) {
  85. this.__btn_map__.forEach(btn => btn.interactable = able);
  86. }
  87. /** 初始化组件基本逻辑 */
  88. private __init() {
  89. if (!this._click_event_.__common) this._click_event_.__common = (() => { }).bind(this);
  90. this.__ButtonBindCall();
  91. if (this.sframe.length > 0) {
  92. this.sframe.forEach(frame => this.smap.set(frame.name, frame));
  93. this.sframe = undefined;
  94. }
  95. if (this.initAfterOnLoad) this.initAfterOnLoad();
  96. }
  97. /** 组件事件对象 */
  98. protected _click_event_: { [name: string]: (this: UI, button: Button) => void } = {};
  99. /** 组件上的按钮通用回调 */
  100. protected __handle: EventHandler = null;
  101. protected __btn_map__: Map<string, Button> = new Map();
  102. /** ui常用贴图映射 */
  103. protected smap: Map<string, SpriteFrame> = new Map();
  104. /** 在加载后的一些自定义初始化 */
  105. protected initAfterOnLoad(): void {
  106. };
  107. @property([SpriteFrame])
  108. /** ui常用贴图 */
  109. private sframe: SpriteFrame[] = [];
  110. protected onLoad() {
  111. this.__init();
  112. }
  113. }