Compare commits
	
		
			No commits in common. "feb277c3a295fb1d51478d6586e5ceb495d07b4e" and "021e2e7821c12e2fe13715e7c6ba8b2386dd9a28" have entirely different histories.
		
	
	
		
			feb277c3a2
			...
			021e2e7821
		
	
		
| @ -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,328 +3,40 @@ 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"; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 行为构造函数类型 |  * 群体的某种行为 | ||||||
|  */ |  */ | ||||||
| type IBehaviorConstructor<B extends Behavior<any, any>> = | abstract class Behavior< | ||||||
|     new (id: string, parameter: IBehaviorParameterValue<B["parameterOption"]>) => B; |     P extends IAnyObject = {}, | ||||||
| 
 |     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 | ||||||
|      */ |      */ | ||||||
|     public behaviorId: string = ""; |     abstract id: string; | ||||||
|          |      | ||||||
|     /** |     /** | ||||||
|      * 行为名称 |      * 行为名称 | ||||||
|      */ |      */ | ||||||
|     public behaviorName: string = ""; |     abstract name: 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; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 行为参数 |      * 行为参数 | ||||||
|      */ |      */ | ||||||
|     public parameter: IBehaviorParameterValue<P>; |     abstract parameter?: 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 {} |  | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 全部影响作用前 |      * 全部影响作用前 | ||||||
| @ -355,5 +67,5 @@ class Behavior< | |||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export { Behavior, BehaviorRecorder }; | export { Behavior }; | ||||||
| export default { Behavior }; | export default { Behavior }; | ||||||
| @ -60,36 +60,22 @@ 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 testDelete() { |     public isDeleted(): boolean { | ||||||
|  |         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)) { |             if (this.model.objectPool[i].equal(this)) return false; | ||||||
|                 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.Range; |     public genMethod: GenMod = GenMod.Point; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 生成位置坐标 |      * 生成位置坐标 | ||||||
|  | |||||||
| @ -1,3 +1,4 @@ | |||||||
|  | 
 | ||||||
| import { Individual } from "./Individual"; | import { Individual } from "./Individual"; | ||||||
| import { Group } from "./Group"; | import { Group } from "./Group"; | ||||||
| import { Range } from "./Range"; | import { Range } from "./Range"; | ||||||
| @ -5,14 +6,18 @@ 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; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -63,6 +68,7 @@ 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; | ||||||
|     } |     } | ||||||
| @ -91,6 +97,7 @@ 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); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -128,6 +135,8 @@ 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; | ||||||
|     } |     } | ||||||
| @ -139,6 +148,8 @@ 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; | ||||||
|     } |     } | ||||||
| @ -165,7 +176,6 @@ 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; | ||||||
| @ -174,68 +184,12 @@ 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