Files
esengine/packages/rendering/mesh-3d/src/MeshComponent.ts

152 lines
4.1 KiB
TypeScript
Raw Normal View History

/**
* MeshComponent - 3D mesh rendering component.
* MeshComponent - 3D
*/
import { Component, ECSComponent, Property, Serializable, Serialize } from '@esengine/ecs-framework';
import { SortingLayers, type ISortable } from '@esengine/engine-core';
import type { IGLTFAsset, IMeshData } from '@esengine/asset-system';
/**
* 3D Mesh component for rendering GLTF models.
* GLTF 3D
*
* Requires TransformComponent for positioning and MeshRenderSystem for rendering.
* TransformComponent MeshRenderSystem
*/
@ECSComponent('Mesh', { requires: ['Transform'] })
@Serializable({ version: 1, typeId: 'Mesh' })
export class MeshComponent extends Component implements ISortable {
/**
* GUID
* Model asset GUID
*
* Stores the unique identifier of the GLTF/GLB/OBJ/FBX model asset.
* GLTF/GLB/OBJ/FBX
*/
@Serialize()
@Property({ type: 'asset', label: 'Model', assetType: 'any', extensions: ['.gltf', '.glb', '.obj', '.fbx'] })
public modelGuid: string = '';
/**
*
* Runtime mesh data (loaded from asset)
*/
public meshAsset: IGLTFAsset | null = null;
/**
*
* Active mesh index (for multi-mesh models)
*/
@Serialize()
@Property({ type: 'integer', label: 'Mesh Index', min: 0 })
public meshIndex: number = 0;
/**
*
* Whether to cast shadows
*/
@Serialize()
@Property({ type: 'boolean', label: 'Cast Shadows' })
public castShadows: boolean = true;
/**
*
* Whether to receive shadows
*/
@Serialize()
@Property({ type: 'boolean', label: 'Receive Shadows' })
public receiveShadows: boolean = true;
/**
*
* Visibility
*/
@Serialize()
@Property({ type: 'boolean', label: 'Visible' })
public visible: boolean = true;
/**
*
* Sorting layer (for transparent object sorting)
*/
@Serialize()
@Property({
type: 'enum',
label: 'Sorting Layer',
options: ['Background', 'Default', 'Foreground', 'WorldOverlay', 'UI', 'ScreenOverlay', 'Modal']
})
public sortingLayer: string = SortingLayers.Default;
/**
*
* Order in layer
*/
@Serialize()
@Property({ type: 'integer', label: 'Order In Layer' })
public orderInLayer: number = 0;
/**
* GUID
* Material override GUIDs (optional)
*/
@Serialize()
public materialOverrides: string[] = [];
/**
* ID
* Runtime material IDs
*/
public runtimeMaterialIds: number[] = [];
/**
* ID
* Runtime texture IDs
*/
public runtimeTextureIds: number[] = [];
/**
*
* Whether asset is loaded
*/
public get isLoaded(): boolean {
return this.meshAsset !== null;
}
/**
*
* Get current mesh data
*/
public get currentMesh(): IMeshData | null {
if (!this.meshAsset || !this.meshAsset.meshes.length) return null;
const index = Math.min(this.meshIndex, this.meshAsset.meshes.length - 1);
return this.meshAsset.meshes[index];
}
/**
*
* Get all mesh data
*/
public get allMeshes(): IMeshData[] {
return this.meshAsset?.meshes ?? [];
}
/**
*
* Reset component
*/
reset(): void {
this.modelGuid = '';
this.meshAsset = null;
this.meshIndex = 0;
this.castShadows = true;
this.receiveShadows = true;
this.visible = true;
this.sortingLayer = 'Default';
this.orderInLayer = 0;
this.materialOverrides = [];
this.runtimeMaterialIds = [];
this.runtimeTextureIds = [];
}
}