Mod boundary constraint func & Separate parameter model & Add parameter component #36
| @ -1,8 +1,8 @@ | ||||
| import { BehaviorRecorder, IAnyBehaviorRecorder } from "@Model/Behavior"; | ||||
| import { Template } from "./Template"; | ||||
| import { Dynamics } from "./Dynamics"; | ||||
| import { Brownian } from "./Brownian"; | ||||
| import { BoundaryConstraint } from "./BoundaryConstraint";  | ||||
| import { Template } from "@Behavior/Template"; | ||||
| import { Dynamics } from "@Behavior/Dynamics"; | ||||
| import { Brownian } from "@Behavior/Brownian"; | ||||
| import { BoundaryConstraint } from "@Behavior/BoundaryConstraint"; | ||||
| 
 | ||||
| const AllBehaviors: IAnyBehaviorRecorder[] = [ | ||||
|     new BehaviorRecorder(Template), | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| import { Behavior } from "@Model/Behavior"; | ||||
| import { Group } from "@Model/Group"; | ||||
| import { Individual } from "@Model/Individual"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import { Model } from "@Model/Model"; | ||||
| import { Range } from "@Model/Range"; | ||||
| 
 | ||||
| type IBoundaryConstraintBehaviorParameter = { | ||||
|     range: "LR" | ||||
|     range: "LR", | ||||
| 	strength: "number" | ||||
| } | ||||
| 
 | ||||
| type IBoundaryConstraintBehaviorEvent = {} | ||||
| @ -27,6 +27,13 @@ class BoundaryConstraint extends Behavior<IBoundaryConstraintBehaviorParameter, | ||||
| 		range: { | ||||
| 			type: "LR", | ||||
| 			name: "$range" | ||||
| 		}, | ||||
| 		strength: { | ||||
| 			type: "number", | ||||
| 			name: "$Strength", | ||||
| 			defaultValue: 1, | ||||
|             numberMin: 0, | ||||
|             numberStep: .1 | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| @ -35,6 +42,14 @@ class BoundaryConstraint extends Behavior<IBoundaryConstraintBehaviorParameter, | ||||
|             "ZH_CN": "边界约束", | ||||
|             "EN_US": "Boundary constraint" | ||||
|         }, | ||||
| 		"$range": { | ||||
| 			"ZH_CN": "约束范围", | ||||
| 			"EN_US": "Constraint range" | ||||
| 		}, | ||||
| 		"$Strength": { | ||||
| 			"ZH_CN": "约束强度系数", | ||||
| 			"EN_US": "Restraint strength coefficient" | ||||
| 		}, | ||||
|         "$Intro": { | ||||
|             "ZH_CN": "个体越出边界后将主动返回", | ||||
|             "EN_US": "Individuals will return actively after crossing the border" | ||||
| @ -43,6 +58,12 @@ class BoundaryConstraint extends Behavior<IBoundaryConstraintBehaviorParameter, | ||||
| 
 | ||||
|     public effect(individual: Individual, group: Group, model: Model, t: number): void { | ||||
|         let rangeList: Range[] = this.parameter.range.objects; | ||||
| 
 | ||||
| 		let fx = 0; | ||||
| 		let fy = 0; | ||||
| 		let fz = 0; | ||||
| 		let fLen = Infinity; | ||||
| 
 | ||||
| 		for (let i = 0; i < rangeList.length; i++) { | ||||
| 
 | ||||
| 			let rx = rangeList[i].position[0] - individual.position[0]; | ||||
| @ -53,12 +74,30 @@ class BoundaryConstraint extends Behavior<IBoundaryConstraintBehaviorParameter, | ||||
| 			let oy = Math.abs(ry) > rangeList[i].radius[1]; | ||||
| 			let oz = Math.abs(rz) > rangeList[i].radius[2]; | ||||
| 
 | ||||
| 			individual.applyForce( | ||||
| 				ox ? rx : 0, | ||||
| 				oy ? ry : 0, | ||||
| 				oz ? rz : 0 | ||||
| 			) | ||||
| 			if (ox || oy || oz) { | ||||
| 
 | ||||
| 				let currentFLen = individual.vectorLength(rx, ry, rz); | ||||
| 				if (currentFLen < fLen) { | ||||
| 					fx = rx; | ||||
| 					fy = ry; | ||||
| 					fz = rz; | ||||
| 					fLen = currentFLen; | ||||
| 				} | ||||
| 
 | ||||
| 			} else { | ||||
| 
 | ||||
| 				fx = 0; | ||||
| 				fy = 0; | ||||
| 				fz = 0; | ||||
| 				fLen = 0; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		individual.applyForce( | ||||
| 			fx * this.parameter.strength, | ||||
| 			fy * this.parameter.strength, | ||||
| 			fz * this.parameter.strength | ||||
| 		); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -49,7 +49,7 @@ class Dynamics extends Behavior<IDynamicsBehaviorParameter, IDynamicsBehaviorEve | ||||
| 		resistance: { | ||||
| 			name: "$Resistance", | ||||
| 			type: "number", | ||||
| 			defaultValue: 0.1, | ||||
| 			defaultValue: 0.5, | ||||
| 			numberStep: .1, | ||||
| 			numberMin: 0 | ||||
| 		} | ||||
| @ -76,6 +76,10 @@ class Dynamics extends Behavior<IDynamicsBehaviorParameter, IDynamicsBehaviorEve | ||||
| 			"ZH_CN": "最大速度 (m/s)", | ||||
|             "EN_US": "Maximum velocity (m/s)" | ||||
| 		}, | ||||
| 		"$Resistance": { | ||||
| 			"ZH_CN": "阻力系数", | ||||
| 			"EN_US": "Resistance coefficient" | ||||
| 		}, | ||||
| 		"$Physics": { | ||||
| 			"ZH_CN": "物理", | ||||
|             "EN_US": "Physics" | ||||
|  | ||||
| @ -1,11 +1,13 @@ | ||||
| import { Theme } from "@Component/Theme/Theme"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { IRenderBehavior, Behavior, BehaviorRecorder } from "@Model/Behavior"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { useSettingWithEvent, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { useStatus, IMixinStatusProps } from "@Context/Status"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { IRenderBehavior, Behavior, BehaviorRecorder } from "@Model/Behavior"; | ||||
| import { Theme } from "@Component/Theme/Theme"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { Message } from "@Input/Message/Message"; | ||||
| 
 | ||||
| 
 | ||||
| import "./BehaviorList.scss"; | ||||
| 
 | ||||
| interface IBehaviorListProps { | ||||
|  | ||||
| @ -1,15 +1,15 @@ | ||||
| import { Component, ReactNode, Fragment } from "react"; | ||||
| import { Popup } from "@Context/Popups"; | ||||
| import { useStatus, IMixinStatusProps, randomColor } from "@Context/Status"; | ||||
| import { useSettingWithEvent, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import { SearchBox } from "@Component/SearchBox/SearchBox"; | ||||
| import { SearchBox } from "@Input/SearchBox/SearchBox"; | ||||
| import { ConfirmContent } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { BehaviorList } from "@Component/BehaviorList/BehaviorList"; | ||||
| import { AllBehaviorsWithCategory, ICategoryBehavior } from "@Behavior/Behavior"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { Message } from "@Input/Message/Message"; | ||||
| import { IRenderBehavior, BehaviorRecorder } from "@Model/Behavior"; | ||||
| import { useStatus, IMixinStatusProps, randomColor } from "@Context/Status"; | ||||
| import { useSettingWithEvent, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| 
 | ||||
| import "./BehaviorPopup.scss"; | ||||
| 
 | ||||
| interface IBehaviorPopupProps { | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| import { BackgroundLevel, Theme } from "@Component/Theme/Theme"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { DirectionalHint, IconButton } from "@fluentui/react"; | ||||
| import { LocalizationTooltipHost } from "../Localization/LocalizationTooltipHost"; | ||||
| import { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { AllI18nKeys } from "../Localization/Localization"; | ||||
| import { SettingPopup } from "../SettingPopup/SettingPopup"; | ||||
| import { BehaviorPopup } from "../BehaviorPopup/BehaviorPopup"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { BackgroundLevel, Theme } from "@Component/Theme/Theme"; | ||||
| import { LocalizationTooltipHost } from "@Component/Localization/LocalizationTooltipHost"; | ||||
| import { AllI18nKeys } from "@Component/Localization/Localization"; | ||||
| import { SettingPopup } from "@Component/SettingPopup/SettingPopup"; | ||||
| import { BehaviorPopup } from "@Component/BehaviorPopup/BehaviorPopup"; | ||||
| import { MouseMod } from "@GLRender/ClassicRenderer"; | ||||
| import "./CommandBar.scss"; | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import { Popup } from "@Context/Popups"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { Popup } from "@Context/Popups"; | ||||
| import { Message } from "@Input/Message/Message"; | ||||
| import { Theme } from "@Component/Theme/Theme"; | ||||
| import { AllI18nKeys, Localization } from "@Component/Localization/Localization"; | ||||
| import "./ConfirmPopup.scss"; | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import { Theme, BackgroundLevel, FontLevel } from "@Component/Theme/Theme"; | ||||
| import { Themes } from "@Context/Setting"; | ||||
| import { DirectionalHint } from "@fluentui/react"; | ||||
| import { ILayout, LayoutDirection } from "@Context/Layout"; | ||||
| import { Component, ReactNode, MouseEvent } from "react"; | ||||
| import { getPanelById, getPanelInfoById } from "../../Panel/Panel"; | ||||
| import { LocalizationTooltipHost } from "../Localization/LocalizationTooltipHost"; | ||||
| import { DirectionalHint } from "@fluentui/react"; | ||||
| import { Themes } from "@Context/Setting"; | ||||
| import { ILayout, LayoutDirection } from "@Context/Layout"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import { BackgroundLevel, FontLevel } from "@Component/Theme/Theme"; | ||||
| import { getPanelById, getPanelInfoById } from "@Panel/Panel"; | ||||
| import { LocalizationTooltipHost } from "@Component/Localization/LocalizationTooltipHost"; | ||||
| import "./Container.scss"; | ||||
| 
 | ||||
| interface IContainerProps extends ILayout { | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { BackgroundLevel, FontLevel, Theme } from "../Theme/Theme"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; | ||||
| import "./DetailsList.scss"; | ||||
| 
 | ||||
| type IItems = Record<string, any> & {key: string, select?: boolean}; | ||||
|  | ||||
| @ -1,12 +1,11 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { Icon } from '@fluentui/react/lib/Icon'; | ||||
| import { useStatus, IMixinStatusProps } from "@Context/Status"; | ||||
| import { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { Theme, BackgroundLevel, FontLevel } from "@Component/Theme/Theme"; | ||||
| import { Icon } from '@fluentui/react/lib/Icon'; | ||||
| import { LocalizationTooltipHost } from "../Localization/LocalizationTooltipHost"; | ||||
| import { I18N } from "../Localization/Localization"; | ||||
| import { LocalizationTooltipHost } from "@Component/Localization/LocalizationTooltipHost"; | ||||
| import { I18N } from "@Component/Localization/Localization"; | ||||
| import "./HeaderBar.scss"; | ||||
| import { Tooltip, TooltipHost } from "@fluentui/react"; | ||||
| 
 | ||||
| interface IHeaderBarProps { | ||||
|     height: number; | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import { Component, RefObject } from "react"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { useSetting, IMixinSettingProps, Themes } from "@Context/Setting"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import "./LabelList.scss"; | ||||
| 
 | ||||
| interface ILabelListProps { | ||||
|  | ||||
| @ -78,4 +78,4 @@ class Localization extends Component<ILocalizationProps & IMixinSettingProps & | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { Localization, I18N, LanguageDataBase, AllI18nKeys }; | ||||
| export { Localization, I18N, LanguageDataBase, AllI18nKeys, ILocalizationProps }; | ||||
| @ -1,9 +1,9 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { IMixinStatusProps, useStatusWithEvent } from "@Context/Status"; | ||||
| import { IMixinSettingProps, useSettingWithEvent } from "@Context/Setting"; | ||||
| import { BackgroundLevel, FontLevel, getClassList, Theme } from "@Component/Theme/Theme"; | ||||
| import { Popup as PopupModel, ResizeDragDirection } from "@Context/Popups"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import "./Popup.scss"; | ||||
| 
 | ||||
| interface IPopupProps {} | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { useSettingWithEvent, Themes, IMixinSettingProps, Setting } from "@Context/Setting"; | ||||
| import { Component, ReactNode, DetailedHTMLProps, HTMLAttributes } from "react"; | ||||
| import { useSettingWithEvent, Themes, IMixinSettingProps, Setting } from "@Context/Setting"; | ||||
| import "./Theme.scss"; | ||||
| 
 | ||||
| enum FontLevel { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { Emitter, EventType } from "@Model/Emitter"; | ||||
| import { Component, FunctionComponent, ReactNode, Consumer } from "react"; | ||||
| import { Emitter, EventType } from "@Model/Emitter"; | ||||
| 
 | ||||
| type RenderComponent = (new (...p: any) => Component<any, any, any>) | FunctionComponent<any>; | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import { createContext } from "react"; | ||||
| import { superConnect, superConnectWithEvent } from "./Context"; | ||||
| import { superConnect, superConnectWithEvent } from "@Context/Context"; | ||||
| import { Emitter } from "@Model/Emitter"; | ||||
| import { Layout } from "./Layout"; | ||||
| import { Layout } from "@Context/Layout"; | ||||
| 
 | ||||
| /** | ||||
|  * 主题模式 | ||||
|  | ||||
| @ -7,11 +7,12 @@ import { Group } from "@Model/Group"; | ||||
| import { Archive } from "@Model/Archive"; | ||||
| import { AbstractRenderer } from "@Model/Renderer"; | ||||
| import { ClassicRenderer, MouseMod } from "@GLRender/ClassicRenderer"; | ||||
| import { Setting } from "./Setting"; | ||||
| import { Setting } from "@Context/Setting"; | ||||
| import { I18N } from "@Component/Localization/Localization"; | ||||
| import { superConnectWithEvent, superConnect } from "./Context"; | ||||
| import { PopupController } from "./Popups"; | ||||
| import { Behavior, IBehaviorParameter, IParamValue } from "@Model/Behavior"; | ||||
| import { superConnectWithEvent, superConnect } from "@Context/Context"; | ||||
| import { PopupController } from "@Context/Popups"; | ||||
| 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) { | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| @import "../Theme/Theme.scss"; | ||||
| @import "../../Component/Theme/Theme.scss"; | ||||
| 
 | ||||
| $line-min-height: 24px; | ||||
| 
 | ||||
| @ -1,8 +1,8 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { Localization, AllI18nKeys } from "@Component/Localization/Localization"; | ||||
| import { AllI18nKeys } from "@Component/Localization/Localization"; | ||||
| import { ObjectID } from "@Model/Renderer"; | ||||
| import { TextField, ITextFieldProps } from "../TextField/TextField"; | ||||
| import { TextField, ITextFieldProps } from "@Input/TextField/TextField"; | ||||
| import "./AttrInput.scss"; | ||||
| 
 | ||||
| interface IAttrInputProps extends ITextFieldProps { | ||||
| @ -1,4 +1,4 @@ | ||||
| @import "../Theme/Theme.scss"; | ||||
| @import "../../Component/Theme/Theme.scss"; | ||||
| 
 | ||||
| div.behavior-picker-list { | ||||
|     width: 100%; | ||||
| @ -1,11 +1,11 @@ | ||||
| import { DetailsList } from "@Component/DetailsList/DetailsList"; | ||||
| import { Component, ReactNode, createRef } from "react"; | ||||
| import { Behavior } from "@Model/Behavior"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { Behavior } from "@Model/Behavior"; | ||||
| import { useSettingWithEvent, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { DetailsList } from "@Component/DetailsList/DetailsList"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import { PickerList } from "@Component/PickerList/PickerList"; | ||||
| import { PickerList } from "@Input/PickerList/PickerList"; | ||||
| import "./BehaviorPicker.scss"; | ||||
| 
 | ||||
| interface IBehaviorPickerProps { | ||||
| @ -1,6 +1,6 @@ | ||||
| import { Component, createRef, ReactNode } from "react"; | ||||
| import { TextField, ITextFieldProps } from "@Component/TextField/TextField"; | ||||
| import { Callout, ColorPicker, DirectionalHint } from "@fluentui/react"; | ||||
| import { TextField, ITextFieldProps } from "@Input/TextField/TextField"; | ||||
| import "./ColorInput.scss"; | ||||
| 
 | ||||
| interface IColorInputProps extends ITextFieldProps { | ||||
| @ -1,4 +1,4 @@ | ||||
| @import "../Theme/Theme.scss"; | ||||
| @import "../../Component/Theme/Theme.scss"; | ||||
| 
 | ||||
| $line-min-height: 24px; | ||||
| 
 | ||||
| @ -1,7 +1,7 @@ | ||||
| import { Component, createRef, ReactNode } from "react"; | ||||
| import { PickerList, IDisplayItem } from "../PickerList/PickerList"; | ||||
| import { TextField, ITextFieldProps } from "../TextField/TextField"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { PickerList, IDisplayItem } from "@Input/PickerList/PickerList"; | ||||
| import { TextField, ITextFieldProps } from "@Input/TextField/TextField"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import "./ComboInput.scss"; | ||||
| interface IComboInputProps extends ITextFieldProps { | ||||
| @ -1,4 +1,4 @@ | ||||
| @import "../Theme/Theme.scss"; | ||||
| @import "../../Component/Theme/Theme.scss"; | ||||
| 
 | ||||
| $line-min-height: 26px; | ||||
| 
 | ||||
| @ -1,9 +1,9 @@ | ||||
| import { PickerList } from "../PickerList/PickerList"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import { TextField, ITextFieldProps } from "../TextField/TextField"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { Component, ReactNode, createRef } from "react"; | ||||
| import { LabelList } from "../LabelList/LabelList"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import { PickerList } from "@Input/PickerList/PickerList"; | ||||
| import { TextField, ITextFieldProps } from "@Input/TextField/TextField"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { LabelList } from "@Component/LabelList/LabelList"; | ||||
| import "./LabelPicker.scss" | ||||
| 
 | ||||
| interface ILabelPickerProps extends ITextFieldProps { | ||||
| @ -1,6 +1,6 @@ | ||||
| import { FunctionComponent } from "react"; | ||||
| import { AllI18nKeys, I18N } from "@Component/Localization/Localization"; | ||||
| import { useSettingWithEvent, IMixinSettingProps, Themes, Language } from "@Context/Setting"; | ||||
| import { FunctionComponent } from "react"; | ||||
| import "./Message.scss"; | ||||
| 
 | ||||
| interface IMessageProps { | ||||
| @ -1,4 +1,4 @@ | ||||
| @import "../Theme/Theme.scss"; | ||||
| @import "../../Component/Theme/Theme.scss"; | ||||
| @import "../PickerList/RainbowBg.scss"; | ||||
| 
 | ||||
| $line-min-height: 24px; | ||||
| @ -1,14 +1,14 @@ | ||||
| import { Component, createRef, ReactNode } from "react"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import { Group } from "@Model/Group"; | ||||
| import { Range } from "@Model/Range"; | ||||
| import { TextField, ITextFieldProps } from "../TextField/TextField"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { PickerList, IDisplayItem, getObjectDisplayInfo, IDisplayInfo } from "../PickerList/PickerList"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { CtrlObject } from "@Model/CtrlObject"; | ||||
| import { Behavior } from "@Model/Behavior"; | ||||
| import { TextField, ITextFieldProps } from "@Input/TextField/TextField"; | ||||
| import { PickerList, IDisplayItem, getObjectDisplayInfo, IDisplayInfo } from "@Input/PickerList/PickerList"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import "./ObjectPicker.scss"; | ||||
| 
 | ||||
| type IObjectType = Label | Group | Range | CtrlObject; | ||||
							
								
								
									
										0
									
								
								source/Input/Parameter/Parameter.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								source/Input/Parameter/Parameter.scss
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										202
									
								
								source/Input/Parameter/Parameter.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								source/Input/Parameter/Parameter.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,202 @@ | ||||
| import { Component, Fragment, ReactNode } from "react"; | ||||
| import { useSettingWithEvent, IMixinSettingProps, Language } from "@Context/Setting"; | ||||
| import { AttrInput } from "@Input/AttrInput/AttrInput"; | ||||
| import { ObjectID } from "@Model/Renderer"; | ||||
| import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; | ||||
| import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker"; | ||||
| import { AllI18nKeys } from "@Component/Localization/Localization"; | ||||
| import { Message } from "@Input/Message/Message"; | ||||
| import { | ||||
|     IParameter, IParameterOption, IParameterOptionItem, | ||||
|     IParameterValue, IParamValue, isObjectType, isVectorType | ||||
| } from "@Model/Parameter"; | ||||
| 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 } | ||||
| @ -1,4 +1,4 @@ | ||||
| @import "../Theme/Theme.scss"; | ||||
| @import "../../Component/Theme/Theme.scss"; | ||||
| 
 | ||||
| $search-box-height: 26px; | ||||
| 
 | ||||
| @ -1,8 +1,8 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { AllI18nKeys, I18N } from "@Component/Localization/Localization"; | ||||
| import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; | ||||
| import { useSettingWithEvent, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import "./SearchBox.scss"; | ||||
| 
 | ||||
| interface ISearchBoxProps { | ||||
| @ -1,4 +1,4 @@ | ||||
| @import "../Theme/Theme.scss"; | ||||
| @import "../../Component/Theme/Theme.scss"; | ||||
| 
 | ||||
| $line-min-height: 26px; | ||||
| 
 | ||||
| @ -1,4 +1,4 @@ | ||||
| @import "../Theme/Theme.scss"; | ||||
| @import "../../Component/Theme/Theme.scss"; | ||||
| 
 | ||||
| $line-min-height: 26px; | ||||
| 
 | ||||
| @ -1,6 +1,6 @@ | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { TextField, ITextFieldProps } from "../TextField/TextField"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { TextField, ITextFieldProps } from "@Input/TextField/TextField"; | ||||
| import "./TogglesInput.scss"; | ||||
| 
 | ||||
| interface ITogglesInputProps extends ITextFieldProps { | ||||
| @ -25,7 +25,7 @@ const ZH_CN = { | ||||
|     "Input.Error.Length": "输入内容长度须小于 {number}", | ||||
|     "Input.Error.Length.Less": "输入内容长度须大于 {number}", | ||||
|     "Input.Error.Select": "选择对象 ...", | ||||
|     "Object.List.New.Group": "组对象 {id}", | ||||
|     "Object.List.New.Group": "群对象 {id}", | ||||
|     "Object.List.New.Range": "范围对象 {id}", | ||||
|     "Object.List.New.Label": "标签 {id}", | ||||
|     "Object.List.No.Data": "模型中没有任何对象,点击按钮以创建", | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { Model } from "./Model"; | ||||
| import { Emitter } from "./Emitter";  | ||||
| import { Model } from "@Model/Model"; | ||||
| import { Emitter } from "@Model/Emitter"; | ||||
| 
 | ||||
| interface IActuatorEvent { | ||||
| 	startChange: boolean; | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import { Emitter, EventType, EventMixin } from "./Emitter"; | ||||
| import { Emitter, EventType } from "@Model/Emitter"; | ||||
| 
 | ||||
| interface IArchiveEvent { | ||||
|     save: Archive; | ||||
|  | ||||
| @ -1,136 +1,16 @@ | ||||
| import { IAnyObject } from "./Renderer"; | ||||
| import { Emitter, EventType } from "./Emitter"; | ||||
| import type { Individual } from "./Individual"; | ||||
| import type { Group } from "./Group"; | ||||
| import type { Model } from "./Model"; | ||||
| import type { Range } from "./Range"; | ||||
| import type { Label } from "./Label"; | ||||
| 
 | ||||
| type IObjectParamCacheType<P, Q = P> = { | ||||
|     picker: P; | ||||
|     objects: Q; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 参数类型 | ||||
|  */ | ||||
| type IMapBasicParamTypeKeyToType = { | ||||
|     "number": number; | ||||
|     "string": string; | ||||
|     "boolean": boolean; | ||||
| } | ||||
| 
 | ||||
| type IMapObjectParamTypeKeyToType = { | ||||
|     "R": IObjectParamCacheType<Range | undefined>; | ||||
|     "G": IObjectParamCacheType<Group | undefined>; | ||||
|     "LR": IObjectParamCacheType<Label | Range | undefined, Range[]>; | ||||
|     "LG": IObjectParamCacheType<Label | Group | undefined, Group[]>; | ||||
| } | ||||
| 
 | ||||
| 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", "LR", "LG"]); | ||||
| 
 | ||||
| /** | ||||
|  * 对象断言表达式 | ||||
|  */ | ||||
| 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 | string; | ||||
| 
 | ||||
|     /** | ||||
|      * 参数默认值 | ||||
|      */ | ||||
|     defaultValue?: IParamValue<T>; | ||||
| 
 | ||||
|     /** | ||||
|      * 数值变化回调 | ||||
|      */ | ||||
|     onChange?: (value: IParamValue<T>) => any; | ||||
| 
 | ||||
|     /** | ||||
|      * 名字 | ||||
|      */ | ||||
|     name: string; | ||||
| 
 | ||||
|     /** | ||||
|      * 字符长度 | ||||
|      */ | ||||
|     maxLength?: number; | ||||
| 
 | ||||
|     /** | ||||
|      * 数字步长 | ||||
|      */ | ||||
|     numberStep?: number; | ||||
| 
 | ||||
|     /** | ||||
|      * 最大值最小值 | ||||
|      */ | ||||
|     numberMax?: number; | ||||
|     numberMin?: number; | ||||
| 
 | ||||
|     /** | ||||
|      * 图标名字 | ||||
|      */ | ||||
|     iconName?: string; | ||||
| } | ||||
| 
 | ||||
| interface IBehaviorParameter { | ||||
|     [x: string]: IParamType; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 参数类型列表 | ||||
|  */ | ||||
| type IBehaviorParameterOption<P extends IBehaviorParameter> = { | ||||
|     [X in keyof P]: IBehaviorParameterOptionItem<P[X]>; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 参数类型列表映射到参数对象 | ||||
|  */ | ||||
| type IBehaviorParameterValue<P extends IBehaviorParameter> = { | ||||
|     [X in keyof P]: IParamValue<P[X]> | ||||
| } | ||||
| import { Emitter, EventType } from "@Model/Emitter"; | ||||
| import type { Individual } from "@Model/Individual"; | ||||
| import type { Group } from "@Model/Group"; | ||||
| import type { Model } from "@Model/Model"; | ||||
| import { getDefaultValue, IParameter, IParameterOption, IParameterValue } from "@Model/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>; | ||||
| @ -192,7 +72,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<{}> { | ||||
| 
 | ||||
| @ -221,62 +101,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>) { | ||||
| @ -297,7 +128,7 @@ class BehaviorRecorder< | ||||
|  * 群体的某种行为 | ||||
|  */ | ||||
| class Behavior< | ||||
|     P extends IBehaviorParameter = {}, | ||||
|     P extends IParameter = {}, | ||||
|     E extends Record<EventType, any> = {} | ||||
| > extends BehaviorInfo<E> { | ||||
| 
 | ||||
| @ -325,14 +156,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; | ||||
| @ -416,8 +247,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 }; | ||||
| @ -1,6 +1,6 @@ | ||||
| import { LabelObject } from "./Label" | ||||
| import type { Model } from "./Model"; | ||||
| import type { ObjectID } from "./Renderer"; | ||||
| import { LabelObject } from "@Model/Label" | ||||
| import type { Model } from "@Model/Model"; | ||||
| import type { ObjectID } from "@Model/Renderer"; | ||||
| 
 | ||||
| /** | ||||
|  * 可控对象 | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| import { Individual } from "./Individual"; | ||||
| import { CtrlObject } from "./CtrlObject"; | ||||
| import type { Behavior } from "./Behavior";  | ||||
| import { Label } from "./Label"; | ||||
| import { Range } from "./Range"; | ||||
| import { Individual } from "@Model/Individual"; | ||||
| import { CtrlObject } from "@Model/CtrlObject"; | ||||
| import type { Behavior } from "@Model/Behavior";  | ||||
| import { Label } from "@Model/Label"; | ||||
| import { Range } from "@Model/Range"; | ||||
| 
 | ||||
| enum GenMod { | ||||
|     Point = "p", | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import type { Group } from "./Group"; | ||||
| import { ObjectID } from "./Renderer"; | ||||
| import type { Group } from "@Model/Group"; | ||||
| import { ObjectID } from "@Model/Renderer"; | ||||
| 
 | ||||
| /** | ||||
|  * 群中的个体类型 | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import type { Model } from "./Model"; | ||||
| import { ObjectID } from "./Renderer"; | ||||
| import type { Model } from "@Model/Model"; | ||||
| import { ObjectID } from "@Model/Renderer"; | ||||
| 
 | ||||
| /** | ||||
|  * 数据标签 | ||||
|  | ||||
| @ -1,11 +1,12 @@ | ||||
| import { Individual } from "./Individual"; | ||||
| import { Group } from "./Group"; | ||||
| import { Range } from "./Range"; | ||||
| 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 { Label } from "@Model/Label"; | ||||
| import { Group } from "@Model/Group"; | ||||
| import { Range } from "@Model/Range"; | ||||
| import { IParamValue } from "@Model/Parameter"; | ||||
| import { Individual } from "@Model/Individual"; | ||||
| import { CtrlObject } from "@Model/CtrlObject"; | ||||
| import { Emitter, EventType, EventMixin } from "@Model/Emitter"; | ||||
| import { ObjectID, AbstractRenderer } from "@Model/Renderer"; | ||||
| import { Behavior, IAnyBehavior, IAnyBehaviorRecorder } from "@Model/Behavior"; | ||||
| 
 | ||||
| type ModelEvent = { | ||||
|     labelChange: Label[]; | ||||
|  | ||||
							
								
								
									
										173
									
								
								source/Model/Parameter.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								source/Model/Parameter.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,173 @@ | ||||
| import type { Group } from "@Model/Group"; | ||||
| import type { Range } from "@Model/Range"; | ||||
| import type { Label } from "@Model/Label"; | ||||
| 
 | ||||
| type IObjectParamCacheType<P, Q = P> = { | ||||
|     picker: P; | ||||
|     objects: Q; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 参数类型 | ||||
|  */ | ||||
| type IMapBasicParamTypeKeyToType = { | ||||
|     "number": number; | ||||
|     "string": string; | ||||
|     "boolean": boolean; | ||||
| } | ||||
| 
 | ||||
| type IMapObjectParamTypeKeyToType = { | ||||
|     "R": IObjectParamCacheType<Range | undefined>; | ||||
|     "G": IObjectParamCacheType<Group | undefined>; | ||||
|     "LR": IObjectParamCacheType<Label | Range | undefined, Range[]>; | ||||
|     "LG": IObjectParamCacheType<Label | Group | undefined, Group[]>; | ||||
| } | ||||
| 
 | ||||
| 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<string>(["R", "G", "LR", "LG"]); | ||||
| 
 | ||||
|  /** | ||||
|   * 对象断言表达式 | ||||
|   */ | ||||
| function isObjectType(key: string): key is IVectorType { | ||||
|     return objectTypeListEnumSet.has(key); | ||||
| } | ||||
|   | ||||
|  /** | ||||
|   * 向量断言表达式 | ||||
|   */ | ||||
| function isVectorType(key: string): key is IObjectType { | ||||
|     return key === "vec"; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 模型参数类型 | ||||
|  */ | ||||
| interface IParameterOptionItem<T extends IParamType = IParamType> { | ||||
| 
 | ||||
|     /** | ||||
|      * 参数类型 | ||||
|      */ | ||||
|     type: T | string; | ||||
| 
 | ||||
|     /** | ||||
|      * 参数默认值 | ||||
|      */ | ||||
|     defaultValue?: IParamValue<T>; | ||||
| 
 | ||||
|     /** | ||||
|      * 数值变化回调 | ||||
|      */ | ||||
|     onChange?: (value: IParamValue<T>) => any; | ||||
| 
 | ||||
|     /** | ||||
|      * 名字 | ||||
|      */ | ||||
|     name: string; | ||||
| 
 | ||||
|     /** | ||||
|      * 字符长度 | ||||
|      */ | ||||
|     maxLength?: number; | ||||
| 
 | ||||
|     /** | ||||
|      * 数字步长 | ||||
|      */ | ||||
|     numberStep?: number; | ||||
| 
 | ||||
|     /** | ||||
|      * 最大值最小值 | ||||
|      */ | ||||
|     numberMax?: number; | ||||
|     numberMin?: number; | ||||
| 
 | ||||
|     /** | ||||
|      * 图标名字 | ||||
|      */ | ||||
|     iconName?: string; | ||||
| } | ||||
| 
 | ||||
| interface IParameter { | ||||
|     [x: string]: IParamType; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 参数类型列表 | ||||
|  */ | ||||
| type IParameterOption<P extends IParameter> = { | ||||
|     [X in keyof P]: IParameterOptionItem<P[X]>; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 参数类型列表映射到参数对象 | ||||
|  */ | ||||
| type IParameterValue<P extends IParameter> = { | ||||
|     [X in keyof P]: IParamValue<P[X]> | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| import { CtrlObject } from "./CtrlObject"; | ||||
| import { CtrlObject } from "@Model/CtrlObject"; | ||||
| 
 | ||||
| /** | ||||
|  * 范围 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import { Component, ReactNode, createRef } from "react"; | ||||
| import { ClassicRenderer } from "@GLRender/ClassicRenderer"; | ||||
| import { Entry } from "../Entry/Entry"; | ||||
| import { Model } from "@Model/Model"; | ||||
| import { Entry } from "../Entry/Entry"; | ||||
| import "./Laboratory.scss"; | ||||
| 
 | ||||
| class Laboratory extends Component { | ||||
|  | ||||
| @ -1,16 +1,16 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { SettingProvider, Setting } from "@Context/Setting"; | ||||
| import { HeaderBar } from "@Component/HeaderBar/HeaderBar"; | ||||
| import { Theme, BackgroundLevel, FontLevel } from "@Component/Theme/Theme"; | ||||
| import { Entry } from "../Entry/Entry"; | ||||
| import { StatusProvider, Status } from "@Context/Status"; | ||||
| import { ClassicRenderer } from "@GLRender/ClassicRenderer"; | ||||
| import { initializeIcons } from '@fluentui/font-icons-mdl2'; | ||||
| import { RootContainer } from "@Component/Container/RootContainer"; | ||||
| import { LayoutDirection } from "@Context/Layout"; | ||||
| import { CommandBar } from "@Component/CommandBar/CommandBar"; | ||||
| import { Popup } from "@Component/Popup/Popup"; | ||||
| import { AllBehaviors } from "@Behavior/Behavior"; | ||||
| import { CommandBar } from "@Component/CommandBar/CommandBar"; | ||||
| import { HeaderBar } from "@Component/HeaderBar/HeaderBar"; | ||||
| import { Popup } from "@Component/Popup/Popup"; | ||||
| import { Entry } from "../Entry/Entry"; | ||||
| import "./SimulatorWeb.scss"; | ||||
| 
 | ||||
| initializeIcons("https://img.mrkbear.com/fabric-cdn-prod_20210407.001/"); | ||||
| @ -63,7 +63,7 @@ class SimulatorWeb extends Component { | ||||
|             brownian.name = "Brownian"; brownian.color = [200, 80, 250]; | ||||
|             let boundary = this.status.model.addBehavior(AllBehaviors[3]); | ||||
|             boundary.name = "Boundary"; boundary.color = [80, 200, 250]; | ||||
|             // boundary.parameter.range = this.status.model.allRangeLabel;
 | ||||
|             boundary.parameter.range.picker = this.status.model.allRangeLabel; | ||||
|             group.addBehavior(template); | ||||
|             group.addBehavior(dynamic); | ||||
|             group.addBehavior(brownian); | ||||
|  | ||||
| @ -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 { Message } from "@Component/Message/Message"; | ||||
| import { AttrInput } from "@Component/AttrInput/AttrInput"; | ||||
| import { ColorInput } from "@Component/ColorInput/ColorInput"; | ||||
| import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | ||||
| import { IAnyBehavior } from "@Model/Behavior"; | ||||
| import { Message } from "@Input/Message/Message"; | ||||
| import { AttrInput } from "@Input/AttrInput/AttrInput"; | ||||
| import { ColorInput } from "@Input/ColorInput/ColorInput"; | ||||
| import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { ObjectPicker } from "@Component/ObjectPicker/ObjectPicker"; | ||||
| import { Parameter } from "@Input/Parameter/Parameter"; | ||||
| import "./BehaviorDetails.scss"; | ||||
| 
 | ||||
| interface IBehaviorDetailsProps {} | ||||
| @ -16,11 +16,24 @@ interface IBehaviorDetailsProps {} | ||||
| @useStatusWithEvent("focusBehaviorChange", "behaviorAttrChange") | ||||
| class BehaviorDetails extends Component<IBehaviorDetailsProps & IMixinStatusProps & IMixinSettingProps> { | ||||
| 
 | ||||
| 	private renderFrom<T extends IBehaviorParameter> | ||||
|     (behavior: Behavior<T, Record<string, any>>): ReactNode { | ||||
| 
 | ||||
|         const allParameterKeys = Object.getOwnPropertyNames(behavior.parameterOption); | ||||
|     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(); | ||||
|                 } | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	private renderFrom(behavior: IAnyBehavior): ReactNode { | ||||
|          | ||||
| 		return <> | ||||
|          | ||||
|             <Message i18nKey="Common.Attr.Title.Basic" isTitle first/> | ||||
| @ -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} | ||||
|                 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); | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| import { BehaviorList as BehaviorListComponent } from "@Component/BehaviorList/BehaviorList"; | ||||
| import { Component } from "react"; | ||||
| import { BehaviorList as BehaviorListComponent } from "@Component/BehaviorList/BehaviorList"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { Behavior } from "@Model/Behavior"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { BehaviorPopup } from "@Component/BehaviorPopup/BehaviorPopup"; | ||||
| import { Behavior } from "@Model/Behavior"; | ||||
| import { Message } from "@Input/Message/Message"; | ||||
| import "./BehaviorList.scss"; | ||||
| 
 | ||||
| interface IBehaviorListProps { | ||||
|  | ||||
| @ -1,18 +1,18 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { AttrInput } from "@Component/AttrInput/AttrInput"; | ||||
| import { AttrInput } from "@Input/AttrInput/AttrInput"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { ComboInput, IDisplayItem } from "@Input/ComboInput/ComboInput"; | ||||
| import { Message } from "@Input/Message/Message"; | ||||
| import { ObjectID } from "@Model/Renderer"; | ||||
| import { ColorInput } from "@Component/ColorInput/ColorInput"; | ||||
| import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | ||||
| import { LabelPicker } from "@Component/LabelPicker/LabelPicker"; | ||||
| import { ColorInput } from "@Input/ColorInput/ColorInput"; | ||||
| import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; | ||||
| import { LabelPicker } from "@Input/LabelPicker/LabelPicker"; | ||||
| import { Group, GenMod } from "@Model/Group"; | ||||
| import { AllI18nKeys } from "@Component/Localization/Localization"; | ||||
| import { ComboInput, IDisplayItem } from "@Component/ComboInput/ComboInput"; | ||||
| import { ObjectPicker } from "@Component/ObjectPicker/ObjectPicker"; | ||||
| import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { BehaviorPicker } from "@Component/BehaviorPicker/BehaviorPicker"; | ||||
| import { BehaviorPicker } from "@Input/BehaviorPicker/BehaviorPicker"; | ||||
| import "./GroupDetails.scss"; | ||||
| 
 | ||||
| interface IGroupDetailsProps {} | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { AttrInput } from "@Component/AttrInput/AttrInput"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { ColorInput } from "@Component/ColorInput/ColorInput"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | ||||
| import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { ColorInput } from "@Input/ColorInput/ColorInput"; | ||||
| import { AttrInput } from "@Input/AttrInput/AttrInput"; | ||||
| import { Message } from "@Input/Message/Message"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import "./LabelDetails.scss"; | ||||
| 
 | ||||
| @useStatusWithEvent("focusLabelChange", "labelAttrChange", "labelChange") | ||||
|  | ||||
| @ -1,10 +1,10 @@ | ||||
| import { LabelList as LabelListComponent } from "@Component/LabelList/LabelList"; | ||||
| import { Component } from "react"; | ||||
| import { LabelList as LabelListComponent } from "@Component/LabelList/LabelList"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { Message } from "@Input/Message/Message"; | ||||
| import { Label } from "@Model/Label"; | ||||
| import "./LabelList.scss"; | ||||
| 
 | ||||
| interface ILabelListProps { | ||||
|  | ||||
| @ -1,9 +1,9 @@ | ||||
| import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; | ||||
| import { useStatus, IMixinStatusProps } from "../../Context/Status"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; | ||||
| import { useStatus, IMixinStatusProps } from "@Context/Status"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import { ObjectID } from "@Model/Renderer"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import "./ObjectList.scss"; | ||||
| 
 | ||||
| @useStatus | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { DetailsList } from "@Component/DetailsList/DetailsList"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import { DetailsList } from "@Component/DetailsList/DetailsList"; | ||||
| import { ObjectID } from "@Model/Renderer"; | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import "./ObjectList.scss"; | ||||
|  | ||||
| @ -1,15 +1,15 @@ | ||||
| import { ReactNode, Component, FunctionComponent } from "react"; | ||||
| import { Theme } from "@Component/Theme/Theme"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { RenderView } from "./RenderView/RenderView"; | ||||
| import { ObjectList } from "./ObjectList/ObjectList"; | ||||
| import { ObjectCommand } from "./ObjectList/ObjectCommand"; | ||||
| import { RangeDetails } from "./RangeDetails/RangeDetails"; | ||||
| import { LabelList } from "./LabelList/LabelList"; | ||||
| import { LabelDetails } from "./LabelDetails/LabelDetails"; | ||||
| import { GroupDetails } from "./GroupDetails/GroupDetails"; | ||||
| import { BehaviorList } from "./BehaviorList/BehaviorList"; | ||||
| import { BehaviorDetails } from "./BehaviorDetails/BehaviorDetails"; | ||||
| import { Message } from "@Input/Message/Message"; | ||||
| import { RenderView } from "@Panel/RenderView/RenderView"; | ||||
| import { ObjectList } from "@Panel/ObjectList/ObjectList"; | ||||
| import { ObjectCommand } from "@Panel/ObjectList/ObjectCommand"; | ||||
| import { RangeDetails } from "@Panel/RangeDetails/RangeDetails"; | ||||
| import { LabelList } from "@Panel/LabelList/LabelList"; | ||||
| import { LabelDetails } from "@Panel/LabelDetails/LabelDetails"; | ||||
| import { GroupDetails } from "@Panel/GroupDetails/GroupDetails"; | ||||
| import { BehaviorList } from "@Panel/BehaviorList/BehaviorList"; | ||||
| import { BehaviorDetails } from "@Panel/BehaviorDetails/BehaviorDetails"; | ||||
| 
 | ||||
| interface IPanelInfo { | ||||
| 	nameKey: string; | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { AttrInput } from "@Component/AttrInput/AttrInput"; | ||||
| import { useStatusWithEvent, IMixinStatusProps, Status } from "@Context/Status"; | ||||
| import { Message } from "@Component/Message/Message"; | ||||
| import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | ||||
| import { AttrInput } from "@Input/AttrInput/AttrInput"; | ||||
| import { Message } from "@Input/Message/Message"; | ||||
| import { Range } from "@Model/Range"; | ||||
| import { ObjectID } from "@Model/Renderer"; | ||||
| import { ColorInput } from "@Component/ColorInput/ColorInput"; | ||||
| import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; | ||||
| import { LabelPicker } from "@Component/LabelPicker/LabelPicker"; | ||||
| import { ColorInput } from "@Input/ColorInput/ColorInput"; | ||||
| import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; | ||||
| import { LabelPicker } from "@Input/LabelPicker/LabelPicker"; | ||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||
| import "./RangeDetails.scss"; | ||||
| 
 | ||||
|  | ||||
| @ -32,6 +32,9 @@ | ||||
|             "@Component/*": [ | ||||
|                 "./source/Component/*" | ||||
|             ], | ||||
|             "@Input/*": [ | ||||
|                 "./source/Input/*" | ||||
|             ], | ||||
|             "@Localization/*": [ | ||||
|                 "./source/Localization/*" | ||||
|             ], | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user