feat(asset): 统一资产引用使用 GUID 替代路径 (#287)
* feat(world-streaming): 添加世界流式加载系统 实现基于区块的世界流式加载系统,支持开放世界游戏: 运行时包 (@esengine/world-streaming): - ChunkComponent: 区块实体组件,包含坐标、边界、状态 - StreamingAnchorComponent: 流式锚点组件(玩家/摄像机) - ChunkLoaderComponent: 流式加载配置组件 - ChunkStreamingSystem: 区块加载/卸载调度系统 - ChunkCullingSystem: 区块可见性剔除系统 - ChunkManager: 区块生命周期管理服务 - SpatialHashGrid: 空间哈希网格 - ChunkSerializer: 区块序列化 编辑器包 (@esengine/world-streaming-editor): - ChunkVisualizer: 区块可视化覆盖层 - ChunkLoaderInspectorProvider: 区块加载器检视器 - StreamingAnchorInspectorProvider: 流式锚点检视器 - WorldStreamingPlugin: 完整插件导出 * feat(asset): 统一资产引用使用 GUID 替代路径 将所有组件的资产引用字段从路径改为 GUID: - SpriteComponent: texture -> textureGuid, material -> materialGuid - SpriteAnimatorComponent: AnimationFrame.texture -> textureGuid - UIRenderComponent: texture -> textureGuid - UIButtonComponent: normalTexture -> normalTextureGuid 等 - AudioSourceComponent: clip -> clipGuid - ParticleSystemComponent: 已使用 textureGuid 修复 AssetRegistryService 注册问题和路径规范化, 添加渲染系统的 GUID 解析支持。 * fix(sprite-editor): 更新 material 为 materialGuid * fix(editor-app): 更新 AnimationFrame.texture 为 textureGuid
This commit is contained in:
@@ -155,9 +155,9 @@ export class EditorEngineSync {
|
||||
if (bridge) {
|
||||
for (const clip of animator.clips) {
|
||||
for (const frame of clip.frames) {
|
||||
if (frame.texture) {
|
||||
if (frame.textureGuid) {
|
||||
// Trigger texture loading
|
||||
bridge.getOrLoadTextureByPath(frame.texture);
|
||||
bridge.getOrLoadTextureByPath(frame.textureGuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,8 +168,8 @@ export class EditorEngineSync {
|
||||
const firstClip = animator.clips[0];
|
||||
if (firstClip && firstClip.frames && firstClip.frames.length > 0) {
|
||||
const firstFrame = firstClip.frames[0];
|
||||
if (firstFrame && firstFrame.texture && spriteComponent) {
|
||||
spriteComponent.texture = firstFrame.texture;
|
||||
if (firstFrame && firstFrame.textureGuid && spriteComponent) {
|
||||
spriteComponent.textureGuid = firstFrame.textureGuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,8 +228,8 @@ export class EditorEngineSync {
|
||||
// Preload all frame textures
|
||||
for (const clip of animator.clips) {
|
||||
for (const frame of clip.frames) {
|
||||
if (frame.texture) {
|
||||
bridge.getOrLoadTextureByPath(frame.texture);
|
||||
if (frame.textureGuid) {
|
||||
bridge.getOrLoadTextureByPath(frame.textureGuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,8 +240,8 @@ export class EditorEngineSync {
|
||||
const firstClip = animator.clips[0];
|
||||
if (firstClip && firstClip.frames && firstClip.frames.length > 0) {
|
||||
const firstFrame = firstClip.frames[0];
|
||||
if (firstFrame && firstFrame.texture) {
|
||||
sprite.texture = firstFrame.texture;
|
||||
if (firstFrame && firstFrame.textureGuid) {
|
||||
sprite.textureGuid = firstFrame.textureGuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Uses the unified GameRuntime architecture
|
||||
*/
|
||||
|
||||
import { GizmoRegistry, EntityStoreService, MessageHub, SceneManagerService, ProjectService, PluginManager, IPluginManager, type SystemContext } from '@esengine/editor-core';
|
||||
import { GizmoRegistry, EntityStoreService, MessageHub, SceneManagerService, ProjectService, PluginManager, IPluginManager, AssetRegistryService, type SystemContext } from '@esengine/editor-core';
|
||||
import { Core, Scene, Entity, SceneSerializer, ProfilerSDK } from '@esengine/ecs-framework';
|
||||
import { CameraConfig } from '@esengine/ecs-engine-bindgen';
|
||||
import { TransformComponent } from '@esengine/engine-core';
|
||||
@@ -148,6 +148,10 @@ export class EngineService {
|
||||
// 初始化资产系统
|
||||
await this._initializeAssetSystem();
|
||||
|
||||
// 设置资产路径解析器(用于 GUID 到路径的转换)
|
||||
// Set asset path resolver (for GUID to path conversion)
|
||||
this._setupAssetPathResolver();
|
||||
|
||||
// 同步视口尺寸
|
||||
const canvas = document.getElementById(canvasId) as HTMLCanvasElement;
|
||||
if (canvas && canvas.parentElement) {
|
||||
@@ -339,8 +343,8 @@ export class EngineService {
|
||||
const firstClip = animator.clips[0];
|
||||
if (firstClip && firstClip.frames && firstClip.frames.length > 0) {
|
||||
const firstFrame = firstClip.frames[0];
|
||||
if (firstFrame && firstFrame.texture) {
|
||||
sprite.texture = firstFrame.texture;
|
||||
if (firstFrame && firstFrame.textureGuid) {
|
||||
sprite.textureGuid = firstFrame.textureGuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -427,6 +431,59 @@ export class EngineService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup asset path resolver for EngineRenderSystem.
|
||||
* 为 EngineRenderSystem 设置资产路径解析器。
|
||||
*
|
||||
* This enables GUID-based asset references. When a component stores a GUID,
|
||||
* the resolver converts it to an actual file path for loading.
|
||||
* 这启用了基于 GUID 的资产引用。当组件存储 GUID 时,
|
||||
* 解析器将其转换为实际文件路径以进行加载。
|
||||
*/
|
||||
private _setupAssetPathResolver(): void {
|
||||
const renderSystem = this._runtime?.renderSystem;
|
||||
if (!renderSystem) return;
|
||||
|
||||
// UUID v4 regex for GUID detection
|
||||
// UUID v4 正则表达式用于 GUID 检测
|
||||
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
||||
|
||||
renderSystem.setAssetPathResolver((guidOrPath: string): string => {
|
||||
// Skip if already a valid URL
|
||||
// 如果已经是有效的 URL 则跳过
|
||||
if (!guidOrPath || guidOrPath.startsWith('http') || guidOrPath.startsWith('asset://') || guidOrPath.startsWith('data:')) {
|
||||
return guidOrPath;
|
||||
}
|
||||
|
||||
// Check if this is a GUID
|
||||
// 检查是否为 GUID
|
||||
if (uuidRegex.test(guidOrPath)) {
|
||||
const assetRegistry = Core.services.tryResolve(AssetRegistryService) as AssetRegistryService | null;
|
||||
if (assetRegistry) {
|
||||
const relativePath = assetRegistry.getPathByGuid(guidOrPath);
|
||||
if (relativePath) {
|
||||
// Convert relative path to absolute
|
||||
// 将相对路径转换为绝对路径
|
||||
const absolutePath = assetRegistry.relativeToAbsolute(relativePath);
|
||||
if (absolutePath) {
|
||||
// Convert to Tauri asset URL for WebView loading
|
||||
// 转换为 Tauri 资产 URL 以便 WebView 加载
|
||||
return convertFileSrc(absolutePath);
|
||||
}
|
||||
return relativePath;
|
||||
}
|
||||
}
|
||||
// GUID not found, return original value
|
||||
// 未找到 GUID,返回原值
|
||||
return guidOrPath;
|
||||
}
|
||||
|
||||
// Not a GUID, treat as file path and convert
|
||||
// 不是 GUID,当作文件路径处理并转换
|
||||
return convertFileSrc(guidOrPath);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create entity with sprite and transform.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user