diff --git a/source/Component/CommandBar/CommandBar.tsx b/source/Component/CommandBar/CommandBar.tsx index dfcb06c..98e6a14 100644 --- a/source/Component/CommandBar/CommandBar.tsx +++ b/source/Component/CommandBar/CommandBar.tsx @@ -2,7 +2,7 @@ import { BackgroundLevel, Theme } from "@Component/Theme/Theme"; import { DirectionalHint, IconButton } from "@fluentui/react"; import { LocalizationTooltipHost } from "../Localization/LocalizationTooltipHost"; import { useSetting, IMixinSettingProps } from "@Context/Setting"; -import { useStatus, IMixinStatusProps } from "@Context/Status"; +import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; import { AllI18nKeys } from "../Localization/Localization"; import { Component, ReactNode } from "react"; import { MouseMod } from "@GLRender/ClassicRenderer"; @@ -12,26 +12,10 @@ interface ICommandBarProps { width: number; } -@useStatus @useSetting +@useStatusWithEvent("mouseModChange") class CommandBar extends Component { - private handelChange = () => { - this.forceUpdate(); - } - - componentDidMount() { - if (this.props.status) { - this.props.status.on("mouseModChange", this.handelChange) - } - } - - componentWillUnmount() { - if (this.props.status) { - this.props.status.off("mouseModChange", this.handelChange) - } - } - render(): ReactNode { const mouseMod = this.props.status?.mouseMod ?? MouseMod.Drag; @@ -64,7 +48,6 @@ class CommandBar extends Component { this.props.status ? this.props.status.newGroup() : undefined; - this.props.status ? this.props.status.model.draw() : undefined; } })} {this.getRenderButton({ @@ -72,7 +55,6 @@ class CommandBar extends Component { this.props.status ? this.props.status.newRange() : undefined; - this.props.status ? this.props.status.model.draw() : undefined; } })} {this.getRenderButton({ iconName: "StepSharedAdd", i18NKey: "Command.Bar.Add.Behavior.Info" })} diff --git a/source/Component/HeaderBar/HeaderBar.tsx b/source/Component/HeaderBar/HeaderBar.tsx index 9453c85..5b51313 100644 --- a/source/Component/HeaderBar/HeaderBar.tsx +++ b/source/Component/HeaderBar/HeaderBar.tsx @@ -62,8 +62,8 @@ class HeaderBar extends Component< } if (status) { status.archive.on("save", this.changeListener); - status.model.on("loop", this.physicsFpsCalc); - status.renderer.on("loop", this.renderFpsCalc); + status.on("physicsLoop", this.physicsFpsCalc); + status.on("renderLoop", this.renderFpsCalc); } } @@ -74,8 +74,8 @@ class HeaderBar extends Component< } if (status) { status.archive.off("save", this.changeListener); - status.model.off("loop", this.physicsFpsCalc); - status.renderer.off("loop", this.renderFpsCalc); + status.off("physicsLoop", this.physicsFpsCalc); + status.off("renderLoop", this.renderFpsCalc); } } diff --git a/source/Context/Status.tsx b/source/Context/Status.tsx index cea98b7..3289c69 100644 --- a/source/Context/Status.tsx +++ b/source/Context/Status.tsx @@ -1,8 +1,7 @@ -import { createContext, Component, FunctionComponent } from "react"; +import { createContext, Component, FunctionComponent, useState, useEffect, ReactNode } from "react"; import { Emitter } from "@Model/Emitter"; import { Model, ObjectID } from "@Model/Model"; import { Archive } from "@Model/Archive"; -import { CtrlObject } from "@Model/CtrlObject"; import { AbstractRenderer } from "@Model/Renderer"; import { ClassicRenderer, MouseMod } from "@GLRender/ClassicRenderer"; import { Setting } from "./Setting"; @@ -16,10 +15,16 @@ function randomColor() { ] } -class Status extends Emitter<{ - mouseModChange: MouseMod, - focusObjectChange: Set -}> { +interface IStatusEvent { + renderLoop: number; + physicsLoop: number; + mouseModChange: void; + focusObjectChange: void; + objectChange: void; + labelChange: void; +} + +class Status extends Emitter { public setting: Setting = undefined as any; @@ -48,12 +53,34 @@ class Status extends Emitter<{ */ public focusObject: Set = new Set(); + public constructor() { + super(); + + // 循环事件 + this.model.on("loop", (t) => { this.emit("physicsLoop", t) }); + + // 对象变化事件 + this.model.on("objectChange", () => this.emit("objectChange")); + this.model.on("labelChange", () => this.emit("labelChange")); + + // 对象变换时执行渲染,更新渲染器数据 + this.on("objectChange", () => { + this.model.draw(); + }) + } + + public bindRenderer(renderer: AbstractRenderer) { + this.renderer = renderer; + this.renderer.on("loop", (t) => { this.emit("renderLoop", t) }); + this.model.bindRenderer(this.renderer); + } + /** * 更新焦点对象 */ public setFocusObject(focusObject: Set) { this.focusObject = focusObject; - this.emit("focusObjectChange", this.focusObject); + this.emit("focusObjectChange"); } /** @@ -87,7 +114,7 @@ class Status extends Emitter<{ this.renderer.mouseMod = mod; this.renderer.setMouseIcon(); } - this.emit("mouseModChange", mod); + this.emit("mouseModChange"); } } @@ -116,7 +143,55 @@ function useStatus(components: R): R { }) as any; } +function useStatusWithEvent(...events: Array) { + return (components: R): R => { + const C = components as any; + return class extends Component { + + private status: Status | undefined; + private isEventMount: boolean = false; + + private handelChange = () => { + this.forceUpdate(); + } + + private mountEvent() { + if (this.status && !this.isEventMount) { + this.isEventMount = true; + console.log("event mount"); + for (let i = 0; i < events.length; i++) { + this.status.on(events[i], this.handelChange); + } + } + } + + private unmountEvent() { + if (this.status) { + for (let i = 0; i < events.length; i++) { + this.status.off(events[i], this.handelChange); + } + } + } + + public render(): ReactNode { + return + {(status: Status) => { + this.status = status; + this.mountEvent(); + return ; + }} + + } + + public componentWillUnmount() { + this.unmountEvent(); + } + + } as any; + } +} + export { - Status, StatusContext, useStatus, + Status, StatusContext, useStatus, useStatusWithEvent, IMixinStatusProps, StatusProvider, StatusConsumer }; \ No newline at end of file diff --git a/source/Page/SimulatorWeb/SimulatorWeb.tsx b/source/Page/SimulatorWeb/SimulatorWeb.tsx index 2559350..ebc510e 100644 --- a/source/Page/SimulatorWeb/SimulatorWeb.tsx +++ b/source/Page/SimulatorWeb/SimulatorWeb.tsx @@ -35,7 +35,7 @@ class SimulatorWeb extends Component { // TODO: 这里要读取存档 this.status = new Status(); this.status.renderer = new ClassicRenderer({ className: "canvas" }).onLoad(); - this.status.model.bindRenderer(this.status.renderer); + this.status.bindRenderer(this.status.renderer); this.status.setting = this.setting; // 测试代码 diff --git a/source/Panel/ObjectList/ObjectCommand.tsx b/source/Panel/ObjectList/ObjectCommand.tsx index 5af857b..71cbe42 100644 --- a/source/Panel/ObjectList/ObjectCommand.tsx +++ b/source/Panel/ObjectList/ObjectCommand.tsx @@ -41,7 +41,6 @@ class ObjectCommand extends Component { className="command-item" onClick={() => { this.props.status ? this.props.status.newGroup() : undefined; - this.props.status ? this.props.status.model.draw() : undefined; }} > @@ -50,7 +49,6 @@ class ObjectCommand extends Component { className="command-item" onClick={() => { this.props.status ? this.props.status.newRange() : undefined; - this.props.status ? this.props.status.model.draw() : undefined; }} > @@ -65,7 +63,6 @@ class ObjectCommand extends Component { }) this.props.status.model.deleteObject(deleteId); this.props.status.setFocusObject(new Set()); - this.props.status.model.draw(); } }} > diff --git a/source/Panel/ObjectList/ObjectList.tsx b/source/Panel/ObjectList/ObjectList.tsx index cff972f..5d6fc7e 100644 --- a/source/Panel/ObjectList/ObjectList.tsx +++ b/source/Panel/ObjectList/ObjectList.tsx @@ -1,33 +1,15 @@ import { Component, ReactNode } from "react"; import { DetailsList } from "@Component/DetailsList/DetailsList"; -import { useStatus, IMixinStatusProps } from "@Context/Status"; +import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; import { useSetting, IMixinSettingProps } from "@Context/Setting"; import { Localization } from "@Component/Localization/Localization"; import { ObjectID } from "@Model/Renderer"; import "./ObjectList.scss"; @useSetting -@useStatus +@useStatusWithEvent("objectChange", "focusObjectChange") class ObjectList extends Component { - private handelChange = () => { - this.forceUpdate(); - } - - public componentDidMount(){ - if (this.props.status) { - this.props.status.model.on("objectChange", this.handelChange); - this.props.status.on("focusObjectChange", this.handelChange); - } - } - - public componentWillUnmount(){ - if (this.props.status) { - this.props.status.model.off("objectChange", this.handelChange); - this.props.status.off("focusObjectChange", this.handelChange); - } - } - private renderList() { const objList = this.props.status?.model.objectPool ?? [];