| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- import { _decorator, Component, find, game } from "cc";
- import { Constructor } from "../core";
- import { Data } from "./Data";
- const { ccclass, property, executionOrder } = _decorator;
- /**
- * 数据系统组件,常驻节点,可创建数据、获取数据、观察数据变化
- * @description 创建数据:g.userData = DataSystem.createData<UserData>(UserData);update方法里:DataSystem.watch(g.userData,"money") && this.moneyLabel.string = g.userData.money;
- * @description Data的数组属性也可以watch到变化:g.userData.bagList.push("数据");DataSystem.watch(g.userData,"bagList")
- * @author 袁浩
- */
- @ccclass('DataSystem')
- @executionOrder(-1)
- export class DataSystem extends Component {
- private dataMap: Map<Constructor, Data | Map<PropertyKey, Data>> = new Map<Constructor, Data | Map<PropertyKey, Data>>();
- private watchData: Map<Data, Map<PropertyKey, number>> = new Map<Data, Map<PropertyKey, number>>();
- private watchedList: Array<{ data: Data, key: PropertyKey }> = [];
- private static thisObject: DataSystem;
- start() {
- game.addPersistRootNode(this.node);//常驻节点
- DataSystem.thisObject = this;
- }
- /**
- * 创建数据
- * @param classConstructor 数据对象类型
- * @returns
- */
- static createData<T extends Data>(classConstructor: Constructor<T>): T {
- this.deleteData(classConstructor);
- let data = new classConstructor();
- DataSystem.thisObject.dataMap.set(classConstructor, data);
- DataSystem.thisObject.watchData.set(data, new Map<string, number>());
- return data;
- }
- /**
- * 注册已经实例好的数据对象
- * @param data 数据对象
- * @param mainKey 主键
- */
- static regeditData(data: Data, mainKey?: PropertyKey): void {
- var constructor = data.constructor as Constructor;
- if (!mainKey) {
- DataSystem.thisObject.dataMap.set(constructor, data);
- }
- else {
- let oneDataMap: Map<PropertyKey, Data> = DataSystem.thisObject.dataMap.get(constructor) as Map<PropertyKey, Data>;
- if (!DataSystem.thisObject.dataMap.has(constructor)) {
- oneDataMap = new Map<PropertyKey, Data>();
- }
- oneDataMap.set(data[mainKey], data);
- DataSystem.thisObject.dataMap.set(constructor, oneDataMap);
- }
- DataSystem.thisObject.watchData.set(data, new Map<string, number>());
- }
- /**
- * 获取数据
- * @param classConstructor 数据对象类型
- * @param mainValue 主键的值
- * @returns
- */
- static getData<T extends Data>(classConstructor: Constructor<T>, mainValue?: PropertyKey): T {
- if (mainValue === undefined) {
- return DataSystem.thisObject.dataMap.get(classConstructor) as T;
- }
- else {
- let oneDataMap: Map<PropertyKey, Data> = DataSystem.thisObject.dataMap.get(classConstructor) as Map<PropertyKey, Data>;
- if (oneDataMap) {
- return oneDataMap.get(mainValue) as T;
- }
- }
- }
- /**
- * 删除数据
- * @param classConstructor 数据对象类型
- * @param mainValue 主键的值
- */
- static deleteData<T extends Data>(classConstructor: Constructor<T>, mainValue?: PropertyKey): void {
- if (mainValue === undefined) {
- DataSystem.thisObject.watchData.delete(DataSystem.thisObject.dataMap.get(classConstructor) as Data);
- DataSystem.thisObject.dataMap.delete(classConstructor);
- }
- else {
- let oneDataMap: Map<PropertyKey, Data> = DataSystem.thisObject.dataMap.get(classConstructor) as Map<PropertyKey, Data>;
- if (oneDataMap) {
- oneDataMap.delete(mainValue);
- }
- if (!oneDataMap || !oneDataMap.size) {
- DataSystem.thisObject.watchData.delete(DataSystem.thisObject.dataMap.get(classConstructor) as Data);
- }
- DataSystem.thisObject.watchData.delete(oneDataMap.get(mainValue));
- }
- }
- /**
- * 观察数据,当数据产生变化时会被观察到,被观察后会在帧尾清空标记
- * 注意:在watch帧的时候,改变正在watch的属性值是不会被观察到变化的
- * @param data 数据对象
- * @param key 数据的属性名
- * @returns
- */
- static watch(data: Data | Constructor, key: PropertyKey) {
- let d: Data;
- if (data instanceof Data) {
- d = data;
- }
- else {
- d = this.getData(data as any);
- }
- if (!d || !DataSystem.thisObject.watchData.has(d)) {
- return false;
- }
- let propertyKeyMap = DataSystem.thisObject.watchData.get(d);
- let result = propertyKeyMap.has(key);
- if (result && DataSystem.frameID <= propertyKeyMap.get(key)) {
- return false;
- }
- !result && typeof key != 'symbol' && (result = propertyKeyMap.has(key + ""));
- result && DataSystem.thisObject.watchedList.push({ data: d, key });
- return result;
- }
- lateUpdate() {
- for (let i = 0; i < this.watchedList.length; i++) {
- const watchedData = this.watchedList[i];
- let propertyKeyMap = DataSystem.thisObject.watchData.get(watchedData.data);
- if (propertyKeyMap.has(watchedData.key)) {
- this.watchData.get(watchedData.data).delete(watchedData.key);
- }
- else if (typeof watchedData.key != 'symbol' && propertyKeyMap.has(watchedData.key + "")) {
- this.watchData.get(watchedData.data).delete(watchedData.key + "");
- this.watchData.get(watchedData.data).delete(watchedData.key);
- }
- }
- this.watchedList = [];
- }
- private static frameID: number = 1;
- update() {
- DataSystem.frameID++;
- }
- public static onPropertyChange(data: Data, key: PropertyKey) {
- if (!this.thisObject) {
- return;
- }
- if (!this.thisObject.watchData.has(data)) {
- this.thisObject.watchData.set(data, new Map<string, number>());
- }
- let propertyKeyMap = this.thisObject.watchData.get(data);
- propertyKeyMap.set(key, this.frameID);
- }
- }
|