Compare commits
	
		
			2 Commits
		
	
	
		
			021e2e7821
			...
			feb277c3a2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| feb277c3a2 | |||
| 156b4651f5 | 
| @ -83,13 +83,13 @@ class Status extends Emitter<IStatusEvent> { | |||||||
|      */ |      */ | ||||||
|     public focusLabel?: Label; |     public focusLabel?: Label; | ||||||
| 
 | 
 | ||||||
|     private drawtimer?: NodeJS.Timeout; |     private drawTimer?: NodeJS.Timeout; | ||||||
| 
 | 
 | ||||||
|     private delayDraw = () => { |     private delayDraw = () => { | ||||||
|         this.drawtimer ? clearTimeout(this.drawtimer) : null; |         this.drawTimer ? clearTimeout(this.drawTimer) : null; | ||||||
|         this.drawtimer = setTimeout(() => { |         this.drawTimer = setTimeout(() => { | ||||||
|             this.model.draw(); |             this.model.draw(); | ||||||
|             this.drawtimer = undefined; |             this.drawTimer = undefined; | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,40 +3,328 @@ import { Emitter, EventType } from "./Emitter"; | |||||||
| import type { Individual } from "./Individual"; | import type { Individual } from "./Individual"; | ||||||
| import type { Group } from "./Group"; | import type { Group } from "./Group"; | ||||||
| import type { Model } from "./Model"; | import type { Model } from "./Model"; | ||||||
|  | import type { Range } from "./Range"; | ||||||
|  | import type { Label } from "./Label"; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 群体的某种行为 |  * 行为构造函数类型 | ||||||
|  */ |  */ | ||||||
| abstract class Behavior< | type IBehaviorConstructor<B extends Behavior<any, any>> = | ||||||
|     P extends IAnyObject = {}, |     new (id: string, parameter: IBehaviorParameterValue<B["parameterOption"]>) => B; | ||||||
|     E extends Record<EventType, any> = {} | 
 | ||||||
| > extends Emitter<E> { | /** | ||||||
|  |  * 参数类型 | ||||||
|  |  */ | ||||||
|  | type IMapBasicParamTypeKeyToType = { | ||||||
|  |     "number": number; | ||||||
|  |     "string": string; | ||||||
|  |     "boolean": boolean; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type IMapObjectParamTypeKeyToType = { | ||||||
|  |     "R"?: Range; | ||||||
|  |     "G"?: Group; | ||||||
|  |     "GR"?: Group | Range; | ||||||
|  |     "LR"?: Label | Range; | ||||||
|  |     "LG"?: Label | Group; | ||||||
|  |     "LGR"?: Label | Group | Range; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type IMapVectorParamTypeKeyToType = { | ||||||
|  |     "vec": number[]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 参数类型映射 | ||||||
|  |  */ | ||||||
|  | type AllMapType = IMapBasicParamTypeKeyToType & IMapObjectParamTypeKeyToType & IMapVectorParamTypeKeyToType; | ||||||
|  | type IParamType = keyof AllMapType; | ||||||
|  | type IObjectType = keyof IMapObjectParamTypeKeyToType; | ||||||
|  | type IVectorType = keyof IMapVectorParamTypeKeyToType; | ||||||
|  | type IParamValue<K extends IParamType> = AllMapType[K]; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 特殊对象类型判定 | ||||||
|  |  */ | ||||||
|  | const objectTypeListEnumSet = new Set<IParamType>(["R", "G", "GR", "LR", "LG", "LGR"]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 对象断言表达式 | ||||||
|  |  */ | ||||||
|  | function isObjectType(key: IParamType): key is IVectorType { | ||||||
|  |     return objectTypeListEnumSet.has(key); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 向量断言表达式 | ||||||
|  |  */ | ||||||
|  | function isVectorType(key: IParamType): key is IObjectType { | ||||||
|  |     return key === "vec"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 模型参数类型 | ||||||
|  |  */ | ||||||
|  | interface IBehaviorParameterOptionItem<T extends IParamType = IParamType> { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 参数类型 | ||||||
|  |      */ | ||||||
|  |     type: T; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 参数默认值 | ||||||
|  |      */ | ||||||
|  |     defaultValue?: IParamValue<T>; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 数值变化回调 | ||||||
|  |      */ | ||||||
|  |     onChange?: (value: IParamValue<T>) => any; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 名字 | ||||||
|  |      */ | ||||||
|  |     name: string; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 字符长度 | ||||||
|  |      */ | ||||||
|  |     stringLength?: number; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 数字步长 | ||||||
|  |      */ | ||||||
|  |     numberStep?: number; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 最大值最小值 | ||||||
|  |      */ | ||||||
|  |     numberMax?: number; | ||||||
|  |     numberMin?: number; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 图标名字 | ||||||
|  |      */ | ||||||
|  |     iconName?: string; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 参数键值类型 | ||||||
|  |  */ | ||||||
|  | type IBehaviorParameterValueItem<P extends IBehaviorParameterOptionItem> = IParamValue<P["type"]>; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 参数类型列表 | ||||||
|  |  */ | ||||||
|  | interface IBehaviorParameterOption { | ||||||
|  |     [x: string]: IBehaviorParameterOptionItem; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 参数类型列表映射到参数对象 | ||||||
|  |  */ | ||||||
|  | type IBehaviorParameterValue<P extends IBehaviorParameterOption> = { | ||||||
|  |     [x in keyof P]: IBehaviorParameterValueItem<P[x]> | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 行为的基础信息 | ||||||
|  |  */ | ||||||
|  | class BehaviorInfo<E extends Record<EventType, any> = {}> extends Emitter<E> { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 图标名字 | ||||||
|  |      */ | ||||||
|  |     public iconName: string = "" | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 行为 ID |      * 行为 ID | ||||||
|      */ |      */ | ||||||
|     abstract id: string; |     public behaviorId: string = ""; | ||||||
|          |          | ||||||
|     /** |     /** | ||||||
|      * 行为名称 |      * 行为名称 | ||||||
|      */ |      */ | ||||||
|     abstract name: string; |     public behaviorName: string = ""; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 行为描述 |      * 行为描述 | ||||||
|      */ |      */ | ||||||
|     public describe?: string = ""; |     public describe?: string = ""; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class BehaviorRecorder< | ||||||
|  |     B extends Behavior<any, any> | ||||||
|  | > extends BehaviorInfo { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 命名序号 | ||||||
|  |      */ | ||||||
|  |     public nameIndex: number = 0; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 获取下一个 ID | ||||||
|  |      */ | ||||||
|  |     public getNextId() { | ||||||
|  |         return `B-${this.behaviorName}-${this.nameIndex ++}`; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 行为类型 | ||||||
|  |      */ | ||||||
|  |     public behavior: IBehaviorConstructor<B>; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 行为实例 | ||||||
|  |      */ | ||||||
|  |     public behaviorInstance: B; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 对象参数列表 | ||||||
|  |      */ | ||||||
|  |     public parameterOption: B["parameterOption"]; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 获取参数列表的默认值 | ||||||
|  |      */ | ||||||
|  |     public getDefaultValue(): IBehaviorParameterValue<B["parameterOption"]> { | ||||||
|  |         let defaultObj = {} as IBehaviorParameterValue<B["parameterOption"]>; | ||||||
|  |         for (let key in this.parameterOption) { | ||||||
|  |             let defaultVal = this.parameterOption[key].defaultValue; | ||||||
|  |              | ||||||
|  |             defaultObj[key] = defaultVal as any; | ||||||
|  |             if (defaultObj[key] === undefined) { | ||||||
|  | 
 | ||||||
|  |                 switch (this.parameterOption[key].type) { | ||||||
|  |                     case "string": | ||||||
|  |                         defaultObj[key] = "" as any; | ||||||
|  |                         break; | ||||||
|  | 
 | ||||||
|  |                     case "number": | ||||||
|  |                         defaultObj[key] = 0 as any; | ||||||
|  |                         break; | ||||||
|  | 
 | ||||||
|  |                     case "boolean": | ||||||
|  |                         defaultObj[key] = false as any; | ||||||
|  |                         break; | ||||||
|  | 
 | ||||||
|  |                     case "vec": | ||||||
|  |                         defaultObj[key] = [0, 0, 0] as any; | ||||||
|  |                         break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return defaultObj; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 创建一个新的行为实例 | ||||||
|  |      */ | ||||||
|  |     public new(): B { | ||||||
|  |         return new this.behavior(this.getNextId(), this.getDefaultValue()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public constructor(behavior: IBehaviorConstructor<B>) { | ||||||
|  |         super(); | ||||||
|  |         this.behavior = behavior; | ||||||
|  |         this.behaviorInstance = new this.behavior(this.getNextId(), {} as any); | ||||||
|  |         this.parameterOption = this.behaviorInstance.parameterOption; | ||||||
|  |         this.iconName = this.behaviorInstance.iconName; | ||||||
|  |         this.behaviorId = this.behaviorInstance.behaviorId; | ||||||
|  |         this.behaviorName = this.behaviorInstance.behaviorName; | ||||||
|  |         this.describe = this.behaviorInstance.describe; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 群体的某种行为 | ||||||
|  |  */ | ||||||
|  | class Behavior< | ||||||
|  |     P extends IBehaviorParameterOption = {}, | ||||||
|  |     E extends Record<EventType, any> = {} | ||||||
|  | > extends BehaviorInfo<E> { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 用户自定义名字 | ||||||
|  |      */ | ||||||
|  |     public name: string = ""; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 实例 ID | ||||||
|  |      */ | ||||||
|  |     public id: string = ""; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 优先级 |      * 优先级 | ||||||
|      * 值越大执行顺序越靠后 |      * 值越大执行顺序越靠后 | ||||||
|      */ |      */ | ||||||
|     public priority?: number = 0; |     public priority: number = 0; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 行为参数 |      * 行为参数 | ||||||
|      */ |      */ | ||||||
|     abstract parameter?: P; |     public parameter: IBehaviorParameterValue<P>; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 对象参数列表 | ||||||
|  |      */ | ||||||
|  |     public parameterOption: P = {} as any; | ||||||
|  | 
 | ||||||
|  |     public constructor(id: string, parameter: IBehaviorParameterValue<P>) { | ||||||
|  |         super(); | ||||||
|  |         this.id = id; | ||||||
|  |         this.parameter = parameter; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 相等校验 | ||||||
|  |      */ | ||||||
|  |     public equal(behavior: Behavior<any, any>): boolean { | ||||||
|  |         return this === behavior || this.id === behavior.id; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 删除标记 | ||||||
|  |      */ | ||||||
|  |     private deleteFlag: boolean = false; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 标记对象被删除 | ||||||
|  |      */ | ||||||
|  |     public markDelete() { | ||||||
|  |         this.deleteFlag = true; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 是否被删除 | ||||||
|  |      */ | ||||||
|  |     public isDeleted(): boolean { | ||||||
|  |         return this.deleteFlag; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 加载时调用 | ||||||
|  |      */ | ||||||
|  |     public load(model: Model): void {} | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 卸载时调用 | ||||||
|  |      */ | ||||||
|  |     public unload(model: Model): void {} | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 挂载时调用 | ||||||
|  |      */ | ||||||
|  |     public mount(group: Group, model: Model): void {} | ||||||
|  | 
 | ||||||
|  |      /** | ||||||
|  |       * 挂载时调用 | ||||||
|  |       */ | ||||||
|  |     public unmount(group: Group, model: Model): void {} | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 全部影响作用前 |      * 全部影响作用前 | ||||||
| @ -67,5 +355,5 @@ abstract class Behavior< | |||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export { Behavior }; | export { Behavior, BehaviorRecorder }; | ||||||
| export default { Behavior }; | export default { Behavior }; | ||||||
| @ -60,22 +60,36 @@ class CtrlObject extends LabelObject { | |||||||
|         return this === obj || this.id === obj.id; |         return this === obj || this.id === obj.id; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * 标记对象被删除 | ||||||
|  |      */ | ||||||
|  |     public markDelete() { | ||||||
|  |         this.deleteFlag = true; | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 删除标记 |      * 删除标记 | ||||||
|      */ |      */ | ||||||
|     private deleteFlag: boolean = false; |     private deleteFlag: boolean = false; | ||||||
| 
 | 
 | ||||||
|      /** |     /** | ||||||
|       * 是否被删除 |      * 检测是否被删除 | ||||||
|       */ |      */ | ||||||
|     public isDeleted(): boolean { |     public testDelete() { | ||||||
|         if (this.deleteFlag) return true; |  | ||||||
|         for (let i = 0; i < this.model.objectPool.length; i++) { |         for (let i = 0; i < this.model.objectPool.length; i++) { | ||||||
|             if (this.model.objectPool[i].equal(this)) return false; |             if (this.model.objectPool[i].equal(this)) { | ||||||
|  |                 this.deleteFlag = false; | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         this.deleteFlag = true; |         this.deleteFlag = true; | ||||||
|         return true; |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 是否被删除 | ||||||
|  |      */ | ||||||
|  |     public isDeleted(): boolean { | ||||||
|  |         return this.deleteFlag; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -22,7 +22,7 @@ class Group extends CtrlObject { | |||||||
|     /** |     /** | ||||||
|      * 个体生成方式 |      * 个体生成方式 | ||||||
|      */ |      */ | ||||||
|     public genMethod: GenMod = GenMod.Point; |     public genMethod: GenMod = GenMod.Range; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 生成位置坐标 |      * 生成位置坐标 | ||||||
|  | |||||||
| @ -1,4 +1,3 @@ | |||||||
| 
 |  | ||||||
| import { Individual } from "./Individual"; | import { Individual } from "./Individual"; | ||||||
| import { Group } from "./Group"; | import { Group } from "./Group"; | ||||||
| import { Range } from "./Range"; | import { Range } from "./Range"; | ||||||
| @ -6,18 +5,14 @@ import { Emitter, EventType, EventMixin } from "./Emitter"; | |||||||
| import { CtrlObject } from "./CtrlObject"; | import { CtrlObject } from "./CtrlObject"; | ||||||
| import { ObjectID, AbstractRenderer } from "./Renderer"; | import { ObjectID, AbstractRenderer } from "./Renderer"; | ||||||
| import { Label } from "./Label"; | import { Label } from "./Label"; | ||||||
|  | import { Behavior, BehaviorRecorder } from "./Behavior"; | ||||||
| 
 | 
 | ||||||
| type ModelEvent = { | type ModelEvent = { | ||||||
|     loop: number; |     loop: number; | ||||||
|     groupAdd: Group; |  | ||||||
|     rangeAdd: Range; |  | ||||||
|     labelAdd: Label; |  | ||||||
|     labelDelete: Label; |  | ||||||
|     labelChange: Label[]; |     labelChange: Label[]; | ||||||
|     objectAdd: CtrlObject; |  | ||||||
|     objectDelete: CtrlObject[]; |  | ||||||
|     objectChange: CtrlObject[]; |     objectChange: CtrlObject[]; | ||||||
|     individualChange: Group; |     individualChange: Group; | ||||||
|  |     behaviorChange: Behavior; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -68,7 +63,6 @@ class Model extends Emitter<ModelEvent> { | |||||||
|         console.log(`Model: Creat label with id ${this.idIndex}`); |         console.log(`Model: Creat label with id ${this.idIndex}`); | ||||||
|         let label = new Label(this, this.nextId("L"), name); |         let label = new Label(this, this.nextId("L"), name); | ||||||
|         this.labelPool.push(label); |         this.labelPool.push(label); | ||||||
|         this.emit("labelAdd", label); |  | ||||||
|         this.emit("labelChange", this.labelPool); |         this.emit("labelChange", this.labelPool); | ||||||
|         return label; |         return label; | ||||||
|     } |     } | ||||||
| @ -97,7 +91,6 @@ class Model extends Emitter<ModelEvent> { | |||||||
|             this.labelPool.splice(index, 1); |             this.labelPool.splice(index, 1); | ||||||
|             deletedLabel.testDelete(); |             deletedLabel.testDelete(); | ||||||
|             console.log(`Model: Delete label ${deletedLabel.name ?? deletedLabel.id}`); |             console.log(`Model: Delete label ${deletedLabel.name ?? deletedLabel.id}`); | ||||||
|             this.emit("labelDelete", deletedLabel); |  | ||||||
|             this.emit("labelChange", this.labelPool); |             this.emit("labelChange", this.labelPool); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -135,8 +128,6 @@ class Model extends Emitter<ModelEvent> { | |||||||
|         console.log(`Model: Creat group with id ${this.idIndex}`); |         console.log(`Model: Creat group with id ${this.idIndex}`); | ||||||
|         let group = new Group(this, this.nextId("G")); |         let group = new Group(this, this.nextId("G")); | ||||||
|         this.objectPool.push(group); |         this.objectPool.push(group); | ||||||
|         this.emit("groupAdd", group); |  | ||||||
|         this.emit("objectAdd", group); |  | ||||||
|         this.emit("objectChange", this.objectPool); |         this.emit("objectChange", this.objectPool); | ||||||
|         return group; |         return group; | ||||||
|     } |     } | ||||||
| @ -148,8 +139,6 @@ class Model extends Emitter<ModelEvent> { | |||||||
|         console.log(`Model: Creat range with id ${this.idIndex}`); |         console.log(`Model: Creat range with id ${this.idIndex}`); | ||||||
|         let range = new Range(this, this.nextId("R")); |         let range = new Range(this, this.nextId("R")); | ||||||
|         this.objectPool.push(range); |         this.objectPool.push(range); | ||||||
|         this.emit("rangeAdd", range); |  | ||||||
|         this.emit("objectAdd", range); |  | ||||||
|         this.emit("objectChange", this.objectPool); |         this.emit("objectChange", this.objectPool); | ||||||
|         return range; |         return range; | ||||||
|     } |     } | ||||||
| @ -176,6 +165,7 @@ class Model extends Emitter<ModelEvent> { | |||||||
| 
 | 
 | ||||||
|             if (needDeleted) { |             if (needDeleted) { | ||||||
|                 deletedObject.push(currentObject); |                 deletedObject.push(currentObject); | ||||||
|  |                 currentObject.markDelete(); | ||||||
|                 return false; |                 return false; | ||||||
|             } else { |             } else { | ||||||
|                 return true; |                 return true; | ||||||
| @ -184,12 +174,68 @@ class Model extends Emitter<ModelEvent> { | |||||||
| 
 | 
 | ||||||
|         if (deletedObject.length) { |         if (deletedObject.length) { | ||||||
|             console.log(`Model: Delete object ${deletedObject.map((object) => object.id).join(", ")}`); |             console.log(`Model: Delete object ${deletedObject.map((object) => object.id).join(", ")}`); | ||||||
|             this.emit("objectDelete", deletedObject); |  | ||||||
|             this.emit("objectChange", this.objectPool); |             this.emit("objectChange", this.objectPool); | ||||||
|         } |         } | ||||||
|         return deletedObject; |         return deletedObject; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * 行为池 | ||||||
|  |      */ | ||||||
|  |     public behaviorPool: Behavior<any, any>[] = []; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 添加一个行为 | ||||||
|  |      */ | ||||||
|  |     public addBehavior<B extends Behavior<any, any>>(recorder: BehaviorRecorder<B>): B { | ||||||
|  |         let behavior = recorder.new(); | ||||||
|  |         behavior.load(this); | ||||||
|  |         this.behaviorPool.push(behavior); | ||||||
|  |         console.log(`Model: Add ${behavior.behaviorName} behavior ${behavior.id}`); | ||||||
|  |         this.emit("behaviorChange", behavior); | ||||||
|  |         return behavior; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 通过 ID 获取行为 | ||||||
|  |      */ | ||||||
|  |     public getBehaviorById(id: ObjectID): Behavior<any, any> | undefined { | ||||||
|  |         for (let i = 0; i < this.behaviorPool.length; i++) { | ||||||
|  |             if (this.behaviorPool[i].id.toString() === id.toString()) { | ||||||
|  |                 return this.behaviorPool[i]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 搜索并删除一个 Behavior | ||||||
|  |      * @param name 搜索值 | ||||||
|  |      */ | ||||||
|  |     public deleteBehavior(name: Behavior<any, any> | ObjectID) { | ||||||
|  |         let deletedBehavior: Behavior<any, any> | undefined; | ||||||
|  |         let index = 0; | ||||||
|  | 
 | ||||||
|  |         for (let i = 0; i < this.behaviorPool.length; i++) { | ||||||
|  |             if (name instanceof Behavior) { | ||||||
|  |                 if (this.behaviorPool[i].equal(name)) { | ||||||
|  |                     deletedBehavior = this.behaviorPool[i]; | ||||||
|  |                     index = i; | ||||||
|  |                 } | ||||||
|  |             } else if (name === this.behaviorPool[i].id) { | ||||||
|  |                 deletedBehavior = this.behaviorPool[i]; | ||||||
|  |                 index = i; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (deletedBehavior) { | ||||||
|  |             this.behaviorPool.splice(index, 1); | ||||||
|  |             deletedBehavior.unload(this); | ||||||
|  |             deletedBehavior.markDelete(); | ||||||
|  |             console.log(`Model: Delete behavior ${deletedBehavior.name ?? deletedBehavior.id}`); | ||||||
|  |             this.emit("behaviorChange", deletedBehavior); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * 渲染器 |      * 渲染器 | ||||||
|      */ |      */ | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user