DataSystem.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import { _decorator, Component, find, game } from "cc";
  2. import { Constructor } from "../core";
  3. import { Data } from "./Data";
  4. const { ccclass, property, executionOrder } = _decorator;
  5. /**
  6. * 数据系统组件,常驻节点,可创建数据、获取数据、观察数据变化
  7. * @description 创建数据:g.userData = DataSystem.createData<UserData>(UserData);update方法里:DataSystem.watch(g.userData,"money") && this.moneyLabel.string = g.userData.money;
  8. * @description Data的数组属性也可以watch到变化:g.userData.bagList.push("数据");DataSystem.watch(g.userData,"bagList")
  9. * @author 袁浩
  10. */
  11. @ccclass('DataSystem')
  12. @executionOrder(-1)
  13. export class DataSystem extends Component {
  14. private dataMap: Map<Constructor, Data | Map<PropertyKey, Data>> = new Map<Constructor, Data | Map<PropertyKey, Data>>();
  15. private watchData: Map<Data, Map<PropertyKey, number>> = new Map<Data, Map<PropertyKey, number>>();
  16. private watchedList: Array<{ data: Data, key: PropertyKey }> = [];
  17. private static thisObject: DataSystem;
  18. start() {
  19. game.addPersistRootNode(this.node);//常驻节点
  20. DataSystem.thisObject = this;
  21. }
  22. /**
  23. * 创建数据
  24. * @param classConstructor 数据对象类型
  25. * @returns
  26. */
  27. static createData<T extends Data>(classConstructor: Constructor<T>): T {
  28. this.deleteData(classConstructor);
  29. let data = new classConstructor();
  30. DataSystem.thisObject.dataMap.set(classConstructor, data);
  31. DataSystem.thisObject.watchData.set(data, new Map<string, number>());
  32. return data;
  33. }
  34. /**
  35. * 注册已经实例好的数据对象
  36. * @param data 数据对象
  37. * @param mainKey 主键
  38. */
  39. static regeditData(data: Data, mainKey?: PropertyKey): void {
  40. var constructor = data.constructor as Constructor;
  41. if (!mainKey) {
  42. DataSystem.thisObject.dataMap.set(constructor, data);
  43. }
  44. else {
  45. let oneDataMap: Map<PropertyKey, Data> = DataSystem.thisObject.dataMap.get(constructor) as Map<PropertyKey, Data>;
  46. if (!DataSystem.thisObject.dataMap.has(constructor)) {
  47. oneDataMap = new Map<PropertyKey, Data>();
  48. }
  49. oneDataMap.set(data[mainKey], data);
  50. DataSystem.thisObject.dataMap.set(constructor, oneDataMap);
  51. }
  52. DataSystem.thisObject.watchData.set(data, new Map<string, number>());
  53. }
  54. /**
  55. * 获取数据
  56. * @param classConstructor 数据对象类型
  57. * @param mainValue 主键的值
  58. * @returns
  59. */
  60. static getData<T extends Data>(classConstructor: Constructor<T>, mainValue?: PropertyKey): T {
  61. if (mainValue === undefined) {
  62. return DataSystem.thisObject.dataMap.get(classConstructor) as T;
  63. }
  64. else {
  65. let oneDataMap: Map<PropertyKey, Data> = DataSystem.thisObject.dataMap.get(classConstructor) as Map<PropertyKey, Data>;
  66. if (oneDataMap) {
  67. return oneDataMap.get(mainValue) as T;
  68. }
  69. }
  70. }
  71. /**
  72. * 删除数据
  73. * @param classConstructor 数据对象类型
  74. * @param mainValue 主键的值
  75. */
  76. static deleteData<T extends Data>(classConstructor: Constructor<T>, mainValue?: PropertyKey): void {
  77. if (mainValue === undefined) {
  78. DataSystem.thisObject.watchData.delete(DataSystem.thisObject.dataMap.get(classConstructor) as Data);
  79. DataSystem.thisObject.dataMap.delete(classConstructor);
  80. }
  81. else {
  82. let oneDataMap: Map<PropertyKey, Data> = DataSystem.thisObject.dataMap.get(classConstructor) as Map<PropertyKey, Data>;
  83. if (oneDataMap) {
  84. oneDataMap.delete(mainValue);
  85. }
  86. if (!oneDataMap || !oneDataMap.size) {
  87. DataSystem.thisObject.watchData.delete(DataSystem.thisObject.dataMap.get(classConstructor) as Data);
  88. }
  89. DataSystem.thisObject.watchData.delete(oneDataMap.get(mainValue));
  90. }
  91. }
  92. /**
  93. * 观察数据,当数据产生变化时会被观察到,被观察后会在帧尾清空标记
  94. * 注意:在watch帧的时候,改变正在watch的属性值是不会被观察到变化的
  95. * @param data 数据对象
  96. * @param key 数据的属性名
  97. * @returns
  98. */
  99. static watch(data: Data | Constructor, key: PropertyKey) {
  100. let d: Data;
  101. if (data instanceof Data) {
  102. d = data;
  103. }
  104. else {
  105. d = this.getData(data as any);
  106. }
  107. if (!d || !DataSystem.thisObject.watchData.has(d)) {
  108. return false;
  109. }
  110. let propertyKeyMap = DataSystem.thisObject.watchData.get(d);
  111. let result = propertyKeyMap.has(key);
  112. if (result && DataSystem.frameID <= propertyKeyMap.get(key)) {
  113. return false;
  114. }
  115. !result && typeof key != 'symbol' && (result = propertyKeyMap.has(key + ""));
  116. result && DataSystem.thisObject.watchedList.push({ data: d, key });
  117. return result;
  118. }
  119. lateUpdate() {
  120. for (let i = 0; i < this.watchedList.length; i++) {
  121. const watchedData = this.watchedList[i];
  122. let propertyKeyMap = DataSystem.thisObject.watchData.get(watchedData.data);
  123. if (propertyKeyMap.has(watchedData.key)) {
  124. this.watchData.get(watchedData.data).delete(watchedData.key);
  125. }
  126. else if (typeof watchedData.key != 'symbol' && propertyKeyMap.has(watchedData.key + "")) {
  127. this.watchData.get(watchedData.data).delete(watchedData.key + "");
  128. this.watchData.get(watchedData.data).delete(watchedData.key);
  129. }
  130. }
  131. this.watchedList = [];
  132. }
  133. private static frameID: number = 1;
  134. update() {
  135. DataSystem.frameID++;
  136. }
  137. public static onPropertyChange(data: Data, key: PropertyKey) {
  138. if (!this.thisObject) {
  139. return;
  140. }
  141. if (!this.thisObject.watchData.has(data)) {
  142. this.thisObject.watchData.set(data, new Map<string, number>());
  143. }
  144. let propertyKeyMap = this.thisObject.watchData.get(data);
  145. propertyKeyMap.set(key, this.frameID);
  146. }
  147. }