Files
esengine/packages/editor-core/src/Services/PreviewSceneService.ts
yhh ad96edfad0 fix: 恢复 @esengine/ecs-framework 包名
上一个提交错误地将 npm 包名也改了,这里恢复正确的包名。
只更新 GitHub 仓库 URL,不改变 npm 包名。
2025-12-08 21:26:35 +08:00

273 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Preview Scene Service
* 预览场景服务
*
* Manages isolated preview scenes for editor tools (tilemap editor, material preview, etc.)
* 管理编辑器工具的隔离预览场景(瓦片地图编辑器、材质预览等)
*/
import { Scene, EntitySystem, Entity } from '@esengine/ecs-framework';
/**
* Configuration for creating a preview scene
* 创建预览场景的配置
*/
export interface PreviewSceneConfig {
/** Unique identifier for the preview scene | 预览场景的唯一标识符 */
id: string;
/** Scene name | 场景名称 */
name?: string;
/** Systems to add to the scene | 要添加到场景的系统 */
systems?: EntitySystem[];
/** Initial clear color | 初始清除颜色 */
clearColor?: { r: number; g: number; b: number; a: number };
}
/**
* Represents an isolated preview scene for editor tools
* 表示编辑器工具的隔离预览场景
*/
export interface IPreviewScene {
/** Scene instance | 场景实例 */
readonly scene: Scene;
/** Unique identifier | 唯一标识符 */
readonly id: string;
/** Scene name | 场景名称 */
readonly name: string;
/** Clear color | 清除颜色 */
clearColor: { r: number; g: number; b: number; a: number };
/**
* Create a temporary entity (auto-cleaned on dispose)
* 创建临时实体dispose 时自动清理)
*/
createEntity(name: string): Entity;
/**
* Remove a temporary entity
* 移除临时实体
*/
removeEntity(entity: Entity): void;
/**
* Get all entities in the scene
* 获取场景中的所有实体
*/
getEntities(): readonly Entity[];
/**
* Clear all temporary entities
* 清除所有临时实体
*/
clearEntities(): void;
/**
* Add a system to the scene
* 向场景添加系统
*/
addSystem(system: EntitySystem): void;
/**
* Remove a system from the scene
* 从场景移除系统
*/
removeSystem(system: EntitySystem): void;
/**
* Update the scene (process systems)
* 更新场景(处理系统)
*/
update(deltaTime: number): void;
/**
* Dispose the preview scene
* 释放预览场景
*/
dispose(): void;
}
/**
* Preview scene implementation
* 预览场景实现
*/
class PreviewScene implements IPreviewScene {
readonly scene: Scene;
readonly id: string;
readonly name: string;
clearColor: { r: number; g: number; b: number; a: number };
private _entities: Set<Entity> = new Set();
private _disposed = false;
constructor(config: PreviewSceneConfig) {
this.id = config.id;
this.name = config.name ?? `PreviewScene_${config.id}`;
this.clearColor = config.clearColor ?? { r: 0.1, g: 0.1, b: 0.12, a: 1.0 };
// Create isolated scene
this.scene = new Scene({ name: this.name });
// Add configured systems
if (config.systems) {
for (const system of config.systems) {
this.scene.addSystem(system);
}
}
}
createEntity(name: string): Entity {
if (this._disposed) {
throw new Error(`PreviewScene ${this.id} is disposed`);
}
const entity = this.scene.createEntity(name);
this._entities.add(entity);
return entity;
}
removeEntity(entity: Entity): void {
if (this._disposed) return;
if (this._entities.has(entity)) {
this._entities.delete(entity);
this.scene.destroyEntities([entity]);
}
}
getEntities(): readonly Entity[] {
return Array.from(this._entities);
}
clearEntities(): void {
if (this._disposed) return;
const entities = Array.from(this._entities);
if (entities.length > 0) {
this.scene.destroyEntities(entities);
}
this._entities.clear();
}
addSystem(system: EntitySystem): void {
if (this._disposed) return;
this.scene.addSystem(system);
}
removeSystem(system: EntitySystem): void {
if (this._disposed) return;
this.scene.removeSystem(system);
}
update(_deltaTime: number): void {
if (this._disposed) return;
this.scene.update();
}
dispose(): void {
if (this._disposed) return;
this._disposed = true;
// Clear all entities
this.clearEntities();
// Scene cleanup is handled by GC
}
}
/**
* Preview Scene Service - manages all preview scenes
* 预览场景服务 - 管理所有预览场景
*/
export class PreviewSceneService {
private static _instance: PreviewSceneService | null = null;
private _scenes: Map<string, PreviewScene> = new Map();
private constructor() {}
/**
* Get singleton instance
* 获取单例实例
*/
static getInstance(): PreviewSceneService {
if (!PreviewSceneService._instance) {
PreviewSceneService._instance = new PreviewSceneService();
}
return PreviewSceneService._instance;
}
/**
* Create a new preview scene
* 创建新的预览场景
*/
createScene(config: PreviewSceneConfig): IPreviewScene {
if (this._scenes.has(config.id)) {
throw new Error(`Preview scene with id "${config.id}" already exists`);
}
const scene = new PreviewScene(config);
this._scenes.set(config.id, scene);
return scene;
}
/**
* Get a preview scene by ID
* 通过 ID 获取预览场景
*/
getScene(id: string): IPreviewScene | null {
return this._scenes.get(id) ?? null;
}
/**
* Check if a preview scene exists
* 检查预览场景是否存在
*/
hasScene(id: string): boolean {
return this._scenes.has(id);
}
/**
* Dispose a preview scene
* 释放预览场景
*/
disposeScene(id: string): void {
const scene = this._scenes.get(id);
if (scene) {
scene.dispose();
this._scenes.delete(id);
}
}
/**
* Get all preview scene IDs
* 获取所有预览场景 ID
*/
getSceneIds(): string[] {
return Array.from(this._scenes.keys());
}
/**
* Dispose all preview scenes
* 释放所有预览场景
*/
disposeAll(): void {
for (const scene of this._scenes.values()) {
scene.dispose();
}
this._scenes.clear();
}
/**
* Dispose the service
* 释放服务
*/
dispose(): void {
this.disposeAll();
}
}
/**
* Service identifier for dependency injection
* 依赖注入的服务标识符
*/
export const IPreviewSceneService = Symbol.for('IPreviewSceneService');