可动态识别属性

This commit is contained in:
YHH
2025-10-15 17:15:05 +08:00
parent b69b81f63a
commit fb7a1b1282
30 changed files with 2069 additions and 461 deletions

View File

@@ -57,40 +57,58 @@ export class ComponentLoaderService implements IService {
modulePathTransform?: (filePath: string) => string
): Promise<LoadedComponentInfo | null> {
try {
const modulePath = modulePathTransform
? modulePathTransform(componentInfo.path)
: this.convertToModulePath(componentInfo.path);
logger.debug(`Loading component from: ${modulePath}`);
const module = await import(/* @vite-ignore */ modulePath);
if (!componentInfo.className) {
logger.warn(`No class name found for component: ${componentInfo.fileName}`);
return null;
}
const componentClass = module[componentInfo.className];
let componentClass: typeof Component | undefined;
if (!componentClass || !(componentClass.prototype instanceof Component)) {
logger.error(`Invalid component class: ${componentInfo.className}`);
return null;
if (modulePathTransform) {
const modulePath = modulePathTransform(componentInfo.path);
logger.info(`Attempting to load component from: ${modulePath}`);
logger.info(`Looking for export: ${componentInfo.className}`);
try {
const module = await import(/* @vite-ignore */ modulePath);
logger.info(`Module loaded, exports:`, Object.keys(module));
componentClass = module[componentInfo.className] || module.default;
if (!componentClass) {
logger.warn(`Component class ${componentInfo.className} not found in module exports`);
logger.warn(`Available exports: ${Object.keys(module).join(', ')}`);
} else {
logger.info(`Successfully loaded component class: ${componentInfo.className}`);
}
} catch (error) {
logger.error(`Failed to import component module: ${modulePath}`, error);
}
}
this.componentRegistry.register({
name: componentInfo.className,
type: componentClass
type: componentClass as any,
category: componentInfo.className.includes('Transform') ? 'Transform' :
componentInfo.className.includes('Render') || componentInfo.className.includes('Sprite') ? 'Rendering' :
componentInfo.className.includes('Physics') || componentInfo.className.includes('RigidBody') ? 'Physics' :
'Custom',
description: `Component from ${componentInfo.fileName}`,
metadata: {
path: componentInfo.path,
fileName: componentInfo.fileName
}
});
const loadedInfo: LoadedComponentInfo = {
fileInfo: componentInfo,
componentClass,
componentClass: (componentClass || Component) as any,
loadedAt: Date.now()
};
this.loadedComponents.set(componentInfo.path, loadedInfo);
logger.info(`Component loaded and registered: ${componentInfo.className}`);
logger.info(`Component ${componentClass ? 'loaded' : 'metadata registered'}: ${componentInfo.className}`);
return loadedInfo;
} catch (error) {
@@ -125,13 +143,7 @@ export class ComponentLoaderService implements IService {
}
private convertToModulePath(filePath: string): string {
const normalizedPath = filePath.replace(/\\/g, '/');
if (normalizedPath.startsWith('http://') || normalizedPath.startsWith('https://')) {
return normalizedPath;
}
return `file:///${normalizedPath}`;
return filePath;
}
public dispose(): void {

View File

@@ -2,9 +2,14 @@ import { Injectable, IService, Component } from '@esengine/ecs-framework';
export interface ComponentTypeInfo {
name: string;
type: new (...args: any[]) => Component;
type?: new (...args: any[]) => Component;
category?: string;
description?: string;
metadata?: {
path?: string;
fileName?: string;
[key: string]: any;
};
}
/**
@@ -40,7 +45,7 @@ export class ComponentRegistry implements IService {
public createInstance(name: string, ...args: any[]): Component | null {
const info = this.components.get(name);
if (!info) return null;
if (!info || !info.type) return null;
return new info.type(...args);
}

View File

@@ -4,7 +4,7 @@ import { createLogger } from '@esengine/ecs-framework';
const logger = createLogger('PropertyMetadata');
export type PropertyType = 'number' | 'string' | 'boolean' | 'color' | 'vector2' | 'vector3';
export type PropertyType = 'number' | 'string' | 'boolean' | 'color' | 'vector2' | 'vector3' | 'enum';
export interface PropertyMetadata {
type: PropertyType;