mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-06-25 17:10:43 +00:00
wip
This commit is contained in:
parent
de27cc92dc
commit
646b0ca041
8 changed files with 141 additions and 208 deletions
105
packages/frontend/src/world/EngineBase.ts
Normal file
105
packages/frontend/src/world/EngineBase.ts
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import * as BABYLON from '@babylonjs/core';
|
||||
import EventEmitter from 'eventemitter3';
|
||||
|
||||
export type EngineBaseEvents = {
|
||||
'loadingProgress': (ctx: { progress: number }) => void;
|
||||
};
|
||||
|
||||
export abstract class EngineBase<EVs extends EngineBaseEvents> extends EventEmitter<{
|
||||
'ev': (ctx: { type: keyof EVs; ctx: Parameters<EVs[keyof EVs]>[0] }) => void;
|
||||
}> {
|
||||
protected engine: BABYLON.WebGPUEngine;
|
||||
protected scene: BABYLON.Scene;
|
||||
protected fps: number | null = null;
|
||||
protected disposed = false;
|
||||
|
||||
public inputs: EventEmitter<{
|
||||
'click': (event: { x: number; y: number; }) => void;
|
||||
'keydown': (event: { code: string; shiftKey: boolean; }) => void;
|
||||
'keyup': (event: { code: string; shiftKey: boolean; }) => void;
|
||||
'wheel': (event: { deltaY: number; }) => void;
|
||||
'zoom': (event: { delta: number; }) => void;
|
||||
'pointer': (event: { x: number; y: number; }) => void;
|
||||
}> = new EventEmitter();
|
||||
|
||||
constructor(options: {
|
||||
engine: BABYLON.WebGPUEngine;
|
||||
fps: number | null;
|
||||
}) {
|
||||
super();
|
||||
|
||||
this.fps = options.fps;
|
||||
|
||||
this.engine = options.engine;
|
||||
this.scene = new BABYLON.Scene(this.engine);
|
||||
}
|
||||
|
||||
private currentRafId: number | null = null;
|
||||
|
||||
private startRenderLoop() {
|
||||
if (this.fps == null) {
|
||||
this.engine.runRenderLoop(() => {
|
||||
this.scene.render();
|
||||
});
|
||||
} else {
|
||||
let then = 0;
|
||||
const interval = 1000 / this.fps;
|
||||
|
||||
const renderLoop = (timeStamp: number) => {
|
||||
if (this.disposed) return;
|
||||
|
||||
// workerで実行される可能性がある
|
||||
this.currentRafId = requestAnimationFrame(renderLoop);
|
||||
|
||||
const delta = timeStamp - then;
|
||||
if (delta <= interval) return;
|
||||
then = timeStamp - (delta % interval);
|
||||
|
||||
this.engine.beginFrame();
|
||||
this.scene.render();
|
||||
this.engine.endFrame();
|
||||
};
|
||||
|
||||
// workerで実行される可能性がある
|
||||
this.currentRafId = requestAnimationFrame(renderLoop);
|
||||
}
|
||||
}
|
||||
|
||||
public pauseRender() { // TODO: srと同じく参照カウント方式にした方が便利そう
|
||||
this.engine.stopRenderLoop();
|
||||
if (this.currentRafId != null) {
|
||||
// workerで実行される可能性がある
|
||||
cancelAnimationFrame(this.currentRafId);
|
||||
this.currentRafId = null;
|
||||
}
|
||||
}
|
||||
|
||||
public resumeRender() {
|
||||
this.startRenderLoop();
|
||||
}
|
||||
|
||||
public abstract init(): Promise<void>;
|
||||
|
||||
protected ev<K extends keyof EVs>(type: K, ctx: Parameters<EVs[K]>[0]) {
|
||||
this.emit('ev', { type, ctx });
|
||||
}
|
||||
|
||||
public abstract resize(): void;
|
||||
|
||||
public destroy() {
|
||||
this.engine.stopRenderLoop();
|
||||
if (this.currentRafId != null) {
|
||||
// workerで実行される可能性がある
|
||||
cancelAnimationFrame(this.currentRafId);
|
||||
this.currentRafId = null;
|
||||
}
|
||||
this.engine.dispose();
|
||||
this.scene.dispose();
|
||||
this.disposed = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,8 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { EngineControllerBase } from './engineControllerBase.js';
|
||||
import { EngineControllerBase } from './EngineControllerBase.js';
|
||||
import type { WorldEngine } from './engine.js';
|
||||
|
||||
export type WorldEngineControllerOptions = {
|
||||
workerMode?: boolean;
|
||||
|
|
@ -14,7 +15,7 @@ export type WorldEngineControllerOptions = {
|
|||
};
|
||||
|
||||
// 抽象化レイヤー
|
||||
export class WorldEngineController extends EngineControllerBase {
|
||||
export class WorldEngineController extends EngineControllerBase<WorldEngine> {
|
||||
constructor(options: WorldEngineControllerOptions) {
|
||||
super({
|
||||
...options,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import tinycolor from 'tinycolor2';
|
|||
import Hls from 'hls.js';
|
||||
import { RecyvlingTextGrid, Timer, WORLD_SCALE, camelToKebab, cm, createPlaneUvMapper, normalizeUvToSquare, randomRange } from './utility.js';
|
||||
import { TIME_MAP } from './utility.js';
|
||||
import { EngineBase } from './EngineBase.js';
|
||||
import { genId } from '@/utility/id.js';
|
||||
import { deepClone } from '@/utility/clone.js';
|
||||
|
||||
|
|
@ -18,7 +19,7 @@ const SNAPSHOT_RENDERING = false; // 実験的
|
|||
const USE_GLOW = true; // ドローコールが増えて重い
|
||||
const IN_WEB_WORKER = typeof window === 'undefined';
|
||||
|
||||
export type WorldEngineEvents = {
|
||||
export class WorldEngine extends EngineBase<{
|
||||
'playSfxUrl': (ctx: {
|
||||
url: string;
|
||||
options: {
|
||||
|
|
@ -27,13 +28,7 @@ export type WorldEngineEvents = {
|
|||
};
|
||||
}) => void;
|
||||
'loadingProgress': (ctx: { progress: number }) => void;
|
||||
};
|
||||
|
||||
// TODO: RoomEngineBaseとしてabstract classを抽出
|
||||
export class WorldEngine extends EventEmitter<WorldEngineEvents> {
|
||||
private canvas: HTMLCanvasElement;
|
||||
private engine: BABYLON.WebGPUEngine;
|
||||
public scene: BABYLON.Scene;
|
||||
}> {
|
||||
private shadowGeneratorForSunLight: BABYLON.ShadowGenerator;
|
||||
public camera: BABYLON.UniversalCamera;
|
||||
private time: 0 | 1 | 2 = 0; // 0: 昼, 1: 夕, 2: 夜
|
||||
|
|
@ -45,30 +40,19 @@ export class WorldEngine extends EventEmitter<WorldEngineEvents> {
|
|||
private translucentTextMaterial: BABYLON.StandardMaterial;
|
||||
private reflectionProbe: BABYLON.ReflectionProbe;
|
||||
public timer: Timer = new Timer();
|
||||
|
||||
public isSitting = false;
|
||||
private fps: number | null = null;
|
||||
private disposed = false;
|
||||
|
||||
public inputs: EventEmitter<{
|
||||
'click': (event: { offsetX: number; offsetY: number; }) => void;
|
||||
'keydown': (event: { code: string; shiftKey: boolean; }) => void;
|
||||
'keyup': (event: { code: string; shiftKey: boolean; }) => void;
|
||||
'wheel': (event: { deltaY: number; }) => void;
|
||||
}> = new EventEmitter();
|
||||
|
||||
constructor(options: {
|
||||
canvas: HTMLCanvasElement;
|
||||
engine: BABYLON.WebGPUEngine;
|
||||
}) {
|
||||
super();
|
||||
|
||||
this.canvas = options.canvas;
|
||||
super({
|
||||
engine: options.engine,
|
||||
fps: null,
|
||||
});
|
||||
|
||||
registerBuiltInLoaders();
|
||||
|
||||
this.engine = options.engine;
|
||||
this.scene = new BABYLON.Scene(this.engine);
|
||||
this.scene.autoClear = false;
|
||||
//this.scene.autoClearDepthAndStencil = false;
|
||||
this.scene.skipPointerMovePicking = true;
|
||||
|
|
@ -206,31 +190,6 @@ export class WorldEngine extends EventEmitter<WorldEngineEvents> {
|
|||
this.sr.enableSnapshotRendering();
|
||||
}
|
||||
|
||||
if (this.fps == null) {
|
||||
this.engine.runRenderLoop(() => {
|
||||
this.scene.render();
|
||||
});
|
||||
} else {
|
||||
let then = 0;
|
||||
const interval = 1000 / this.fps;
|
||||
|
||||
const renderLoop = (timeStamp: number) => {
|
||||
if (this.disposed) return;
|
||||
|
||||
window.requestAnimationFrame(renderLoop);
|
||||
|
||||
const delta = timeStamp - then;
|
||||
if (delta <= interval) return;
|
||||
then = timeStamp - (delta % interval);
|
||||
|
||||
this.engine.beginFrame();
|
||||
this.scene.render();
|
||||
this.engine.endFrame();
|
||||
};
|
||||
|
||||
window.requestAnimationFrame(renderLoop);
|
||||
}
|
||||
|
||||
this.inputs.on('keydown', (ev) => {
|
||||
});
|
||||
|
||||
|
|
@ -621,9 +580,8 @@ export class WorldEngine extends EventEmitter<WorldEngineEvents> {
|
|||
}
|
||||
|
||||
public destroy() {
|
||||
super.destroy();
|
||||
this.timer.dispose();
|
||||
this.engine.dispose();
|
||||
this.disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
import { reactive, ref, shallowRef, triggerRef, watch } from 'vue';
|
||||
import * as BABYLON from '@babylonjs/core';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import type { EngineBase, EngineBaseEvents } from './EngineBase.js';
|
||||
import * as os from '@/os.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
|
|
@ -17,9 +18,12 @@ export type EngineControllerBaseOptions = {
|
|||
antialias: boolean;
|
||||
};
|
||||
|
||||
type EngineEventsOf<T> = T extends EngineBase<infer X> ? X : EngineBaseEvents;
|
||||
|
||||
// UIとエンジンの間に挟まり抽象化を行うレイヤー。
|
||||
// UIからは、エンジンが直で動いててもワーカーで動いてても同じように操作できるように見える
|
||||
export abstract class EngineControllerBase<T extends RoomEngineBase> {
|
||||
// infer EVs from T
|
||||
export abstract class EngineControllerBase<T extends EngineBase<EngineBaseEvents>> {
|
||||
private worker: Worker | null = null;
|
||||
private engine: T | null = null;
|
||||
private canvas: HTMLCanvasElement | null = null;
|
||||
|
|
@ -45,7 +49,7 @@ export abstract class EngineControllerBase<T extends RoomEngineBase> {
|
|||
this.canvas.width = canvas.clientWidth > 4 ? canvas.clientWidth : 4;
|
||||
this.canvas.height = canvas.clientHeight > 4 ? canvas.clientHeight : 4;
|
||||
|
||||
const engineEvents = new EventEmitter<RoomEngineBaseEvents>();
|
||||
const engineEvents = new EventEmitter<EngineEventsOf<T>>();
|
||||
|
||||
engineEvents.on('loadingProgress', ({ progress }) => {
|
||||
this.initializeProgress.value = progress;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { ref, shallowRef } from 'vue';
|
||||
import { cm } from '../utility.js';
|
||||
import { EngineControllerBase } from '../engineControllerBase.js';
|
||||
import { EngineControllerBase } from '../EngineControllerBase.js';
|
||||
import type { ShallowRef } from 'vue';
|
||||
import type { RoomEngine, RoomState } from './engine.js';
|
||||
import type { RoomStateObject } from './object.js';
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import * as BABYLON from '@babylonjs/core';
|
|||
import { registerBuiltInLoaders } from '@babylonjs/loaders/dynamic';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import { TIME_MAP, scaleMorph, camelToKebab, cm, WORLD_SCALE, getMeshesBoundingBox, Timer, getYRotationDirection, FreeCameraManualInput, remap } from '../utility.js';
|
||||
import { EngineBase } from '../EngineBase.js';
|
||||
import { getObjectDef } from './object-defs.js';
|
||||
import { findMaterial, GRAPHICS_QUALITY, ModelManager, SYSTEM_HEYA_MESH_NAMES, SYSTEM_MESH_NAMES } from './utility.js';
|
||||
import { JapaneseEnvManager, MuseumEnvManager, SimpleEnvManager } from './env.js';
|
||||
|
|
@ -111,7 +112,7 @@ function enableObjectCollision(meshes: BABYLON.Mesh[]) {
|
|||
}
|
||||
}
|
||||
|
||||
export type RoomEngineEvents = {
|
||||
export class RoomEngine extends EngineBase<{
|
||||
'changeSelectedState': (ctx: {
|
||||
selected: {
|
||||
objectId: string;
|
||||
|
|
@ -130,13 +131,8 @@ export type RoomEngineEvents = {
|
|||
};
|
||||
}) => void;
|
||||
'loadingProgress': (ctx: { progress: number }) => void;
|
||||
};
|
||||
|
||||
// TODO: RoomEngineBaseとしてabstract classを抽出
|
||||
export class RoomEngine extends EventEmitter {
|
||||
}> {
|
||||
private useGlow: boolean;
|
||||
private engine: BABYLON.WebGPUEngine;
|
||||
public scene: BABYLON.Scene;
|
||||
public camera: BABYLON.UniversalCamera;
|
||||
private fixedCamera: BABYLON.FreeCamera;
|
||||
public objectEntities: Map<string, {
|
||||
|
|
@ -223,17 +219,6 @@ export class RoomEngine extends EventEmitter {
|
|||
|
||||
public isSitting = false;
|
||||
private inited = false;
|
||||
private fps: number | null = null;
|
||||
private disposed = false;
|
||||
|
||||
public inputs: EventEmitter<{
|
||||
'click': (event: { x: number; y: number; }) => void;
|
||||
'keydown': (event: { code: string; shiftKey: boolean; }) => void;
|
||||
'keyup': (event: { code: string; shiftKey: boolean; }) => void;
|
||||
'wheel': (event: { deltaY: number; }) => void;
|
||||
'zoom': (event: { delta: number; }) => void;
|
||||
'pointer': (event: { x: number; y: number; }) => void;
|
||||
}> = new EventEmitter();
|
||||
|
||||
constructor(roomState: RoomState, roomAttachments: RoomAttachments, options: {
|
||||
engine: BABYLON.WebGPUEngine;
|
||||
|
|
@ -242,7 +227,10 @@ export class RoomEngine extends EventEmitter {
|
|||
antialias: boolean;
|
||||
useVirtualJoystick?: boolean;
|
||||
}) {
|
||||
super();
|
||||
super({
|
||||
engine: options.engine,
|
||||
fps: options.fps,
|
||||
});
|
||||
|
||||
this.roomState = {
|
||||
...deepClone(roomState),
|
||||
|
|
@ -253,14 +241,11 @@ export class RoomEngine extends EventEmitter {
|
|||
};
|
||||
this.roomAttachments = roomAttachments;
|
||||
this.graphicsQuality = options.graphicsQuality;
|
||||
this.fps = options.fps;
|
||||
this.useGlow = this.graphicsQuality >= GRAPHICS_QUALITY.MEDIUM;
|
||||
this.time = TIME_MAP[new Date().getHours() as keyof typeof TIME_MAP];
|
||||
|
||||
registerBuiltInLoaders();
|
||||
|
||||
this.engine = options.engine;
|
||||
this.scene = new BABYLON.Scene(this.engine);
|
||||
// なんかレンダリングがおかしくなるときがあるのでコメントアウト
|
||||
// オブジェクトを選択し、後ろを向いて別のオブジェクトを選択した後、最初のオブジェクトに振り返ると消えているなど
|
||||
//this.scene.performancePriority = BABYLON.ScenePerformancePriority.Intermediate;
|
||||
|
|
@ -399,10 +384,6 @@ export class RoomEngine extends EventEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
private ev<K extends keyof RoomEngineEvents>(type: K, ctx: Parameters<RoomEngineEvents[K]>[0]) {
|
||||
this.emit('ev', { type, ctx });
|
||||
}
|
||||
|
||||
public async init() {
|
||||
await this.loadEnv();
|
||||
|
||||
|
|
@ -546,50 +527,6 @@ export class RoomEngine extends EventEmitter {
|
|||
this.inited = true;
|
||||
}
|
||||
|
||||
private currentRafId: number | null = null;
|
||||
|
||||
private startRenderLoop() {
|
||||
if (this.fps == null) {
|
||||
this.engine.runRenderLoop(() => {
|
||||
this.scene.render();
|
||||
});
|
||||
} else {
|
||||
let then = 0;
|
||||
const interval = 1000 / this.fps;
|
||||
|
||||
const renderLoop = (timeStamp: number) => {
|
||||
if (this.disposed) return;
|
||||
|
||||
// workerで実行される可能性がある
|
||||
this.currentRafId = requestAnimationFrame(renderLoop);
|
||||
|
||||
const delta = timeStamp - then;
|
||||
if (delta <= interval) return;
|
||||
then = timeStamp - (delta % interval);
|
||||
|
||||
this.engine.beginFrame();
|
||||
this.scene.render();
|
||||
this.engine.endFrame();
|
||||
};
|
||||
|
||||
// workerで実行される可能性がある
|
||||
this.currentRafId = requestAnimationFrame(renderLoop);
|
||||
}
|
||||
}
|
||||
|
||||
public pauseRender() { // TODO: srと同じく参照カウント方式にした方が便利そう
|
||||
this.engine.stopRenderLoop();
|
||||
if (this.currentRafId != null) {
|
||||
// workerで実行される可能性がある
|
||||
cancelAnimationFrame(this.currentRafId);
|
||||
this.currentRafId = null;
|
||||
}
|
||||
}
|
||||
|
||||
public resumeRender() {
|
||||
this.startRenderLoop();
|
||||
}
|
||||
|
||||
// TODO: 初回以外で呼び出すとエンジンがクラッシュするのを修正
|
||||
public async changeEnvType(type: RoomState['env']['type'], forInit = false) {
|
||||
this.roomState.env.type = type;
|
||||
|
|
@ -1778,16 +1715,8 @@ export class RoomEngine extends EventEmitter {
|
|||
}
|
||||
|
||||
public destroy() {
|
||||
this.engine.stopRenderLoop();
|
||||
if (this.currentRafId != null) {
|
||||
// workerで実行される可能性がある
|
||||
cancelAnimationFrame(this.currentRafId);
|
||||
this.currentRafId = null;
|
||||
}
|
||||
super.destroy();
|
||||
this.timer.dispose();
|
||||
this.envManager.dispose();
|
||||
this.engine.dispose();
|
||||
this.scene.dispose();
|
||||
this.disposed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
import * as BABYLON from '@babylonjs/core';
|
||||
import { registerBuiltInLoaders } from '@babylonjs/loaders/dynamic.js';
|
||||
import { GridMaterial } from '@babylonjs/materials';
|
||||
import EventEmitter from 'eventemitter3';
|
||||
import { camelToKebab, WORLD_SCALE, cm, getMeshesBoundingBox, Timer, sleep, ArcRotateCameraManualInput } from '../utility.js';
|
||||
import { EngineBase } from '../EngineBase.js';
|
||||
import { getObjectDef } from './object-defs.js';
|
||||
import { SYSTEM_MESH_NAMES, ModelManager, GRAPHICS_QUALITY } from './utility.js';
|
||||
import { convertRawOptions } from './object.js';
|
||||
|
|
@ -16,10 +16,9 @@ import type { RoomAttachments } from './utility.js';
|
|||
import { genId } from '@/utility/id.js';
|
||||
import { deepClone } from '@/utility/clone.js';
|
||||
|
||||
// TODO: RoomEngineBaseとしてabstract classを抽出
|
||||
export class RoomObjectPreviewEngine extends EventEmitter {
|
||||
private engine: BABYLON.WebGPUEngine;
|
||||
private scene: BABYLON.Scene;
|
||||
export class RoomObjectPreviewEngine extends EngineBase<{
|
||||
'loadingProgress': (ctx: { progress: number }) => void;
|
||||
}> {
|
||||
private sr: BABYLON.SnapshotRenderingHelper;
|
||||
private shadowGenerator: BABYLON.ShadowGenerator;
|
||||
private camera: BABYLON.ArcRotateCamera;
|
||||
|
|
@ -34,32 +33,21 @@ export class RoomObjectPreviewEngine extends EventEmitter {
|
|||
private timerForEachObject: Timer | null = null;
|
||||
private pipeline: BABYLON.DefaultRenderingPipeline;
|
||||
private graphicsQuality: number;
|
||||
private fps: number | null = null;
|
||||
private disposed = false;
|
||||
|
||||
public inputs: EventEmitter<{
|
||||
'click': (event: { x: number; y: number; }) => void;
|
||||
'keydown': (event: { code: string; shiftKey: boolean; }) => void;
|
||||
'keyup': (event: { code: string; shiftKey: boolean; }) => void;
|
||||
'wheel': (event: { deltaY: number; }) => void;
|
||||
'zoom': (event: { delta: number; }) => void;
|
||||
'pointer': (event: { x: number; y: number; }) => void;
|
||||
}> = new EventEmitter();
|
||||
|
||||
constructor(options: {
|
||||
engine: BABYLON.WebGPUEngine;
|
||||
graphicsQuality: number;
|
||||
fps: number | null;
|
||||
}) {
|
||||
super();
|
||||
super({
|
||||
engine: options.engine,
|
||||
fps: options.fps,
|
||||
});
|
||||
|
||||
registerBuiltInLoaders();
|
||||
|
||||
this.graphicsQuality = options.graphicsQuality;
|
||||
this.fps = options.fps;
|
||||
|
||||
this.engine = options.engine;
|
||||
this.scene = new BABYLON.Scene(this.engine);
|
||||
this.scene.autoClear = false;
|
||||
this.scene.skipPointerMovePicking = true;
|
||||
this.scene.skipFrustumClipping = true; // snapshot renderingでは全てのメッシュがアクティブになっている必要があるため
|
||||
|
|
@ -158,50 +146,6 @@ export class RoomObjectPreviewEngine extends EventEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
private currentRafId: number | null = null;
|
||||
|
||||
private startRenderLoop() {
|
||||
if (this.fps == null) {
|
||||
this.engine.runRenderLoop(() => {
|
||||
this.scene.render();
|
||||
});
|
||||
} else {
|
||||
let then = 0;
|
||||
const interval = 1000 / this.fps;
|
||||
|
||||
const renderLoop = (timeStamp: number) => {
|
||||
if (this.disposed) return;
|
||||
|
||||
// workerで実行される可能性がある
|
||||
this.currentRafId = requestAnimationFrame(renderLoop);
|
||||
|
||||
const delta = timeStamp - then;
|
||||
if (delta <= interval) return;
|
||||
then = timeStamp - (delta % interval);
|
||||
|
||||
this.engine.beginFrame();
|
||||
this.scene.render();
|
||||
this.engine.endFrame();
|
||||
};
|
||||
|
||||
// workerで実行される可能性がある
|
||||
this.currentRafId = requestAnimationFrame(renderLoop);
|
||||
}
|
||||
}
|
||||
|
||||
public pauseRender() { // TODO: srと同じく参照カウント方式にした方が便利そう
|
||||
this.engine.stopRenderLoop();
|
||||
if (this.currentRafId != null) {
|
||||
// workerで実行される可能性がある
|
||||
cancelAnimationFrame(this.currentRafId);
|
||||
this.currentRafId = null;
|
||||
}
|
||||
}
|
||||
|
||||
public resumeRender() {
|
||||
this.startRenderLoop();
|
||||
}
|
||||
|
||||
public async init() {
|
||||
await this.scene.whenReadyAsync();
|
||||
this.sr.enableSnapshotRendering();
|
||||
|
|
@ -428,17 +372,9 @@ export class RoomObjectPreviewEngine extends EventEmitter {
|
|||
}
|
||||
|
||||
public destroy() {
|
||||
this.engine.stopRenderLoop();
|
||||
if (this.currentRafId != null) {
|
||||
// workerで実行される可能性がある
|
||||
cancelAnimationFrame(this.currentRafId);
|
||||
this.currentRafId = null;
|
||||
}
|
||||
super.destroy();
|
||||
if (this.timerForEachObject != null) {
|
||||
this.timerForEachObject.dispose();
|
||||
}
|
||||
this.engine.dispose();
|
||||
this.scene.dispose();
|
||||
this.disposed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { EngineControllerBase } from '../engineControllerBase.js';
|
||||
import { EngineControllerBase } from '../EngineControllerBase.js';
|
||||
import type { RoomObjectPreviewEngine } from './previewEngine.js';
|
||||
import type { RoomAttachments } from './utility.js';
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue