feat: 添加跨平台运行时、资产系统和UI适配功能 (#256)
* feat(platform-common): 添加WASM加载器和环境检测API * feat(rapier2d): 新增Rapier2D WASM绑定包 * feat(physics-rapier2d): 添加跨平台WASM加载器 * feat(asset-system): 添加运行时资产目录和bundle格式 * feat(asset-system-editor): 新增编辑器资产管理包 * feat(editor-core): 添加构建系统和模块管理 * feat(editor-app): 重构浏览器预览使用import maps * feat(platform-web): 添加BrowserRuntime和资产读取 * feat(engine): 添加材质系统和着色器管理 * feat(material): 新增材质系统和着色器编辑器 * feat(tilemap): 增强tilemap编辑器和动画系统 * feat(modules): 添加module.json配置 * feat(core): 添加module.json和类型定义更新 * chore: 更新依赖和构建配置 * refactor(plugins): 更新插件模板使用ModuleManifest * chore: 添加第三方依赖库 * chore: 移除BehaviourTree-ai和ecs-astar子模块 * docs: 更新README和文档主题样式 * fix: 修复Rust文档测试和添加rapier2d WASM绑定 * fix(tilemap-editor): 修复画布高DPI屏幕分辨率适配问题 * feat(ui): 添加UI屏幕适配系统(CanvasScaler/SafeArea) * fix(ecs-engine-bindgen): 添加缺失的ecs-framework-math依赖 * fix: 添加缺失的包依赖修复CI构建 * fix: 修复CodeQL检测到的代码问题 * fix: 修复构建错误和缺失依赖 * fix: 修复类型检查错误 * fix(material-system): 修复tsconfig配置支持TypeScript项目引用 * fix(editor-core): 修复Rollup构建配置添加tauri external * fix: 修复CodeQL检测到的代码问题 * fix: 修复CodeQL检测到的代码问题
This commit is contained in:
@@ -11,6 +11,41 @@ export type ResizeAnchor =
|
||||
| 'middle-left' | 'center' | 'middle-right'
|
||||
| 'bottom-left' | 'bottom-center' | 'bottom-right';
|
||||
|
||||
/**
|
||||
* Animation frame definition
|
||||
* 动画帧定义
|
||||
*/
|
||||
export interface ITileAnimationFrame {
|
||||
/** Tile ID to display for this frame (local ID within tileset) | 此帧显示的瓦片ID(图块集内的本地ID) */
|
||||
tileId: number;
|
||||
/** Frame duration in milliseconds | 帧持续时间(毫秒) */
|
||||
duration: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tile animation definition
|
||||
* 瓦片动画定义
|
||||
*/
|
||||
export interface ITileAnimation {
|
||||
/** Animation frame sequence | 动画帧序列 */
|
||||
frames: ITileAnimationFrame[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Individual tile metadata
|
||||
* 单个瓦片元数据
|
||||
*/
|
||||
export interface ITileMetadata {
|
||||
/** Tile ID (local ID within tileset) | 瓦片ID(图块集内的本地ID) */
|
||||
id: number;
|
||||
/** Tile class/type | 瓦片类型 */
|
||||
type?: string;
|
||||
/** Custom properties | 自定义属性 */
|
||||
properties?: Record<string, unknown>;
|
||||
/** Tile animation (if any) | 瓦片动画(如果有) */
|
||||
animation?: ITileAnimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tileset data interface
|
||||
* 图块集数据接口
|
||||
@@ -41,11 +76,7 @@ export interface ITilesetData {
|
||||
/** Spacing between tiles in pixels | 图块间距(像素) */
|
||||
spacing?: number;
|
||||
/** Individual tile metadata | 单个图块元数据 */
|
||||
tiles?: Array<{
|
||||
id: number;
|
||||
type?: string;
|
||||
properties?: Record<string, unknown>;
|
||||
}>;
|
||||
tiles?: ITileMetadata[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,6 +100,14 @@ export interface ITilemapLayerData {
|
||||
offsetX?: number;
|
||||
/** Layer Y offset in pixels | 图层Y偏移(像素) */
|
||||
offsetY?: number;
|
||||
/** Material asset path for this layer (.mat file) | 此图层的材质资源路径(.mat 文件) */
|
||||
materialPath?: string;
|
||||
/** Runtime material ID (set after loading) | 运行时材质ID(加载后设置) */
|
||||
materialId?: number;
|
||||
/** Tint color in hex format | 着色颜色(十六进制格式) */
|
||||
color?: string;
|
||||
/** Hidden in game (visible only in editor) | 游戏中隐藏(仅在编辑器中可见) */
|
||||
hiddenInGame?: boolean;
|
||||
/** Custom layer properties | 自定义图层属性 */
|
||||
properties?: Record<string, unknown>;
|
||||
}
|
||||
@@ -440,6 +479,40 @@ export class TilemapComponent extends Component implements IResourceComponent {
|
||||
return layer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate a layer
|
||||
* 复制图层
|
||||
* @param index Layer index to duplicate | 要复制的图层索引
|
||||
* @returns The duplicated layer data, or null if index is invalid | 复制的图层数据,如果索引无效则返回 null
|
||||
*/
|
||||
duplicateLayer(index: number): ITilemapLayerData | null {
|
||||
if (index < 0 || index >= this._layers.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sourceLayer = this._layers[index];
|
||||
const sourceData = this._layersData.get(sourceLayer.id);
|
||||
if (!sourceData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const id = `layer_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
||||
const newLayer: ITilemapLayerData = {
|
||||
id,
|
||||
name: `${sourceLayer.name} (副本)`,
|
||||
visible: sourceLayer.visible,
|
||||
opacity: sourceLayer.opacity,
|
||||
data: Array.from(sourceData)
|
||||
};
|
||||
|
||||
// Insert after the source layer
|
||||
this._layers.splice(index + 1, 0, newLayer);
|
||||
this._layersData.set(id, new Uint32Array(sourceData));
|
||||
this.renderDirty = true;
|
||||
|
||||
return newLayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a layer by index (cannot remove last layer)
|
||||
* 按索引移除图层(不能移除最后一个图层)
|
||||
@@ -527,6 +600,96 @@ export class TilemapComponent extends Component implements IResourceComponent {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set layer color (tint)
|
||||
* 设置图层颜色(着色)
|
||||
*/
|
||||
setLayerColor(index: number, color: string): void {
|
||||
if (index >= 0 && index < this._layers.length) {
|
||||
this._layers[index].color = color;
|
||||
this.renderDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get layer color
|
||||
* 获取图层颜色
|
||||
*/
|
||||
getLayerColor(index: number): string {
|
||||
if (index >= 0 && index < this._layers.length) {
|
||||
return this._layers[index].color ?? '#ffffff';
|
||||
}
|
||||
return '#ffffff';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set layer hidden in game
|
||||
* 设置图层在游戏中隐藏
|
||||
*/
|
||||
setLayerHiddenInGame(index: number, hidden: boolean): void {
|
||||
if (index >= 0 && index < this._layers.length) {
|
||||
this._layers[index].hiddenInGame = hidden;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get layer hidden in game
|
||||
* 获取图层在游戏中是否隐藏
|
||||
*/
|
||||
getLayerHiddenInGame(index: number): boolean {
|
||||
if (index >= 0 && index < this._layers.length) {
|
||||
return this._layers[index].hiddenInGame ?? false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set layer material path
|
||||
* 设置图层材质路径
|
||||
* @param index Layer index | 图层索引
|
||||
* @param materialPath Material asset path (.mat file) | 材质资源路径(.mat 文件)
|
||||
*/
|
||||
setLayerMaterial(index: number, materialPath: string): void {
|
||||
if (index >= 0 && index < this._layers.length) {
|
||||
this._layers[index].materialPath = materialPath;
|
||||
this._layers[index].materialId = undefined;
|
||||
this.renderDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get layer material path
|
||||
* 获取图层材质路径
|
||||
* @param index Layer index | 图层索引
|
||||
* @returns Material path or undefined | 材质路径或 undefined
|
||||
*/
|
||||
getLayerMaterial(index: number): string | undefined {
|
||||
return this._layers[index]?.materialPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set layer material ID (runtime)
|
||||
* 设置图层材质ID(运行时)
|
||||
* @param index Layer index | 图层索引
|
||||
* @param materialId Runtime material ID | 运行时材质ID
|
||||
*/
|
||||
setLayerMaterialId(index: number, materialId: number): void {
|
||||
if (index >= 0 && index < this._layers.length) {
|
||||
this._layers[index].materialId = materialId;
|
||||
this.renderDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get layer material ID
|
||||
* 获取图层材质ID
|
||||
* @param index Layer index | 图层索引
|
||||
* @returns Material ID or 0 (default) | 材质ID 或 0(默认)
|
||||
*/
|
||||
getLayerMaterialId(index: number): number {
|
||||
return this._layers[index]?.materialId ?? 0;
|
||||
}
|
||||
|
||||
// ===== Tile Operations | 瓦片操作 =====
|
||||
|
||||
/**
|
||||
@@ -591,6 +754,22 @@ export class TilemapComponent extends Component implements IResourceComponent {
|
||||
return this._layersData.get(layer.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set raw tile data array for a layer
|
||||
* 设置图层的原始图块数据数组
|
||||
* @param layerIndex Layer index | 图层索引
|
||||
* @param data Uint32Array of tile indices | 图块索引的Uint32Array
|
||||
*/
|
||||
setLayerData(layerIndex: number, data: Uint32Array): void {
|
||||
const layer = this._layers[layerIndex];
|
||||
if (!layer) return;
|
||||
|
||||
// Copy data to both the layer object and the internal map
|
||||
layer.data = Array.from(data);
|
||||
this._layersData.set(layer.id, new Uint32Array(data));
|
||||
this.renderDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get merged tile data from all visible layers
|
||||
* 获取所有可见图层合并后的图块数据
|
||||
@@ -846,8 +1025,8 @@ export class TilemapComponent extends Component implements IResourceComponent {
|
||||
|
||||
// Parse anchor to get X and Y alignment
|
||||
// 解析锚点获取X和Y方向的对齐方式
|
||||
let xAnchor: 'start' | 'center' | 'end' = 'start';
|
||||
let yAnchor: 'start' | 'center' | 'end' = 'end'; // 'end' means bottom in Y-up system
|
||||
let xAnchor: 'start' | 'center' | 'end';
|
||||
let yAnchor: 'start' | 'center' | 'end';
|
||||
|
||||
if (anchor.includes('left')) xAnchor = 'start';
|
||||
else if (anchor.includes('right')) xAnchor = 'end';
|
||||
@@ -1002,6 +1181,18 @@ export class TilemapComponent extends Component implements IResourceComponent {
|
||||
}
|
||||
}
|
||||
|
||||
// 收集所有图层材质引用
|
||||
// Collect all layer material references
|
||||
for (const layer of this._layers) {
|
||||
if (layer.materialPath) {
|
||||
refs.push({
|
||||
path: layer.materialPath,
|
||||
type: 'data',
|
||||
runtimeId: layer.materialId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
@@ -1021,6 +1212,17 @@ export class TilemapComponent extends Component implements IResourceComponent {
|
||||
}
|
||||
}
|
||||
|
||||
// 为每个图层设置材质 ID
|
||||
// Set material ID for each layer
|
||||
for (const layer of this._layers) {
|
||||
if (layer.materialPath) {
|
||||
const materialId = pathToId.get(layer.materialPath);
|
||||
if (materialId !== undefined) {
|
||||
layer.materialId = materialId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 标记渲染数据为脏,需要重新构建
|
||||
// Mark render data as dirty, needs rebuild
|
||||
this.renderDirty = true;
|
||||
|
||||
Reference in New Issue
Block a user