新增场景释放机制和Dispose方法
This commit is contained in:
		@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "material-editor",
 | 
					  "name": "material-editor",
 | 
				
			||||||
  "private": true,
 | 
					  "private": true,
 | 
				
			||||||
  "version": "1.0.2",
 | 
					  "version": "1.0.3",
 | 
				
			||||||
  "type": "module",
 | 
					  "type": "module",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "dev": "vite",
 | 
					    "dev": "vite",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,8 +29,6 @@ async function textureRenderUpdate(textureRecord:TextureTableRecord){
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export class MaterialEditor extends Singleton
 | 
					export class MaterialEditor extends Singleton
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    private _pointerLocked = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Geometrys: Map<string, Geometry | BufferGeometry>;
 | 
					    Geometrys: Map<string, Geometry | BufferGeometry>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CurGeometryName = "球";
 | 
					    CurGeometryName = "球";
 | 
				
			||||||
@@ -38,6 +36,7 @@ export class MaterialEditor extends Singleton
 | 
				
			|||||||
    ShowObject: Object3D;
 | 
					    ShowObject: Object3D;
 | 
				
			||||||
    ShowMesh: Mesh;
 | 
					    ShowMesh: Mesh;
 | 
				
			||||||
    Viewer: Viewer;
 | 
					    Viewer: Viewer;
 | 
				
			||||||
 | 
					    CameraControl?: MaterialEditorCameraControl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private _MeshMaterial: MeshPhysicalMaterial = new MeshPhysicalMaterial({});
 | 
					    private _MeshMaterial: MeshPhysicalMaterial = new MeshPhysicalMaterial({});
 | 
				
			||||||
    //构造
 | 
					    //构造
 | 
				
			||||||
@@ -72,7 +71,7 @@ export class MaterialEditor extends Singleton
 | 
				
			|||||||
            // this.Viewer.PreViewer.Cursor.CursorObject.visible = false;
 | 
					            // this.Viewer.PreViewer.Cursor.CursorObject.visible = false;
 | 
				
			||||||
            // this.Viewer.UsePass = false;
 | 
					            // this.Viewer.UsePass = false;
 | 
				
			||||||
            this.initScene();
 | 
					            this.initScene();
 | 
				
			||||||
            new MaterialEditorCameraControl(this.Viewer, this.ShowObject.position);
 | 
					            this.CameraControl = new MaterialEditorCameraControl(this.Viewer, this.ShowObject.position);
 | 
				
			||||||
            this.Viewer.ZoomAll();
 | 
					            this.Viewer.ZoomAll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // 初始化相机位置到观察物体的正后方
 | 
					            // 初始化相机位置到观察物体的正后方
 | 
				
			||||||
@@ -82,6 +81,9 @@ export class MaterialEditor extends Singleton
 | 
				
			|||||||
            this.Viewer.UpdateRender();
 | 
					            this.Viewer.UpdateRender();
 | 
				
			||||||
            this.Viewer.Fov = 90;
 | 
					            this.Viewer.Fov = 90;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            console.warn("Viewer has already been initialized");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    SetViewer(canvas: HTMLElement)
 | 
					    SetViewer(canvas: HTMLElement)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -186,8 +188,24 @@ export class MaterialEditor extends Singleton
 | 
				
			|||||||
        this.Update();
 | 
					        this.Update();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dispose()
 | 
					    Dispose()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        this.Geometrys.clear();
 | 
				
			||||||
 | 
					        this.Geometrys = undefined;
 | 
				
			||||||
 | 
					        this.Canvas = undefined;
 | 
				
			||||||
 | 
					        // object在Viewer中进行释放
 | 
				
			||||||
 | 
					        this.ShowObject = undefined;
 | 
				
			||||||
 | 
					        this.ShowMesh = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.CameraControl?.dispose();
 | 
				
			||||||
 | 
					        this.Viewer?.Dispose();
 | 
				
			||||||
 | 
					        this.CameraControl = undefined;
 | 
				
			||||||
 | 
					        this.Viewer = undefined;
 | 
				
			||||||
 | 
					        this.exrPromise = undefined;
 | 
				
			||||||
 | 
					        this.exrTexture?.dispose();
 | 
				
			||||||
 | 
					        this.exrTexture = undefined;
 | 
				
			||||||
 | 
					        this.metaTexture?.dispose();
 | 
				
			||||||
 | 
					        this.metaTexture = undefined;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async Update()
 | 
					    async Update()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,12 +24,24 @@ export class MaterialEditorCameraControl {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    initMouseControl() {
 | 
					    initMouseControl() {
 | 
				
			||||||
        let el = this.Viewer.Renderer.domElement;
 | 
					        let el = this.Viewer.Renderer.domElement;
 | 
				
			||||||
        el.addEventListener("pointerdown", (e) => { this.pointId = e.pointerId; }, false);
 | 
					        el.addEventListener("pointerdown", this.onPointerDown, false);
 | 
				
			||||||
        el.addEventListener("mousedown", this.onMouseDown, false);
 | 
					        el.addEventListener("mousedown", this.onMouseDown, false);
 | 
				
			||||||
        el.addEventListener("mousemove", this.onMouseMove, false);
 | 
					        el.addEventListener("mousemove", this.onMouseMove, false);
 | 
				
			||||||
        el.addEventListener("mouseup", this.onMouseUp, false);
 | 
					        el.addEventListener("mouseup", this.onMouseUp, false);
 | 
				
			||||||
        el.addEventListener('wheel', this.onMouseWheel, false);
 | 
					        el.addEventListener('wheel', this.onMouseWheel, false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dispose() {
 | 
				
			||||||
 | 
					        const el = this.Viewer.Renderer.domElement;
 | 
				
			||||||
 | 
					        el.removeEventListener("pointerdown", this.onPointerDown);
 | 
				
			||||||
 | 
					        el.removeEventListener("mousedown", this.onMouseDown);
 | 
				
			||||||
 | 
					        el.removeEventListener("mousemove", this.onMouseMove);
 | 
				
			||||||
 | 
					        el.removeEventListener("mouseup", this.onMouseUp);
 | 
				
			||||||
 | 
					        el.removeEventListener('wheel', this.onMouseWheel, false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onPointerDown = (event: PointerEvent) => { this.pointId = event.pointerId; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onMouseDown = (event: MouseEvent) => {
 | 
					    onMouseDown = (event: MouseEvent) => {
 | 
				
			||||||
        this.requestPointerLock();
 | 
					        this.requestPointerLock();
 | 
				
			||||||
        this._MouseIsDown = true;
 | 
					        this._MouseIsDown = true;
 | 
				
			||||||
@@ -49,14 +61,11 @@ export class MaterialEditorCameraControl {
 | 
				
			|||||||
            else this.Viewer.Rotate(this._movement);
 | 
					            else this.Viewer.Rotate(this._movement);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    onMouseWheel = (event: WheelEvent) =>
 | 
					    onMouseWheel = (event: WheelEvent) => {
 | 
				
			||||||
    {
 | 
					        if (event.deltaY < 0) {
 | 
				
			||||||
        if (event.deltaY < 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            this.Viewer.Zoom(0.6);
 | 
					            this.Viewer.Zoom(0.6);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (event.deltaY > 0)
 | 
					        else if (event.deltaY > 0) {
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            this.Viewer.Zoom(1.4);
 | 
					            this.Viewer.Zoom(1.4);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,13 +2,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
let instanceMap = new Map();
 | 
					let instanceMap = new Map();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface PrototypeType<T> extends Function
 | 
					export interface PrototypeType<T> extends Function {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    prototype: T;
 | 
					    prototype: T;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ConstructorFunctionType<T = any> extends PrototypeType<T>
 | 
					export interface ConstructorFunctionType<T = any> extends PrototypeType<T> {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    new(...args: any[]): T;
 | 
					    new(...args: any[]): T;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,13 +21,11 @@ export type ConstructorType<T = unknown, Static extends Record<string, any> = Pr
 | 
				
			|||||||
 *     //获得单例
 | 
					 *     //获得单例
 | 
				
			||||||
 *     let a = A.GetInstance();
 | 
					 *     let a = A.GetInstance();
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export class Singleton
 | 
					export class Singleton {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    protected constructor() { }
 | 
					    protected constructor() { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //ref:https://github.com/Microsoft/TypeScript/issues/5863
 | 
					    //ref:https://github.com/Microsoft/TypeScript/issues/5863
 | 
				
			||||||
    static GetInstance<T extends Singleton>(this: ConstructorType<T, typeof Singleton>): T
 | 
					    static GetInstance<T extends Singleton>(this: ConstructorType<T, typeof Singleton>): T {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (instanceMap.has(this))
 | 
					        if (instanceMap.has(this))
 | 
				
			||||||
            return instanceMap.get(this);
 | 
					            return instanceMap.get(this);
 | 
				
			||||||
        //@ts-ignore
 | 
					        //@ts-ignore
 | 
				
			||||||
@@ -37,4 +33,23 @@ export class Singleton
 | 
				
			|||||||
        instanceMap.set(this, __instance__);
 | 
					        instanceMap.set(this, __instance__);
 | 
				
			||||||
        return __instance__;
 | 
					        return __instance__;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * 释放指定类型的单例实例。
 | 
				
			||||||
 | 
					    * @returns {boolean} 如果实例存在并被释放则返回 true,否则返回 false。
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    static ReleaseInstance<T extends Singleton>(this: ConstructorType<T, typeof Singleton>): boolean {
 | 
				
			||||||
 | 
					        if (instanceMap.has(this)) {
 | 
				
			||||||
 | 
					            const instance = instanceMap.get(this);
 | 
				
			||||||
 | 
					            // 如果实例有清理方法,可以在这里调用
 | 
				
			||||||
 | 
					            if (typeof (instance as any).dispose === 'function') {
 | 
				
			||||||
 | 
					                (instance as any).dispose();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            instanceMap.delete(this);
 | 
				
			||||||
 | 
					            console.log(`Singleton instance of ${this.name} has been released.`);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        console.log(`No singleton instance of ${this.name} found to release.`);
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,20 +1,25 @@
 | 
				
			|||||||
import { Raycaster, Scene, Vector3, WebGLRenderer, type Vector, type WebGLRendererParameters } from "three";
 | 
					import { Raycaster, Scene, Vector3, WebGLRenderer, type WebGLRendererParameters, Object3D, Mesh, Line, Points, Material, Texture } from "three";
 | 
				
			||||||
import { cZeroVec, GetBox, GetBoxArr } from "./GeUtils";
 | 
					import { cZeroVec, GetBox, GetBoxArr } from "./GeUtils";
 | 
				
			||||||
import { PlaneExt } from "./PlaneExt";
 | 
					import { PlaneExt } from "./PlaneExt";
 | 
				
			||||||
import { CameraType, CameraUpdate } from "webcad_ue4_api";
 | 
					import { CameraType, CameraUpdate } from "webcad_ue4_api";
 | 
				
			||||||
 | 
					import { disposeNode } from "../helpers/helper.three";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class Viewer {
 | 
					export class Viewer {
 | 
				
			||||||
    m_LookTarget: any;
 | 
					    m_LookTarget: any;
 | 
				
			||||||
    m_Camera: CameraUpdate = new CameraUpdate();
 | 
					    m_Camera: CameraUpdate = new CameraUpdate();
 | 
				
			||||||
    protected NeedUpdate: boolean = true;
 | 
					    protected NeedUpdate: boolean = true;
 | 
				
			||||||
    Renderer: WebGLRenderer;//渲染器  //暂时只用这个类型
 | 
					    Renderer!: WebGLRenderer; // 在 initRender 中初始化,使用 ! 断言
 | 
				
			||||||
    m_DomEl: HTMLElement;    //画布容器
 | 
					    m_DomEl: HTMLElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _Height: number = 0;
 | 
					    _Height: number = 0;
 | 
				
			||||||
    _Width: number = 0;
 | 
					    _Width: number = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _Scene: Scene = new Scene();
 | 
					    _Scene: Scene = new Scene();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private m_IsDisposed: boolean = false; // 添加一个标志来停止渲染循环和防止重复释放
 | 
				
			||||||
 | 
					    private m_AnimationFrameId: number | null = null; // 用于取消动画帧
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    get Scene() {
 | 
					    get Scene() {
 | 
				
			||||||
        return this._Scene;
 | 
					        return this._Scene;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -28,90 +33,95 @@ export class Viewer {
 | 
				
			|||||||
        this.NeedUpdate = true;
 | 
					        this.NeedUpdate = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    UpdateRender()
 | 
					    UpdateRender() {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        this.NeedUpdate = true;
 | 
					        this.NeedUpdate = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param {HTMLElement} canvasContainer 可以传入一个div或者一个画布
 | 
					 | 
				
			||||||
     * @memberof Viewer
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    constructor(canvasContainer: HTMLElement) {
 | 
					    constructor(canvasContainer: HTMLElement) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.m_DomEl = canvasContainer;
 | 
					        this.m_DomEl = canvasContainer;
 | 
				
			||||||
        this.initRender(canvasContainer);
 | 
					        this.initRender(canvasContainer);
 | 
				
			||||||
        this.OnSize();
 | 
					        this.SetSize(); // 初始尺寸设置
 | 
				
			||||||
        this.StartRender();
 | 
					        this.StartRender(); // 开始渲染循环
 | 
				
			||||||
        window.addEventListener("resize", () => {
 | 
					
 | 
				
			||||||
            this.OnSize();
 | 
					        // 注意: OnSize 是一个箭头函数属性,它的 this 上下文是固定的
 | 
				
			||||||
        });
 | 
					        // 因此可以直接用于添加和移除事件监听器
 | 
				
			||||||
 | 
					        window.addEventListener("resize", this.OnResize);
 | 
				
			||||||
        this.InitCamera();
 | 
					        this.InitCamera();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //初始化render
 | 
					 | 
				
			||||||
    initRender(canvasContainer: HTMLElement) {
 | 
					    initRender(canvasContainer: HTMLElement) {
 | 
				
			||||||
        let params: WebGLRendererParameters = {
 | 
					        let params: WebGLRendererParameters = {
 | 
				
			||||||
            antialias: true,//antialias:true/false是否开启反锯齿
 | 
					            antialias: true,
 | 
				
			||||||
            precision: "highp",//precision:highp/mediump/lowp着色精度选择
 | 
					            precision: "highp",
 | 
				
			||||||
            alpha: true//alpha:true/false是否可以设置背景色透明
 | 
					            alpha: true
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        this.Renderer = new WebGLRenderer(params);
 | 
					        this.Renderer = new WebGLRenderer(params);
 | 
				
			||||||
        //加到画布
 | 
					 | 
				
			||||||
        canvasContainer.appendChild(this.Renderer.domElement);
 | 
					        canvasContainer.appendChild(this.Renderer.domElement);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.Renderer.autoClear = true;
 | 
					        this.Renderer.autoClear = true;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        //如果设置,那么它希望所有的纹理和颜色都是预乘的伽玛。默认值为false。
 | 
					 | 
				
			||||||
        // this.Renderer.gammaInput = true;
 | 
					 | 
				
			||||||
        // this.Renderer.gammaOutput = true;
 | 
					 | 
				
			||||||
        // this.Renderer.shadowMap.enabled = true;
 | 
					 | 
				
			||||||
        // this.Renderer.toneMapping = ReinhardToneMapping;
 | 
					 | 
				
			||||||
        //设置设备像素比。 这通常用于HiDPI设备,以防止模糊输出画布。
 | 
					 | 
				
			||||||
        this.Renderer.setPixelRatio(window.devicePixelRatio);
 | 
					        this.Renderer.setPixelRatio(window.devicePixelRatio);
 | 
				
			||||||
        this.Renderer.physicallyCorrectLights = true;
 | 
					        this.Renderer.physicallyCorrectLights = true; //  r150 后默认 false, 根据需要设置
 | 
				
			||||||
        //this.Renderer.toneMappingExposure = Math.pow(1, 5.0); // to allow for very bright scenes.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //设置它的背景色为黑色
 | 
					 | 
				
			||||||
        this.Renderer.setClearColor(0xffffff, 1);
 | 
					        this.Renderer.setClearColor(0xffffff, 1);
 | 
				
			||||||
 | 
					        // this.OnSize(); // 在构造函数中调用,这里可以不用重复
 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.OnSize();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    InitCamera() {
 | 
					    InitCamera() {
 | 
				
			||||||
        this.m_Camera.CameraType = CameraType.PerspectiveCamera;
 | 
					        this.m_Camera.CameraType = CameraType.PerspectiveCamera;
 | 
				
			||||||
        this.m_Camera.Near = 0.001;
 | 
					        this.m_Camera.Near = 0.001;
 | 
				
			||||||
 | 
					        if (this.m_Camera.Camera) { // 确保 CameraUpdate 内部的 Camera 已初始化
 | 
				
			||||||
            this.m_Camera.Camera.far = 1000000000;
 | 
					            this.m_Camera.Camera.far = 1000000000;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    OnSize = (width?: number, height?: number) => {
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    OnResize = (evt: UIEvent) => this.SetSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SetSize = (width?: number, height?: number) => {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed || !this.m_DomEl) return; // 如果已销毁或容器不存在,则不执行
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this._Width = width ? width : this.m_DomEl.clientWidth;
 | 
					        this._Width = width ? width : this.m_DomEl.clientWidth;
 | 
				
			||||||
        this._Height = height ? height : this.m_DomEl.clientHeight;
 | 
					        this._Height = height ? height : this.m_DomEl.clientHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //校验.成为2的倍数 避免外轮廓错误.
 | 
					        if (this._Width % 2 === 1) this._Width -= 1;
 | 
				
			||||||
        if (this._Width % 2 == 1)
 | 
					        if (this._Height % 2 === 1) this._Height -= 1;
 | 
				
			||||||
            this._Width -= 1;
 | 
					 | 
				
			||||||
        if (this._Height % 2 == 1)
 | 
					 | 
				
			||||||
            this._Height -= 1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.Renderer) {
 | 
				
			||||||
            this.Renderer.setSize(this._Width, this._Height);
 | 
					            this.Renderer.setSize(this._Width, this._Height);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (this.m_Camera) {
 | 
				
			||||||
            this.m_Camera.SetSize(this._Width, this._Height);
 | 
					            this.m_Camera.SetSize(this._Width, this._Height);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.NeedUpdate = true; // 尺寸变化后需要重新渲染
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    StartRender = () => {
 | 
					    StartRender = () => {
 | 
				
			||||||
        requestAnimationFrame(this.StartRender);
 | 
					        if (this.m_IsDisposed) {
 | 
				
			||||||
        if (this._Scene != null && this.NeedUpdate) {
 | 
					            if (this.m_AnimationFrameId !== null) {
 | 
				
			||||||
 | 
					                cancelAnimationFrame(this.m_AnimationFrameId);
 | 
				
			||||||
 | 
					                this.m_AnimationFrameId = null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.m_AnimationFrameId = requestAnimationFrame(this.StartRender);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this._Scene && this.NeedUpdate) { // 确保 _Scene 存在
 | 
				
			||||||
            this.Render();
 | 
					            this.Render();
 | 
				
			||||||
 | 
					            if (this.m_Camera) { // 确保 m_Camera 存在
 | 
				
			||||||
                this.m_Camera.Update();
 | 
					                this.m_Camera.Update();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            this.NeedUpdate = false;
 | 
					            this.NeedUpdate = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Render() {
 | 
					    Render() {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed || !this.Renderer || !this._Scene || !this.m_Camera || !this.m_Camera.Camera) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        this.Renderer.render(this._Scene, this.m_Camera.Camera);
 | 
					        this.Renderer.render(this._Scene, this.m_Camera.Camera);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ScreenToWorld, WorldToScreen, UpdateLockTarget, Rotate, Pan, Zoom, etc. methods remain the same...
 | 
				
			||||||
 | 
					    // ... (省略了您提供的其他方法,它们与 dispose 无直接关系,保持不变) ...
 | 
				
			||||||
    ScreenToWorld(pt: Vector3, planVec?: Vector3) {
 | 
					    ScreenToWorld(pt: Vector3, planVec?: Vector3) {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed || !this._Scene || !this.m_Camera || !this.m_Camera.Camera) return;
 | 
				
			||||||
        //变换和求交点
 | 
					        //变换和求交点
 | 
				
			||||||
        let plan = new PlaneExt(planVec || new Vector3(0, 0, 1));
 | 
					        let plan = new PlaneExt(planVec || new Vector3(0, 0, 1));
 | 
				
			||||||
        let raycaster = new Raycaster();
 | 
					        let raycaster = new Raycaster();
 | 
				
			||||||
@@ -123,9 +133,10 @@ export class Viewer {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            , this.m_Camera.Camera
 | 
					            , this.m_Camera.Camera
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        plan.intersectRay(raycaster.ray, pt, true);
 | 
					        plan.intersectRay(raycaster.ray, pt, true); // 假设 intersectRay 修改 pt
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    WorldToScreen(pt: Vector3) {
 | 
					    WorldToScreen(pt: Vector3) {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed || !this.m_Camera || !this.m_Camera.Camera) return;
 | 
				
			||||||
        let widthHalf = this._Width * 0.5;
 | 
					        let widthHalf = this._Width * 0.5;
 | 
				
			||||||
        let heightHalf = this._Height * 0.5;
 | 
					        let heightHalf = this._Height * 0.5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -135,51 +146,133 @@ export class Viewer {
 | 
				
			|||||||
        pt.y = - (pt.y * heightHalf) + heightHalf;
 | 
					        pt.y = - (pt.y * heightHalf) + heightHalf;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 更新视角观测目标(物体中心)
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @memberof Viewer
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    UpdateLockTarget() {
 | 
					    UpdateLockTarget() {
 | 
				
			||||||
        let renderList = this.Renderer.renderLists.get(this._Scene, this.m_Camera.Camera);
 | 
					        if (this.m_IsDisposed || !this.Renderer || !this._Scene || !this.m_Camera || !this.m_Camera.Camera) return;
 | 
				
			||||||
        let box = GetBoxArr(renderList.opaque.map(o => o.object));
 | 
					        // @ts-ignore access to private renderLists
 | 
				
			||||||
 | 
					        const renderList = this.Renderer.renderLists.get(this._Scene, this.m_Camera.Camera);
 | 
				
			||||||
 | 
					        // @ts-ignore
 | 
				
			||||||
 | 
					        const box = GetBoxArr(renderList.opaque.map(o => o.object)); // 确保 GetBoxArr 定义正确
 | 
				
			||||||
        if (box)
 | 
					        if (box)
 | 
				
			||||||
 | 
					            // @ts-ignore
 | 
				
			||||||
            this.m_LookTarget = box.getCenter(new Vector3());
 | 
					            this.m_LookTarget = box.getCenter(new Vector3());
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            this.m_LookTarget = cZeroVec;
 | 
					            // @ts-ignore
 | 
				
			||||||
 | 
					            this.m_LookTarget = cZeroVec; // 确保 cZeroVec 定义正确
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Rotate(mouseMove: Vector3) {
 | 
					    Rotate(mouseMove: Vector3) {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed || !this.m_Camera) return;
 | 
				
			||||||
        this.m_Camera.Rotate(mouseMove, this.m_LookTarget);
 | 
					        this.m_Camera.Rotate(mouseMove, this.m_LookTarget);
 | 
				
			||||||
        this.NeedUpdate = true;
 | 
					        this.NeedUpdate = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    RotateAround(movement: Vector3, center: Vector3) {
 | 
					    RotateAround(movement: Vector3, center: Vector3) {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed || !this.m_Camera) return;
 | 
				
			||||||
        this.m_Camera.Rotate(movement, center);
 | 
					        this.m_Camera.Rotate(movement, center);
 | 
				
			||||||
        this.NeedUpdate = true;
 | 
					        this.NeedUpdate = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Pan(mouseMove: Vector3) {
 | 
					    Pan(mouseMove: Vector3) {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed || !this.m_Camera) return;
 | 
				
			||||||
        this.m_Camera.Pan(mouseMove);
 | 
					        this.m_Camera.Pan(mouseMove);
 | 
				
			||||||
        this.NeedUpdate = true;
 | 
					        this.NeedUpdate = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    Zoom(scale: number, center?: Vector3) {
 | 
					    Zoom(scale: number, center?: Vector3) {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed || !this.m_Camera) return;
 | 
				
			||||||
        this.m_Camera.Zoom(scale, center);
 | 
					        this.m_Camera.Zoom(scale, center);
 | 
				
			||||||
        this.NeedUpdate = true;
 | 
					        this.NeedUpdate = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ZoomAll()
 | 
					    ZoomAll() {
 | 
				
			||||||
    {
 | 
					        if (this.m_IsDisposed || !this.m_Camera || !this._Scene) return;
 | 
				
			||||||
        this.m_Camera.ZoomExtentsBox3(GetBox(this._Scene, true));
 | 
					        // @ts-ignore
 | 
				
			||||||
 | 
					        this.m_Camera.ZoomExtentsBox3(GetBox(this._Scene, true)); // 确保 GetBox 定义正确
 | 
				
			||||||
        this.NeedUpdate = true;
 | 
					        this.NeedUpdate = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ViewToTop() {
 | 
					    ViewToTop() {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed || !this.m_Camera) return;
 | 
				
			||||||
        this.m_Camera.LookAt(new Vector3(0, 0, -1));
 | 
					        this.m_Camera.LookAt(new Vector3(0, 0, -1));
 | 
				
			||||||
        this.NeedUpdate = true;
 | 
					        this.NeedUpdate = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ViewToFront() {
 | 
					    ViewToFront() {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed || !this.m_Camera) return;
 | 
				
			||||||
        this.m_Camera.LookAt(new Vector3(0, 1, 0));
 | 
					        this.m_Camera.LookAt(new Vector3(0, 1, 0));
 | 
				
			||||||
        this.NeedUpdate = true;
 | 
					        this.NeedUpdate = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    ViewToSwiso() {
 | 
					    ViewToSwiso() {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed || !this.m_Camera) return;
 | 
				
			||||||
        this.m_Camera.LookAt(new Vector3(1, 1, -1));
 | 
					        this.m_Camera.LookAt(new Vector3(1, 1, -1));
 | 
				
			||||||
        this.NeedUpdate = true;
 | 
					        this.NeedUpdate = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 销毁 Viewer 实例并释放所有相关资源。
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public Dispose(): void {
 | 
				
			||||||
 | 
					        if (this.m_IsDisposed) {
 | 
				
			||||||
 | 
					            return; // 防止重复释放
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        console.log("Disposing Viewer...");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 1. 停止渲染循环
 | 
				
			||||||
 | 
					        this.m_IsDisposed = true; // 设置标志,渲染循环将在下一帧停止
 | 
				
			||||||
 | 
					        if (this.m_AnimationFrameId !== null) {
 | 
				
			||||||
 | 
					            cancelAnimationFrame(this.m_AnimationFrameId);
 | 
				
			||||||
 | 
					            this.m_AnimationFrameId = null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 2. 移除事件监听器
 | 
				
			||||||
 | 
					        window.removeEventListener("resize", this.OnResize);
 | 
				
			||||||
 | 
					        // 如果 m_DomEl 上有其他直接添加的事件监听器,也应在此移除
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 3. 销毁场景内容 (几何体、材质、纹理)
 | 
				
			||||||
 | 
					        if (this._Scene) {
 | 
				
			||||||
 | 
					            // 遍历场景中的所有对象并释放它们的资源
 | 
				
			||||||
 | 
					            this._Scene.traverse((object) => {
 | 
				
			||||||
 | 
					                disposeNode(object);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 从场景中移除所有子对象
 | 
				
			||||||
 | 
					            // scene.clear() 也可以,但在此之前我们已经遍历并释放了资源
 | 
				
			||||||
 | 
					            while (this._Scene.children.length > 0) {
 | 
				
			||||||
 | 
					                const child = this._Scene.children[0];
 | 
				
			||||||
 | 
					                // 确保子对象的资源已通过上面的 traverse 处理
 | 
				
			||||||
 | 
					                this._Scene.remove(child);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // console.log("Scene cleared and resources disposed.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 4. 销毁渲染器
 | 
				
			||||||
 | 
					        if (this.Renderer) {
 | 
				
			||||||
 | 
					            // @ts-ignore access to private renderLists
 | 
				
			||||||
 | 
					            if (this.Renderer.renderLists) { // 检查 renderLists 是否存在
 | 
				
			||||||
 | 
					                // @ts-ignore
 | 
				
			||||||
 | 
					                this.Renderer.renderLists.dispose();
 | 
				
			||||||
 | 
					                // console.log("Renderer renderLists disposed.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            this.Renderer.dispose();
 | 
				
			||||||
 | 
					            // console.log("Renderer disposed.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 从 DOM 中移除渲染器的 canvas 元素
 | 
				
			||||||
 | 
					            if (this.Renderer.domElement && this.Renderer.domElement.parentElement) {
 | 
				
			||||||
 | 
					                this.Renderer.domElement.parentElement.removeChild(this.Renderer.domElement);
 | 
				
			||||||
 | 
					                // console.log("Renderer DOM element removed.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 5. 清除引用 (帮助垃圾回收)
 | 
				
			||||||
 | 
					        // @ts-ignore
 | 
				
			||||||
 | 
					        this._Scene = null;
 | 
				
			||||||
 | 
					        // @ts-ignore
 | 
				
			||||||
 | 
					        this.Renderer = null;
 | 
				
			||||||
 | 
					        // @ts-ignore
 | 
				
			||||||
 | 
					        this.m_DomEl = null;
 | 
				
			||||||
 | 
					        // @ts-ignore
 | 
				
			||||||
 | 
					        this.m_Camera = null;
 | 
				
			||||||
 | 
					        // @ts-ignore
 | 
				
			||||||
 | 
					        this.m_LookTarget = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        console.log("Viewer disposed successfully.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -5,7 +5,7 @@
 | 
				
			|||||||
    </CfFlex>
 | 
					    </CfFlex>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { onMounted, ref, useTemplateRef } from 'vue';
 | 
					import { onBeforeUnmount, onMounted, onUnmounted, ref, useTemplateRef } from 'vue';
 | 
				
			||||||
import MaterialAdjuster from './MaterialAdjuster.vue';
 | 
					import MaterialAdjuster from './MaterialAdjuster.vue';
 | 
				
			||||||
import { useScene } from '../stores/sceneStore';
 | 
					import { useScene } from '../stores/sceneStore';
 | 
				
			||||||
import CfFlex from './CfFlex.vue';
 | 
					import CfFlex from './CfFlex.vue';
 | 
				
			||||||
@@ -21,15 +21,26 @@ const textureSrc = ref(config.textureSrc);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// 禁用右键菜单
 | 
					// 禁用右键菜单
 | 
				
			||||||
document.addEventListener('contextmenu', (e) => e.preventDefault()); 
 | 
					document.addEventListener('contextmenu', (e) => e.preventDefault()); 
 | 
				
			||||||
 | 
					 | 
				
			||||||
onMounted(() => {
 | 
					onMounted(() => {
 | 
				
			||||||
    scene.Initial(container.value);
 | 
					    scene.Initial(container.value);
 | 
				
			||||||
    eventbus.Subscribe('submit', () => adjusterRef.value.Upload());
 | 
					    eventbus.Subscribe('submit', HandleUpload);
 | 
				
			||||||
    eventbus.Subscribe('update-texture', () => {
 | 
					    eventbus.Subscribe('update-texture', HandleChangeTexture);
 | 
				
			||||||
        textureSrc.value = config.textureSrc
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					onBeforeUnmount(() => {
 | 
				
			||||||
 | 
					    eventbus.Unsubscribe('submit', HandleUpload);
 | 
				
			||||||
 | 
					    eventbus.Unsubscribe('update-texture', HandleChangeTexture);
 | 
				
			||||||
 | 
					    scene.Dispose();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function HandleUpload() {
 | 
				
			||||||
 | 
					    adjusterRef.value.Upload();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function HandleChangeTexture() {
 | 
				
			||||||
 | 
					    textureSrc.value = config.textureSrc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style scoped lang="scss">
 | 
					<style scoped lang="scss">
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										39
									
								
								src/helpers/helper.three.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/helpers/helper.three.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					import type { Material, Texture, Object3D, Mesh, Line, Points } from "three";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 深度释放材质和纹理 */
 | 
				
			||||||
 | 
					export function disposeMaterial(material: Material | Material[]): void {
 | 
				
			||||||
 | 
					    if (Array.isArray(material)) {
 | 
				
			||||||
 | 
					        material.forEach(mat => disposeSingleMaterial(mat));
 | 
				
			||||||
 | 
					    } else if (material) { // 确保 material 不是 undefined 或 null
 | 
				
			||||||
 | 
					        disposeSingleMaterial(material);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function disposeSingleMaterial(material: Material): void {
 | 
				
			||||||
 | 
					    material.dispose();
 | 
				
			||||||
 | 
					    // 遍历材质的属性,查找并释放纹理
 | 
				
			||||||
 | 
					    for (const key in material) {
 | 
				
			||||||
 | 
					        const value = (material as any)[key] as unknown; // 使用 unknown 来进行更安全的类型检查
 | 
				
			||||||
 | 
					        if (value && typeof value === 'object' && 'isTexture' in value && (value as Texture).isTexture) {
 | 
				
			||||||
 | 
					            (value as Texture).dispose();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 释放节点的几何体、材质和纹理 */
 | 
				
			||||||
 | 
					export function disposeNode(node: Object3D): void {
 | 
				
			||||||
 | 
					    // 类型守卫,检查节点是否为 Mesh, Line, 或 Points
 | 
				
			||||||
 | 
					    if ((node as Mesh).isMesh || (node as Line).isLine || (node as Points).isPoints) {
 | 
				
			||||||
 | 
					        const obj = node as Mesh | Line | Points;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (obj.geometry) {
 | 
				
			||||||
 | 
					            obj.geometry.dispose();
 | 
				
			||||||
 | 
					            // console.log("Disposed geometry:", obj.geometry.uuid);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (obj.material) {
 | 
				
			||||||
 | 
					            disposeMaterial(obj.material);
 | 
				
			||||||
 | 
					            // console.log("Disposed material(s) for node:", obj.uuid);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -12,7 +12,11 @@ export const useEvent = defineStore('event', () => {
 | 
				
			|||||||
        events[name]?.forEach(e => e(...args));
 | 
					        events[name]?.forEach(e => e(...args));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return { Subscribe, Publish };
 | 
					    function Unsubscribe(name: EventNames, callback: Function) {
 | 
				
			||||||
 | 
					        events[name] = events[name]?.filter(e => e !== callback) || [];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return { Subscribe, Publish, Unsubscribe };
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type EventNames = 'submit' | 'update-texture'
 | 
					export type EventNames = 'submit' | 'update-texture'
 | 
				
			||||||
@@ -8,7 +8,7 @@ import { materialRenderer } from "../common/MaterialRenderer";
 | 
				
			|||||||
import { MaterialOut } from "../common/MaterialSerializer";
 | 
					import { MaterialOut } from "../common/MaterialSerializer";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useScene = defineStore('scene', () => {
 | 
					export const useScene = defineStore('scene', () => {
 | 
				
			||||||
    let _editor: MaterialEditor;
 | 
					    let _editor: MaterialEditor | undefined;
 | 
				
			||||||
    const _currGeometry = ref<string>('球');
 | 
					    const _currGeometry = ref<string>('球');
 | 
				
			||||||
    const _currTexture = ref<Texture>();
 | 
					    const _currTexture = ref<Texture>();
 | 
				
			||||||
    const CurrGeometry = computed({
 | 
					    const CurrGeometry = computed({
 | 
				
			||||||
@@ -37,11 +37,22 @@ export const useScene = defineStore('scene', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        const view = _editor.Viewer;
 | 
					        const view = _editor.Viewer;
 | 
				
			||||||
        window.onresize = () => {
 | 
					        window.onresize = () => {
 | 
				
			||||||
            view.OnSize(canvas.clientWidth, canvas.clientHeight);
 | 
					            view.SetSize(canvas.clientWidth, canvas.clientHeight);
 | 
				
			||||||
            view.UpdateRender();
 | 
					            view.UpdateRender();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function Dispose() {
 | 
				
			||||||
 | 
					        console.log("Disposing...");
 | 
				
			||||||
 | 
					        Material.value.GoodBye();
 | 
				
			||||||
 | 
					        _editor?.Dispose();
 | 
				
			||||||
 | 
					        _editor = undefined;
 | 
				
			||||||
 | 
					        window.onresize = undefined;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // 释放Singleton
 | 
				
			||||||
 | 
					        MaterialEditor.ReleaseInstance();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function ChangeGeometry(geoName: string) {
 | 
					    function ChangeGeometry(geoName: string) {
 | 
				
			||||||
        _currGeometry.value = geoName;
 | 
					        _currGeometry.value = geoName;
 | 
				
			||||||
        let geo = _editor.Geometrys.get(_currGeometry.value);
 | 
					        let geo = _editor.Geometrys.get(_currGeometry.value);
 | 
				
			||||||
@@ -121,7 +132,8 @@ export const useScene = defineStore('scene', () => {
 | 
				
			|||||||
        ChangeTextureAsync,
 | 
					        ChangeTextureAsync,
 | 
				
			||||||
        UpdateTexture,
 | 
					        UpdateTexture,
 | 
				
			||||||
        SerializeMaterialAsync,
 | 
					        SerializeMaterialAsync,
 | 
				
			||||||
        GenerateMaterialLogoAsync
 | 
					        GenerateMaterialLogoAsync,
 | 
				
			||||||
 | 
					        Dispose
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user