Nodes.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import * as cc from "cc";
  2. class node_extends {
  3. constructor(node_: cc.Node) {
  4. this._node = node_;
  5. this._node.components.forEach((v) => {
  6. if (v instanceof cc.Label) {
  7. this.label = v;
  8. } else if (v instanceof cc.Sprite) {
  9. this.sprite = v;
  10. } else if (v instanceof cc.UIOpacity) {
  11. this.ui_opacity = v;
  12. } else if (v instanceof cc.UITransform) {
  13. this.ui_transform = v;
  14. } else if (v instanceof cc.Animation) {
  15. this.animation = v;
  16. } else if (v instanceof cc.EditBox) {
  17. this.edit_box = v;
  18. } else if (v instanceof cc.RichText) {
  19. this.rich_text = v;
  20. } else if (v instanceof cc.Layout) {
  21. this.layout = v;
  22. } else if (v instanceof cc.ProgressBar) {
  23. this.progress_bar = v;
  24. } else if (v instanceof cc.Slider) {
  25. this.slider = v;
  26. } else if (v instanceof cc.Toggle) {
  27. this.toggle = v;
  28. }
  29. });
  30. }
  31. /* --------------- static --------------- */
  32. /** 节点扩展数据 */
  33. static node_extends_map = new Map<cc.Node, node_extends>();
  34. /** 渲染顺序更新倒计时 */
  35. static order_update_timer: any = null;
  36. /** 渲染顺序更新时间 */
  37. private static _order_update_time_n = 0;
  38. /** 更新任务 */
  39. private static _order_update_task_fs: Function[] = [];
  40. /* --------------- public --------------- */
  41. label!: cc.Label;
  42. sprite!: cc.Sprite;
  43. ui_opacity!: cc.UIOpacity;
  44. ui_transform!: cc.UITransform;
  45. animation!: cc.Animation;
  46. edit_box!: cc.EditBox;
  47. rich_text!: cc.RichText;
  48. layout!: cc.Layout;
  49. progress_bar!: cc.ProgressBar;
  50. slider!: cc.Slider;
  51. toggle!: cc.Toggle;
  52. /** 节点渲染次序 */
  53. // eslint-disable-next-line @typescript-eslint/naming-convention
  54. get order_n(): number {
  55. return this._order_n;
  56. }
  57. set order_n(value_n_: number) {
  58. this._set_order_n(value_n_);
  59. }
  60. /** 宽 */
  61. get width(): number {
  62. return this.ui_transform.width;
  63. }
  64. set width(value_n_) {
  65. this.ui_transform.width = value_n_;
  66. }
  67. /** 高 */
  68. get height(): number {
  69. return this.ui_transform.height;
  70. }
  71. set height(value_n_) {
  72. this.ui_transform.height = value_n_;
  73. }
  74. /** 透明度 */
  75. get opacity(): number {
  76. return this.ui_opacity.opacity;
  77. }
  78. set opacity(value_n_) {
  79. this.ui_opacity.opacity = value_n_;
  80. }
  81. /** 锚点 */
  82. get anchor(): Readonly<cc.Vec2> {
  83. return this.ui_transform.anchorPoint;
  84. }
  85. set anchor(value_v2_: cc.Vec2) {
  86. this.ui_transform.anchorPoint = value_v2_;
  87. }
  88. /* --------------- private --------------- */
  89. /** 持有节点 */
  90. private _node: cc.Node;
  91. /** 节点渲染次序 */
  92. // eslint-disable-next-line @typescript-eslint/naming-convention
  93. private _order_n = 0;
  94. /* ------------------------------- 功能 ------------------------------- */
  95. /* ------------------------------- get/set ------------------------------- */
  96. private _set_order_n(value_n_: number): void {
  97. if (
  98. // 未改变渲染顺序
  99. this._order_n === value_n_ ||
  100. // 节点失效
  101. !this._node.isValid
  102. ) {
  103. return;
  104. }
  105. /** 父节点层级数据 */
  106. const parent = N(this._node.parent!);
  107. if (!parent) {
  108. this._node.once(
  109. cc.Node.EventType.PARENT_CHANGED,
  110. () => {
  111. // 延迟一帧避免 children 数据未更新
  112. setTimeout(() => {
  113. this._set_order_n(value_n_);
  114. }, 0);
  115. },
  116. this
  117. );
  118. return;
  119. }
  120. // 更新渲染顺序
  121. this._order_n = value_n_;
  122. /** 距离上次更新的时间 */
  123. const time_since_last_update_n = Date.now() - node_extends._order_update_time_n;
  124. // 添加任务
  125. node_extends._order_update_task_fs.push((): void => {
  126. // (节点/父节点)失效
  127. if (!this._node.isValid || !parent._node.isValid || this._node.parent !== parent._node) {
  128. return;
  129. }
  130. /** 同级节点 */
  131. const node_as = [...parent._node.children].sort((va, vb) => (N(va, false)?._order_n ?? 0) - (N(vb, false)?._order_n ?? 0));
  132. // 更新渲染顺序
  133. node_as.forEach((v, k_n) => {
  134. v.setSiblingIndex(k_n);
  135. });
  136. });
  137. // 已经准备更新
  138. if (node_extends.order_update_timer !== null) {
  139. return;
  140. }
  141. // 小于间隔时间更新
  142. if (node_extends.order_update_timer === null && time_since_last_update_n < cc.game.frameTime) {
  143. node_extends.order_update_timer = setTimeout(() => {
  144. // 清理定时器数据
  145. node_extends.order_update_timer = null;
  146. // 更新时间
  147. node_extends._order_update_time_n = Date.now();
  148. // 更新渲染顺序
  149. node_extends._order_update_task_fs.splice(0, node_extends._order_update_task_fs.length).forEach((v_f) => v_f());
  150. }, cc.game.frameTime - time_since_last_update_n);
  151. return;
  152. }
  153. // 延迟一帧避免同帧内使用 children 下标获取节点不正确
  154. setTimeout(() => {
  155. // 更新时间
  156. node_extends._order_update_time_n = Date.now();
  157. // 更新渲染顺序
  158. node_extends._order_update_task_fs.splice(0, node_extends._order_update_task_fs.length).forEach((v_f) => v_f());
  159. }, 0);
  160. }
  161. }
  162. // eslint-disable-next-line @typescript-eslint/naming-convention
  163. function N(node_: cc.Node, force_b_ = true): node_extends {
  164. if (!node_?.isValid) {
  165. return null!;
  166. }
  167. let node_extend = node_extends.node_extends_map.get(node_) ?? null;
  168. if (!node_extend && force_b_) {
  169. node_extend = new node_extends(node_);
  170. node_extends.node_extends_map.set(node_, node_extend);
  171. }
  172. return node_extend!;
  173. }
  174. namespace N {
  175. /** order 刷新间隔时间(毫秒) */
  176. export const order_refresh_interval_ms_n = cc.game.frameTime;
  177. /** 清理节点数据 */
  178. export function clear(): void {
  179. // 清理定时器
  180. if (node_extends.order_update_timer) {
  181. clearTimeout(node_extends.order_update_timer);
  182. node_extends.order_update_timer = null;
  183. }
  184. // 清理节点数据
  185. node_extends.node_extends_map.clear();
  186. }
  187. }
  188. // 切换场景后自动清理
  189. cc.director.on(cc.Director.EVENT_BEFORE_SCENE_LAUNCH, N.clear, this);
  190. export default N;