Add parameter component
This commit is contained in:
		
							parent
							
								
									d7e15793b9
								
							
						
					
					
						commit
						7556ea983e
					
				| @ -5,7 +5,7 @@ import { Brownian } from "./Brownian"; | ||||
| import { BoundaryConstraint } from "./BoundaryConstraint";  | ||||
| 
 | ||||
| const AllBehaviors: IAnyBehaviorRecorder[] = [ | ||||
|     // new BehaviorRecorder(Template),
 | ||||
|     new BehaviorRecorder(Template), | ||||
|     new BehaviorRecorder(Dynamics), | ||||
|     new BehaviorRecorder(Brownian), | ||||
|     new BehaviorRecorder(BoundaryConstraint), | ||||
|  | ||||
| @ -78,4 +78,4 @@ class Localization extends Component<ILocalizationProps & IMixinSettingProps & | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { Localization, I18N, LanguageDataBase, AllI18nKeys }; | ||||
| export { Localization, I18N, LanguageDataBase, AllI18nKeys, ILocalizationProps }; | ||||
							
								
								
									
										0
									
								
								source/Component/Parameter/Parameter.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								source/Component/Parameter/Parameter.scss
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										202
									
								
								source/Component/Parameter/Parameter.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								source/Component/Parameter/Parameter.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,202 @@ | ||||
| import { AttrInput } from "@Component/AttrInput/AttrInput"; | ||||
| import { | ||||
|     IParameter, IParameterOption, IParameterOptionItem, | ||||
|     IParameterValue, IParamValue, isObjectType, isVectorType | ||||
| } from "@Model/Parameter"; | ||||
| import { ObjectID } from "@Model/Renderer"; | ||||
| import { Component, Fragment, ReactNode } from "react"; | ||||
| import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | ||||
| import { ObjectPicker } from "@Component/ObjectPicker/ObjectPicker"; | ||||
| import { useSettingWithEvent, IMixinSettingProps, Language } from "@Context/Setting"; | ||||
| import { AllI18nKeys } from "@Component/Localization/Localization"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import "./Parameter.scss"; | ||||
| 
 | ||||
| interface IParameterProps<P extends IParameter = {}> { | ||||
|     option: IParameterOption<P>; | ||||
|     value: IParameterValue<P>; | ||||
|     key: ObjectID; | ||||
|     change: <K extends keyof P>(key: K, val: IParamValue<P[K]>) => any; | ||||
|     i18n: <K extends keyof P>(option: IParameterOptionItem<P[K]>, language: Language) => string; | ||||
|     title?: AllI18nKeys; | ||||
|     titleOption?: Record<string, string>; | ||||
|     isFirst?: boolean; | ||||
| } | ||||
| 
 | ||||
| @useSettingWithEvent("language") | ||||
| class Parameter<P extends IParameter> extends Component<IParameterProps<P> & IMixinSettingProps> { | ||||
| 
 | ||||
|     private renderParameter<K extends keyof P> | ||||
|     (key: K, option: IParameterOptionItem<P[K]>, value: IParamValue<P[K]>): ReactNode { | ||||
| 
 | ||||
|         const indexKey = `${this.props.key}-${key}`; | ||||
|         const type = option.type; | ||||
|         const i18nString = this.props.i18n(option, this.props.setting?.language ?? "EN_US"); | ||||
| 
 | ||||
|         if (type === "number") { | ||||
|             return <AttrInput | ||||
|                 key={indexKey} | ||||
|                 id={indexKey} | ||||
|                 keyI18n="Panel.Info.Behavior.Details.Parameter.Key" | ||||
|                 keyI18nOption={{ key: i18nString }} | ||||
|                 isNumber={true} | ||||
|                 step={option.numberStep} | ||||
|                 maxLength={option.maxLength} | ||||
|                 max={option.numberMax} | ||||
|                 min={option.numberMin} | ||||
|                 value={value as IParamValue<"number"> ?? 0} | ||||
|                 valueChange={(val) => { | ||||
|                     this.props.change(key, parseFloat(val) as IParamValue<P[K]>); | ||||
|                 }} | ||||
|             />; | ||||
|         } | ||||
| 
 | ||||
|         else if (type === "string") { | ||||
|             return <AttrInput | ||||
|                 key={indexKey} | ||||
|                 id={indexKey} | ||||
|                 keyI18n="Panel.Info.Behavior.Details.Parameter.Key" | ||||
|                 keyI18nOption={{ key: i18nString }} | ||||
|                 maxLength={option.maxLength} | ||||
|                 value={value as IParamValue<"string"> ?? ""} | ||||
|                 valueChange={(val) => { | ||||
|                     this.props.change(key, val as IParamValue<P[K]>); | ||||
|                 }} | ||||
|             />; | ||||
|         } | ||||
| 
 | ||||
|         else if (type === "boolean") { | ||||
|             return <TogglesInput | ||||
|                 key={indexKey} | ||||
|                 keyI18n="Panel.Info.Behavior.Details.Parameter.Key" | ||||
|                 keyI18nOption={{ key: i18nString }} | ||||
| 				onIconName={option.iconName} | ||||
|                 value={value as IParamValue<"boolean"> ?? false} | ||||
| 				valueChange={(val) => { | ||||
| 					this.props.change(key, val as IParamValue<P[K]>); | ||||
| 				}} | ||||
| 			/> | ||||
|         } | ||||
| 
 | ||||
|         else if (isObjectType(type)) { | ||||
| 
 | ||||
|             type IObjectParamValue = IParamValue<"G" | "R" | "LG" | "LR">; | ||||
|             const typedValue = value as IObjectParamValue; | ||||
| 
 | ||||
|             return <ObjectPicker | ||||
|                 key={indexKey} | ||||
|                 keyI18n="Panel.Info.Behavior.Details.Parameter.Key" | ||||
|                 keyI18nOption={{ key: i18nString }} | ||||
|                 type={type} | ||||
|                 value={typedValue.picker} | ||||
|                 valueChange={(obj) => { | ||||
|                     typedValue.picker = obj as IObjectParamValue["picker"]; | ||||
|                     this.props.change(key, typedValue as IParamValue<P[K]>); | ||||
|                 }} | ||||
|                 cleanValue={() => { | ||||
|                     typedValue.picker = undefined as IObjectParamValue["picker"]; | ||||
|                     this.props.change(key, typedValue as IParamValue<P[K]>); | ||||
|                 }} | ||||
|             /> | ||||
|         } | ||||
| 
 | ||||
|         else if (isVectorType(type)) { | ||||
| 
 | ||||
|             type IObjectParamValue = IParamValue<"vec">; | ||||
|             const typedValue = value as IObjectParamValue; | ||||
|              | ||||
|             return <Fragment key={indexKey}> | ||||
|                  | ||||
|                 <AttrInput | ||||
|                     key={`${indexKey}-X`} | ||||
|                     id={indexKey} | ||||
|                     keyI18n="Panel.Info.Behavior.Details.Parameter.Key.Vec.X" | ||||
|                     keyI18nOption={{ key: i18nString }} | ||||
|                     isNumber={true} | ||||
|                     step={option.numberStep} | ||||
|                     maxLength={option.maxLength} | ||||
|                     max={option.numberMax} | ||||
|                     min={option.numberMin} | ||||
|                     value={typedValue[0] ?? 0} | ||||
|                     valueChange={(val) => { | ||||
|                         typedValue[0] = parseFloat(val); | ||||
|                         this.props.change(key, typedValue as IParamValue<P[K]>); | ||||
|                     }} | ||||
|                 /> | ||||
| 
 | ||||
|                 <AttrInput | ||||
|                     key={`${indexKey}-Y`} | ||||
|                     id={indexKey} | ||||
|                     keyI18n="Panel.Info.Behavior.Details.Parameter.Key.Vec.Y" | ||||
|                     keyI18nOption={{ key: i18nString }} | ||||
|                     isNumber={true} | ||||
|                     step={option.numberStep} | ||||
|                     maxLength={option.maxLength} | ||||
|                     max={option.numberMax} | ||||
|                     min={option.numberMin} | ||||
|                     value={typedValue[1] ?? 0} | ||||
|                     valueChange={(val) => { | ||||
|                         typedValue[1] = parseFloat(val); | ||||
|                         this.props.change(key, typedValue as IParamValue<P[K]>); | ||||
|                     }} | ||||
|                 /> | ||||
| 
 | ||||
|                 <AttrInput | ||||
|                     key={`${indexKey}-Z`} | ||||
|                     id={indexKey} | ||||
|                     keyI18n="Panel.Info.Behavior.Details.Parameter.Key.Vec.Z" | ||||
|                     keyI18nOption={{ key: i18nString }} | ||||
|                     isNumber={true} | ||||
|                     step={option.numberStep} | ||||
|                     maxLength={option.maxLength} | ||||
|                     max={option.numberMax} | ||||
|                     min={option.numberMin} | ||||
|                     value={typedValue[2] ?? 0} | ||||
|                     valueChange={(val) => { | ||||
|                         typedValue[2] = parseFloat(val); | ||||
|                         this.props.change(key, typedValue as IParamValue<P[K]>); | ||||
|                     }} | ||||
|                 /> | ||||
| 
 | ||||
|             </Fragment> | ||||
|         } | ||||
| 
 | ||||
|         else { | ||||
|             return <Fragment key={indexKey}/> | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private renderAllParameter(key: Array<keyof P>) { | ||||
|         return key.map((key) => { | ||||
|             return this.renderParameter( | ||||
|                 key, | ||||
|                 this.props.option[key], | ||||
|                 this.props.value[key], | ||||
|             ); | ||||
|         }); | ||||
|     } | ||||
|      | ||||
|     public render(): ReactNode { | ||||
|         const allOptionKeys: Array<keyof P> = Object.getOwnPropertyNames(this.props.option); | ||||
|          | ||||
|         return <> | ||||
|          | ||||
|             { | ||||
|                 allOptionKeys.length <= 0 && this.props.title ? | ||||
|                     <Message | ||||
|                         isTitle | ||||
|                         first={this.props.isFirst} | ||||
|                         i18nKey={this.props.title} | ||||
|                         options={this.props.titleOption} | ||||
|                     /> : null | ||||
|             } | ||||
| 
 | ||||
|             { | ||||
|                 this.renderAllParameter(allOptionKeys) | ||||
|             } | ||||
|          | ||||
|         </> | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { Parameter } | ||||
| @ -11,7 +11,8 @@ import { Setting } from "./Setting"; | ||||
| import { I18N } from "@Component/Localization/Localization"; | ||||
| import { superConnectWithEvent, superConnect } from "./Context"; | ||||
| import { PopupController } from "./Popups"; | ||||
| import { Behavior, IBehaviorParameter, IParamValue } from "@Model/Behavior"; | ||||
| import { Behavior } from "@Model/Behavior"; | ||||
| import { IParameter, IParamValue } from "@Model/Parameter"; | ||||
| import { Actuator } from "@Model/Actuator"; | ||||
| 
 | ||||
| function randomColor(unNormal: boolean = false) { | ||||
| @ -208,7 +209,7 @@ class Status extends Emitter<IStatusEvent> { | ||||
|     /** | ||||
|      * 修改群属性 | ||||
|      */ | ||||
|     public changeBehaviorAttrib<K extends IBehaviorParameter, P extends keyof K | keyof Behavior<K>> | ||||
|     public changeBehaviorAttrib<K extends IParameter, P extends keyof K | keyof Behavior<K>> | ||||
|     (id: ObjectID, key: P, val: IParamValue<K[P]>, noParameter?: boolean) { | ||||
|         const behavior = this.model.getBehaviorById(id); | ||||
|         if (behavior) { | ||||
|  | ||||
| @ -3,17 +3,17 @@ import type { Individual } from "./Individual"; | ||||
| import type { Group } from "./Group"; | ||||
| import type { Model } from "./Model"; | ||||
| import { | ||||
|     IParamValue, isObjectType, isVectorType, | ||||
|     IBehaviorParameterOptionItem, IBehaviorParameter, IBehaviorParameterOption, IBehaviorParameterValue | ||||
|     IParamValue, isObjectType, isVectorType, getDefaultValue, | ||||
|     IParameterOptionItem, IParameter, IParameterOption, IParameterValue | ||||
| } from "./Parameter"; | ||||
| 
 | ||||
| /** | ||||
|  * 行为构造函数类型 | ||||
|  */ | ||||
| type IBehaviorConstructor< | ||||
|     P extends IBehaviorParameter = {}, | ||||
|     P extends IParameter = {}, | ||||
|     E extends Record<EventType, any> = {} | ||||
| > = new (id: string, parameter: IBehaviorParameterValue<P>) => Behavior<P, E>; | ||||
| > = new (id: string, parameter: IParameterValue<P>) => Behavior<P, E>; | ||||
| 
 | ||||
| type IAnyBehavior = Behavior<any, any>; | ||||
| type IAnyBehaviorRecorder = BehaviorRecorder<any, any>; | ||||
| @ -75,7 +75,7 @@ class BehaviorInfo<E extends Record<EventType, any> = {}> extends Emitter<E> { | ||||
| } | ||||
| 
 | ||||
| class BehaviorRecorder< | ||||
|     P extends IBehaviorParameter = {}, | ||||
|     P extends IParameter = {}, | ||||
|     E extends Record<EventType, any> = {} | ||||
| > extends BehaviorInfo<{}> { | ||||
| 
 | ||||
| @ -104,62 +104,13 @@ class BehaviorRecorder< | ||||
|     /** | ||||
|      * 对象参数列表 | ||||
|      */ | ||||
|     public parameterOption: IBehaviorParameterOption<P>; | ||||
| 
 | ||||
|     /** | ||||
|      * 获取参数列表的默认值 | ||||
|      */ | ||||
|     public getDefaultValue(): IBehaviorParameterValue<P> { | ||||
|         let defaultObj = {} as IBehaviorParameterValue<P>; | ||||
|         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; | ||||
|                      | ||||
|                     case "G": | ||||
|                     case "R": | ||||
|                         defaultObj[key] = { | ||||
|                             picker: undefined, | ||||
|                             objects: undefined | ||||
|                         } as any; | ||||
|                         break; | ||||
| 
 | ||||
|                     case "LR": | ||||
|                     case "LG": | ||||
|                         defaultObj[key] = { | ||||
|                             picker: undefined, | ||||
|                             objects: [] | ||||
|                         } as any; | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return defaultObj; | ||||
|     } | ||||
|     public parameterOption: IParameterOption<P>; | ||||
| 
 | ||||
|     /** | ||||
|      * 创建一个新的行为实例 | ||||
|      */ | ||||
|     public new(): Behavior<P, E> { | ||||
|         return new this.behavior(this.getNextId(), this.getDefaultValue()); | ||||
|         return new this.behavior(this.getNextId(), getDefaultValue(this.parameterOption)); | ||||
|     } | ||||
| 
 | ||||
|     public constructor(behavior: IBehaviorConstructor<P, E>) { | ||||
| @ -180,7 +131,7 @@ class BehaviorRecorder< | ||||
|  * 群体的某种行为 | ||||
|  */ | ||||
| class Behavior< | ||||
|     P extends IBehaviorParameter = {}, | ||||
|     P extends IParameter = {}, | ||||
|     E extends Record<EventType, any> = {} | ||||
| > extends BehaviorInfo<E> { | ||||
| 
 | ||||
| @ -208,14 +159,14 @@ class Behavior< | ||||
|     /** | ||||
|      * 行为参数 | ||||
|      */ | ||||
|     public parameter: IBehaviorParameterValue<P>; | ||||
|     public parameter: IParameterValue<P>; | ||||
| 
 | ||||
|     /** | ||||
|      * 对象参数列表 | ||||
|      */ | ||||
|     public parameterOption: IBehaviorParameterOption<P> = {} as any; | ||||
|     public parameterOption: IParameterOption<P> = {} as any; | ||||
| 
 | ||||
|     public constructor(id: string, parameter: IBehaviorParameterValue<P>) { | ||||
|     public constructor(id: string, parameter: IParameterValue<P>) { | ||||
|         super(); | ||||
|         this.id = id; | ||||
|         this.parameter = parameter; | ||||
| @ -299,8 +250,6 @@ class Behavior< | ||||
| type IRenderBehavior = BehaviorInfo | Behavior; | ||||
| 
 | ||||
| export { | ||||
|     Behavior, BehaviorRecorder, IBehaviorParameterOption, IBehaviorParameterOptionItem, IParamValue, | ||||
|     IAnyBehavior, IAnyBehaviorRecorder, BehaviorInfo, IRenderBehavior, IBehaviorParameter, | ||||
|     isObjectType, isVectorType | ||||
|     Behavior, BehaviorRecorder, IAnyBehavior, IAnyBehaviorRecorder, BehaviorInfo, IRenderBehavior | ||||
| }; | ||||
| export default { Behavior }; | ||||
| @ -5,7 +5,8 @@ import { Emitter, EventType, EventMixin } from "./Emitter"; | ||||
| import { CtrlObject } from "./CtrlObject"; | ||||
| import { ObjectID, AbstractRenderer } from "./Renderer"; | ||||
| import { Label } from "./Label"; | ||||
| import { Behavior, IAnyBehavior, IAnyBehaviorRecorder, IParamValue } from "./Behavior"; | ||||
| import { Behavior, IAnyBehavior, IAnyBehaviorRecorder } from "./Behavior"; | ||||
| import { IParamValue } from "@Model/Parameter";  | ||||
| 
 | ||||
| type ModelEvent = { | ||||
|     labelChange: Label[]; | ||||
|  | ||||
| @ -39,26 +39,26 @@ type IParamValue<K extends IParamType> = AllMapType[K]; | ||||
| /** | ||||
|  * 特殊对象类型判定 | ||||
|  */ | ||||
| const objectTypeListEnumSet = new Set<IParamType>(["R", "G", "LR", "LG"]); | ||||
| const objectTypeListEnumSet = new Set<string>(["R", "G", "LR", "LG"]); | ||||
| 
 | ||||
|  /** | ||||
|   * 对象断言表达式 | ||||
|   */ | ||||
| function isObjectType(key: IParamType): key is IVectorType { | ||||
| function isObjectType(key: string): key is IVectorType { | ||||
|     return objectTypeListEnumSet.has(key); | ||||
| } | ||||
|   | ||||
|  /** | ||||
|   * 向量断言表达式 | ||||
|   */ | ||||
| function isVectorType(key: IParamType): key is IObjectType { | ||||
| function isVectorType(key: string): key is IObjectType { | ||||
|     return key === "vec"; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 模型参数类型 | ||||
|  */ | ||||
| interface IBehaviorParameterOptionItem<T extends IParamType = IParamType> { | ||||
| interface IParameterOptionItem<T extends IParamType = IParamType> { | ||||
| 
 | ||||
|     /** | ||||
|      * 参数类型 | ||||
| @ -102,25 +102,72 @@ interface IBehaviorParameterOptionItem<T extends IParamType = IParamType> { | ||||
|     iconName?: string; | ||||
| } | ||||
| 
 | ||||
| interface IBehaviorParameter { | ||||
| interface IParameter { | ||||
|     [x: string]: IParamType; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 参数类型列表 | ||||
|  */ | ||||
| type IBehaviorParameterOption<P extends IBehaviorParameter> = { | ||||
|     [X in keyof P]: IBehaviorParameterOptionItem<P[X]>; | ||||
| type IParameterOption<P extends IParameter> = { | ||||
|     [X in keyof P]: IParameterOptionItem<P[X]>; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 参数类型列表映射到参数对象 | ||||
|  */ | ||||
| type IBehaviorParameterValue<P extends IBehaviorParameter> = { | ||||
| type IParameterValue<P extends IParameter> = { | ||||
|     [X in keyof P]: IParamValue<P[X]> | ||||
| } | ||||
| 
 | ||||
| export { | ||||
|     IParamType, IParamValue, isObjectType, isVectorType, | ||||
|     IBehaviorParameterOptionItem, IBehaviorParameter, IBehaviorParameterOption, IBehaviorParameterValue | ||||
| function getDefaultValue<P extends IParameter> (option: IParameterOption<P>): IParameterValue<P> { | ||||
|     let defaultObj = {} as IParameterValue<P>; | ||||
|     for (let key in option) { | ||||
|         let defaultVal = option[key].defaultValue; | ||||
|          | ||||
|         if (defaultVal !== undefined) { | ||||
|             defaultObj[key] = defaultVal; | ||||
|         } else { | ||||
| 
 | ||||
|             switch (option[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; | ||||
|                  | ||||
|                 case "G": | ||||
|                 case "R": | ||||
|                     defaultObj[key] = { | ||||
|                         picker: undefined, | ||||
|                         objects: undefined | ||||
|                     } as any; | ||||
|                     break; | ||||
| 
 | ||||
|                 case "LR": | ||||
|                 case "LG": | ||||
|                     defaultObj[key] = { | ||||
|                         picker: undefined, | ||||
|                         objects: [] | ||||
|                     } as any; | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return defaultObj; | ||||
| } | ||||
| 
 | ||||
| export { | ||||
|     IParamType, IParamValue, isObjectType, isVectorType, getDefaultValue, | ||||
|     IParameterOptionItem, IParameter, IParameterOption, IParameterValue | ||||
| } | ||||
| @ -55,16 +55,16 @@ class SimulatorWeb extends Component { | ||||
|             this.status.model.update(0); | ||||
|             this.status.newLabel().name = "New Label"; | ||||
|             this.status.newLabel().name = "Test Label 01"; | ||||
|             // let template = this.status.model.addBehavior(AllBehaviors[0]);
 | ||||
|             // template.name = "Template"; template.color = [150, 20, 220];
 | ||||
|             let dynamic = this.status.model.addBehavior(AllBehaviors[0]); | ||||
|             let template = this.status.model.addBehavior(AllBehaviors[0]); | ||||
|             template.name = "Template"; template.color = [150, 20, 220]; | ||||
|             let dynamic = this.status.model.addBehavior(AllBehaviors[1]); | ||||
|             dynamic.name = "Dynamic"; dynamic.color = [250, 200, 80]; | ||||
|             let brownian = this.status.model.addBehavior(AllBehaviors[1]); | ||||
|             let brownian = this.status.model.addBehavior(AllBehaviors[2]); | ||||
|             brownian.name = "Brownian"; brownian.color = [200, 80, 250]; | ||||
|             let boundary = this.status.model.addBehavior(AllBehaviors[2]); | ||||
|             let boundary = this.status.model.addBehavior(AllBehaviors[3]); | ||||
|             boundary.name = "Boundary"; boundary.color = [80, 200, 250]; | ||||
|             // boundary.parameter.range.picker = this.status.model.allRangeLabel;
 | ||||
|             // group.addBehavior(template);
 | ||||
|             boundary.parameter.range.picker = this.status.model.allRangeLabel; | ||||
|             group.addBehavior(template); | ||||
|             group.addBehavior(dynamic); | ||||
|             group.addBehavior(brownian); | ||||
|             group.addBehavior(boundary); | ||||
|  | ||||
| @ -1,13 +1,13 @@ | ||||
| import { Component, Fragment, ReactNode} from "react"; | ||||
| import { Component, ReactNode} from "react"; | ||||
| import { useSettingWithEvent, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { Behavior, IBehaviorParameter, isObjectType, isVectorType } from "@Model/Behavior"; | ||||
| import { IAnyBehavior } from "@Model/Behavior"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { AttrInput } from "@Component/AttrInput/AttrInput"; | ||||
| import { ColorInput } from "@Component/ColorInput/ColorInput"; | ||||
| import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { ObjectPicker } from "@Component/ObjectPicker/ObjectPicker"; | ||||
| import { Parameter } from "@Component/Parameter/Parameter"; | ||||
| import "./BehaviorDetails.scss"; | ||||
| 
 | ||||
| interface IBehaviorDetailsProps {} | ||||
| @ -16,10 +16,23 @@ interface IBehaviorDetailsProps {} | ||||
| @useStatusWithEvent("focusBehaviorChange", "behaviorAttrChange") | ||||
| class BehaviorDetails extends Component<IBehaviorDetailsProps & IMixinStatusProps & IMixinSettingProps> { | ||||
| 
 | ||||
| 	private renderFrom<T extends IBehaviorParameter> | ||||
|     (behavior: Behavior<T, Record<string, any>>): ReactNode { | ||||
|     private handelDeleteBehavior = (behavior: IAnyBehavior) => { | ||||
|         if (this.props.status) { | ||||
|             const status = this.props.status; | ||||
|             status.popup.showPopup(ConfirmPopup, { | ||||
|                 infoI18n: "Popup.Delete.Behavior.Confirm", | ||||
|                 titleI18N: "Popup.Action.Objects.Confirm.Title", | ||||
|                 yesI18n: "Popup.Action.Objects.Confirm.Delete", | ||||
|                 red: "yes", | ||||
|                 yes: () => { | ||||
|                     status.model.deleteBehavior(behavior); | ||||
|                     status.setBehaviorObject(); | ||||
|                 } | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|         const allParameterKeys = Object.getOwnPropertyNames(behavior.parameterOption); | ||||
| 	private renderFrom(behavior: IAnyBehavior): ReactNode { | ||||
|          | ||||
| 		return <> | ||||
|          | ||||
| @ -44,145 +57,29 @@ class BehaviorDetails extends Component<IBehaviorDetailsProps & IMixinStatusProp | ||||
| 				keyI18n="Common.Attr.Key.Delete" red | ||||
| 				onIconName="delete" offIconName="delete" | ||||
| 				valueChange={() => { | ||||
| 					if (this.props.status) { | ||||
|                         const status = this.props.status; | ||||
|                         status.popup.showPopup(ConfirmPopup, { | ||||
|                             infoI18n: "Popup.Delete.Behavior.Confirm", | ||||
|                             titleI18N: "Popup.Action.Objects.Confirm.Title", | ||||
|                             yesI18n: "Popup.Action.Objects.Confirm.Delete", | ||||
|                             red: "yes", | ||||
|                             yes: () => { | ||||
|                                 status.model.deleteBehavior(behavior); | ||||
|                                 status.setBehaviorObject(); | ||||
|                             } | ||||
|                         }) | ||||
|                     } | ||||
| 					this.handelDeleteBehavior(behavior) | ||||
| 				}} | ||||
| 			/> | ||||
|              | ||||
|             { | ||||
|                 allParameterKeys.length > 0 ? | ||||
|                     <Message | ||||
|                         isTitle | ||||
|                         i18nKey="Panel.Info.Behavior.Details.Behavior.Props" | ||||
|                         options={{ | ||||
|                             behavior: behavior.getTerms(behavior.behaviorName, this.props.setting?.language) | ||||
|                         }} | ||||
|                     /> : null | ||||
|             } | ||||
|              | ||||
|             { | ||||
|                 allParameterKeys.map((key) => { | ||||
|                     return this.renderParameter(behavior, key); | ||||
|                 }) | ||||
|             } | ||||
|             <Parameter | ||||
|                 key={behavior.id} | ||||
|                 option={behavior.parameterOption} | ||||
|                 value={behavior.parameter} | ||||
|                 i18n={(option, language) => behavior.getTerms(option.name, language)} | ||||
|                 title={"Panel.Info.Behavior.Details.Behavior.Props"} | ||||
|                 titleOption={{ | ||||
|                     behavior: behavior.getTerms(behavior.behaviorName, this.props.setting?.language) | ||||
|                 }} | ||||
|                 change={(key, value) => { | ||||
|                     this.props.status?.changeBehaviorAttrib( | ||||
|                         behavior.id, key as string, value | ||||
|                     ); | ||||
|                 }} | ||||
|             /> | ||||
| 
 | ||||
|         </>; | ||||
| 	} | ||||
| 
 | ||||
|     private renderParameter<T extends IBehaviorParameter> | ||||
|     (behavior: Behavior<T, Record<string, any>>, key: keyof T): ReactNode { | ||||
|         const type = behavior.parameterOption[key]; | ||||
|         const value = behavior.parameter[key]; | ||||
|         const indexKey = `${behavior.id}-${key}`; | ||||
| 
 | ||||
|         if (type.type === "number") { | ||||
|             return <AttrInput | ||||
|                 keyI18n="Panel.Info.Behavior.Details.Parameter.Key" | ||||
|                 keyI18nOption={{ key: behavior.getTerms(type.name, this.props.setting?.language) }} | ||||
|                 key={indexKey} id={indexKey} isNumber={true} step={type.numberStep} maxLength={type.maxLength} | ||||
|                 max={type.numberMax} min={type.numberMin} | ||||
|                 value={(value as number) ?? 0} | ||||
|                 valueChange={(val) => { | ||||
|                     this.props.status?.changeBehaviorAttrib(behavior.id, key as string, (val as any) / 1); | ||||
|                 }} | ||||
|             /> | ||||
|         } | ||||
| 
 | ||||
|         if (type.type === "string") { | ||||
|             return <AttrInput | ||||
|                 keyI18n="Panel.Info.Behavior.Details.Parameter.Key" | ||||
|                 keyI18nOption={{ key: behavior.getTerms(type.name, this.props.setting?.language) }} | ||||
|                 key={indexKey} id={indexKey} maxLength={type.maxLength} | ||||
|                 value={(value as string) ?? ""} | ||||
|                 valueChange={(val) => { | ||||
|                     this.props.status?.changeBehaviorAttrib(behavior.id, key as string, val); | ||||
|                 }} | ||||
|             /> | ||||
|         } | ||||
| 
 | ||||
|         if (type.type === "boolean") { | ||||
|             return <TogglesInput | ||||
|                 keyI18n="Panel.Info.Behavior.Details.Parameter.Key" | ||||
|                 keyI18nOption={{ key: behavior.getTerms(type.name, this.props.setting?.language) }} | ||||
| 				onIconName={type.iconName} key={indexKey} value={(value as boolean) ?? false} | ||||
| 				valueChange={(val) => { | ||||
| 					this.props.status?.changeBehaviorAttrib(behavior.id, key as string, val); | ||||
| 				}} | ||||
| 			/> | ||||
|         } | ||||
| 
 | ||||
|         if (isObjectType(type.type as any)) { | ||||
|             return <ObjectPicker | ||||
|                 keyI18n="Panel.Info.Behavior.Details.Parameter.Key" | ||||
|                 keyI18nOption={{ key: behavior.getTerms(type.name, this.props.setting?.language) }} | ||||
|                 type={type.type} value={(value as any).picker} key={indexKey} | ||||
|                 valueChange={(obj) => { | ||||
|                     (value as any).picker = obj; | ||||
|                     this.props.status?.changeBehaviorAttrib(behavior.id, key as string, value); | ||||
|                 }} | ||||
|                 cleanValue={() => { | ||||
|                     (value as any).picker = undefined; | ||||
|                     this.props.status?.changeBehaviorAttrib(behavior.id, key as string, value); | ||||
|                 }} | ||||
|             /> | ||||
|         } | ||||
| 
 | ||||
|         if (isVectorType(type.type as any)) { | ||||
|             return <Fragment key={indexKey}> | ||||
|                  | ||||
|                 <AttrInput | ||||
|                     keyI18n="Panel.Info.Behavior.Details.Parameter.Key.Vec.X" | ||||
|                     keyI18nOption={{ key: behavior.getTerms(type.name, this.props.setting?.language) }} | ||||
|                     key={`${indexKey}-X`} id={indexKey} isNumber={true} step={type.numberStep} maxLength={type.maxLength} | ||||
|                     max={type.numberMax} min={type.numberMin} | ||||
|                     value={(value as number[])[0] ?? 0} | ||||
|                     valueChange={(val) => { | ||||
|                         (value as number[])[0] = (val as any) / 1; | ||||
|                         this.props.status?.changeBehaviorAttrib(behavior.id, key as string, value); | ||||
|                     }} | ||||
|                 /> | ||||
| 
 | ||||
|                 <AttrInput | ||||
|                     keyI18n="Panel.Info.Behavior.Details.Parameter.Key.Vec.Y" | ||||
|                     keyI18nOption={{ key: behavior.getTerms(type.name, this.props.setting?.language) }} | ||||
|                     key={`${indexKey}-Y`} id={indexKey} isNumber={true} step={type.numberStep} maxLength={type.maxLength} | ||||
|                     max={type.numberMax} min={type.numberMin} | ||||
|                     value={(value as number[])[1] ?? 0} | ||||
|                     valueChange={(val) => { | ||||
|                         (value as number[])[1] = (val as any) / 1; | ||||
|                         this.props.status?.changeBehaviorAttrib(behavior.id, key as string, value); | ||||
|                     }} | ||||
|                 /> | ||||
| 
 | ||||
|                 <AttrInput | ||||
|                     keyI18n="Panel.Info.Behavior.Details.Parameter.Key.Vec.Z" | ||||
|                     keyI18nOption={{ key: behavior.getTerms(type.name, this.props.setting?.language) }} | ||||
|                     key={`${indexKey}-Z`} id={indexKey} isNumber={true} step={type.numberStep} maxLength={type.maxLength} | ||||
|                     max={type.numberMax} min={type.numberMin} | ||||
|                     value={(value as number[])[2] ?? 0} | ||||
|                     valueChange={(val) => { | ||||
|                         (value as number[])[2] = (val as any) / 1; | ||||
|                         this.props.status?.changeBehaviorAttrib(behavior.id, key as string, value); | ||||
|                     }} | ||||
|                 /> | ||||
| 
 | ||||
|             </Fragment> | ||||
|         } | ||||
| 
 | ||||
|         return <Fragment key={indexKey}/> | ||||
|     } | ||||
| 
 | ||||
| 	public render(): ReactNode { | ||||
| 		if (this.props.status && this.props.status.focusBehavior) { | ||||
|             return this.renderFrom(this.props.status.focusBehavior); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user