From cad68e8b9b5fb3053b8be17591fb72276f6d9c93 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Tue, 5 Apr 2022 16:37:36 +0800 Subject: [PATCH] Add behavior details panel --- source/Behavior/Behavior.ts | 3 +- source/Behavior/Template.ts | 60 ++++++- source/Component/TextField/TextField.tsx | 3 +- source/Context/Status.tsx | 11 +- source/Localization/EN-US.ts | 4 + source/Localization/ZH-CN.ts | 4 + source/Model/Behavior.ts | 5 +- source/Page/SimulatorWeb/SimulatorWeb.tsx | 9 +- .../Panel/BehaviorDetails/BehaviorDetails.tsx | 151 ++++++++++++++++-- 9 files changed, 220 insertions(+), 30 deletions(-) diff --git a/source/Behavior/Behavior.ts b/source/Behavior/Behavior.ts index 0309072..15c2dad 100644 --- a/source/Behavior/Behavior.ts +++ b/source/Behavior/Behavior.ts @@ -5,9 +5,10 @@ import { Brownian } from "./Brownian"; import { BoundaryConstraint } from "./BoundaryConstraint"; const AllBehaviors: IAnyBehaviorRecorder[] = [ + new BehaviorRecorder(Template), new BehaviorRecorder(Dynamics), new BehaviorRecorder(Brownian), - new BehaviorRecorder(BoundaryConstraint) + new BehaviorRecorder(BoundaryConstraint), ] /** diff --git a/source/Behavior/Template.ts b/source/Behavior/Template.ts index b862559..916c5eb 100644 --- a/source/Behavior/Template.ts +++ b/source/Behavior/Template.ts @@ -4,7 +4,14 @@ import { Individual } from "@Model/Individual"; import { Model } from "@Model/Model"; type ITemplateBehaviorParameter = { - + testNumber: "number"; + testString: "string"; + testBoolean: "boolean"; + testR: "R"; + testG: "G"; + testLR: "LR"; + testLG: "LG"; + testVec: "vec"; } type ITemplateBehaviorEvent = {} @@ -21,6 +28,53 @@ class Template extends Behavior> = { "$Title": { "ZH_CN": "行为", @@ -29,6 +83,10 @@ class Template extends Behavior; infoI18n?: AllI18nKeys; disableI18n?: AllI18nKeys; disableI18nOption?: Record; @@ -82,7 +83,7 @@ class TextField extends Component { return <>
- +
{ diff --git a/source/Context/Status.tsx b/source/Context/Status.tsx index 838b3e3..42b5ba0 100644 --- a/source/Context/Status.tsx +++ b/source/Context/Status.tsx @@ -209,15 +209,16 @@ class Status extends Emitter { * 修改群属性 */ public changeBehaviorAttrib> - (id: ObjectID, key: P, val: IParamValue) { + (id: ObjectID, key: P, val: IParamValue, noParameter?: boolean) { const behavior = this.model.getBehaviorById(id); if (behavior) { - if (key === "color") { - behavior.color = val as number[]; - } else if (key === "name") { - behavior.name = val as string; + if (noParameter) { + behavior[key as keyof Behavior] = val as never; } else { behavior.parameter[key] = val; + behavior.parameterOption[key]?.onChange ? + behavior.parameterOption[key]?.onChange!(val) : + undefined; } this.emit("behaviorAttrChange"); } diff --git a/source/Localization/EN-US.ts b/source/Localization/EN-US.ts index d28b7f9..b172fad 100644 --- a/source/Localization/EN-US.ts +++ b/source/Localization/EN-US.ts @@ -113,5 +113,9 @@ const EN_US = { "Panel.Info.Label.List.Error.Nodata": "There are no labels in the model, click the button to create", "Panel.Info.Behavior.Details.Error.Not.Behavior": "Please specify a behavior first to view the details", "Panel.Info.Behavior.Details.Behavior.Props": "{behavior} parameter", + "Panel.Info.Behavior.Details.Parameter.Key": "{key}", + "Panel.Info.Behavior.Details.Parameter.Key.Vec.X": "{key} X", + "Panel.Info.Behavior.Details.Parameter.Key.Vec.Y": "{key} Y", + "Panel.Info.Behavior.Details.Parameter.Key.Vec.Z": "{key} Z", } export default EN_US; \ No newline at end of file diff --git a/source/Localization/ZH-CN.ts b/source/Localization/ZH-CN.ts index c28978a..add0744 100644 --- a/source/Localization/ZH-CN.ts +++ b/source/Localization/ZH-CN.ts @@ -113,5 +113,9 @@ const ZH_CN = { "Panel.Info.Label.List.Error.Nodata": "模型中没有标签,点击按钮以创建", "Panel.Info.Behavior.Details.Error.Not.Behavior": "请先指定一个行为以查看详情", "Panel.Info.Behavior.Details.Behavior.Props": "{behavior}参数", + "Panel.Info.Behavior.Details.Parameter.Key": "{key}", + "Panel.Info.Behavior.Details.Parameter.Key.Vec.X": "{key} X 坐标", + "Panel.Info.Behavior.Details.Parameter.Key.Vec.Y": "{key} Y 坐标", + "Panel.Info.Behavior.Details.Parameter.Key.Vec.Z": "{key} Z 坐标", } export default ZH_CN; \ No newline at end of file diff --git a/source/Model/Behavior.ts b/source/Model/Behavior.ts index b5f40bf..37618ff 100644 --- a/source/Model/Behavior.ts +++ b/source/Model/Behavior.ts @@ -87,7 +87,7 @@ interface IBehaviorParameterOptionItem { /** * 字符长度 */ - stringLength?: number; + maxLength?: number; /** * 数字步长 @@ -417,6 +417,7 @@ type IRenderBehavior = BehaviorInfo | Behavior; export { Behavior, BehaviorRecorder, IBehaviorParameterOption, IBehaviorParameterOptionItem, IParamValue, - IAnyBehavior, IAnyBehaviorRecorder, BehaviorInfo, IRenderBehavior, IBehaviorParameter + IAnyBehavior, IAnyBehaviorRecorder, BehaviorInfo, IRenderBehavior, IBehaviorParameter, + isObjectType, isVectorType }; export default { Behavior }; \ No newline at end of file diff --git a/source/Page/SimulatorWeb/SimulatorWeb.tsx b/source/Page/SimulatorWeb/SimulatorWeb.tsx index e5aaec6..80e0b04 100644 --- a/source/Page/SimulatorWeb/SimulatorWeb.tsx +++ b/source/Page/SimulatorWeb/SimulatorWeb.tsx @@ -55,13 +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 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 = this.status.model.allRangeLabel; + group.addBehavior(template); group.addBehavior(dynamic); group.addBehavior(brownian); group.addBehavior(boundary); diff --git a/source/Panel/BehaviorDetails/BehaviorDetails.tsx b/source/Panel/BehaviorDetails/BehaviorDetails.tsx index 9bfcbde..448c98c 100644 --- a/source/Panel/BehaviorDetails/BehaviorDetails.tsx +++ b/source/Panel/BehaviorDetails/BehaviorDetails.tsx @@ -1,19 +1,26 @@ -import { Component, ReactNode} from "react"; +import { Component, Fragment, ReactNode} from "react"; +import { useSettingWithEvent, IMixinSettingProps } from "@Context/Setting"; import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; -import { Behavior } from "@Model/Behavior"; +import { Behavior, IBehaviorParameter, isObjectType, isVectorType } 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 "./BehaviorDetails.scss"; interface IBehaviorDetailsProps {} +@useSettingWithEvent("language") @useStatusWithEvent("focusBehaviorChange", "behaviorAttrChange") -class BehaviorDetails extends Component { +class BehaviorDetails extends Component { + + private renderFrom + (behavior: Behavior>): ReactNode { + + const allParameterKeys = Object.getOwnPropertyNames(behavior.parameterOption); - private renderFrom(behavior: Behavior): ReactNode { return <> @@ -21,7 +28,7 @@ class BehaviorDetails extends Component { - this.props.status?.changeBehaviorAttrib(behavior.id, "name", val); + this.props.status?.changeBehaviorAttrib(behavior.id, "name", val, true); }} /> @@ -29,7 +36,7 @@ class BehaviorDetails extends Component { - this.props.status?.changeBehaviorAttrib(behavior.id, "color", color); + this.props.status?.changeBehaviorAttrib(behavior.id, "color", color, true); }} /> @@ -53,22 +60,132 @@ class BehaviorDetails extends Component - + { + allParameterKeys.length > 0 ? + : null + } + + { + allParameterKeys.map((key) => { + return this.renderParameter(behavior, key); + }) + } ; } + private renderParameter + (behavior: Behavior>, key: keyof T): ReactNode { + const type = behavior.parameterOption[key]; + const value = behavior.parameter[key]; + const indexKey = `${behavior.id}-${key}`; + + if (type.type === "number") { + return { + this.props.status?.changeBehaviorAttrib(behavior.id, key as string, (val as any) / 1); + }} + /> + } + + if (type.type === "string") { + return { + this.props.status?.changeBehaviorAttrib(behavior.id, key as string, val); + }} + /> + } + + if (type.type === "boolean") { + return { + this.props.status?.changeBehaviorAttrib(behavior.id, key as string, val); + }} + /> + } + + if (isObjectType(type.type as any)) { + return { + (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 + + { + (value as number[])[0] = (val as any) / 1; + this.props.status?.changeBehaviorAttrib(behavior.id, key as string, value); + }} + /> + + { + (value as number[])[1] = (val as any) / 1; + this.props.status?.changeBehaviorAttrib(behavior.id, key as string, value); + }} + /> + + { + (value as number[])[2] = (val as any) / 1; + this.props.status?.changeBehaviorAttrib(behavior.id, key as string, value); + }} + /> + + + } + + return + } + public render(): ReactNode { - if (this.props.status) { - if (this.props.status.focusBehavior) { - return this.renderFrom(this.props.status.focusBehavior); - } + if (this.props.status && this.props.status.focusBehavior) { + return this.renderFrom(this.props.status.focusBehavior); } return ; }