From 8ced3d82f3b62e09f5d491a08c30cdb4bbd44cf4 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Sat, 9 Apr 2022 12:21:08 +0800 Subject: [PATCH 1/4] Move objectID into model --- source/Context/Popups.ts | 2 +- source/GLRender/BasicRenderer.ts | 3 ++- source/GLRender/ClassicRenderer.ts | 3 ++- source/Input/AttrInput/AttrInput.tsx | 2 +- source/Input/Parameter/Parameter.tsx | 2 +- source/Model/CtrlObject.ts | 2 +- source/Model/Individual.ts | 2 +- source/Model/Label.ts | 3 +-- source/Model/Model.ts | 15 +++++++++++++-- source/Model/Renderer.ts | 14 +++----------- source/Panel/GroupDetails/GroupDetails.tsx | 2 +- source/Panel/ObjectList/ObjectCommand.tsx | 2 +- source/Panel/ObjectList/ObjectList.tsx | 2 +- source/Panel/RangeDetails/RangeDetails.tsx | 2 +- 14 files changed, 30 insertions(+), 26 deletions(-) diff --git a/source/Context/Popups.ts b/source/Context/Popups.ts index e5e4cd6..5ee7767 100644 --- a/source/Context/Popups.ts +++ b/source/Context/Popups.ts @@ -1,7 +1,7 @@ import { ReactNode, createElement } from "react"; import { Emitter } from "@Model/Emitter"; import { Localization } from "@Component/Localization/Localization"; -import { IAnyObject } from "@Model/Renderer"; +import { IAnyObject } from "@Model/Model"; enum ResizeDragDirection { top = 1, diff --git a/source/GLRender/BasicRenderer.ts b/source/GLRender/BasicRenderer.ts index 661c6cf..855e0dd 100644 --- a/source/GLRender/BasicRenderer.ts +++ b/source/GLRender/BasicRenderer.ts @@ -1,4 +1,5 @@ -import { AbstractRenderer, IRendererParam, IAnyObject } from "@Model/Renderer"; +import { AbstractRenderer, IRendererParam } from "@Model/Renderer"; +import { IAnyObject } from "@Model/Model"; import { EventType } from "@Model/Emitter"; import { GLCanvas, GLCanvasOption } from "./GLCanvas"; import { GLContext } from "./GLContext"; diff --git a/source/GLRender/ClassicRenderer.ts b/source/GLRender/ClassicRenderer.ts index 29dc2b7..426f2b1 100644 --- a/source/GLRender/ClassicRenderer.ts +++ b/source/GLRender/ClassicRenderer.ts @@ -1,4 +1,5 @@ -import { ObjectID, ObjectData, ICommonParam } from "@Model/Renderer"; +import { ObjectData, ICommonParam } from "@Model/Renderer"; +import { ObjectID } from "@Model/Model"; import { BasicRenderer } from "./BasicRenderer"; import { BasicsShader } from "./BasicShader"; import { Axis } from "./Axis"; diff --git a/source/Input/AttrInput/AttrInput.tsx b/source/Input/AttrInput/AttrInput.tsx index 575f93c..26f0853 100644 --- a/source/Input/AttrInput/AttrInput.tsx +++ b/source/Input/AttrInput/AttrInput.tsx @@ -1,7 +1,7 @@ import { Component, ReactNode } from "react"; import { Icon } from "@fluentui/react"; import { AllI18nKeys } from "@Component/Localization/Localization"; -import { ObjectID } from "@Model/Renderer"; +import { ObjectID } from "@Model/Model"; import { TextField, ITextFieldProps } from "@Input/TextField/TextField"; import "./AttrInput.scss"; diff --git a/source/Input/Parameter/Parameter.tsx b/source/Input/Parameter/Parameter.tsx index deb6c4b..9ae2368 100644 --- a/source/Input/Parameter/Parameter.tsx +++ b/source/Input/Parameter/Parameter.tsx @@ -1,7 +1,7 @@ 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 { ObjectID } from "@Model/Model"; import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker"; import { AllI18nKeys, I18N } from "@Component/Localization/Localization"; diff --git a/source/Model/CtrlObject.ts b/source/Model/CtrlObject.ts index 5faa7e1..b9d5eaf 100644 --- a/source/Model/CtrlObject.ts +++ b/source/Model/CtrlObject.ts @@ -1,6 +1,6 @@ import { LabelObject } from "@Model/Label" import type { Model } from "@Model/Model"; -import type { ObjectID } from "@Model/Renderer"; +import type { ObjectID } from "@Model/Model"; /** * 可控对象 diff --git a/source/Model/Individual.ts b/source/Model/Individual.ts index 8f84077..2685dfa 100644 --- a/source/Model/Individual.ts +++ b/source/Model/Individual.ts @@ -1,5 +1,5 @@ import type { Group } from "@Model/Group"; -import { ObjectID } from "@Model/Renderer"; +import { ObjectID } from "@Model/Model"; /** * 群中的个体类型 diff --git a/source/Model/Label.ts b/source/Model/Label.ts index 21ae946..cd1f31f 100644 --- a/source/Model/Label.ts +++ b/source/Model/Label.ts @@ -1,5 +1,4 @@ -import type { Model } from "@Model/Model"; -import { ObjectID } from "@Model/Renderer"; +import type { Model, ObjectID } from "@Model/Model"; /** * 数据标签 diff --git a/source/Model/Model.ts b/source/Model/Model.ts index 5b15d85..f8bf940 100644 --- a/source/Model/Model.ts +++ b/source/Model/Model.ts @@ -5,9 +5,19 @@ 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 { AbstractRenderer } from "@Model/Renderer"; import { Behavior, IAnyBehavior, IAnyBehaviorRecorder } from "@Model/Behavior"; +/** + * 对象标识符 + */ +type ObjectID = string; + +/** + * 任意类型对象 + */ +type IAnyObject = Record; + type ModelEvent = { labelChange: Label[]; objectChange: CtrlObject[]; @@ -376,5 +386,6 @@ export { EventMixin, Model, CtrlObject, - ObjectID + ObjectID, + IAnyObject } \ No newline at end of file diff --git a/source/Model/Renderer.ts b/source/Model/Renderer.ts index 2c9ee64..be157c5 100644 --- a/source/Model/Renderer.ts +++ b/source/Model/Renderer.ts @@ -1,9 +1,5 @@ import { Emitter, EventType } from "@Model/Emitter"; - -/** - * 任意类型对象 - */ -type IAnyObject = Record; +import { IAnyObject, ObjectID } from "@Model/Model"; /** * 渲染器参数 @@ -32,10 +28,7 @@ interface ICommonParam { color?: ObjectData; } -/** - * 对象标识符 - */ -type ObjectID = string; + /** * 接收的数据类型 @@ -125,7 +118,6 @@ abstract class AbstractRenderer< export default AbstractRenderer; export { - AbstractRenderer, ObjectID, IAnyObject, - ICommonParam, IRendererParam, + AbstractRenderer, ICommonParam, IRendererParam, ObjectData, IRendererConstructor }; \ No newline at end of file diff --git a/source/Panel/GroupDetails/GroupDetails.tsx b/source/Panel/GroupDetails/GroupDetails.tsx index 51d94c2..495daf2 100644 --- a/source/Panel/GroupDetails/GroupDetails.tsx +++ b/source/Panel/GroupDetails/GroupDetails.tsx @@ -4,7 +4,7 @@ import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; import { useSetting, IMixinSettingProps } from "@Context/Setting"; import { ComboInput, IDisplayItem } from "@Input/ComboInput/ComboInput"; import { Message } from "@Input/Message/Message"; -import { ObjectID } from "@Model/Renderer"; +import { ObjectID } from "@Model/Model"; import { ColorInput } from "@Input/ColorInput/ColorInput"; import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; import { LabelPicker } from "@Input/LabelPicker/LabelPicker"; diff --git a/source/Panel/ObjectList/ObjectCommand.tsx b/source/Panel/ObjectList/ObjectCommand.tsx index 97b856c..ff65e1d 100644 --- a/source/Panel/ObjectList/ObjectCommand.tsx +++ b/source/Panel/ObjectList/ObjectCommand.tsx @@ -2,7 +2,7 @@ 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 { ObjectID } from "@Model/Model"; import { Icon } from "@fluentui/react"; import "./ObjectList.scss"; diff --git a/source/Panel/ObjectList/ObjectList.tsx b/source/Panel/ObjectList/ObjectList.tsx index 22a39aa..7961d26 100644 --- a/source/Panel/ObjectList/ObjectList.tsx +++ b/source/Panel/ObjectList/ObjectList.tsx @@ -3,7 +3,7 @@ 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 { ObjectID } from "@Model/Model"; import { Icon } from "@fluentui/react"; import "./ObjectList.scss"; diff --git a/source/Panel/RangeDetails/RangeDetails.tsx b/source/Panel/RangeDetails/RangeDetails.tsx index 81fe910..e2f0e2a 100644 --- a/source/Panel/RangeDetails/RangeDetails.tsx +++ b/source/Panel/RangeDetails/RangeDetails.tsx @@ -3,7 +3,7 @@ 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 { ObjectID } from "@Model/Model"; import { ColorInput } from "@Input/ColorInput/ColorInput"; import { TogglesInput } from "@Input/TogglesInput/TogglesInput"; import { LabelPicker } from "@Input/LabelPicker/LabelPicker"; From ed8269ff5072dfb0a94a37c9093902e1248daa85 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Sat, 9 Apr 2022 15:07:45 +0800 Subject: [PATCH 2/4] Optmi renderer model --- source/GLRender/BasicRenderer.ts | 26 +++----- source/GLRender/ClassicRenderer.ts | 75 ++++++++++++++--------- source/Model/Model.ts | 5 +- source/Model/Renderer.ts | 55 ++++++++--------- source/Page/Laboratory/Laboratory.tsx | 12 ++-- source/Page/SimulatorWeb/SimulatorWeb.tsx | 4 +- 6 files changed, 92 insertions(+), 85 deletions(-) diff --git a/source/GLRender/BasicRenderer.ts b/source/GLRender/BasicRenderer.ts index 855e0dd..bd36370 100644 --- a/source/GLRender/BasicRenderer.ts +++ b/source/GLRender/BasicRenderer.ts @@ -1,5 +1,4 @@ import { AbstractRenderer, IRendererParam } from "@Model/Renderer"; -import { IAnyObject } from "@Model/Model"; import { EventType } from "@Model/Emitter"; import { GLCanvas, GLCanvasOption } from "./GLCanvas"; import { GLContext } from "./GLContext"; @@ -17,19 +16,13 @@ type IRendererParams = IRendererOwnParams & GLCanvasOption; abstract class BasicRenderer< P extends IRendererParam = {}, - M extends IAnyObject = {}, E extends Record = {} -> extends AbstractRenderer { +> extends AbstractRenderer { public get dom() { return this.canvas.dom } - /** - * 渲染器参数 - */ - public param: Partial = {}; - /** * 使用的画布 */ @@ -45,19 +38,16 @@ abstract class BasicRenderer< */ protected clock: Clock; - public constructor(param: Partial = {}) { + public constructor() { 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); diff --git a/source/GLRender/ClassicRenderer.ts b/source/GLRender/ClassicRenderer.ts index 426f2b1..935fb1f 100644 --- a/source/GLRender/ClassicRenderer.ts +++ b/source/GLRender/ClassicRenderer.ts @@ -1,28 +1,40 @@ -import { 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 { BasicsShader } from "./BasicShader"; import { Axis } from "./Axis"; import { BasicCube } from "./BasicCube"; import { GroupShader } from "./GroupShader"; import { BasicGroup } from "./BasicGroup"; -import DisplayObject from "./DisplayObject"; - -interface IClassicRendererParams { - point: { - size: number; - } - cube: { - radius: number[]; - } -} +import { DisplayObject } from "./DisplayObject"; enum MouseMod { Drag = 1, click = 2 } -class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { +type IClassicRendererParameter = { + renderer: {}; + points: { + color: "color", + size: "number" + }; + cube: { + color: "color" + }; +} + +class ClassicRenderer extends BasicRenderer { + + public override rendererParameterOption = {}; + public override pointsParameterOption = { + color: { type: "color", name: "" }, + size: { type: "number", name: "Common.Attr.Key.Size" } + }; + public override cubeParameterOption = { + color: { type: "color", name: "" }, + }; private basicShader: BasicsShader = undefined as any; private axisObject: Axis = undefined as any; @@ -52,6 +64,8 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { } public onLoad(): this { + + this.rendererParameter = getDefaultValue(this.rendererParameterOption); // 自动调节分辨率 this.autoResize(); @@ -188,7 +202,7 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { points( id: ObjectID, position?: ObjectData, - param?: Readonly> + param?: Readonly> ): this { let object = this.objectPool.get(id); let group: BasicGroup; @@ -236,8 +250,8 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { } cube( - id: ObjectID, position?: ObjectData, - param?: Readonly> + id: ObjectID, position?: ObjectData, radius?: ObjectData, + param?: Readonly> ): this { let object = this.objectPool.get(id); let cube: BasicCube; @@ -251,6 +265,13 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { cube.position[1] = position[1] ?? cube.position[1]; 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 { throw new Error("Renderer: Use duplicate ObjectID when drawing different types of objects"); } @@ -264,6 +285,12 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { 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); console.log(`Renderer: Create new cube object with id ${id}`); } @@ -272,21 +299,11 @@ class ClassicRenderer extends BasicRenderer<{}, IClassicRendererParams> { cube.isDraw = true; // 参数传递 - if (param) { + if (param && param.color) { - // 颜色数据 - if (param.color) { - cube.color[0] = param.color[0] ?? cube.color[0] - 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]; - } + cube.color[0] = param.color[0] ?? cube.color[0]; + cube.color[1] = param.color[1] ?? cube.color[1]; + cube.color[2] = param.color[2] ?? cube.color[2]; } return this; diff --git a/source/Model/Model.ts b/source/Model/Model.ts index f8bf940..4eef3a5 100644 --- a/source/Model/Model.ts +++ b/source/Model/Model.ts @@ -369,9 +369,8 @@ class Model extends Emitter { } as any); } if (object.display && object instanceof Range) { - this.renderer.cube(object.id, object.position, { - color: object.color, - radius: object.radius + this.renderer.cube(object.id, object.position, object.radius, { + color: object.color } as any); } } diff --git a/source/Model/Renderer.ts b/source/Model/Renderer.ts index be157c5..00f491b 100644 --- a/source/Model/Renderer.ts +++ b/source/Model/Renderer.ts @@ -1,20 +1,31 @@ import { Emitter, EventType } from "@Model/Emitter"; import { IAnyObject, ObjectID } from "@Model/Model"; +import { IParameter, IParameterOption, IParameterValue } from "@Model/Parameter"; + +/** + * 默认类型 + */ +type IDefaultType = T extends undefined ? D : T; /** * 渲染器参数 */ interface IRendererParam { + /** + * 渲染器参数 + */ + renderer?: IParameter; + /** * 绘制点需要的参数 */ - points?: IAnyObject + points?: IParameter; /** * 绘制立方体需要的参数 */ - cube?: IAnyObject + cube?: IParameter; } /** @@ -35,12 +46,8 @@ interface ICommonParam { */ type ObjectData = Array | Float32Array; -interface IRendererConstructor< - M extends IAnyObject = {} -> { - new (canvas: HTMLCanvasElement, param?: M): AbstractRenderer< - IRendererParam, IAnyObject, AbstractRendererEvent - > +interface IRendererConstructor { + new (): AbstractRenderer } type AbstractRendererEvent = { @@ -56,7 +63,6 @@ type AbstractRendererEvent = { */ abstract class AbstractRenderer< P extends IRendererParam = {}, - M extends IAnyObject = {}, E extends AbstractRendererEvent = {loop: number} > extends Emitter { @@ -65,28 +71,17 @@ abstract class AbstractRenderer< /** * 渲染器参数 */ - abstract param: Partial; + public rendererParameterOption: IParameterOption> = {} as any; + public pointsParameterOption: IParameterOption> = {} as any; + public cubeParameterOption: IParameterOption> = {} as any; /** - * 类型断言 + * 渲染器参数 */ - get isRenderer() { - return true; - } + public rendererParameter: IParameterValue> = {} as any; /** - * 断言对象是否是渲染器 - */ - public static isRenderer(render: any): render is AbstractRenderer { - if (render instanceof Object) { - return !!(render as AbstractRenderer).isRenderer; - } else { - return false; - } - }; - - /** - * @function start + * @function clean * 开始一次数据更新 \ * 此函数将清除固定对象的绘制状态 \ * 在每次数据更新前调用 \ @@ -103,7 +98,9 @@ abstract class AbstractRenderer< * @param id 使用的标识符 * @param position 做标集合 */ - abstract points(id: ObjectID, position?: ObjectData, param?: Readonly): this; + abstract points(id: ObjectID, position?: ObjectData, param?: + Readonly>> + ): this; /** * @function cube 绘制立方体 @@ -113,7 +110,9 @@ abstract class AbstractRenderer< * * 注意: 这里的半径指的是立方体重心与立方体任意一面几何中心的距离 */ - abstract cube(id: ObjectID, position?: ObjectData, param?: Readonly): this; + abstract cube(id: ObjectID, position?: ObjectData, radius?: ObjectData, param?: + Readonly>> + ): this; } export default AbstractRenderer; diff --git a/source/Page/Laboratory/Laboratory.tsx b/source/Page/Laboratory/Laboratory.tsx index e3eeb43..b829eba 100644 --- a/source/Page/Laboratory/Laboratory.tsx +++ b/source/Page/Laboratory/Laboratory.tsx @@ -21,7 +21,7 @@ class Laboratory extends Component { throw new Error("Laboratory: 重复引用 canvas 节点"); } - const renderer = new ClassicRenderer({ className: "canvas" }).onLoad(); + const renderer = new ClassicRenderer().onLoad(); this.canvasContRef.current.appendChild(renderer.canvas.dom); let model = new Model().bindRenderer(renderer); @@ -51,10 +51,12 @@ class Laboratory extends Component { }); renderer.points("2"); renderer.cube("4"); - renderer.cube("5", new Array(3).fill(0).map(() => (Math.random() - .5) * 2), { - radius: new Array(3).fill(0).map(() => Math.random() * 1.2), - color: [1, 1, 0] - }) + renderer.cube("5", + new Array(3).fill(0).map(() => (Math.random() - .5) * 2), + new Array(3).fill(0).map(() => Math.random() * 1.2), { + color: [1, 1, 0] + } + ) } (window as any).renderer = renderer; diff --git a/source/Page/SimulatorWeb/SimulatorWeb.tsx b/source/Page/SimulatorWeb/SimulatorWeb.tsx index 9e67110..2b53cfb 100644 --- a/source/Page/SimulatorWeb/SimulatorWeb.tsx +++ b/source/Page/SimulatorWeb/SimulatorWeb.tsx @@ -35,9 +35,9 @@ class SimulatorWeb extends Component { (window as any).setting = (this.setting as any); // TODO: 这里要读取存档 + const classicRender = new ClassicRenderer().onLoad(); this.status = new Status(); - this.status.renderer = new ClassicRenderer({ className: "canvas" }).onLoad(); - this.status.bindRenderer(this.status.renderer); + this.status.bindRenderer(classicRender); this.status.setting = this.setting; // 测试代码 From a31bb73faa49bdf0aa73655284590117f8a715ee Mon Sep 17 00:00:00 2001 From: MrKBear Date: Sat, 9 Apr 2022 16:04:46 +0800 Subject: [PATCH 3/4] Move the size parameter to the renderer control --- source/GLRender/ClassicRenderer.ts | 6 ++--- source/Input/Parameter/Parameter.tsx | 13 ++++++++--- source/Localization/EN-US.ts | 1 + source/Localization/ZH-CN.ts | 1 + source/Model/CtrlObject.ts | 7 +++++- source/Model/Group.ts | 14 ++++++++---- source/Model/Model.ts | 10 +++------ source/Model/Range.ts | 11 +++++++++ source/Panel/GroupDetails/GroupDetails.tsx | 26 +++++++++++++++------- source/Panel/RangeDetails/RangeDetails.tsx | 18 +++++++++++++++ 10 files changed, 81 insertions(+), 26 deletions(-) diff --git a/source/GLRender/ClassicRenderer.ts b/source/GLRender/ClassicRenderer.ts index 935fb1f..801236e 100644 --- a/source/GLRender/ClassicRenderer.ts +++ b/source/GLRender/ClassicRenderer.ts @@ -29,11 +29,11 @@ class ClassicRenderer extends BasicRenderer { public override rendererParameterOption = {}; public override pointsParameterOption = { - color: { type: "color", name: "" }, - size: { type: "number", name: "Common.Attr.Key.Size" } + color: { type: "color", name: "", defaultValue: [0, 0, 0] }, + size: { type: "number", name: "Common.Attr.Key.Size", defaultValue: 60, numberStep: 10, numberMin: 0 } }; public override cubeParameterOption = { - color: { type: "color", name: "" }, + color: { type: "color", name: "", defaultValue: [0, 0, 0] }, }; private basicShader: BasicsShader = undefined as any; diff --git a/source/Input/Parameter/Parameter.tsx b/source/Input/Parameter/Parameter.tsx index 9ae2368..23bd4ab 100644 --- a/source/Input/Parameter/Parameter.tsx +++ b/source/Input/Parameter/Parameter.tsx @@ -10,7 +10,7 @@ import { ColorInput } from "@Input/ColorInput/ColorInput"; import { ComboInput, IDisplayItem } from "@Input/ComboInput/ComboInput"; import { IParameter, IParameterOption, IParameterOptionItem, - IParameterValue, IParamValue, isObjectType, isVectorType + IParameterValue, IParamValue, isObjectType } from "@Model/Parameter"; import "./Parameter.scss"; @@ -20,6 +20,7 @@ interface IParameterProps

{ key: ObjectID; change: (key: K, val: IParamValue) => any; i18n?: (key: string, language: Language) => string; + renderKey?: Array; title?: AllI18nKeys; titleOption?: Record; isFirst?: boolean; @@ -249,12 +250,18 @@ class Parameter

extends Component & IMi } public render(): ReactNode { - const allOptionKeys: Array = Object.getOwnPropertyNames(this.props.option); + let allOptionKeys: Array; + if (this.props.renderKey) { + allOptionKeys = this.props.renderKey; + } else { + allOptionKeys = Object.getOwnPropertyNames(this.props.option); + } + return <> { - allOptionKeys.length <= 0 && this.props.title ? + allOptionKeys.length > 0 && this.props.title ? { // 渲染 for (let i = 0; i < this.objectPool.length; i++) { let object = this.objectPool[i]; + object.renderParameter.color = object.color; if (object.display && object instanceof Group) { - this.renderer.points(object.id, object.exportPositionData(), { - color: object.color, - size: object.size - } as any); + this.renderer.points(object.id, object.exportPositionData(), object.renderParameter); } if (object.display && object instanceof Range) { - this.renderer.cube(object.id, object.position, object.radius, { - color: object.color - } as any); + this.renderer.cube(object.id, object.position, object.radius, object.renderParameter); } } } diff --git a/source/Model/Range.ts b/source/Model/Range.ts index f6a0191..197b30c 100644 --- a/source/Model/Range.ts +++ b/source/Model/Range.ts @@ -1,4 +1,6 @@ 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 constructor(model: Model, id: ObjectID) { + + super(model, id); + + if (model.renderer) { + this.renderParameter = getDefaultValue(model.renderer.cubeParameterOption); + } + } + } export default Range; diff --git a/source/Panel/GroupDetails/GroupDetails.tsx b/source/Panel/GroupDetails/GroupDetails.tsx index 495daf2..299bc9e 100644 --- a/source/Panel/GroupDetails/GroupDetails.tsx +++ b/source/Panel/GroupDetails/GroupDetails.tsx @@ -13,6 +13,7 @@ import { AllI18nKeys } from "@Component/Localization/Localization"; import { ObjectPicker } from "@Input/ObjectPicker/ObjectPicker"; import { ConfirmPopup } from "@Component/ConfirmPopup/ConfirmPopup"; import { BehaviorPicker } from "@Input/BehaviorPicker/BehaviorPicker"; +import { Parameter } from "@Input/Parameter/Parameter"; import "./GroupDetails.scss"; interface IGroupDetailsProps {} @@ -54,14 +55,6 @@ class GroupDetails extends Component - { - this.props.status?.changeGroupAttrib(group.id, "size", (val as any) / 1); - }} - /> - + + key !== "color") + } + change={(key, value) => { + group.renderParameter[key as any] = value; + this.props.status?.changeGroupAttrib( + group.id, "renderParameter", group.renderParameter + ); + }} + /> diff --git a/source/Panel/RangeDetails/RangeDetails.tsx b/source/Panel/RangeDetails/RangeDetails.tsx index e2f0e2a..efe8eeb 100644 --- a/source/Panel/RangeDetails/RangeDetails.tsx +++ b/source/Panel/RangeDetails/RangeDetails.tsx @@ -8,6 +8,7 @@ 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 { Parameter } from "@Input/Parameter/Parameter"; import "./RangeDetails.scss"; @useStatusWithEvent("rangeAttrChange", "focusObjectChange", "rangeLabelChange") @@ -72,6 +73,23 @@ class RangeDetails extends Component { }} /> + key !== "color") + } + change={(key, value) => { + range.renderParameter[key as any] = value; + this.props.status?.changeRangeAttrib( + range.id, "renderParameter", range.renderParameter + ); + }} + /> + Date: Sat, 9 Apr 2022 17:48:26 +0800 Subject: [PATCH 4/4] Add renderer shape parameter --- source/GLRender/BasicGroup.ts | 8 +++++ source/GLRender/ClassicRenderer.ts | 18 ++++++++++-- source/GLRender/GroupShader.ts | 42 +++++++++++++++++++++++++++ source/Localization/EN-US.ts | 7 +++++ source/Localization/ZH-CN.ts | 7 +++++ source/Page/Laboratory/Laboratory.tsx | 36 +++++++++++------------ 6 files changed, 98 insertions(+), 20 deletions(-) diff --git a/source/GLRender/BasicGroup.ts b/source/GLRender/BasicGroup.ts index 4c79403..15c4af2 100644 --- a/source/GLRender/BasicGroup.ts +++ b/source/GLRender/BasicGroup.ts @@ -44,6 +44,11 @@ class BasicGroup extends DisplayObject { */ public color = [1, 1, 1]; + /** + * 形状 + */ + public shape: number = 0; + /** * 绘制立方体 */ @@ -66,6 +71,9 @@ class BasicGroup extends DisplayObject { // 半径传递 this.shader.radius(this.size); + // 形状传递 + this.shader.shape(this.shape); + // 指定颜色 this.shader.color(this.color); diff --git a/source/GLRender/ClassicRenderer.ts b/source/GLRender/ClassicRenderer.ts index 801236e..10e5fbe 100644 --- a/source/GLRender/ClassicRenderer.ts +++ b/source/GLRender/ClassicRenderer.ts @@ -18,7 +18,8 @@ type IClassicRendererParameter = { renderer: {}; points: { color: "color", - size: "number" + size: "number", + shape: "option" }; cube: { color: "color" @@ -30,7 +31,15 @@ class ClassicRenderer extends BasicRenderer { 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 } + 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] }, @@ -244,6 +253,11 @@ class ClassicRenderer extends BasicRenderer { if (param.size) { group.size = param.size; } + + // 半径数据 + if (param.shape) { + group.shape = parseInt(param.shape); + } } return this; diff --git a/source/GLRender/GroupShader.ts b/source/GLRender/GroupShader.ts index e422863..ee4b05f 100644 --- a/source/GLRender/GroupShader.ts +++ b/source/GLRender/GroupShader.ts @@ -10,6 +10,7 @@ interface IGroupShaderAttribute { interface IGroupShaderUniform { uRadius: number, + uShape: number, uMvp: ObjectData, uColor: ObjectData, uFogColor: ObjectData, @@ -50,10 +51,42 @@ class GroupShader extends GLShader{ uniform vec3 uColor; uniform vec3 uFogColor; + uniform int uShape; varying float vFogPower; 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.); } `; @@ -111,4 +144,13 @@ class GroupShader extends GLShader{ this.uniformLocate("uFogDensity"), rgb ) } + + /** + * 形状 + */ + public shape(shape: number) { + this.gl.uniform1i( + this.uniformLocate("uShape"), shape + ) + } } \ No newline at end of file diff --git a/source/Localization/EN-US.ts b/source/Localization/EN-US.ts index aabfb23..4107788 100644 --- a/source/Localization/EN-US.ts +++ b/source/Localization/EN-US.ts @@ -107,6 +107,13 @@ const EN_US = { "Common.Attr.Key.Generation.Error.Invalid.Label": "The specified label has expired", "Common.Attr.Key.Kill.Random": "Random kill", "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.Unspecified": "Unspecified range object", "Panel.Info.Group.Details.Attr.Error.Not.Group": "Object is not a Group", diff --git a/source/Localization/ZH-CN.ts b/source/Localization/ZH-CN.ts index f1116bd..712f78b 100644 --- a/source/Localization/ZH-CN.ts +++ b/source/Localization/ZH-CN.ts @@ -107,6 +107,13 @@ const ZH_CN = { "Common.Attr.Key.Generation.Error.Invalid.Label": "指定的标签已失效", "Common.Attr.Key.Kill.Random": "随机消除", "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.Unspecified": "未指定范围对象", "Panel.Info.Group.Details.Attr.Error.Not.Group": "对象不是一个群", diff --git a/source/Page/Laboratory/Laboratory.tsx b/source/Page/Laboratory/Laboratory.tsx index b829eba..8415ae6 100644 --- a/source/Page/Laboratory/Laboratory.tsx +++ b/source/Page/Laboratory/Laboratory.tsx @@ -39,24 +39,24 @@ class Laboratory extends Component { // 测试渲染器 if (false) { - renderer.points("0"); - 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), { - size: 100, - color: [1, 0, 1] - }); - renderer.points("3", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2), { - size: 80, - color: [0, 1, 1] - }); - renderer.points("2"); - renderer.cube("4"); - renderer.cube("5", - new Array(3).fill(0).map(() => (Math.random() - .5) * 2), - new Array(3).fill(0).map(() => Math.random() * 1.2), { - color: [1, 1, 0] - } - ) + // renderer.points("0"); + // 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), { + // size: 100, + // color: [1, 0, 1] + // }); + // renderer.points("3", new Array(100 * 3).fill(0).map(() => (Math.random() - .5) * 2), { + // size: 80, + // color: [0, 1, 1] + // }); + // renderer.points("2"); + // renderer.cube("4"); + // renderer.cube("5", + // new Array(3).fill(0).map(() => (Math.random() - .5) * 2), + // new Array(3).fill(0).map(() => Math.random() * 1.2), { + // color: [1, 1, 0] + // } + // ) } (window as any).renderer = renderer;