Files
esengine/packages/editor-core/src/Services/FileActionRegistry.ts
YHH b42a7b4e43 Feature/editor optimization (#251)
* refactor: 编辑器/运行时架构拆分与构建系统升级

* feat(core): 层级系统重构与UI变换矩阵修复

* refactor: 移除 ecs-components 聚合包并修复跨包组件查找问题

* fix(physics): 修复跨包组件类引用问题

* feat: 统一运行时架构与浏览器运行支持

* feat(asset): 实现浏览器运行时资产加载系统

* fix: 修复文档、CodeQL安全问题和CI类型检查错误

* fix: 修复文档、CodeQL安全问题和CI类型检查错误

* fix: 修复文档、CodeQL安全问题、CI类型检查和测试错误

* test: 补齐核心模块测试用例,修复CI构建配置

* fix: 修复测试用例中的类型错误和断言问题

* fix: 修复 turbo build:npm 任务的依赖顺序问题

* fix: 修复 CI 构建错误并优化构建性能
2025-12-01 22:28:51 +08:00

210 lines
6.1 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.
import { IService } from '@esengine/ecs-framework';
import type { FileActionHandler, FileCreationTemplate } from '../Plugin/IPluginLoader';
// Re-export for backwards compatibility
export type { FileCreationTemplate } from '../Plugin/IPluginLoader';
/**
* 资产创建消息映射
* Asset creation message mapping
*
* 定义扩展名到创建消息的映射,用于 PropertyInspector 中的资产字段创建按钮
*/
export interface AssetCreationMapping {
/** 文件扩展名(包含点号,如 '.tilemap'| File extension (with dot) */
extension: string;
/** 创建资产时发送的消息名 | Message name to publish when creating asset */
createMessage: string;
/** 是否支持创建(可选,默认 true| Whether creation is supported */
canCreate?: boolean;
}
/**
* FileActionRegistry 服务标识符
* FileActionRegistry service identifier
*/
export const IFileActionRegistry = Symbol.for('IFileActionRegistry');
/**
* 文件操作注册表服务
*
* 管理插件注册的文件操作处理器和文件创建模板
*/
export class FileActionRegistry implements IService {
private actionHandlers: Map<string, FileActionHandler[]> = new Map();
private creationTemplates: FileCreationTemplate[] = [];
private assetCreationMappings: Map<string, AssetCreationMapping> = new Map();
/**
* 注册文件操作处理器
*/
registerActionHandler(handler: FileActionHandler): void {
for (const ext of handler.extensions) {
const handlers = this.actionHandlers.get(ext) || [];
handlers.push(handler);
this.actionHandlers.set(ext, handlers);
}
}
/**
* 注销文件操作处理器
*/
unregisterActionHandler(handler: FileActionHandler): void {
for (const ext of handler.extensions) {
const handlers = this.actionHandlers.get(ext);
if (handlers) {
const index = handlers.indexOf(handler);
if (index !== -1) {
handlers.splice(index, 1);
}
if (handlers.length === 0) {
this.actionHandlers.delete(ext);
}
}
}
}
/**
* 注册文件创建模板
*/
registerCreationTemplate(template: FileCreationTemplate): void {
this.creationTemplates.push(template);
}
/**
* 注销文件创建模板
*/
unregisterCreationTemplate(template: FileCreationTemplate): void {
const index = this.creationTemplates.indexOf(template);
if (index !== -1) {
this.creationTemplates.splice(index, 1);
}
}
/**
* 获取文件扩展名的处理器
*/
getHandlersForExtension(extension: string): FileActionHandler[] {
return this.actionHandlers.get(extension) || [];
}
/**
* 获取文件的处理器
*/
getHandlersForFile(filePath: string): FileActionHandler[] {
const extension = this.getFileExtension(filePath);
return extension ? this.getHandlersForExtension(extension) : [];
}
/**
* 获取所有文件创建模板
*/
getCreationTemplates(): FileCreationTemplate[] {
return this.creationTemplates;
}
/**
* 处理文件双击
*/
async handleDoubleClick(filePath: string): Promise<boolean> {
const handlers = this.getHandlersForFile(filePath);
for (const handler of handlers) {
if (handler.onDoubleClick) {
await handler.onDoubleClick(filePath);
return true;
}
}
return false;
}
/**
* 处理文件打开
*/
async handleOpen(filePath: string): Promise<boolean> {
const handlers = this.getHandlersForFile(filePath);
for (const handler of handlers) {
if (handler.onOpen) {
await handler.onOpen(filePath);
return true;
}
}
return false;
}
/**
* 注册资产创建消息映射
* Register asset creation message mapping
*/
registerAssetCreationMapping(mapping: AssetCreationMapping): void {
const normalizedExt = mapping.extension.startsWith('.')
? mapping.extension.toLowerCase()
: `.${mapping.extension.toLowerCase()}`;
this.assetCreationMappings.set(normalizedExt, {
...mapping,
extension: normalizedExt
});
}
/**
* 注销资产创建消息映射
* Unregister asset creation message mapping
*/
unregisterAssetCreationMapping(extension: string): void {
const normalizedExt = extension.startsWith('.')
? extension.toLowerCase()
: `.${extension.toLowerCase()}`;
this.assetCreationMappings.delete(normalizedExt);
}
/**
* 获取扩展名对应的资产创建消息映射
* Get asset creation mapping for extension
*/
getAssetCreationMapping(extension: string): AssetCreationMapping | undefined {
const normalizedExt = extension.startsWith('.')
? extension.toLowerCase()
: `.${extension.toLowerCase()}`;
return this.assetCreationMappings.get(normalizedExt);
}
/**
* 检查扩展名是否支持创建资产
* Check if extension supports asset creation
*/
canCreateAsset(extension: string): boolean {
const mapping = this.getAssetCreationMapping(extension);
return mapping?.canCreate !== false;
}
/**
* 获取所有资产创建映射
* Get all asset creation mappings
*/
getAllAssetCreationMappings(): AssetCreationMapping[] {
return Array.from(this.assetCreationMappings.values());
}
/**
* 清空所有注册
*/
clear(): void {
this.actionHandlers.clear();
this.creationTemplates = [];
this.assetCreationMappings.clear();
}
/**
* 释放资源
*/
dispose(): void {
this.clear();
}
private getFileExtension(filePath: string): string | null {
const lastDot = filePath.lastIndexOf('.');
if (lastDot === -1) return null;
return filePath.substring(lastDot + 1).toLowerCase();
}
}