Compare commits
	
		
			6 Commits
		
	
	
		
			0120a4972d
			...
			27d4b07b41
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 27d4b07b41 | |||
| f8fbb70608 | |||
| a0cf289bb5 | |||
| a31bb73faa | |||
| ed8269ff50 | |||
| 8ced3d82f3 | 
| @ -1,7 +1,7 @@ | |||||||
| import { ReactNode, createElement } from "react"; | import { ReactNode, createElement } from "react"; | ||||||
| import { Emitter } from "@Model/Emitter"; | import { Emitter } from "@Model/Emitter"; | ||||||
| import { Localization } from "@Component/Localization/Localization"; | import { Localization } from "@Component/Localization/Localization"; | ||||||
| import { IAnyObject } from "@Model/Renderer"; | import { IAnyObject } from "@Model/Model"; | ||||||
| 
 | 
 | ||||||
| enum ResizeDragDirection { | enum ResizeDragDirection { | ||||||
|     top = 1, |     top = 1, | ||||||
|  | |||||||
| @ -44,6 +44,11 @@ class BasicGroup extends DisplayObject<GroupShader> { | |||||||
|      */ |      */ | ||||||
|     public color = [1, 1, 1]; |     public color = [1, 1, 1]; | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * 形状 | ||||||
|  |      */ | ||||||
|  |     public shape: number = 0; | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * 绘制立方体 |      * 绘制立方体 | ||||||
|      */ |      */ | ||||||
| @ -66,6 +71,9 @@ class BasicGroup extends DisplayObject<GroupShader> { | |||||||
|         // 半径传递
 |         // 半径传递
 | ||||||
|         this.shader.radius(this.size); |         this.shader.radius(this.size); | ||||||
| 
 | 
 | ||||||
|  |         // 形状传递
 | ||||||
|  |         this.shader.shape(this.shape); | ||||||
|  | 
 | ||||||
|         // 指定颜色
 |         // 指定颜色
 | ||||||
|         this.shader.color(this.color); |         this.shader.color(this.color); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import { AbstractRenderer, IRendererParam, IAnyObject } from "@Model/Renderer"; | import { AbstractRenderer, IRendererParam } from "@Model/Renderer"; | ||||||
| import { EventType } from "@Model/Emitter"; | import { EventType } from "@Model/Emitter"; | ||||||
| import { GLCanvas, GLCanvasOption } from "./GLCanvas"; | import { GLCanvas, GLCanvasOption } from "./GLCanvas"; | ||||||
| import { GLContext } from "./GLContext"; | import { GLContext } from "./GLContext"; | ||||||
| @ -16,19 +16,13 @@ type IRendererParams = IRendererOwnParams & GLCanvasOption; | |||||||
| 
 | 
 | ||||||
| abstract class BasicRenderer< | abstract class BasicRenderer< | ||||||
|     P extends IRendererParam = {}, |     P extends IRendererParam = {}, | ||||||
|     M extends IAnyObject = {}, |  | ||||||
|     E extends Record<EventType, any> = {} |     E extends Record<EventType, any> = {} | ||||||
| > extends AbstractRenderer<P, M & IRendererParams, E & {loop: number}> { | > extends AbstractRenderer<P, E & {loop: number}> { | ||||||
| 
 | 
 | ||||||
|     public get dom() { |     public get dom() { | ||||||
|         return this.canvas.dom |         return this.canvas.dom | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
| 	 * 渲染器参数 |  | ||||||
| 	 */ |  | ||||||
| 	public param: Partial<M & IRendererParams> = {}; |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
| 	 * 使用的画布 | 	 * 使用的画布 | ||||||
| 	 */ | 	 */ | ||||||
| @ -44,19 +38,16 @@ abstract class BasicRenderer< | |||||||
|      */ |      */ | ||||||
|     protected clock: Clock; |     protected clock: Clock; | ||||||
| 
 | 
 | ||||||
|     public constructor(param: Partial<M & IRendererParams> = {}) { |     public constructor() { | ||||||
| 		super(); | 		super(); | ||||||
| 		 | 		 | ||||||
| 		// 初始化参数
 |  | ||||||
| 		this.param = { |  | ||||||
| 			autoResize: param.autoResize ?? true, |  | ||||||
| 			mouseEvent: param.autoResize ?? true, |  | ||||||
| 			eventLog: param.eventLog ?? false, |  | ||||||
| 			className: param.className ?? "" |  | ||||||
| 		} as M & IRendererParams; |  | ||||||
| 		 |  | ||||||
| 		// 实例化画布对象
 | 		// 实例化画布对象
 | ||||||
| 		this.canvas = new GLCanvas(param.canvas, this.param); | 		this.canvas = new GLCanvas(undefined, { | ||||||
|  | 			autoResize: true, | ||||||
|  | 			mouseEvent: true, | ||||||
|  | 			eventLog: false, | ||||||
|  | 			className: "canvas" | ||||||
|  | 		}); | ||||||
| 
 | 
 | ||||||
|         // 实例化摄像机
 |         // 实例化摄像机
 | ||||||
|         this.camera = new Camera(this.canvas); |         this.camera = new Camera(this.canvas); | ||||||
|  | |||||||
| @ -1,27 +1,49 @@ | |||||||
| import { ObjectID, ObjectData, ICommonParam } from "@Model/Renderer"; | import { ObjectData } from "@Model/Renderer"; | ||||||
|  | import { ObjectID } from "@Model/Model"; | ||||||
|  | import { IParameterValue, getDefaultValue } from "@Model/Parameter"; | ||||||
| import { BasicRenderer } from "./BasicRenderer"; | import { BasicRenderer } from "./BasicRenderer"; | ||||||
| import { BasicsShader } from "./BasicShader"; | import { BasicsShader } from "./BasicShader"; | ||||||
| import { Axis } from "./Axis"; | import { Axis } from "./Axis"; | ||||||
| import { BasicCube } from "./BasicCube"; | import { BasicCube } from "./BasicCube"; | ||||||
| import { GroupShader } from "./GroupShader"; | import { GroupShader } from "./GroupShader"; | ||||||
| import { BasicGroup } from "./BasicGroup"; | import { BasicGroup } from "./BasicGroup"; | ||||||
| import DisplayObject from "./DisplayObject"; | import { DisplayObject } from "./DisplayObject"; | ||||||
| 
 |  | ||||||
| interface IClassicRendererParams { |  | ||||||
|     point: { |  | ||||||
|         size: number; |  | ||||||
|     } |  | ||||||
|     cube: { |  | ||||||
|         radius: number[]; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| enum MouseMod { | enum MouseMod { | ||||||
|     Drag = 1, |     Drag = 1, | ||||||
|     click = 2 |     click = 2 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { | type IClassicRendererParameter = { | ||||||
|  | 	renderer: {}; | ||||||
|  | 	points: { | ||||||
|  |         color: "color", | ||||||
|  |         size: "number", | ||||||
|  |         shape: "option" | ||||||
|  |     }; | ||||||
|  | 	cube: { | ||||||
|  |         color: "color" | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class ClassicRenderer extends BasicRenderer<IClassicRendererParameter> { | ||||||
|  | 
 | ||||||
|  |     public override rendererParameterOption = {}; | ||||||
|  | 	public override pointsParameterOption = { | ||||||
|  |         color: { type: "color", name: "", defaultValue: [0, 0, 0] }, | ||||||
|  |         size: { type: "number", name: "Common.Attr.Key.Size", defaultValue: 60, numberStep: 10, numberMin: 0 }, | ||||||
|  |         shape: { type: "option", name: "Common.Render.Attr.Key.Display.Shape", defaultValue: "0", allOption: [ | ||||||
|  |             { key: "0", name: "Common.Render.Attr.Key.Display.Shape.Square" }, | ||||||
|  |             { key: "1", name: "Common.Render.Attr.Key.Display.Shape.Hollow.Square" }, | ||||||
|  |             { key: "2", name: "Common.Render.Attr.Key.Display.Shape.Hollow.Plus" }, | ||||||
|  |             { key: "3", name: "Common.Render.Attr.Key.Display.Shape.Hollow.Reduce" }, | ||||||
|  |             { key: "4", name: "Common.Render.Attr.Key.Display.Shape.Hollow.Cross" }, | ||||||
|  |             { key: "5", name: "Common.Render.Attr.Key.Display.Shape.Hollow.Checkerboard" } | ||||||
|  |         ]} | ||||||
|  |     }; | ||||||
|  | 	public override cubeParameterOption = { | ||||||
|  |         color: { type: "color", name: "", defaultValue: [0, 0, 0] }, | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     private basicShader: BasicsShader = undefined as any; |     private basicShader: BasicsShader = undefined as any; | ||||||
|     private axisObject: Axis = undefined as any; |     private axisObject: Axis = undefined as any; | ||||||
| @ -52,6 +74,8 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { | |||||||
| 
 | 
 | ||||||
|     public onLoad(): this { |     public onLoad(): this { | ||||||
| 
 | 
 | ||||||
|  |         this.rendererParameter = getDefaultValue(this.rendererParameterOption); | ||||||
|  |          | ||||||
|         // 自动调节分辨率
 |         // 自动调节分辨率
 | ||||||
|         this.autoResize(); |         this.autoResize(); | ||||||
| 
 | 
 | ||||||
| @ -187,7 +211,7 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { | |||||||
| 
 | 
 | ||||||
|     points( |     points( | ||||||
|         id: ObjectID, position?: ObjectData, |         id: ObjectID, position?: ObjectData, | ||||||
|         param?: Readonly<Partial<ICommonParam & IClassicRendererParams["point"]>> |         param?: Readonly<IParameterValue<IClassicRendererParameter["points"]>> | ||||||
|     ): this { |     ): this { | ||||||
|         let object = this.objectPool.get(id); |         let object = this.objectPool.get(id); | ||||||
|         let group: BasicGroup; |         let group: BasicGroup; | ||||||
| @ -229,14 +253,19 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { | |||||||
|             if (param.size) { |             if (param.size) { | ||||||
|                 group.size = param.size; |                 group.size = param.size; | ||||||
|             } |             } | ||||||
|  | 
 | ||||||
|  |             // 半径数据
 | ||||||
|  |             if (param.shape) { | ||||||
|  |                 group.shape = parseInt(param.shape); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cube( |     cube( | ||||||
|         id: ObjectID, position?: ObjectData, |         id: ObjectID, position?: ObjectData, radius?: ObjectData, | ||||||
|         param?: Readonly<Partial<ICommonParam & IClassicRendererParams["cube"]>> |         param?: Readonly<IParameterValue<IClassicRendererParameter["cube"]>> | ||||||
|     ): this { |     ): this { | ||||||
|         let object = this.objectPool.get(id); |         let object = this.objectPool.get(id); | ||||||
|         let cube: BasicCube; |         let cube: BasicCube; | ||||||
| @ -250,6 +279,13 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { | |||||||
|                     cube.position[1] = position[1] ?? cube.position[1]; |                     cube.position[1] = position[1] ?? cube.position[1]; | ||||||
|                     cube.position[2] = position[2] ?? cube.position[2]; |                     cube.position[2] = position[2] ?? cube.position[2]; | ||||||
|                 } |                 } | ||||||
|  | 
 | ||||||
|  |                 if (radius) { | ||||||
|  |                     cube.r[0] = radius[0] ?? cube.r[0]; | ||||||
|  |                     cube.r[1] = radius[1] ?? cube.r[1]; | ||||||
|  |                     cube.r[2] = radius[2] ?? cube.r[2]; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|             } else { |             } else { | ||||||
|                 throw new Error("Renderer: Use duplicate ObjectID when drawing different types of objects"); |                 throw new Error("Renderer: Use duplicate ObjectID when drawing different types of objects"); | ||||||
|             } |             } | ||||||
| @ -263,6 +299,12 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { | |||||||
|                 cube.position[2] = position[2] ?? cube.position[2]; |                 cube.position[2] = position[2] ?? cube.position[2]; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             if (radius) { | ||||||
|  |                 cube.r[0] = radius[0] ?? cube.r[0]; | ||||||
|  |                 cube.r[1] = radius[1] ?? cube.r[1]; | ||||||
|  |                 cube.r[2] = radius[2] ?? cube.r[2]; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             this.objectPool.set(id, cube); |             this.objectPool.set(id, cube); | ||||||
|             console.log(`Renderer: Create new cube object with id ${id}`); |             console.log(`Renderer: Create new cube object with id ${id}`); | ||||||
|         } |         } | ||||||
| @ -271,21 +313,11 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { | |||||||
|         cube.isDraw = true; |         cube.isDraw = true; | ||||||
| 
 | 
 | ||||||
|         // 参数传递
 |         // 参数传递
 | ||||||
|         if (param) { |         if (param && param.color) { | ||||||
| 
 | 
 | ||||||
|             // 颜色数据
 |             cube.color[0] = param.color[0] ?? cube.color[0]; | ||||||
|             if (param.color) { |             cube.color[1] = param.color[1] ?? cube.color[1]; | ||||||
|                 cube.color[0] = param.color[0] ?? cube.color[0] |             cube.color[2] = param.color[2] ?? cube.color[2]; | ||||||
|                 cube.color[1] = param.color[1] ?? cube.color[1] |  | ||||||
|                 cube.color[2] = param.color[2] ?? cube.color[2] |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // 半径数据
 |  | ||||||
|             if (param.radius) { |  | ||||||
|                 cube.r[0] = param.radius[0] ?? cube.r[0]; |  | ||||||
|                 cube.r[1] = param.radius[1] ?? cube.r[1]; |  | ||||||
|                 cube.r[2] = param.radius[2] ?? cube.r[2]; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return this; |         return this; | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ interface IGroupShaderAttribute { | |||||||
| 
 | 
 | ||||||
| interface IGroupShaderUniform { | interface IGroupShaderUniform { | ||||||
|     uRadius: number, |     uRadius: number, | ||||||
|  |     uShape: number, | ||||||
|     uMvp: ObjectData, |     uMvp: ObjectData, | ||||||
|     uColor: ObjectData, |     uColor: ObjectData, | ||||||
|     uFogColor: ObjectData, |     uFogColor: ObjectData, | ||||||
| @ -50,10 +51,42 @@ class GroupShader extends GLShader<IGroupShaderAttribute, IGroupShaderUniform>{ | |||||||
|              |              | ||||||
|             uniform vec3 uColor; |             uniform vec3 uColor; | ||||||
|             uniform vec3 uFogColor; |             uniform vec3 uFogColor; | ||||||
|  |             uniform int uShape; | ||||||
| 
 | 
 | ||||||
|             varying float vFogPower; |             varying float vFogPower; | ||||||
|          |          | ||||||
|             void main(){ |             void main(){ | ||||||
|  | 
 | ||||||
|  |                 float dist = distance(gl_PointCoord, vec2(0.5, 0.5)); | ||||||
|  |                 vec2 normalPos = (gl_PointCoord - vec2(0.5, 0.5)) * 2.; | ||||||
|  |                  | ||||||
|  |                 if ( uShape == 1 && abs(normalPos.x) < .6 && abs(normalPos.y) < .6) { | ||||||
|  |                     discard; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if ( uShape == 2 && abs(normalPos.x) > .3 && abs(normalPos.y) > .3) { | ||||||
|  |                     discard; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if ( uShape == 3 && abs(normalPos.y) > .3) { | ||||||
|  |                     discard; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if ( uShape == 4 && | ||||||
|  |                     (abs(normalPos.x) < .4 || abs(normalPos.y) < .4) && | ||||||
|  |                     (abs(normalPos.x) > .4 || abs(normalPos.y) > .4) | ||||||
|  |                 ) { | ||||||
|  |                     discard; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if ( uShape == 5 && | ||||||
|  |                     (abs(normalPos.x) < .75 && abs(normalPos.y) < .75) && | ||||||
|  |                     (abs(normalPos.x) < .28 || abs(normalPos.y) < .28) && | ||||||
|  |                     (abs(normalPos.x) > .28 || abs(normalPos.y) > .28) | ||||||
|  |                 ) { | ||||||
|  |                     discard; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|                 gl_FragColor = vec4(mix(uColor, uFogColor, vFogPower), 1.); |                 gl_FragColor = vec4(mix(uColor, uFogColor, vFogPower), 1.); | ||||||
|             } |             } | ||||||
|         `;
 |         `;
 | ||||||
| @ -111,4 +144,13 @@ class GroupShader extends GLShader<IGroupShaderAttribute, IGroupShaderUniform>{ | |||||||
|             this.uniformLocate("uFogDensity"), rgb |             this.uniformLocate("uFogDensity"), rgb | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 形状 | ||||||
|  |      */ | ||||||
|  |     public shape(shape: number) { | ||||||
|  |         this.gl.uniform1i( | ||||||
|  |             this.uniformLocate("uShape"), shape | ||||||
|  |         ) | ||||||
|  |     } | ||||||
| } | } | ||||||
| @ -1,7 +1,7 @@ | |||||||
| import { Component, ReactNode } from "react"; | import { Component, ReactNode } from "react"; | ||||||
| import { Icon } from "@fluentui/react"; | import { Icon } from "@fluentui/react"; | ||||||
| import { AllI18nKeys } from "@Component/Localization/Localization"; | import { AllI18nKeys } from "@Component/Localization/Localization"; | ||||||
| import { ObjectID } from "@Model/Renderer"; | import { ObjectID } from "@Model/Model"; | ||||||
| import { TextField, ITextFieldProps } from "@Input/TextField/TextField"; | import { TextField, ITextFieldProps } from "@Input/TextField/TextField"; | ||||||
| import "./AttrInput.scss"; | import "./AttrInput.scss"; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| import { Component, Fragment, ReactNode } from "react"; | import { Component, Fragment, ReactNode } from "react"; | ||||||
| import { useSettingWithEvent, IMixinSettingProps, Language } from "@Context/Setting"; | import { useSettingWithEvent, IMixinSettingProps, Language } from "@Context/Setting"; | ||||||
| import { AttrInput } from "@Input/AttrInput/AttrInput"; | import { AttrInput } from "@Input/AttrInput/AttrInput"; | ||||||
| import { ObjectID } from "@Model/Renderer"; | import { ObjectID } from "@Model/Model"; | ||||||
| import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; | import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; | ||||||
| import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker"; | import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker"; | ||||||
| import { AllI18nKeys, I18N } from "@Component/Localization/Localization"; | import { AllI18nKeys, I18N } from "@Component/Localization/Localization"; | ||||||
| @ -10,7 +10,7 @@ import { ColorInput } from "@Input/ColorInput/ColorInput"; | |||||||
| import { ComboInput, IDisplayItem } from "@Input/ComboInput/ComboInput"; | import { ComboInput, IDisplayItem } from "@Input/ComboInput/ComboInput"; | ||||||
| import { | import { | ||||||
|     IParameter, IParameterOption, IParameterOptionItem, |     IParameter, IParameterOption, IParameterOptionItem, | ||||||
|     IParameterValue, IParamValue, isObjectType, isVectorType |     IParameterValue, IParamValue, isObjectType | ||||||
| } from "@Model/Parameter"; | } from "@Model/Parameter"; | ||||||
| import "./Parameter.scss"; | import "./Parameter.scss"; | ||||||
| 
 | 
 | ||||||
| @ -20,6 +20,7 @@ interface IParameterProps<P extends IParameter = {}> { | |||||||
|     key: ObjectID; |     key: ObjectID; | ||||||
|     change: <K extends keyof P>(key: K, val: IParamValue<P[K]>) => any; |     change: <K extends keyof P>(key: K, val: IParamValue<P[K]>) => any; | ||||||
|     i18n?: (key: string, language: Language) => string; |     i18n?: (key: string, language: Language) => string; | ||||||
|  |     renderKey?: Array<keyof P>; | ||||||
|     title?: AllI18nKeys; |     title?: AllI18nKeys; | ||||||
|     titleOption?: Record<string, string>; |     titleOption?: Record<string, string>; | ||||||
|     isFirst?: boolean; |     isFirst?: boolean; | ||||||
| @ -249,12 +250,18 @@ class Parameter<P extends IParameter> extends Component<IParameterProps<P> & IMi | |||||||
|     } |     } | ||||||
|      |      | ||||||
|     public render(): ReactNode { |     public render(): ReactNode { | ||||||
|         const allOptionKeys: Array<keyof P> = Object.getOwnPropertyNames(this.props.option); |          | ||||||
|  |         let allOptionKeys: Array<keyof P>; | ||||||
|  |         if (this.props.renderKey) { | ||||||
|  |             allOptionKeys = this.props.renderKey; | ||||||
|  |         } else { | ||||||
|  |             allOptionKeys = Object.getOwnPropertyNames(this.props.option); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         return <> |         return <> | ||||||
|          |          | ||||||
|             { |             { | ||||||
|                 allOptionKeys.length <= 0 && this.props.title ? |                 allOptionKeys.length > 0 && this.props.title ? | ||||||
|                     <Message |                     <Message | ||||||
|                         isTitle |                         isTitle | ||||||
|                         first={this.props.isFirst} |                         first={this.props.isFirst} | ||||||
|  | |||||||
| @ -76,6 +76,7 @@ const EN_US = { | |||||||
|     "Common.Attr.Title.Individual.Generation": "Individual generation", |     "Common.Attr.Title.Individual.Generation": "Individual generation", | ||||||
|     "Common.Attr.Title.Behaviors": "Behaviors list", |     "Common.Attr.Title.Behaviors": "Behaviors list", | ||||||
|     "Common.Attr.Title.Individual.kill": "Individual kill", |     "Common.Attr.Title.Individual.kill": "Individual kill", | ||||||
|  |     "Common.Attr.Title.Render.Parameter": "Render parameters", | ||||||
|     "Common.Attr.Key.Display.Name": "Display name", |     "Common.Attr.Key.Display.Name": "Display name", | ||||||
|     "Common.Attr.Key.Position.X": "Position X", |     "Common.Attr.Key.Position.X": "Position X", | ||||||
|     "Common.Attr.Key.Position.Y": "Position Y", |     "Common.Attr.Key.Position.Y": "Position Y", | ||||||
| @ -106,6 +107,13 @@ const EN_US = { | |||||||
|     "Common.Attr.Key.Generation.Error.Invalid.Label": "The specified label has expired", |     "Common.Attr.Key.Generation.Error.Invalid.Label": "The specified label has expired", | ||||||
|     "Common.Attr.Key.Kill.Random": "Random kill", |     "Common.Attr.Key.Kill.Random": "Random kill", | ||||||
|     "Common.Attr.Key.Kill.Count": "Kill count", |     "Common.Attr.Key.Kill.Count": "Kill count", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape": "Display Shape", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Square": "Square", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Hollow.Square": "Hollow square", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Hollow.Plus": "Plus", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Hollow.Reduce": "Reduce", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Hollow.Cross": "Cross", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Hollow.Checkerboard": "Checkerboard", | ||||||
|     "Panel.Info.Range.Details.Attr.Error.Not.Range": "Object is not a Range", |     "Panel.Info.Range.Details.Attr.Error.Not.Range": "Object is not a Range", | ||||||
|     "Panel.Info.Range.Details.Attr.Error.Unspecified": "Unspecified range object", |     "Panel.Info.Range.Details.Attr.Error.Unspecified": "Unspecified range object", | ||||||
|     "Panel.Info.Group.Details.Attr.Error.Not.Group": "Object is not a Group", |     "Panel.Info.Group.Details.Attr.Error.Not.Group": "Object is not a Group", | ||||||
|  | |||||||
| @ -76,6 +76,7 @@ const ZH_CN = { | |||||||
|     "Common.Attr.Title.Individual.Generation": "生成个体", |     "Common.Attr.Title.Individual.Generation": "生成个体", | ||||||
|     "Common.Attr.Title.Behaviors": "行为列表", |     "Common.Attr.Title.Behaviors": "行为列表", | ||||||
|     "Common.Attr.Title.Individual.kill": "消除个体", |     "Common.Attr.Title.Individual.kill": "消除个体", | ||||||
|  |     "Common.Attr.Title.Render.Parameter": "渲染参数", | ||||||
|     "Common.Attr.Key.Display.Name": "显示名称", |     "Common.Attr.Key.Display.Name": "显示名称", | ||||||
|     "Common.Attr.Key.Position.X": "X 坐标", |     "Common.Attr.Key.Position.X": "X 坐标", | ||||||
|     "Common.Attr.Key.Position.Y": "Y 坐标", |     "Common.Attr.Key.Position.Y": "Y 坐标", | ||||||
| @ -106,6 +107,13 @@ const ZH_CN = { | |||||||
|     "Common.Attr.Key.Generation.Error.Invalid.Label": "指定的标签已失效", |     "Common.Attr.Key.Generation.Error.Invalid.Label": "指定的标签已失效", | ||||||
|     "Common.Attr.Key.Kill.Random": "随机消除", |     "Common.Attr.Key.Kill.Random": "随机消除", | ||||||
|     "Common.Attr.Key.Kill.Count": "消除数量", |     "Common.Attr.Key.Kill.Count": "消除数量", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape": "显示形状", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Square": "方形", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Hollow.Square": "空心方形", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Hollow.Plus": "加号", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Hollow.Reduce": "减号", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Hollow.Cross": "叉号", | ||||||
|  |     "Common.Render.Attr.Key.Display.Shape.Hollow.Checkerboard": "棋盘", | ||||||
|     "Panel.Info.Range.Details.Attr.Error.Not.Range": "对象不是一个范围", |     "Panel.Info.Range.Details.Attr.Error.Not.Range": "对象不是一个范围", | ||||||
|     "Panel.Info.Range.Details.Attr.Error.Unspecified": "未指定范围对象", |     "Panel.Info.Range.Details.Attr.Error.Unspecified": "未指定范围对象", | ||||||
|     "Panel.Info.Group.Details.Attr.Error.Not.Group": "对象不是一个群", |     "Panel.Info.Group.Details.Attr.Error.Not.Group": "对象不是一个群", | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { LabelObject } from "@Model/Label" | import { LabelObject } from "@Model/Label" | ||||||
| import type { Model } from "@Model/Model"; | import type { IAnyObject, Model } from "@Model/Model"; | ||||||
| import type { ObjectID } from "@Model/Renderer"; | import type { ObjectID } from "@Model/Model"; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 可控对象 |  * 可控对象 | ||||||
| @ -37,6 +37,11 @@ class CtrlObject extends LabelObject { | |||||||
|      */ |      */ | ||||||
|     protected model: Model; |     protected model: Model; | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * 渲染数据 | ||||||
|  |      */ | ||||||
|  |     public renderParameter: IAnyObject = {}; | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * 构造器 |      * 构造器 | ||||||
|      */ |      */ | ||||||
|  | |||||||
| @ -3,6 +3,8 @@ import { CtrlObject } from "@Model/CtrlObject"; | |||||||
| import type { Behavior } from "@Model/Behavior";  | import type { Behavior } from "@Model/Behavior";  | ||||||
| import { Label } from "@Model/Label"; | import { Label } from "@Model/Label"; | ||||||
| import { Range } from "@Model/Range"; | import { Range } from "@Model/Range"; | ||||||
|  | import { Model, ObjectID } from "@Model/Model"; | ||||||
|  | import { getDefaultValue } from "@Model/Parameter"; | ||||||
| 
 | 
 | ||||||
| enum GenMod { | enum GenMod { | ||||||
|     Point = "p", |     Point = "p", | ||||||
| @ -381,10 +383,14 @@ class Group extends CtrlObject { | |||||||
|         return dataBuffer; |         return dataBuffer; | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     /** |     public constructor(model: Model, id: ObjectID) { | ||||||
|      * 绘制大小  | 
 | ||||||
|      */ |         super(model, id); | ||||||
|     public size: number = 60; |          | ||||||
|  |         if (model.renderer) { | ||||||
|  |             this.renderParameter = getDefaultValue(model.renderer.pointsParameterOption); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export default Group; | export default Group; | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import type { Group } from "@Model/Group"; | import type { Group } from "@Model/Group"; | ||||||
| import { ObjectID } from "@Model/Renderer"; | import { ObjectID } from "@Model/Model"; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 群中的个体类型 |  * 群中的个体类型 | ||||||
|  | |||||||
| @ -1,5 +1,4 @@ | |||||||
| import type { Model } from "@Model/Model"; | import type { Model, ObjectID } from "@Model/Model"; | ||||||
| import { ObjectID } from "@Model/Renderer"; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 数据标签 |  * 数据标签 | ||||||
|  | |||||||
| @ -5,9 +5,19 @@ import { IParamValue } from "@Model/Parameter"; | |||||||
| import { Individual } from "@Model/Individual"; | import { Individual } from "@Model/Individual"; | ||||||
| import { CtrlObject } from "@Model/CtrlObject"; | import { CtrlObject } from "@Model/CtrlObject"; | ||||||
| import { Emitter, EventType, EventMixin } from "@Model/Emitter"; | import { Emitter, EventType, EventMixin } from "@Model/Emitter"; | ||||||
| import { ObjectID, AbstractRenderer } from "@Model/Renderer"; | import { AbstractRenderer } from "@Model/Renderer"; | ||||||
| import { Behavior, IAnyBehavior, IAnyBehaviorRecorder } from "@Model/Behavior"; | import { Behavior, IAnyBehavior, IAnyBehaviorRecorder } from "@Model/Behavior"; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * 对象标识符 | ||||||
|  |  */ | ||||||
|  | type ObjectID = string; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 任意类型对象 | ||||||
|  |  */ | ||||||
|  | type IAnyObject = Record<string, any>; | ||||||
|  | 
 | ||||||
| type ModelEvent = { | type ModelEvent = { | ||||||
|     labelChange: Label[]; |     labelChange: Label[]; | ||||||
|     objectChange: CtrlObject[]; |     objectChange: CtrlObject[]; | ||||||
| @ -352,17 +362,12 @@ class Model extends Emitter<ModelEvent> { | |||||||
|         // 渲染
 |         // 渲染
 | ||||||
|         for (let i = 0; i < this.objectPool.length; i++) { |         for (let i = 0; i < this.objectPool.length; i++) { | ||||||
|             let object = this.objectPool[i]; |             let object = this.objectPool[i]; | ||||||
|  |             object.renderParameter.color = object.color; | ||||||
|             if (object.display && object instanceof Group) { |             if (object.display && object instanceof Group) { | ||||||
|                 this.renderer.points(object.id, object.exportPositionData(), { |                 this.renderer.points(object.id, object.exportPositionData(), object.renderParameter); | ||||||
|                     color: object.color, |  | ||||||
|                     size: object.size |  | ||||||
|                 } as any); |  | ||||||
|             } |             } | ||||||
|             if (object.display && object instanceof Range) { |             if (object.display && object instanceof Range) { | ||||||
|                 this.renderer.cube(object.id, object.position, { |                 this.renderer.cube(object.id, object.position, object.radius, object.renderParameter); | ||||||
|                     color: object.color, |  | ||||||
|                     radius: object.radius |  | ||||||
|                 } as any); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -376,5 +381,6 @@ export { | |||||||
|     EventMixin, |     EventMixin, | ||||||
|     Model, |     Model, | ||||||
|     CtrlObject, |     CtrlObject, | ||||||
|     ObjectID |     ObjectID, | ||||||
|  |     IAnyObject | ||||||
| } | } | ||||||
| @ -1,4 +1,6 @@ | |||||||
| import { CtrlObject } from "@Model/CtrlObject"; | import { CtrlObject } from "@Model/CtrlObject"; | ||||||
|  | import { Model, ObjectID } from "@Model/Model"; | ||||||
|  | import { getDefaultValue } from "@Model/Parameter"; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 范围 |  * 范围 | ||||||
| @ -15,6 +17,15 @@ class Range extends CtrlObject { | |||||||
|      */ |      */ | ||||||
|     public radius: number[] = [1, 1, 1]; |     public radius: number[] = [1, 1, 1]; | ||||||
| 
 | 
 | ||||||
|  |     public constructor(model: Model, id: ObjectID) { | ||||||
|  | 
 | ||||||
|  |         super(model, id); | ||||||
|  |          | ||||||
|  |         if (model.renderer) { | ||||||
|  |             this.renderParameter = getDefaultValue(model.renderer.cubeParameterOption); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export default Range; | export default Range; | ||||||
|  | |||||||
| @ -1,24 +1,31 @@ | |||||||
| import { Emitter, EventType } from "@Model/Emitter"; | import { Emitter, EventType } from "@Model/Emitter"; | ||||||
|  | import { IAnyObject, ObjectID } from "@Model/Model";  | ||||||
|  | import { IParameter, IParameterOption, IParameterValue } from "@Model/Parameter"; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 任意类型对象 |  * 默认类型 | ||||||
|  */ |  */ | ||||||
| type IAnyObject = Record<string, any>; | type IDefaultType<T, D> = T extends undefined ? D : T; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 渲染器参数 |  * 渲染器参数 | ||||||
|  */ |  */ | ||||||
| interface IRendererParam { | interface IRendererParam { | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * 渲染器参数 | ||||||
|  | 	 */ | ||||||
|  | 	renderer?: IParameter; | ||||||
|  | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * 绘制点需要的参数 | 	 * 绘制点需要的参数 | ||||||
| 	 */ | 	 */ | ||||||
| 	points?: IAnyObject | 	points?: IParameter; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * 绘制立方体需要的参数 | 	 * 绘制立方体需要的参数 | ||||||
| 	 */ | 	 */ | ||||||
| 	cube?: IAnyObject | 	cube?: IParameter; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -32,22 +39,15 @@ interface ICommonParam { | |||||||
| 	color?: ObjectData; | 	color?: ObjectData; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | 
 | ||||||
|  * 对象标识符 |  | ||||||
|  */ |  | ||||||
| type ObjectID = string; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 接收的数据类型 |  * 接收的数据类型 | ||||||
|  */ |  */ | ||||||
| type ObjectData = Array<number> | Float32Array; | type ObjectData = Array<number> | Float32Array; | ||||||
| 
 | 
 | ||||||
| interface IRendererConstructor< | interface IRendererConstructor { | ||||||
| 	M extends IAnyObject = {} | 	new (): AbstractRenderer<IRendererParam, AbstractRendererEvent> | ||||||
| > { |  | ||||||
| 	new (canvas: HTMLCanvasElement, param?: M): AbstractRenderer< |  | ||||||
| 		IRendererParam, IAnyObject, AbstractRendererEvent |  | ||||||
| 	> |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type AbstractRendererEvent = { | type AbstractRendererEvent = { | ||||||
| @ -63,7 +63,6 @@ type AbstractRendererEvent = { | |||||||
|  */ |  */ | ||||||
| abstract class AbstractRenderer< | abstract class AbstractRenderer< | ||||||
| 	P extends IRendererParam = {}, | 	P extends IRendererParam = {}, | ||||||
| 	M extends IAnyObject = {}, |  | ||||||
| 	E extends AbstractRendererEvent = {loop: number} | 	E extends AbstractRendererEvent = {loop: number} | ||||||
| > extends Emitter<E> { | > extends Emitter<E> { | ||||||
| 
 | 
 | ||||||
| @ -72,28 +71,17 @@ abstract class AbstractRenderer< | |||||||
| 	/** | 	/** | ||||||
| 	 * 渲染器参数 | 	 * 渲染器参数 | ||||||
| 	 */ | 	 */ | ||||||
| 	abstract param: Partial<M>; | 	public rendererParameterOption: IParameterOption<IDefaultType<P["renderer"], {}>> = {} as any; | ||||||
|  | 	public pointsParameterOption: IParameterOption<IDefaultType<P["points"], {}>> = {} as any; | ||||||
|  | 	public cubeParameterOption: IParameterOption<IDefaultType<P["cube"], {}>> = {} as any; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * 类型断言 | 	 * 渲染器参数 | ||||||
| 	 */ | 	 */ | ||||||
| 	get isRenderer() { | 	public rendererParameter: IParameterValue<IDefaultType<P["renderer"], {}>> = {} as any; | ||||||
| 		return true; |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * 断言对象是否是渲染器 | 	 * @function clean  | ||||||
| 	 */ |  | ||||||
| 	public static isRenderer(render: any): render is AbstractRenderer { |  | ||||||
| 		if (render instanceof Object) { |  | ||||||
| 			return !!(render as AbstractRenderer).isRenderer; |  | ||||||
| 		} else { |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
| 	 * @function start  |  | ||||||
| 	 * 开始一次数据更新 \ | 	 * 开始一次数据更新 \ | ||||||
| 	 * 此函数将清除固定对象的绘制状态 \ | 	 * 此函数将清除固定对象的绘制状态 \ | ||||||
| 	 * 在每次数据更新前调用 \ | 	 * 在每次数据更新前调用 \ | ||||||
| @ -110,7 +98,9 @@ abstract class AbstractRenderer< | |||||||
| 	 * @param id 使用的标识符 | 	 * @param id 使用的标识符 | ||||||
| 	 * @param position 做标集合 | 	 * @param position 做标集合 | ||||||
| 	 */ | 	 */ | ||||||
| 	abstract points(id: ObjectID, position?: ObjectData, param?: Readonly<P["points"] & ICommonParam>): this; | 	abstract points(id: ObjectID, position?: ObjectData, param?:  | ||||||
|  | 		Readonly<IParameterValue<IDefaultType<P["points"], {}>>> | ||||||
|  | 	): this; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @function cube 绘制立方体 | 	 * @function cube 绘制立方体 | ||||||
| @ -120,12 +110,13 @@ abstract class AbstractRenderer< | |||||||
| 	 *  | 	 *  | ||||||
| 	 * 注意: 这里的半径指的是立方体重心与立方体任意一面几何中心的距离 | 	 * 注意: 这里的半径指的是立方体重心与立方体任意一面几何中心的距离 | ||||||
| 	 */ | 	 */ | ||||||
| 	abstract cube(id: ObjectID, position?: ObjectData, param?: Readonly<P["cube"] & ICommonParam>): this; | 	abstract cube(id: ObjectID, position?: ObjectData, radius?: ObjectData, param?: | ||||||
|  | 		Readonly<IParameterValue<IDefaultType<P["cube"], {}>>> | ||||||
|  | 	): this; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export default AbstractRenderer; | export default AbstractRenderer; | ||||||
| export {  | export {  | ||||||
|     AbstractRenderer, ObjectID, IAnyObject, |     AbstractRenderer, ICommonParam, IRendererParam,  | ||||||
|     ICommonParam, IRendererParam,  |  | ||||||
|     ObjectData, IRendererConstructor  |     ObjectData, IRendererConstructor  | ||||||
| }; | }; | ||||||
| @ -21,7 +21,7 @@ class Laboratory extends Component { | |||||||
|             throw new Error("Laboratory: 重复引用 canvas 节点"); |             throw new Error("Laboratory: 重复引用 canvas 节点"); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const renderer = new ClassicRenderer({ className: "canvas" }).onLoad(); |         const renderer = new ClassicRenderer().onLoad(); | ||||||
|         this.canvasContRef.current.appendChild(renderer.canvas.dom); |         this.canvasContRef.current.appendChild(renderer.canvas.dom); | ||||||
| 
 | 
 | ||||||
|         let model = new Model().bindRenderer(renderer); |         let model = new Model().bindRenderer(renderer); | ||||||
| @ -39,22 +39,24 @@ class Laboratory extends Component { | |||||||
| 
 | 
 | ||||||
|         // 测试渲染器
 |         // 测试渲染器
 | ||||||
|         if (false) { |         if (false) { | ||||||
|             renderer.points("0"); |             // renderer.points("0");
 | ||||||
|             renderer.points("1", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2)); |             // renderer.points("1", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2));
 | ||||||
|             renderer.points("2", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2), { |             // renderer.points("2", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2), {
 | ||||||
|                 size: 100, |             //     size: 100,
 | ||||||
|                 color: [1, 0, 1] |             //     color: [1, 0, 1]
 | ||||||
|             }); |             // });
 | ||||||
|             renderer.points("3", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2), { |             // renderer.points("3", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2), {
 | ||||||
|                 size: 80, |             //     size: 80,
 | ||||||
|                 color: [0, 1, 1] |             //     color: [0, 1, 1]
 | ||||||
|             }); |             // });
 | ||||||
|             renderer.points("2"); |             // renderer.points("2");
 | ||||||
|             renderer.cube("4"); |             // renderer.cube("4");
 | ||||||
|             renderer.cube("5", new Array(3).fill(0).map(() => (Math.random() - .5) * 2), { |             // renderer.cube("5",
 | ||||||
|                 radius: new Array(3).fill(0).map(() => Math.random() * 1.2), |             //     new Array(3).fill(0).map(() => (Math.random() - .5) * 2),
 | ||||||
|                 color: [1, 1, 0] |             //     new Array(3).fill(0).map(() => Math.random() * 1.2), {
 | ||||||
|             }) |             //         color: [1, 1, 0]
 | ||||||
|  |             //     }
 | ||||||
|  |             // )
 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         (window as any).renderer = renderer; |         (window as any).renderer = renderer; | ||||||
|  | |||||||
| @ -35,9 +35,9 @@ class SimulatorWeb extends Component { | |||||||
|         (window as any).setting = (this.setting as any); |         (window as any).setting = (this.setting as any); | ||||||
| 
 | 
 | ||||||
|         // TODO: 这里要读取存档
 |         // TODO: 这里要读取存档
 | ||||||
|  |         const classicRender = new ClassicRenderer().onLoad(); | ||||||
|         this.status = new Status(); |         this.status = new Status(); | ||||||
|         this.status.renderer = new ClassicRenderer({ className: "canvas" }).onLoad(); |         this.status.bindRenderer(classicRender); | ||||||
|         this.status.bindRenderer(this.status.renderer); |  | ||||||
|         this.status.setting = this.setting; |         this.status.setting = this.setting; | ||||||
| 
 | 
 | ||||||
|         // 测试代码
 |         // 测试代码
 | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | |||||||
| import { useSetting, IMixinSettingProps } from "@Context/Setting"; | import { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||||
| import { ComboInput, IDisplayItem } from "@Input/ComboInput/ComboInput"; | import { ComboInput, IDisplayItem } from "@Input/ComboInput/ComboInput"; | ||||||
| import { Message } from "@Input/Message/Message"; | import { Message } from "@Input/Message/Message"; | ||||||
| import { ObjectID } from "@Model/Renderer"; | import { ObjectID } from "@Model/Model"; | ||||||
| import { ColorInput } from "@Input/ColorInput/ColorInput"; | import { ColorInput } from "@Input/ColorInput/ColorInput"; | ||||||
| import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; | import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; | ||||||
| import { LabelPicker } from "@Input/LabelPicker/LabelPicker"; | import { LabelPicker } from "@Input/LabelPicker/LabelPicker"; | ||||||
| @ -13,6 +13,7 @@ import { AllI18nKeys } from "@Component/Localization/Localization"; | |||||||
| import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker"; | import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker"; | ||||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||||
| import { BehaviorPicker } from "@Input/BehaviorPicker/BehaviorPicker"; | import { BehaviorPicker } from "@Input/BehaviorPicker/BehaviorPicker"; | ||||||
|  | import { Parameter } from "@Input/Parameter/Parameter"; | ||||||
| import "./GroupDetails.scss"; | import "./GroupDetails.scss"; | ||||||
| 
 | 
 | ||||||
| interface IGroupDetailsProps {} | interface IGroupDetailsProps {} | ||||||
| @ -54,14 +55,6 @@ class GroupDetails extends Component<IGroupDetailsProps & IMixinStatusProps & IM | |||||||
|                 }} |                 }} | ||||||
|             /> |             /> | ||||||
| 
 | 
 | ||||||
|             <AttrInput |  | ||||||
|                 id={group.id} isNumber={true} step={10} keyI18n="Common.Attr.Key.Size" |  | ||||||
|                 value={group.size} min={0} |  | ||||||
|                 valueChange={(val) => { |  | ||||||
|                     this.props.status?.changeGroupAttrib(group.id, "size", (val as any) / 1); |  | ||||||
|                 }} |  | ||||||
|             /> |  | ||||||
| 
 |  | ||||||
|             <LabelPicker |             <LabelPicker | ||||||
|                 keyI18n="Common.Attr.Key.Label" |                 keyI18n="Common.Attr.Key.Label" | ||||||
|                 labels={group.allLabels()} |                 labels={group.allLabels()} | ||||||
| @ -115,6 +108,23 @@ class GroupDetails extends Component<IGroupDetailsProps & IMixinStatusProps & IM | |||||||
| 				}} | 				}} | ||||||
| 			/> | 			/> | ||||||
| 
 | 
 | ||||||
|  |             <Parameter | ||||||
|  |                 key={group.id} | ||||||
|  |                 option={this.props.status?.renderer.pointsParameterOption ?? {}} | ||||||
|  |                 title={"Common.Attr.Title.Render.Parameter"} | ||||||
|  |                 value={group.renderParameter} | ||||||
|  |                 renderKey={ | ||||||
|  |                     Object.getOwnPropertyNames(this.props.status?.renderer.pointsParameterOption ?? {}) | ||||||
|  |                     .filter((key) => key !== "color") | ||||||
|  |                 } | ||||||
|  |                 change={(key, value) => { | ||||||
|  |                     group.renderParameter[key as any] = value; | ||||||
|  |                     this.props.status?.changeGroupAttrib( | ||||||
|  |                         group.id, "renderParameter", group.renderParameter | ||||||
|  |                     ); | ||||||
|  |                 }} | ||||||
|  |             /> | ||||||
|  |              | ||||||
|             <Message i18nKey="Common.Attr.Title.Behaviors" isTitle/> |             <Message i18nKey="Common.Attr.Title.Behaviors" isTitle/> | ||||||
| 
 | 
 | ||||||
|             <BehaviorPicker |             <BehaviorPicker | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ import { Component, ReactNode } from "react"; | |||||||
| import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; | import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; | ||||||
| import { useStatus, IMixinStatusProps } from "@Context/Status"; | import { useStatus, IMixinStatusProps } from "@Context/Status"; | ||||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||||
| import { ObjectID } from "@Model/Renderer"; | import { ObjectID } from "@Model/Model"; | ||||||
| import { Icon } from "@fluentui/react"; | import { Icon } from "@fluentui/react"; | ||||||
| import "./ObjectList.scss"; | import "./ObjectList.scss"; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | |||||||
| import { useSetting, IMixinSettingProps } from "@Context/Setting"; | import { useSetting, IMixinSettingProps } from "@Context/Setting"; | ||||||
| import { Localization } from "@Component/Localization/Localization"; | import { Localization } from "@Component/Localization/Localization"; | ||||||
| import { DetailsList } from "@Component/DetailsList/DetailsList"; | import { DetailsList } from "@Component/DetailsList/DetailsList"; | ||||||
| import { ObjectID } from "@Model/Renderer"; | import { ObjectID } from "@Model/Model"; | ||||||
| import { Icon } from "@fluentui/react"; | import { Icon } from "@fluentui/react"; | ||||||
| import "./ObjectList.scss"; | import "./ObjectList.scss"; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,11 +3,12 @@ import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; | |||||||
| import { AttrInput } from "@Input/AttrInput/AttrInput"; | import { AttrInput } from "@Input/AttrInput/AttrInput"; | ||||||
| import { Message } from "@Input/Message/Message"; | import { Message } from "@Input/Message/Message"; | ||||||
| import { Range } from "@Model/Range"; | import { Range } from "@Model/Range"; | ||||||
| import { ObjectID } from "@Model/Renderer"; | import { ObjectID } from "@Model/Model"; | ||||||
| import { ColorInput } from "@Input/ColorInput/ColorInput"; | import { ColorInput } from "@Input/ColorInput/ColorInput"; | ||||||
| import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; | import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; | ||||||
| import { LabelPicker } from "@Input/LabelPicker/LabelPicker"; | import { LabelPicker } from "@Input/LabelPicker/LabelPicker"; | ||||||
| import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; | ||||||
|  | import { Parameter } from "@Input/Parameter/Parameter"; | ||||||
| import "./RangeDetails.scss"; | import "./RangeDetails.scss"; | ||||||
| 
 | 
 | ||||||
| @useStatusWithEvent("rangeAttrChange", "focusObjectChange", "rangeLabelChange") | @useStatusWithEvent("rangeAttrChange", "focusObjectChange", "rangeLabelChange") | ||||||
| @ -72,6 +73,23 @@ class RangeDetails extends Component<IMixinStatusProps> { | |||||||
| 				}} | 				}} | ||||||
| 			/> | 			/> | ||||||
| 
 | 
 | ||||||
|  |             <Parameter | ||||||
|  |                 key={range.id} | ||||||
|  |                 option={this.props.status?.renderer.cubeParameterOption ?? {}} | ||||||
|  |                 title={"Common.Attr.Title.Render.Parameter"} | ||||||
|  |                 value={range.renderParameter} | ||||||
|  |                 renderKey={ | ||||||
|  |                     Object.getOwnPropertyNames(this.props.status?.renderer.cubeParameterOption ?? {}) | ||||||
|  |                     .filter((key) => key !== "color") | ||||||
|  |                 } | ||||||
|  |                 change={(key, value) => { | ||||||
|  |                     range.renderParameter[key as any] = value; | ||||||
|  |                     this.props.status?.changeRangeAttrib( | ||||||
|  |                         range.id, "renderParameter", range.renderParameter | ||||||
|  |                     ); | ||||||
|  |                 }} | ||||||
|  |             /> | ||||||
|  | 
 | ||||||
|             <Message i18nKey="Common.Attr.Title.Spatial" isTitle/> |             <Message i18nKey="Common.Attr.Title.Spatial" isTitle/> | ||||||
| 
 | 
 | ||||||
|             <AttrInput |             <AttrInput | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user