Files
esengine/packages/asset-system/src/integration/EngineIntegration.ts

249 lines
7.6 KiB
TypeScript
Raw Normal View History

/**
* Engine integration for asset system
*
*/
import { AssetManager } from '../core/AssetManager';
import { AssetGUID } from '../types/AssetTypes';
import { ITextureAsset } from '../interfaces/IAssetLoader';
import { globalPathResolver } from '../core/AssetPathResolver';
/**
* Engine bridge interface
*
*/
export interface IEngineBridge {
/**
* Load texture to GPU
* GPU
*/
loadTexture(id: number, url: string): Promise<void>;
/**
* Load multiple textures
*
*/
loadTextures(requests: Array<{ id: number; url: string }>): Promise<void>;
/**
* Unload texture from GPU
* GPU卸载纹理
*/
unloadTexture(id: number): void;
/**
* Get texture info
*
*/
getTextureInfo(id: number): { width: number; height: number } | null;
}
/**
* Asset system engine integration
*
*/
export class EngineIntegration {
private _assetManager: AssetManager;
private _engineBridge?: IEngineBridge;
private _textureIdMap = new Map<AssetGUID, number>();
private _pathToTextureId = new Map<string, number>();
constructor(assetManager: AssetManager, engineBridge?: IEngineBridge) {
this._assetManager = assetManager;
this._engineBridge = engineBridge;
}
/**
* Set engine bridge
*
*/
setEngineBridge(bridge: IEngineBridge): void {
this._engineBridge = bridge;
}
/**
* Load texture for component
*
*
* Tauri asset:// URL
* Unified path resolution entry: relative paths will be converted to Tauri-compatible asset:// URLs
*/
async loadTextureForComponent(texturePath: string): Promise<number> {
// 检查缓存(使用原始路径作为键)
// Check cache (using original path as key)
const existingId = this._pathToTextureId.get(texturePath);
if (existingId) {
return existingId;
}
// 使用 globalPathResolver 转换路径
// Use globalPathResolver to transform the path
const resolvedPath = globalPathResolver.resolve(texturePath);
// 通过资产系统加载(使用解析后的路径)
// Load through asset system (using resolved path)
const result = await this._assetManager.loadAssetByPath<ITextureAsset>(resolvedPath);
const textureAsset = result.asset;
// 如果有引擎桥接上传到GPU使用解析后的路径
// Upload to GPU if bridge exists (using resolved path)
if (this._engineBridge && textureAsset.data) {
await this._engineBridge.loadTexture(textureAsset.textureId, resolvedPath);
}
// 缓存映射(使用原始路径作为键,避免重复解析)
// Cache mapping (using original path as key to avoid re-resolving)
this._pathToTextureId.set(texturePath, textureAsset.textureId);
return textureAsset.textureId;
}
/**
* Load texture by GUID
* GUID加载纹理
*/
async loadTextureByGuid(guid: AssetGUID): Promise<number> {
// 检查是否已有纹理ID / Check if texture ID exists
const existingId = this._textureIdMap.get(guid);
if (existingId) {
return existingId;
}
// 通过资产系统加载 / Load through asset system
const result = await this._assetManager.loadAsset<ITextureAsset>(guid);
const textureAsset = result.asset;
// 如果有引擎桥接上传到GPU / Upload to GPU if bridge exists
if (this._engineBridge && textureAsset.data) {
const metadata = result.metadata;
await this._engineBridge.loadTexture(textureAsset.textureId, metadata.path);
}
// 缓存映射 / Cache mapping
this._textureIdMap.set(guid, textureAsset.textureId);
return textureAsset.textureId;
}
/**
* Batch load textures
*
*/
async loadTexturesBatch(paths: string[]): Promise<Map<string, number>> {
const results = new Map<string, number>();
// 收集需要加载的纹理 / Collect textures to load
const toLoad: string[] = [];
for (const path of paths) {
const existingId = this._pathToTextureId.get(path);
if (existingId) {
results.set(path, existingId);
} else {
toLoad.push(path);
}
}
if (toLoad.length === 0) {
return results;
}
// 并行加载所有纹理 / Load all textures in parallel
const loadPromises = toLoad.map(async (path) => {
try {
const id = await this.loadTextureForComponent(path);
results.set(path, id);
} catch (error) {
console.error(`Failed to load texture: ${path}`, error);
results.set(path, 0); // 使用默认纹理ID / Use default texture ID
}
});
await Promise.all(loadPromises);
return results;
}
/**
* IResourceLoader
* Load resources in batch (generic method for IResourceLoader interface)
*
* @param paths / Array of resource paths
* @param type / Resource type
* @returns ID / Map of paths to runtime IDs
*/
async loadResourcesBatch(paths: string[], type: 'texture' | 'audio' | 'font' | 'data'): Promise<Map<string, number>> {
// 目前只支持纹理 / Currently only supports textures
if (type === 'texture') {
return this.loadTexturesBatch(paths);
}
// 其他资源类型暂未实现 / Other resource types not yet implemented
console.warn(`[EngineIntegration] Resource type '${type}' not yet supported`);
return new Map();
}
/**
* Unload texture
*
*/
unloadTexture(textureId: number): void {
// 从引擎卸载 / Unload from engine
if (this._engineBridge) {
this._engineBridge.unloadTexture(textureId);
}
// 清理映射 / Clean up mappings
for (const [path, id] of this._pathToTextureId.entries()) {
if (id === textureId) {
this._pathToTextureId.delete(path);
break;
}
}
for (const [guid, id] of this._textureIdMap.entries()) {
if (id === textureId) {
this._textureIdMap.delete(guid);
// 也从资产管理器卸载 / Also unload from asset manager
this._assetManager.unloadAsset(guid);
break;
}
}
}
/**
* Get texture ID for path
* ID
*/
getTextureId(path: string): number | null {
return this._pathToTextureId.get(path) || null;
}
/**
* Preload textures for scene
*
*/
async preloadSceneTextures(texturePaths: string[]): Promise<void> {
await this.loadTexturesBatch(texturePaths);
}
/**
* Clear all texture mappings
*
*/
clearTextureMappings(): void {
this._textureIdMap.clear();
this._pathToTextureId.clear();
}
/**
* Get statistics
*
*/
getStatistics(): {
loadedTextures: number;
} {
return {
loadedTextures: this._pathToTextureId.size
};
}
}