fix(particle): 修复粒子系统在浏览器预览中的资产加载和渲染 (#290)

* fix(editor): 修复粒子实体创建和优化检视器

- 添加 effects 分类到右键菜单,修复粒子实体无法创建的问题
- 添加粒子效果的本地化标签
- 简化粒子组件检视器,优先显示资产文件选择
- 高级属性只在未选择资产时显示,且默认折叠
- 添加可折叠的属性分组提升用户体验

* fix(particle): 修复粒子系统在浏览器预览中的资产加载和渲染

- 添加粒子 Gizmo 支持,显示发射形状并响应 Transform 缩放/旋转
- 修复资产热重载:添加 reloadAsset() 方法和 assets:refresh 事件监听
- 修复 VectorFieldEditors 数值输入精度(step 改为 0.01)
- 修复浏览器预览中粒子资产加载失败的问题:
  - 将相对路径转换为绝对路径以正确复制资产文件
  - 使用原始 GUID 而非生成的 GUID 构建 asset catalog
  - 初始化全局 assetManager 单例的 catalog 和 loader
  - 在 GameRuntime 的 systemContext 中添加 engineIntegration
- 公开 AssetManager.initializeFromCatalog 方法供运行时使用
This commit is contained in:
YHH
2025-12-07 01:00:35 +08:00
committed by GitHub
parent 1fb702169e
commit 568b327425
22 changed files with 1628 additions and 782 deletions

View File

@@ -1,10 +1,28 @@
import type { ComponentRegistry as ComponentRegistryType, IScene } from '@esengine/ecs-framework';
import type { IRuntimeModule, IPlugin, ModuleManifest, SystemContext } from '@esengine/engine-core';
import { assetManager as globalAssetManager, type AssetManager } from '@esengine/asset-system';
import { ParticleSystemComponent } from './ParticleSystemComponent';
import { ParticleUpdateSystem } from './systems/ParticleSystem';
import { ParticleLoader, ParticleAssetType } from './loaders/ParticleLoader';
export type { SystemContext, ModuleManifest, IRuntimeModule as IRuntimeModuleLoader, IPlugin as IPluginLoader };
/**
* 引擎桥接接口(用于直接加载纹理)
* Engine bridge interface (for direct texture loading)
*/
export interface IEngineBridge {
loadTexture(id: number, url: string): Promise<void>;
}
/**
* 引擎集成接口(用于加载纹理)
* Engine integration interface (for loading textures)
*/
export interface IEngineIntegration {
loadTextureForComponent(texturePath: string): Promise<number>;
}
/**
* 粒子系统上下文
* Particle system context
@@ -18,10 +36,17 @@ export interface ParticleSystemContext extends SystemContext {
addRenderDataProvider(provider: any): void;
removeRenderDataProvider(provider: any): void;
};
/** 引擎集成(用于加载纹理)| Engine integration (for loading textures) */
engineIntegration?: IEngineIntegration;
/** 引擎桥接(用于直接加载纹理)| Engine bridge (for direct texture loading) */
engineBridge?: IEngineBridge;
/** 资产管理器(用于注册加载器)| Asset manager (for registering loaders) */
assetManager?: AssetManager;
}
class ParticleRuntimeModule implements IRuntimeModule {
private _updateSystem: ParticleUpdateSystem | null = null;
private _loaderRegistered = false;
registerComponents(registry: typeof ComponentRegistryType): void {
registry.register(ParticleSystemComponent);
@@ -30,6 +55,24 @@ class ParticleRuntimeModule implements IRuntimeModule {
createSystems(scene: IScene, context: SystemContext): void {
const particleContext = context as ParticleSystemContext;
// 注册粒子资产加载器到上下文的 assetManager 和全局单例
// Register particle asset loader to context assetManager AND global singleton
if (!this._loaderRegistered) {
const loader = new ParticleLoader();
// Register to context's assetManager (used by GameRuntime)
if (particleContext.assetManager) {
particleContext.assetManager.registerLoader(ParticleAssetType as any, loader);
}
// Also register to global singleton (used by ParticleSystemComponent.loadAsset)
// 同时注册到全局单例ParticleSystemComponent.loadAsset 使用的是全局单例)
globalAssetManager.registerLoader(ParticleAssetType as any, loader);
this._loaderRegistered = true;
console.log('[ParticleRuntimeModule] Registered ParticleLoader to both context and global assetManager');
}
this._updateSystem = new ParticleUpdateSystem();
// 设置 Transform 组件类型 | Set Transform component type
@@ -37,9 +80,14 @@ class ParticleRuntimeModule implements IRuntimeModule {
this._updateSystem.setTransformType(particleContext.transformType);
}
// 在编辑器中禁用系统(手动控制)| Disable in editor (manual control)
if (context.isEditor) {
this._updateSystem.enabled = false;
// 设置引擎集成(用于加载纹理)| Set engine integration (for loading textures)
if (particleContext.engineIntegration) {
this._updateSystem.setEngineIntegration(particleContext.engineIntegration);
}
// 设置引擎桥接(用于加载默认纹理)| Set engine bridge (for loading default texture)
if (particleContext.engineBridge) {
this._updateSystem.setEngineBridge(particleContext.engineBridge);
}
scene.addSystem(this._updateSystem);
@@ -70,7 +118,7 @@ const manifest: ModuleManifest = {
category: 'Rendering',
icon: 'Sparkles',
isCore: false,
defaultEnabled: false,
defaultEnabled: true,
isEngineModule: true,
canContainContent: true,
dependencies: ['core', 'math', 'sprite'],