Feature/render pipeline (#232)
* refactor(engine): 重构2D渲染管线坐标系统 * feat(engine): 完善2D渲染管线和编辑器视口功能 * feat(editor): 实现Viewport变换工具系统 * feat(editor): 优化Inspector渲染性能并修复Gizmo变换工具显示 * feat(editor): 实现Run on Device移动预览功能 * feat(editor): 添加组件属性控制和依赖关系系统 * feat(editor): 实现动画预览功能和优化SpriteAnimator编辑器 * feat(editor): 修复SpriteAnimator动画预览功能并迁移CI到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(editor): 修复SpriteAnimator动画预览并迁移到pnpm * feat(ci): 迁移项目到pnpm并修复CI构建问题 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 迁移CI工作流到pnpm并添加WASM构建支持 * chore: 移除 network 相关包 * chore: 移除 network 相关包
This commit is contained in:
243
packages/components/src/SpriteComponent.ts
Normal file
243
packages/components/src/SpriteComponent.ts
Normal file
@@ -0,0 +1,243 @@
|
||||
import { Component, ECSComponent, Serializable, Serialize, Property } from '@esengine/ecs-framework';
|
||||
import type { AssetReference } from '@esengine/asset-system';
|
||||
|
||||
/**
|
||||
* 精灵组件 - 管理2D图像渲染
|
||||
* Sprite component - manages 2D image rendering
|
||||
*/
|
||||
@ECSComponent('Sprite')
|
||||
@Serializable({ version: 2, typeId: 'Sprite' })
|
||||
export class SpriteComponent extends Component {
|
||||
/** 纹理路径或资源ID | Texture path or asset ID */
|
||||
@Serialize()
|
||||
@Property({ type: 'asset', label: 'Texture', fileExtension: '.png' })
|
||||
public texture: string = '';
|
||||
|
||||
/**
|
||||
* 资产GUID(新的资产系统)
|
||||
* Asset GUID for new asset system
|
||||
*/
|
||||
@Serialize()
|
||||
public assetGuid?: string;
|
||||
|
||||
/**
|
||||
* 纹理ID(运行时使用)
|
||||
* Texture ID for runtime rendering
|
||||
*/
|
||||
public textureId: number = 0;
|
||||
|
||||
/**
|
||||
* 资产引用(运行时,不序列化)
|
||||
* Asset reference (runtime only, not serialized)
|
||||
*/
|
||||
private _assetReference?: AssetReference<HTMLImageElement>;
|
||||
|
||||
/**
|
||||
* 精灵宽度(像素)
|
||||
* Sprite width in pixels
|
||||
*/
|
||||
@Serialize()
|
||||
@Property({
|
||||
type: 'number',
|
||||
label: 'Width',
|
||||
min: 0,
|
||||
actions: [{
|
||||
id: 'nativeSize',
|
||||
label: 'Native',
|
||||
tooltip: 'Set to texture native size',
|
||||
icon: 'Maximize2'
|
||||
}]
|
||||
})
|
||||
public width: number = 64;
|
||||
|
||||
/**
|
||||
* 精灵高度(像素)
|
||||
* Sprite height in pixels
|
||||
*/
|
||||
@Serialize()
|
||||
@Property({
|
||||
type: 'number',
|
||||
label: 'Height',
|
||||
min: 0,
|
||||
actions: [{
|
||||
id: 'nativeSize',
|
||||
label: 'Native',
|
||||
tooltip: 'Set to texture native size',
|
||||
icon: 'Maximize2'
|
||||
}]
|
||||
})
|
||||
public height: number = 64;
|
||||
|
||||
/**
|
||||
* UV坐标 [u0, v0, u1, v1]
|
||||
* UV coordinates [u0, v0, u1, v1]
|
||||
* 默认为完整纹理 [0, 0, 1, 1]
|
||||
* Default is full texture [0, 0, 1, 1]
|
||||
*/
|
||||
@Serialize()
|
||||
public uv: [number, number, number, number] = [0, 0, 1, 1];
|
||||
|
||||
/** 颜色(十六进制)| Color (hex string) */
|
||||
@Serialize()
|
||||
@Property({ type: 'color', label: 'Color' })
|
||||
public color: string = '#ffffff';
|
||||
|
||||
/** 透明度 (0-1) | Alpha (0-1) */
|
||||
@Serialize()
|
||||
@Property({ type: 'number', label: 'Alpha', min: 0, max: 1, step: 0.01 })
|
||||
public alpha: number = 1;
|
||||
|
||||
/**
|
||||
* 原点X (0-1, 0.5为中心)
|
||||
* Origin point X (0-1, where 0.5 is center)
|
||||
*/
|
||||
@Serialize()
|
||||
@Property({ type: 'number', label: 'Origin X', min: 0, max: 1, step: 0.01 })
|
||||
public originX: number = 0.5;
|
||||
|
||||
/**
|
||||
* 原点Y (0-1, 0.5为中心)
|
||||
* Origin point Y (0-1, where 0.5 is center)
|
||||
*/
|
||||
@Serialize()
|
||||
@Property({ type: 'number', label: 'Origin Y', min: 0, max: 1, step: 0.01 })
|
||||
public originY: number = 0.5;
|
||||
|
||||
/**
|
||||
* 精灵是否可见
|
||||
* Whether sprite is visible
|
||||
*/
|
||||
@Serialize()
|
||||
@Property({ type: 'boolean', label: 'Visible' })
|
||||
public visible: boolean = true;
|
||||
|
||||
/** 是否水平翻转 | Flip sprite horizontally */
|
||||
@Serialize()
|
||||
@Property({ type: 'boolean', label: 'Flip X' })
|
||||
public flipX: boolean = false;
|
||||
|
||||
/** 是否垂直翻转 | Flip sprite vertically */
|
||||
@Serialize()
|
||||
@Property({ type: 'boolean', label: 'Flip Y' })
|
||||
public flipY: boolean = false;
|
||||
|
||||
/**
|
||||
* 渲染层级/顺序(越高越在上面)
|
||||
* Render layer/order (higher = rendered on top)
|
||||
*/
|
||||
@Serialize()
|
||||
@Property({ type: 'integer', label: 'Sorting Order' })
|
||||
public sortingOrder: number = 0;
|
||||
|
||||
/** 锚点X (0-1) - 别名为originX | Anchor X (0-1) - alias for originX */
|
||||
get anchorX(): number {
|
||||
return this.originX;
|
||||
}
|
||||
set anchorX(value: number) {
|
||||
this.originX = value;
|
||||
}
|
||||
|
||||
/** 锚点Y (0-1) - 别名为originY | Anchor Y (0-1) - alias for originY */
|
||||
get anchorY(): number {
|
||||
return this.originY;
|
||||
}
|
||||
set anchorY(value: number) {
|
||||
this.originY = value;
|
||||
}
|
||||
|
||||
constructor(texture: string = '') {
|
||||
super();
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从精灵图集区域设置UV
|
||||
* Set UV from a sprite atlas region
|
||||
*
|
||||
* @param x - 区域X(像素)| Region X in pixels
|
||||
* @param y - 区域Y(像素)| Region Y in pixels
|
||||
* @param w - 区域宽度(像素)| Region width in pixels
|
||||
* @param h - 区域高度(像素)| Region height in pixels
|
||||
* @param atlasWidth - 图集总宽度 | Atlas total width
|
||||
* @param atlasHeight - 图集总高度 | Atlas total height
|
||||
*/
|
||||
setAtlasRegion(
|
||||
x: number,
|
||||
y: number,
|
||||
w: number,
|
||||
h: number,
|
||||
atlasWidth: number,
|
||||
atlasHeight: number
|
||||
): void {
|
||||
this.uv = [
|
||||
x / atlasWidth,
|
||||
y / atlasHeight,
|
||||
(x + w) / atlasWidth,
|
||||
(y + h) / atlasHeight
|
||||
];
|
||||
this.width = w;
|
||||
this.height = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置资产引用
|
||||
* Set asset reference
|
||||
*/
|
||||
setAssetReference(reference: AssetReference<HTMLImageElement>): void {
|
||||
// 释放旧引用 / Release old reference
|
||||
if (this._assetReference) {
|
||||
this._assetReference.release();
|
||||
}
|
||||
this._assetReference = reference;
|
||||
if (reference) {
|
||||
this.assetGuid = reference.guid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资产引用
|
||||
* Get asset reference
|
||||
*/
|
||||
getAssetReference(): AssetReference<HTMLImageElement> | undefined {
|
||||
return this._assetReference;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步加载纹理
|
||||
* Load texture asynchronously
|
||||
*/
|
||||
async loadTextureAsync(): Promise<void> {
|
||||
if (this._assetReference) {
|
||||
try {
|
||||
const textureAsset = await this._assetReference.loadAsync();
|
||||
// 如果纹理资产有 textureId 属性,使用它
|
||||
// If texture asset has textureId property, use it
|
||||
if (textureAsset && typeof textureAsset === 'object' && 'textureId' in textureAsset) {
|
||||
this.textureId = (textureAsset as any).textureId;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load texture:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取有效的纹理源
|
||||
* Get effective texture source
|
||||
*/
|
||||
getTextureSource(): string {
|
||||
return this.assetGuid || this.texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组件销毁时调用
|
||||
* Called when component is destroyed
|
||||
*/
|
||||
onDestroy(): void {
|
||||
// 释放资产引用 / Release asset reference
|
||||
if (this._assetReference) {
|
||||
this._assetReference.release();
|
||||
this._assetReference = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user