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; // 测试代码