Add tracking behaviot & current label & Optmi running func & test fish scene
This commit is contained in:
		
							parent
							
								
									f8fbb70608
								
							
						
					
					
						commit
						0e1a070390
					
				@ -3,12 +3,14 @@ import { Template } from "@Behavior/Template";
 | 
				
			|||||||
import { Dynamics } from "@Behavior/Dynamics";
 | 
					import { Dynamics } from "@Behavior/Dynamics";
 | 
				
			||||||
import { Brownian } from "@Behavior/Brownian";
 | 
					import { Brownian } from "@Behavior/Brownian";
 | 
				
			||||||
import { BoundaryConstraint } from "@Behavior/BoundaryConstraint";
 | 
					import { BoundaryConstraint } from "@Behavior/BoundaryConstraint";
 | 
				
			||||||
 | 
					import { Tracking } from "@Behavior/Tracking";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const AllBehaviors: IAnyBehaviorRecorder[] = [
 | 
					const AllBehaviors: IAnyBehaviorRecorder[] = [
 | 
				
			||||||
    new BehaviorRecorder(Template),
 | 
					    new BehaviorRecorder(Template),
 | 
				
			||||||
    new BehaviorRecorder(Dynamics),
 | 
					    new BehaviorRecorder(Dynamics),
 | 
				
			||||||
    new BehaviorRecorder(Brownian),
 | 
					    new BehaviorRecorder(Brownian),
 | 
				
			||||||
    new BehaviorRecorder(BoundaryConstraint),
 | 
					    new BehaviorRecorder(BoundaryConstraint),
 | 
				
			||||||
 | 
					    new BehaviorRecorder(Tracking),
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -54,4 +56,13 @@ function categoryBehaviors(behaviors: IAnyBehaviorRecorder[]): ICategory[] {
 | 
				
			|||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export { AllBehaviors, AllBehaviorsWithCategory, ICategory as ICategoryBehavior };
 | 
					function getBehaviorById(id: string): IAnyBehaviorRecorder {
 | 
				
			||||||
 | 
					    for (let i = 0; i < AllBehaviors.length; i++) {
 | 
				
			||||||
 | 
					        if (AllBehaviors[i].behaviorId === id) {
 | 
				
			||||||
 | 
					            return AllBehaviors[i];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return getBehaviorById("Template");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { AllBehaviors, AllBehaviorsWithCategory, getBehaviorById, ICategory as ICategoryBehavior };
 | 
				
			||||||
@ -28,7 +28,7 @@ class BoundaryConstraint extends Behavior<IBoundaryConstraintBehaviorParameter,
 | 
				
			|||||||
		strength: { type: "number", name: "$Strength", defaultValue: 1, numberMin: 0, numberStep: .1 }
 | 
							strength: { type: "number", name: "$Strength", defaultValue: 1, numberMin: 0, numberStep: .1 }
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public effect(individual: Individual, group: Group, model: Model, t: number): void {
 | 
					    public effect = (individual: Individual, group: Group, model: Model, t: number): void => {
 | 
				
			||||||
        let rangeList: Range[] = this.parameter.range.objects;
 | 
					        let rangeList: Range[] = this.parameter.range.objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let fx = 0;
 | 
							let fx = 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ class Brownian extends Behavior<IBrownianBehaviorParameter, IBrownianBehaviorEve
 | 
				
			|||||||
		minStrength: { type: "number", name: "$Min.Strength", defaultValue: 0, numberStep: .01, numberMin: 0 }
 | 
							minStrength: { type: "number", name: "$Min.Strength", defaultValue: 0, numberStep: .01, numberMin: 0 }
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public effect(individual: Individual, group: Group, model: Model, t: number): void {
 | 
						public effect = (individual: Individual, group: Group, model: Model, t: number): void => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const {maxFrequency, minFrequency, maxStrength, minStrength} = this.parameter;
 | 
							const {maxFrequency, minFrequency, maxStrength, minStrength} = this.parameter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ class Dynamics extends Behavior<IDynamicsBehaviorParameter, IDynamicsBehaviorEve
 | 
				
			|||||||
		resistance: { name: "$Resistance", type: "number", defaultValue: 0.5, numberStep: .1, numberMin: 0 }
 | 
							resistance: { name: "$Resistance", type: "number", defaultValue: 0.5, numberStep: .1, numberMin: 0 }
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public override finalEffect(individual: Individual, group: Group, model: Model, t: number): void {
 | 
						public override finalEffect = (individual: Individual, group: Group, model: Model, t: number): void => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// 计算当前速度
 | 
							// 计算当前速度
 | 
				
			||||||
		const currentV = individual.vectorLength(individual.velocity);
 | 
							const currentV = individual.vectorLength(individual.velocity);
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,8 @@ type ITemplateBehaviorParameter = {
 | 
				
			|||||||
    testLR: "LR";
 | 
					    testLR: "LR";
 | 
				
			||||||
    testLG: "LG";
 | 
					    testLG: "LG";
 | 
				
			||||||
    testVec: "vec";
 | 
					    testVec: "vec";
 | 
				
			||||||
 | 
					    testCG: "CG",
 | 
				
			||||||
 | 
					    testCLG: "CLG",
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ITemplateBehaviorEvent = {}
 | 
					type ITemplateBehaviorEvent = {}
 | 
				
			||||||
@ -42,10 +44,12 @@ class Template extends Behavior<ITemplateBehaviorParameter, ITemplateBehaviorEve
 | 
				
			|||||||
        testG: { name: "$Test", type: "G" },
 | 
					        testG: { name: "$Test", type: "G" },
 | 
				
			||||||
        testLR: { name: "$Test", type: "LR" },
 | 
					        testLR: { name: "$Test", type: "LR" },
 | 
				
			||||||
        testLG: { name: "$Test", type: "LG" },
 | 
					        testLG: { name: "$Test", type: "LG" },
 | 
				
			||||||
 | 
					        testCG: { name: "$Test", type: "CG" },
 | 
				
			||||||
 | 
					        testCLG: { name: "$Test", type: "CLG" },
 | 
				
			||||||
        testVec: { name: "$Test", type: "vec", defaultValue: [1, 2, 3], numberMax: 10, numberMin: 0, numberStep: 1 }
 | 
					        testVec: { name: "$Test", type: "vec", defaultValue: [1, 2, 3], numberMax: 10, numberMin: 0, numberStep: 1 }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public effect(individual: Individual, group: Group, model: Model, t: number): void {
 | 
					    public effect = (individual: Individual, group: Group, model: Model, t: number): void => {
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										84
									
								
								source/Behavior/Tracking.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								source/Behavior/Tracking.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					import { Behavior } from "@Model/Behavior";
 | 
				
			||||||
 | 
					import { Group } from "@Model/Group";
 | 
				
			||||||
 | 
					import { Individual } from "@Model/Individual";
 | 
				
			||||||
 | 
					import { Model } from "@Model/Model";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ITrackingBehaviorParameter = {
 | 
				
			||||||
 | 
					    target: "LG",
 | 
				
			||||||
 | 
						strength: "number"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ITrackingBehaviorEvent = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Tracking extends Behavior<ITrackingBehaviorParameter, ITrackingBehaviorEvent> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override behaviorId: string = "Tracking";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override behaviorName: string = "$Title";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override iconName: string = "BullseyeTarget";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override describe: string = "$Intro";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public override category: string = "$Interactive";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override parameterOption = {
 | 
				
			||||||
 | 
							target: { type: "CLG", name: "$Target" },
 | 
				
			||||||
 | 
							strength: { type: "number", name: "$Strength", defaultValue: 10, numberMin: 0, numberStep: .1 }
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public effect = (individual: Individual, group: Group, model: Model, t: number): void => {
 | 
				
			||||||
 | 
							let target: Individual | undefined;
 | 
				
			||||||
 | 
							let currentDistant: number = Infinity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (let i = 0; i < this.parameter.target.objects.length; i++) {
 | 
				
			||||||
 | 
								const targetGroup = this.parameter.target.objects[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								targetGroup.individuals.forEach((targetIndividual) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// 排除自己
 | 
				
			||||||
 | 
									if (targetIndividual === individual) return;
 | 
				
			||||||
 | 
									let dis = targetIndividual.distanceTo(individual);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (dis < currentDistant) {
 | 
				
			||||||
 | 
										target = targetIndividual;
 | 
				
			||||||
 | 
										currentDistant = dis;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (target) {
 | 
				
			||||||
 | 
								individual.applyForce(
 | 
				
			||||||
 | 
									(target.position[0] - individual.position[0]) * this.parameter.strength,
 | 
				
			||||||
 | 
									(target.position[1] - individual.position[1]) * this.parameter.strength,
 | 
				
			||||||
 | 
									(target.position[2] - individual.position[2]) * this.parameter.strength
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public override terms: Record<string, Record<string, string>> = {
 | 
				
			||||||
 | 
					        "$Title": {
 | 
				
			||||||
 | 
					            "ZH_CN": "追踪",
 | 
				
			||||||
 | 
					            "EN_US": "Tracking"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
							"$Target": {
 | 
				
			||||||
 | 
								"ZH_CN": "追踪目标",
 | 
				
			||||||
 | 
								"EN_US": "Tracking target"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"$Strength": {
 | 
				
			||||||
 | 
								"ZH_CN": "追踪强度系数",
 | 
				
			||||||
 | 
								"EN_US": "Tracking intensity coefficient"
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					        "$Intro": {
 | 
				
			||||||
 | 
					            "ZH_CN": "个体将主动向最近的目标群个体发起追踪",
 | 
				
			||||||
 | 
					            "EN_US": "The individual will actively initiate tracking to the nearest target group individual"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
							"$Interactive": {
 | 
				
			||||||
 | 
								"ZH_CN": "交互",
 | 
				
			||||||
 | 
					            "EN_US": "Interactive"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export { Tracking };
 | 
				
			||||||
@ -59,6 +59,10 @@ class ObjectPicker extends Component<IObjectPickerProps & IMixinStatusProps, IOb
 | 
				
			|||||||
                    option.push(this.props.status.model.objectPool[j]);
 | 
					                    option.push(this.props.status.model.objectPool[j]);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (this.props.type.includes("C")) {
 | 
				
			||||||
 | 
					                option.push(this.props.status.model.currentGroupLabel);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return option;
 | 
					        return option;
 | 
				
			||||||
 | 
				
			|||||||
@ -51,16 +51,25 @@ function getObjectDisplayInfo(item?: IPickerListItem): IDisplayInfo {
 | 
				
			|||||||
	if (item instanceof Label) {
 | 
						if (item instanceof Label) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (item.isBuildIn) {
 | 
							if (item.isBuildIn) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            internal = true;
 | 
					            internal = true;
 | 
				
			||||||
            allLabel = true;
 | 
					            allLabel = true;
 | 
				
			||||||
            color = "transparent";
 | 
					            color = "transparent";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (item.id === "AllRange") {
 | 
					            if (item.id === "AllRange") {
 | 
				
			||||||
                icon = "ProductList";
 | 
					                icon = "ProductList";
 | 
				
			||||||
                name = "Build.In.Label.Name.All.Range";
 | 
					                name = "Build.In.Label.Name.All.Range";
 | 
				
			||||||
            } else if (item.id === "AllGroup") {
 | 
					            }
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								else if (item.id === "AllGroup") {
 | 
				
			||||||
                icon = "SizeLegacy";
 | 
					                icon = "SizeLegacy";
 | 
				
			||||||
                name = "Build.In.Label.Name.All.Group";
 | 
					                name = "Build.In.Label.Name.All.Group";
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								else if (item.id === "CurrentGroupLabel") {
 | 
				
			||||||
 | 
									icon = "TriangleShape";
 | 
				
			||||||
 | 
					                name = "Build.In.Label.Name.Current.Group";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
        } 
 | 
					        } 
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
 | 
				
			|||||||
@ -68,6 +68,7 @@ const EN_US = {
 | 
				
			|||||||
    "Popup.Behavior.Info.Confirm": "OK, I know it",
 | 
					    "Popup.Behavior.Info.Confirm": "OK, I know it",
 | 
				
			||||||
    "Build.In.Label.Name.All.Group": "All group",
 | 
					    "Build.In.Label.Name.All.Group": "All group",
 | 
				
			||||||
    "Build.In.Label.Name.All.Range": "All range",
 | 
					    "Build.In.Label.Name.All.Range": "All range",
 | 
				
			||||||
 | 
					    "Build.In.Label.Name.Current.Group": "Current group",
 | 
				
			||||||
    "Common.Search.Placeholder": "Search in here...",
 | 
					    "Common.Search.Placeholder": "Search in here...",
 | 
				
			||||||
    "Common.No.Data": "No Data",
 | 
					    "Common.No.Data": "No Data",
 | 
				
			||||||
    "Common.No.Unknown.Error": "Unknown error",
 | 
					    "Common.No.Unknown.Error": "Unknown error",
 | 
				
			||||||
 | 
				
			|||||||
@ -68,6 +68,7 @@ const ZH_CN = {
 | 
				
			|||||||
    "Popup.Behavior.Info.Confirm": "好的, 我知道了",
 | 
					    "Popup.Behavior.Info.Confirm": "好的, 我知道了",
 | 
				
			||||||
    "Build.In.Label.Name.All.Group": "全部群",
 | 
					    "Build.In.Label.Name.All.Group": "全部群",
 | 
				
			||||||
    "Build.In.Label.Name.All.Range": "全部范围",
 | 
					    "Build.In.Label.Name.All.Range": "全部范围",
 | 
				
			||||||
 | 
					    "Build.In.Label.Name.Current.Group": "当前群",
 | 
				
			||||||
    "Common.Search.Placeholder": "在此处搜索...",
 | 
					    "Common.Search.Placeholder": "在此处搜索...",
 | 
				
			||||||
    "Common.No.Data": "暂无数据",
 | 
					    "Common.No.Data": "暂无数据",
 | 
				
			||||||
    "Common.No.Unknown.Error": "未知错误",
 | 
					    "Common.No.Unknown.Error": "未知错误",
 | 
				
			||||||
 | 
				
			|||||||
@ -158,6 +158,11 @@ class Behavior<
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public parameter: IParameterValue<P>;
 | 
					    public parameter: IParameterValue<P>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 指定当前群的 Key
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public currentGroupKey: Array<keyof P> = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 对象参数列表
 | 
					     * 对象参数列表
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -222,7 +227,7 @@ class Behavior<
 | 
				
			|||||||
     * @param model 模型
 | 
					     * @param model 模型
 | 
				
			||||||
     * @param t 经过时间
 | 
					     * @param t 经过时间
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public effect(individual: Individual, group: Group, model: Model, t: number): void {};
 | 
					    public effect?: (individual: Individual, group: Group, model: Model, t: number) => void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 作用影响于个体
 | 
					     * 作用影响于个体
 | 
				
			||||||
@ -231,7 +236,7 @@ class Behavior<
 | 
				
			|||||||
     * @param model 模型
 | 
					     * @param model 模型
 | 
				
			||||||
     * @param t 经过时间
 | 
					     * @param t 经过时间
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public afterEffect(individual: Individual, group: Group, model: Model, t: number): void {};
 | 
					    public afterEffect?: (individual: Individual, group: Group, model: Model, t: number) => void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 全部影响作用后
 | 
					     * 全部影响作用后
 | 
				
			||||||
@ -240,7 +245,7 @@ class Behavior<
 | 
				
			|||||||
     * @param model 模型
 | 
					     * @param model 模型
 | 
				
			||||||
     * @param t 经过时间
 | 
					     * @param t 经过时间
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public finalEffect(individual: Individual, group: Group, model: Model, t: number): void {};
 | 
					    public finalEffect?: (individual: Individual, group: Group, model: Model, t: number) => void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import { Individual } from "@Model/Individual";
 | 
					import { Individual } from "@Model/Individual";
 | 
				
			||||||
import { CtrlObject } from "@Model/CtrlObject";
 | 
					import { CtrlObject } from "@Model/CtrlObject";
 | 
				
			||||||
import type { Behavior } from "@Model/Behavior"; 
 | 
					import type { Behavior, IAnyBehavior } from "@Model/Behavior"; 
 | 
				
			||||||
import { Label } from "@Model/Label";
 | 
					import { Label } from "@Model/Label";
 | 
				
			||||||
import { Range } from "@Model/Range";
 | 
					import { Range } from "@Model/Range";
 | 
				
			||||||
import { Model, ObjectID } from "@Model/Model";
 | 
					import { Model, ObjectID } from "@Model/Model";
 | 
				
			||||||
@ -308,7 +308,7 @@ class Group extends CtrlObject {
 | 
				
			|||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * 行为列表
 | 
						 * 行为列表
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public behaviors: Behavior[] = [];
 | 
						public behaviors: IAnyBehavior[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * 添加行为
 | 
						 * 添加行为
 | 
				
			||||||
@ -358,15 +358,37 @@ class Group extends CtrlObject {
 | 
				
			|||||||
	 * @param
 | 
						 * @param
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
	public runner(t: number, effectType: "finalEffect" | "effect" | "afterEffect" ): void {
 | 
						public runner(t: number, effectType: "finalEffect" | "effect" | "afterEffect" ): void {
 | 
				
			||||||
		this.individuals.forEach((individual) => {
 | 
					
 | 
				
			||||||
			for(let j = 0; j < this.behaviors.length; j++) {
 | 
					        for(let j = 0; j < this.behaviors.length; j++) {
 | 
				
			||||||
                if (this.behaviors[j].isDeleted()) {
 | 
					
 | 
				
			||||||
                    continue;
 | 
					            const behavior = this.behaviors[j];
 | 
				
			||||||
 | 
					            if (behavior.isDeleted()) {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const runnerFunction = behavior[effectType];
 | 
				
			||||||
 | 
					            if (!runnerFunction) {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            for (let k = 0; k < behavior.currentGroupKey.length; k++) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                let parameterCache = behavior.parameter[
 | 
				
			||||||
 | 
					                    behavior.currentGroupKey[k] as string
 | 
				
			||||||
 | 
					                ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (Array.isArray(parameterCache?.objects)) {
 | 
				
			||||||
 | 
					                    parameterCache.objects = [this];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    this.behaviors[j][effectType](individual, this, this.model, t);
 | 
					                    parameterCache.objects = this;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
		});
 | 
					
 | 
				
			||||||
 | 
					            this.individuals.forEach((individual) => {
 | 
				
			||||||
 | 
					                runnerFunction(individual, this, this.model, t);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -66,6 +66,11 @@ class Model extends Emitter<ModelEvent> {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public allGroupLabel = new Label(this, "AllGroup").setBuildInLabel();
 | 
					    public allGroupLabel = new Label(this, "AllGroup").setBuildInLabel();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 内置标签-全部群标签
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public currentGroupLabel = new Label(this, "CurrentGroupLabel").setBuildInLabel();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 添加标签
 | 
					     * 添加标签
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -223,6 +228,7 @@ class Model extends Emitter<ModelEvent> {
 | 
				
			|||||||
    public updateBehaviorParameter() {
 | 
					    public updateBehaviorParameter() {
 | 
				
			||||||
        for (let i = 0; i < this.behaviorPool.length; i++) {
 | 
					        for (let i = 0; i < this.behaviorPool.length; i++) {
 | 
				
			||||||
            const behavior = this.behaviorPool[i];
 | 
					            const behavior = this.behaviorPool[i];
 | 
				
			||||||
 | 
					            behavior.currentGroupKey = [];
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            for (let key in behavior.parameterOption) {
 | 
					            for (let key in behavior.parameterOption) {
 | 
				
			||||||
                switch (behavior.parameterOption[key].type) {
 | 
					                switch (behavior.parameterOption[key].type) {
 | 
				
			||||||
@ -236,11 +242,17 @@ class Model extends Emitter<ModelEvent> {
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    case "CG":
 | 
				
			||||||
                    case "G":
 | 
					                    case "G":
 | 
				
			||||||
                        const dataG: IParamValue<"G"> = behavior.parameter[key];
 | 
					                        const dataG: IParamValue<"CG"> = behavior.parameter[key];
 | 
				
			||||||
                        dataG.objects = undefined;
 | 
					                        dataG.objects = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (dataG.picker instanceof Group && !dataG.picker.isDeleted()) {
 | 
					                        if (dataG.picker instanceof Label && dataG.picker.id === this.currentGroupLabel.id) {
 | 
				
			||||||
 | 
					                            behavior.currentGroupKey.push(key);
 | 
				
			||||||
 | 
					                            dataG.objects = undefined;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        else if (dataG.picker instanceof Group && !dataG.picker.isDeleted()) {
 | 
				
			||||||
                            dataG.objects = dataG.picker;
 | 
					                            dataG.objects = dataG.picker;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
@ -260,8 +272,9 @@ class Model extends Emitter<ModelEvent> {
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    case "CLG":
 | 
				
			||||||
                    case "LG":
 | 
					                    case "LG":
 | 
				
			||||||
                        const dataLG: IParamValue<"LG"> = behavior.parameter[key];
 | 
					                        const dataLG: IParamValue<"CLG"> = behavior.parameter[key];
 | 
				
			||||||
                        dataLG.objects = [];
 | 
					                        dataLG.objects = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (dataLG.picker instanceof Group && !dataLG.picker.isDeleted()) {
 | 
					                        if (dataLG.picker instanceof Group && !dataLG.picker.isDeleted()) {
 | 
				
			||||||
@ -269,9 +282,16 @@ class Model extends Emitter<ModelEvent> {
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (dataLG.picker instanceof Label && !dataLG.picker.isDeleted()) {
 | 
					                        if (dataLG.picker instanceof Label && !dataLG.picker.isDeleted()) {
 | 
				
			||||||
                            dataLG.objects = this.getObjectByLabel(dataLG.picker).filter((obj) => {
 | 
					
 | 
				
			||||||
                                return obj instanceof Group;
 | 
					                            if (dataLG.picker.id === this.currentGroupLabel.id) {
 | 
				
			||||||
                            }) as any;
 | 
					                                behavior.currentGroupKey.push(key);
 | 
				
			||||||
 | 
					                                dataLG.objects = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                dataLG.objects = this.getObjectByLabel(dataLG.picker).filter((obj) => {
 | 
				
			||||||
 | 
					                                    return obj instanceof Group;
 | 
				
			||||||
 | 
					                                }) as any;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,8 @@ type IMapObjectParamTypeKeyToType = {
 | 
				
			|||||||
    "G": IObjectParamCacheType<Group | undefined>;
 | 
					    "G": IObjectParamCacheType<Group | undefined>;
 | 
				
			||||||
    "LR": IObjectParamCacheType<Label | Range | undefined, Range[]>;
 | 
					    "LR": IObjectParamCacheType<Label | Range | undefined, Range[]>;
 | 
				
			||||||
    "LG": IObjectParamCacheType<Label | Group | undefined, Group[]>;
 | 
					    "LG": IObjectParamCacheType<Label | Group | undefined, Group[]>;
 | 
				
			||||||
 | 
					    "CG": IObjectParamCacheType<Label | Group | undefined, Group | undefined>;
 | 
				
			||||||
 | 
					    "CLG": IObjectParamCacheType<Label | Group | undefined, Group[]>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type IMapVectorParamTypeKeyToType = {
 | 
					type IMapVectorParamTypeKeyToType = {
 | 
				
			||||||
@ -41,7 +43,7 @@ type IParamValue<K extends IParamType> = AllMapType[K];
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * 特殊对象类型判定
 | 
					 * 特殊对象类型判定
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const objectTypeListEnumSet = new Set<string>(["R", "G", "LR", "LG"]);
 | 
					const objectTypeListEnumSet = new Set<string>(["R", "G", "LR", "LG", "CG", "CLG"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 /**
 | 
					 /**
 | 
				
			||||||
  * 对象断言表达式
 | 
					  * 对象断言表达式
 | 
				
			||||||
@ -163,6 +165,7 @@ function getDefaultValue<P extends IParameter> (option: IParameterOption<P>): IP
 | 
				
			|||||||
                    defaultObj[key] = [0, 0, 0] as any;
 | 
					                    defaultObj[key] = [0, 0, 0] as any;
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
 | 
					                case "CG":
 | 
				
			||||||
                case "G":
 | 
					                case "G":
 | 
				
			||||||
                case "R":
 | 
					                case "R":
 | 
				
			||||||
                    defaultObj[key] = {
 | 
					                    defaultObj[key] = {
 | 
				
			||||||
@ -171,6 +174,7 @@ function getDefaultValue<P extends IParameter> (option: IParameterOption<P>): IP
 | 
				
			|||||||
                    } as any;
 | 
					                    } as any;
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case "CLG":
 | 
				
			||||||
                case "LR":
 | 
					                case "LR":
 | 
				
			||||||
                case "LG":
 | 
					                case "LG":
 | 
				
			||||||
                    defaultObj[key] = {
 | 
					                    defaultObj[key] = {
 | 
				
			||||||
 | 
				
			|||||||
@ -6,11 +6,12 @@ import { ClassicRenderer } from "@GLRender/ClassicRenderer";
 | 
				
			|||||||
import { initializeIcons } from '@fluentui/font-icons-mdl2';
 | 
					import { initializeIcons } from '@fluentui/font-icons-mdl2';
 | 
				
			||||||
import { RootContainer } from "@Component/Container/RootContainer";
 | 
					import { RootContainer } from "@Component/Container/RootContainer";
 | 
				
			||||||
import { LayoutDirection } from "@Context/Layout";
 | 
					import { LayoutDirection } from "@Context/Layout";
 | 
				
			||||||
import { AllBehaviors } from "@Behavior/Behavior";
 | 
					import { AllBehaviors, getBehaviorById } from "@Behavior/Behavior";
 | 
				
			||||||
import { CommandBar } from "@Component/CommandBar/CommandBar";
 | 
					import { CommandBar } from "@Component/CommandBar/CommandBar";
 | 
				
			||||||
import { HeaderBar } from "@Component/HeaderBar/HeaderBar";
 | 
					import { HeaderBar } from "@Component/HeaderBar/HeaderBar";
 | 
				
			||||||
import { Popup } from "@Component/Popup/Popup";
 | 
					import { Popup } from "@Component/Popup/Popup";
 | 
				
			||||||
import { Entry } from "../Entry/Entry";
 | 
					import { Entry } from "../Entry/Entry";
 | 
				
			||||||
 | 
					import { Group } from "@Model/Group";
 | 
				
			||||||
import "./SimulatorWeb.scss";
 | 
					import "./SimulatorWeb.scss";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
initializeIcons("https://img.mrkbear.com/fabric-cdn-prod_20210407.001/");
 | 
					initializeIcons("https://img.mrkbear.com/fabric-cdn-prod_20210407.001/");
 | 
				
			||||||
@ -40,18 +41,22 @@ class SimulatorWeb extends Component {
 | 
				
			|||||||
        this.status.bindRenderer(classicRender);
 | 
					        this.status.bindRenderer(classicRender);
 | 
				
			||||||
        this.status.setting = this.setting;
 | 
					        this.status.setting = this.setting;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 测试代码
 | 
					        const randomPosition = (group: Group) => {
 | 
				
			||||||
        if (true) {
 | 
					 | 
				
			||||||
            let group = this.status.newGroup();
 | 
					 | 
				
			||||||
            let range = this.status.newRange();
 | 
					 | 
				
			||||||
            range.color = [.1, .5, .9];
 | 
					 | 
				
			||||||
            group.new(100);
 | 
					 | 
				
			||||||
            group.color = [.8, .1, .6];
 | 
					 | 
				
			||||||
            group.individuals.forEach((individual) => {
 | 
					            group.individuals.forEach((individual) => {
 | 
				
			||||||
                individual.position[0] = (Math.random() - .5) * 2;
 | 
					                individual.position[0] = (Math.random() - .5) * 2;
 | 
				
			||||||
                individual.position[1] = (Math.random() - .5) * 2;
 | 
					                individual.position[1] = (Math.random() - .5) * 2;
 | 
				
			||||||
                individual.position[2] = (Math.random() - .5) * 2;
 | 
					                individual.position[2] = (Math.random() - .5) * 2;
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 测试代码
 | 
				
			||||||
 | 
					        if (false) {
 | 
				
			||||||
 | 
					            let group = this.status.newGroup();
 | 
				
			||||||
 | 
					            let range = this.status.newRange();
 | 
				
			||||||
 | 
					            range.color = [.1, .5, .9];
 | 
				
			||||||
 | 
					            group.new(100);
 | 
				
			||||||
 | 
					            group.color = [.8, .1, .6];
 | 
				
			||||||
 | 
					            randomPosition(group);
 | 
				
			||||||
            this.status.model.update(0);
 | 
					            this.status.model.update(0);
 | 
				
			||||||
            this.status.newLabel().name = "New Label";
 | 
					            this.status.newLabel().name = "New Label";
 | 
				
			||||||
            this.status.newLabel().name = "Test Label 01";
 | 
					            this.status.newLabel().name = "Test Label 01";
 | 
				
			||||||
@ -70,6 +75,76 @@ class SimulatorWeb extends Component {
 | 
				
			|||||||
            group.addBehavior(boundary);
 | 
					            group.addBehavior(boundary);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 鱼群模型测试
 | 
				
			||||||
 | 
					        if (true) {
 | 
				
			||||||
 | 
					            let fish1 = this.status.newGroup();
 | 
				
			||||||
 | 
					            let fish2 = this.status.newGroup();
 | 
				
			||||||
 | 
					            let shark = this.status.newGroup();
 | 
				
			||||||
 | 
					            let range = this.status.newRange();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            range.displayName = "Experimental site";
 | 
				
			||||||
 | 
					            range.color = [.8, .1, .6];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fish1.new(100);
 | 
				
			||||||
 | 
					            fish1.displayName = "Fish A";            
 | 
				
			||||||
 | 
					            fish1.color = [.1, .5, .9];
 | 
				
			||||||
 | 
					            randomPosition(fish1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fish2.new(50);
 | 
				
			||||||
 | 
					            fish2.displayName = "Fish B";            
 | 
				
			||||||
 | 
					            fish2.color = [.3, .2, .9];
 | 
				
			||||||
 | 
					            randomPosition(fish2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            shark.new(3);
 | 
				
			||||||
 | 
					            shark.displayName = "Shark";
 | 
				
			||||||
 | 
					            shark.color = [.8, .2, .3];
 | 
				
			||||||
 | 
					            shark.renderParameter.size = 100;
 | 
				
			||||||
 | 
					            shark.renderParameter.shape = "5";
 | 
				
			||||||
 | 
					            randomPosition(shark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.status.model.update(0);
 | 
				
			||||||
 | 
					            let fishLabel = this.status.newLabel();
 | 
				
			||||||
 | 
					            fishLabel.name = "Fish";
 | 
				
			||||||
 | 
					            fish1.addLabel(fishLabel);
 | 
				
			||||||
 | 
					            fish2.addLabel(fishLabel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let template = this.status.model.addBehavior(getBehaviorById("Template"));
 | 
				
			||||||
 | 
					            template.name = "Template"; template.color = [150, 20, 220];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let dynamicFish = this.status.model.addBehavior(getBehaviorById("Dynamics"));
 | 
				
			||||||
 | 
					            dynamicFish.name = "Dynamic Fish"; dynamicFish.color = [250, 200, 80];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let dynamicShark = this.status.model.addBehavior(getBehaviorById("Dynamics"));
 | 
				
			||||||
 | 
					            dynamicShark.name = "Dynamic Shark"; dynamicShark.color = [250, 200, 80];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let brownian = this.status.model.addBehavior(getBehaviorById("Brownian"));
 | 
				
			||||||
 | 
					            brownian.name = "Brownian"; brownian.color = [200, 80, 250];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let boundary = this.status.model.addBehavior(getBehaviorById("BoundaryConstraint"));
 | 
				
			||||||
 | 
					            boundary.name = "Boundary"; boundary.color = [80, 200, 250];
 | 
				
			||||||
 | 
					            boundary.parameter.range.picker = this.status.model.allRangeLabel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let tracking = this.status.model.addBehavior(getBehaviorById("Tracking"));
 | 
				
			||||||
 | 
					            tracking.name = "Tracking"; tracking.color = [80, 200, 250];
 | 
				
			||||||
 | 
					            tracking.parameter.target.picker = fishLabel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fish1.addBehavior(dynamicFish);
 | 
				
			||||||
 | 
					            fish1.addBehavior(brownian);
 | 
				
			||||||
 | 
					            fish1.addBehavior(boundary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fish2.addBehavior(dynamicFish);
 | 
				
			||||||
 | 
					            fish2.addBehavior(brownian);
 | 
				
			||||||
 | 
					            fish2.addBehavior(boundary);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            shark.addBehavior(dynamicShark);
 | 
				
			||||||
 | 
					            shark.addBehavior(boundary);
 | 
				
			||||||
 | 
					            shark.addBehavior(tracking);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            setTimeout(() => {
 | 
				
			||||||
 | 
					                this.status.model.updateBehaviorParameter();
 | 
				
			||||||
 | 
					            }, 200)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        (window as any).s = this;
 | 
					        (window as any).s = this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user