更新生成代码工具
This commit is contained in:
54
extensions/cocos/cocos-ecs/.ecs-framework-settings.json
Normal file
54
extensions/cocos/cocos-ecs/.ecs-framework-settings.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"codeGeneration": {
|
||||
"template": "typescript",
|
||||
"useStrictMode": true,
|
||||
"generateComments": true,
|
||||
"generateImports": true,
|
||||
"componentSuffix": "Component",
|
||||
"systemSuffix": "System",
|
||||
"indentStyle": "spaces",
|
||||
"indentSize": 4
|
||||
},
|
||||
"performance": {
|
||||
"enableMonitoring": true,
|
||||
"warningThreshold": 16.67,
|
||||
"criticalThreshold": 33.33,
|
||||
"memoryWarningMB": 100,
|
||||
"memoryCriticalMB": 200,
|
||||
"maxRecentSamples": 60,
|
||||
"enableFpsMonitoring": true,
|
||||
"targetFps": 60
|
||||
},
|
||||
"debugging": {
|
||||
"enableDebugMode": true,
|
||||
"showEntityCount": true,
|
||||
"showSystemExecutionTime": true,
|
||||
"enablePerformanceWarnings": true,
|
||||
"logLevel": "info",
|
||||
"enableDetailedLogs": false
|
||||
},
|
||||
"editor": {
|
||||
"autoRefreshAssets": true,
|
||||
"showWelcomePanelOnStartup": true,
|
||||
"enableAutoUpdates": false,
|
||||
"updateChannel": "stable",
|
||||
"enableNotifications": true
|
||||
},
|
||||
"template": {
|
||||
"defaultEntityName": "GameEntity",
|
||||
"defaultComponentName": "CustomComponent",
|
||||
"defaultSystemName": "CustomSystem",
|
||||
"createExampleFiles": true,
|
||||
"includeDocumentation": true,
|
||||
"useFactoryPattern": true
|
||||
},
|
||||
"events": {
|
||||
"enableEventSystem": true,
|
||||
"defaultEventPriority": 0,
|
||||
"enableAsyncEvents": true,
|
||||
"enableEventBatching": false,
|
||||
"batchSize": 10,
|
||||
"batchDelay": 16,
|
||||
"maxEventListeners": 100
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "80dcbaf5-21f7-4bb1-aff4-2cdbb0b5d364",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -1,25 +1,81 @@
|
||||
# Project Title
|
||||
# ECS Framework for Cocos Creator - 开发扩展插件
|
||||
|
||||
An extension that shows how to open and communicate with the panel through messages and menus.
|
||||
The panel is based on Vue3.x.
|
||||
专业的ECS框架开发助手,为Cocos Creator提供完整的实体组件系统(ECS)开发工具链。
|
||||
|
||||
## Development Environment
|
||||
## 🎯 主要功能
|
||||
|
||||
Node.js
|
||||
### 📦 一键安装管理
|
||||
- **自动检测**:实时检测ECS框架安装状态和版本信息
|
||||
- **一键安装**:快速安装 `@esengine/ecs-framework` 到当前项目
|
||||
- **版本管理**:自动检查更新,支持一键更新到最新版本
|
||||
- **智能卸载**:安全卸载框架,保护项目完整性
|
||||
|
||||
## Install
|
||||
### 🚀 代码生成器
|
||||
- **智能生成**:输入功能名称,自动生成对应的组件和系统代码
|
||||
- **多种系统类型**:支持EntitySystem、ProcessingSystem、IntervalSystem、PassiveSystem
|
||||
- **组件配置**:可选择添加属性、注释等定制化选项
|
||||
- **组件过滤**:支持生成带组件过滤的高级系统
|
||||
|
||||
```bash
|
||||
# Install dependent modules
|
||||
npm install
|
||||
# build
|
||||
npm run build
|
||||
```
|
||||
### 🛠️ 项目模板
|
||||
- **快速启动**:一键生成完整的ECS项目结构
|
||||
- **预设组件**:包含位置、速度、Cocos节点等常用组件
|
||||
- **系统示例**:提供移动系统、节点同步系统等实用示例
|
||||
- **工厂模式**:包含实体工厂和场景管理器模板
|
||||
|
||||
## Usage
|
||||
### 🔍 调试工具
|
||||
- **实时监控**:查看ECS框架运行状态和性能数据
|
||||
- **组件池监控**:实时监控组件对象池使用情况
|
||||
- **性能分析**:提供详细的性能统计和优化建议
|
||||
|
||||
After enabling the extension, click `Panel -> cocos-ecs-extension -> Default Panel` in the main menu bar to open the default panel of the extension.
|
||||
## 📋 面板介绍
|
||||
|
||||
To send a message to the default panel, click `Developer -> cocos-ecs-extension -> Send Message to Panel` at the top of the menu. If the default panel exists, the `hello` method of the panel will be called.
|
||||
### 欢迎面板
|
||||
- ECS框架安装状态检测
|
||||
- 一键安装、更新、卸载操作
|
||||
- 项目模板生成
|
||||
- 快速访问文档和GitHub
|
||||
|
||||
After clicking `Send Message to Panel`, a message `send-to-panel` will be sent to the extension as defined by `contributions.menu` in `package.json`. When the extension receives the `send-to-panel` message, it will cause the `default` panel to call the `hello` method as defined by `contributions.messages` in `package.json`.
|
||||
### 代码生成器
|
||||
- 可视化代码生成界面
|
||||
- 实时预览生成的代码结构
|
||||
- 支持批量生成多个文件
|
||||
|
||||
### 调试面板
|
||||
- 实时性能监控
|
||||
- 组件池状态查看
|
||||
- 系统运行统计
|
||||
|
||||
## 🔧 开发环境
|
||||
|
||||
- **Cocos Creator**: >= 3.8.6
|
||||
- **Node.js**: >= 14.0.0
|
||||
- **依赖框架**: @esengine/ecs-framework
|
||||
|
||||
## 📥 安装使用
|
||||
|
||||
1. 将插件复制到项目的 `extensions` 目录
|
||||
2. 在Cocos Creator中启用插件
|
||||
3. 通过菜单 `面板 -> ECS Framework -> 欢迎面板` 打开主界面
|
||||
4. 按照界面提示安装ECS框架并开始开发
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
1. **安装框架**:在欢迎面板点击"安装 ECS Framework"
|
||||
2. **创建模板**:点击"创建ECS模板"生成项目结构
|
||||
3. **生成代码**:使用代码生成器快速创建组件和系统
|
||||
4. **开始开发**:基于生成的模板开始您的ECS游戏开发
|
||||
|
||||
## 📚 更多资源
|
||||
|
||||
- **GitHub仓库**:[https://github.com/esengine/ecs-framework](https://github.com/esengine/ecs-framework)
|
||||
- **完整文档**:包含详细的API文档和教程
|
||||
- **技术交流**:加入QQ群获取技术支持和交流
|
||||
|
||||
## ⭐ 特色优势
|
||||
|
||||
- **零配置**:开箱即用,无需复杂配置
|
||||
- **可视化**:图形化界面,操作简单直观
|
||||
- **高效率**:大幅减少重复代码编写
|
||||
- **专业性**:基于成熟的ECS框架设计模式
|
||||
|
||||
让ECS开发变得简单高效,专注于游戏逻辑而非框架配置!
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# 项目简介
|
||||
|
||||
一份包含面板的扩展,该面板基于 vue3.x 开发,展示了如何通过消息和菜单打开面板,以及与面板通讯。
|
||||
|
||||
## 开发环境
|
||||
|
||||
Node.js
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
# 安装依赖模块
|
||||
npm install
|
||||
# 构建
|
||||
npm run build
|
||||
```
|
||||
|
||||
## 用法
|
||||
|
||||
启用扩展后,点击主菜单栏中的 `面板 -> cocos-ecs-extension -> 默认面板`,即可打开扩展的默认面板。
|
||||
|
||||
依次点击顶部菜单的 `开发者 -> cocos-ecs-extension -> 发送消息给面板` 即可发送消息给默认面板,如果此时存在默认面板,将会调用面板的 `hello` 方法。
|
||||
|
||||
点击 `发送消息给面板` 后,根据 `package.json` 中 `contributions.menu` 的定义将发送一条消息 `send-to-panel` 给扩展。根据 `package.json` 中 `contributions.messages` 的定义当扩展收到 `send-to-panel` 后将会使 `default` 面板调用 `hello` 方法。
|
||||
@@ -1 +1 @@
|
||||
"use strict";module.exports={open_panel:"Default Panel",send_to_panel:"Send message to Default Panel",description:"Extension with a panel based on Vue3.x"};
|
||||
"use strict";module.exports={open_panel:"Default Panel",send_to_panel:"Send message to Default Panel",description:"Professional ECS Framework Development Assistant: One-click install @esengine/ecs-framework, intelligent code generator for components and systems, project template generation, real-time status monitoring and version management. Features welcome panel, debug panel and code generator to make ECS development in Cocos Creator more efficient and convenient."};
|
||||
@@ -1 +1 @@
|
||||
"use strict";module.exports={open_panel:"默认面板",send_to_panel:"发送消息给面板",description:"含有一个基于Vue3.x开发的面板的扩展"};
|
||||
"use strict";module.exports={open_panel:"默认面板",send_to_panel:"发送消息给面板",description:"专业的ECS框架开发助手:一键安装@esengine/ecs-framework,智能代码生成器快速创建组件和系统,项目模板生成,实时状态检测和版本管理。提供欢迎面板、调试面板和代码生成器,让Cocos Creator的ECS开发更高效便捷。"};
|
||||
@@ -10,12 +10,14 @@
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"fs-extra": "^10.0.0",
|
||||
"vue": "^3.1.4"
|
||||
"vue": "^3.1.4",
|
||||
"ws": "^8.14.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cocos/creator-types": "^3.8.6",
|
||||
"@types/fs-extra": "^9.0.5",
|
||||
"@types/node": "^18.17.1",
|
||||
"@types/ws": "^8.5.10",
|
||||
"typescript": "^5.8.2"
|
||||
}
|
||||
},
|
||||
@@ -57,6 +59,15 @@
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.18.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-core": {
|
||||
"version": "3.3.4",
|
||||
"license": "MIT",
|
||||
@@ -282,6 +293,26 @@
|
||||
"@vue/server-renderer": "3.3.4",
|
||||
"@vue/shared": "3.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.18.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
|
||||
"integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
"main": "./dist/main.js",
|
||||
"dependencies": {
|
||||
"vue": "^3.1.4",
|
||||
"fs-extra": "^10.0.0"
|
||||
"fs-extra": "^10.0.0",
|
||||
"ws": "^8.14.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cocos/creator-types": "^3.8.6",
|
||||
"@types/fs-extra": "^9.0.5",
|
||||
"@types/node": "^18.17.1",
|
||||
"@types/ws": "^8.5.10",
|
||||
"typescript": "^5.8.2"
|
||||
},
|
||||
"panels": {
|
||||
@@ -33,17 +35,6 @@
|
||||
"height": 800
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "ECS Framework - 设置",
|
||||
"type": "dockable",
|
||||
"main": "dist/panels/settings/index.js",
|
||||
"size": {
|
||||
"min-width": 600,
|
||||
"min-height": 700,
|
||||
"width": 800,
|
||||
"height": 900
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"title": "ECS Framework - 调试面板",
|
||||
"type": "dockable",
|
||||
@@ -54,6 +45,17 @@
|
||||
"width": 500,
|
||||
"height": 600
|
||||
}
|
||||
},
|
||||
"generator": {
|
||||
"title": "ECS Framework - 代码生成器",
|
||||
"type": "dockable",
|
||||
"main": "dist/panels/generator/index.js",
|
||||
"size": {
|
||||
"min-width": 600,
|
||||
"min-height": 500,
|
||||
"width": 900,
|
||||
"height": 700
|
||||
}
|
||||
}
|
||||
},
|
||||
"contributions": {
|
||||
@@ -68,13 +70,13 @@
|
||||
},
|
||||
{
|
||||
"path": "i18n:menu.panel/ECS Framework",
|
||||
"label": "插件设置",
|
||||
"message": "open-settings"
|
||||
"label": "调试面板",
|
||||
"message": "open-debug"
|
||||
},
|
||||
{
|
||||
"path": "i18n:menu.panel/ECS Framework",
|
||||
"label": "调试面板",
|
||||
"message": "open-debug"
|
||||
"label": "代码生成器",
|
||||
"message": "open-generator"
|
||||
},
|
||||
{
|
||||
"path": "i18n:menu.develop/ECS Framework",
|
||||
@@ -113,35 +115,25 @@
|
||||
"create-ecs-template"
|
||||
]
|
||||
},
|
||||
"open-settings": {
|
||||
"methods": [
|
||||
"open-settings"
|
||||
]
|
||||
},
|
||||
"open-project-analysis": {
|
||||
"methods": [
|
||||
"open-project-analysis"
|
||||
]
|
||||
},
|
||||
"open-component-library": {
|
||||
"methods": [
|
||||
"open-component-library"
|
||||
]
|
||||
},
|
||||
"open-github": {
|
||||
"methods": [
|
||||
"open-github"
|
||||
]
|
||||
},
|
||||
"settings-updated": {
|
||||
"open-qq-group": {
|
||||
"methods": [
|
||||
"settings-updated"
|
||||
"open-qq-group"
|
||||
]
|
||||
},
|
||||
"open-debug": {
|
||||
"methods": [
|
||||
"open-debug"
|
||||
]
|
||||
},
|
||||
"open-generator": {
|
||||
"methods": [
|
||||
"open-generator"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
import { ensureDir, writeFile } from 'fs-extra';
|
||||
import { join } from 'path';
|
||||
|
||||
/**
|
||||
* 代码生成器工具类
|
||||
* 用于生成基础的ECS框架代码
|
||||
*/
|
||||
|
||||
interface ComponentOptions {
|
||||
includeComments: boolean;
|
||||
addProperties: string[];
|
||||
}
|
||||
|
||||
interface SystemOptions {
|
||||
includeComments: boolean;
|
||||
systemType: 'EntitySystem' | 'ProcessingSystem' | 'IntervalSystem' | 'PassiveSystem';
|
||||
requiredComponents: string[];
|
||||
}
|
||||
|
||||
export class CodeGenerator {
|
||||
|
||||
/**
|
||||
* 生成组件代码
|
||||
*/
|
||||
public async generateComponent(
|
||||
name: string,
|
||||
targetDir: string,
|
||||
options: ComponentOptions = {
|
||||
includeComments: true,
|
||||
addProperties: []
|
||||
}
|
||||
): Promise<void> {
|
||||
const className = `${name}Component`;
|
||||
const fileName = `${className}.ts`;
|
||||
const filePath = join(targetDir, fileName);
|
||||
|
||||
await ensureDir(targetDir);
|
||||
|
||||
const comments = options.includeComments ? this.generateComponentComments(className) : '';
|
||||
const properties = this.generateComponentProperties(options.addProperties);
|
||||
|
||||
const content = `import { Component } from '@esengine/ecs-framework';
|
||||
|
||||
${comments}
|
||||
export class ${className} extends Component {
|
||||
${properties}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置组件状态
|
||||
*/
|
||||
public reset(): void {
|
||||
// 重置组件属性到默认值
|
||||
${this.generateResetCode(options.addProperties)}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
await writeFile(filePath, content, 'utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成系统代码
|
||||
*/
|
||||
public async generateSystem(
|
||||
name: string,
|
||||
targetDir: string,
|
||||
options: SystemOptions = {
|
||||
includeComments: true,
|
||||
systemType: 'EntitySystem',
|
||||
requiredComponents: []
|
||||
}
|
||||
): Promise<void> {
|
||||
const className = `${name}System`;
|
||||
const fileName = `${className}.ts`;
|
||||
const filePath = join(targetDir, fileName);
|
||||
|
||||
await ensureDir(targetDir);
|
||||
|
||||
const comments = options.includeComments ? this.generateSystemComments(className, options.systemType) : '';
|
||||
const imports = this.getSystemImports(options.systemType, options.requiredComponents);
|
||||
const matcherSetup = options.requiredComponents.length > 0 ?
|
||||
`Matcher.empty().all(${options.requiredComponents.join(', ')})` :
|
||||
`Matcher.empty()`;
|
||||
|
||||
const processMethod = this.generateProcessMethod(options.systemType, options.requiredComponents, className);
|
||||
|
||||
const content = `${imports}
|
||||
|
||||
${comments}
|
||||
export class ${className} extends ${options.systemType} {
|
||||
|
||||
constructor() {
|
||||
super(${matcherSetup}${options.systemType === 'IntervalSystem' ? ', 1000 / 60 // 60fps' : ''});
|
||||
}
|
||||
|
||||
${processMethod}
|
||||
|
||||
/**
|
||||
* 系统开始时调用
|
||||
*/
|
||||
public begin(): void {
|
||||
super.begin();
|
||||
// 添加系统初始化逻辑
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统结束时调用
|
||||
*/
|
||||
public end(): void {
|
||||
// 添加系统清理逻辑
|
||||
super.end();
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
await writeFile(filePath, content, 'utf-8');
|
||||
}
|
||||
|
||||
// ============ 辅助方法 ============
|
||||
|
||||
private generateComponentComments(className: string): string {
|
||||
return `/**
|
||||
* ${className}
|
||||
*
|
||||
* 组件描述
|
||||
*
|
||||
* @example
|
||||
* \`\`\`typescript
|
||||
* const entity = scene.createEntity("Example");
|
||||
* const component = entity.addComponent(new ${className}());
|
||||
* \`\`\`
|
||||
*/`;
|
||||
}
|
||||
|
||||
private generateSystemComments(className: string, systemType: string): string {
|
||||
const descriptions = {
|
||||
'EntitySystem': '处理拥有特定组件的实体',
|
||||
'ProcessingSystem': '执行全局游戏逻辑',
|
||||
'IntervalSystem': '按时间间隔处理实体',
|
||||
'PassiveSystem': '被动响应事件或手动调用'
|
||||
};
|
||||
|
||||
return `/**
|
||||
* ${className}
|
||||
*
|
||||
* ${descriptions[systemType as keyof typeof descriptions] || '处理游戏逻辑'}
|
||||
*
|
||||
* @example
|
||||
* \`\`\`typescript
|
||||
* const system = new ${className}();
|
||||
* scene.addEntityProcessor(system);
|
||||
* \`\`\`
|
||||
*/`;
|
||||
}
|
||||
|
||||
private generateComponentProperties(properties: string[]): string {
|
||||
if (properties.length === 0) {
|
||||
return ' // 添加组件属性\n // public value: number = 0;';
|
||||
}
|
||||
|
||||
return properties.map(prop => {
|
||||
const [name, type = 'number', defaultValue = '0'] = prop.split(':');
|
||||
return ` public ${name}: ${type} = ${defaultValue};`;
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
private generateResetCode(properties: string[]): string {
|
||||
if (properties.length === 0) {
|
||||
return ' // this.value = 0;';
|
||||
}
|
||||
|
||||
return properties.map(prop => {
|
||||
const [name, , defaultValue = '0'] = prop.split(':');
|
||||
return ` this.${name} = ${defaultValue};`;
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
private getSystemImports(systemType: string, requiredComponents: string[]): string {
|
||||
const imports = [systemType, 'Entity'];
|
||||
|
||||
// 所有系统类型都可能需要Matcher来过滤组件
|
||||
if (requiredComponents.length > 0 || systemType === 'EntitySystem' || systemType === 'IntervalSystem' || systemType === 'PassiveSystem') {
|
||||
imports.push('Matcher');
|
||||
}
|
||||
|
||||
return `import { ${imports.join(', ')} } from '@esengine/ecs-framework';${requiredComponents.length > 0 ? '\n' + this.generateComponentImports(requiredComponents) : ''}`;
|
||||
}
|
||||
|
||||
private generateComponentImports(components: string[]): string {
|
||||
return components.map(comp => `import { ${comp} } from '../components/${comp}';`).join('\n');
|
||||
}
|
||||
|
||||
private generateProcessMethod(systemType: string, requiredComponents: string[], className: string): string {
|
||||
switch (systemType) {
|
||||
case 'EntitySystem':
|
||||
return ` protected process(entities: Entity[]): void {
|
||||
for (const entity of entities) {
|
||||
this.processEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
private processEntity(entity: Entity): void {
|
||||
${this.generateProcessingLogic(requiredComponents)}
|
||||
}`;
|
||||
|
||||
case 'ProcessingSystem':
|
||||
return ` public processSystem(): void {
|
||||
// 添加全局系统逻辑
|
||||
console.log('${className} processSystem called');
|
||||
}`;
|
||||
|
||||
case 'IntervalSystem':
|
||||
return ` protected process(entities: Entity[]): void {
|
||||
const intervalDelta = this.getIntervalDelta();
|
||||
console.log(\`${className} executing with interval delta: \${intervalDelta}\`);
|
||||
|
||||
for (const entity of entities) {
|
||||
this.processEntity(entity, intervalDelta);
|
||||
}
|
||||
}
|
||||
|
||||
private processEntity(entity: Entity, delta: number): void {
|
||||
${this.generateProcessingLogic(requiredComponents)}
|
||||
}`;
|
||||
|
||||
case 'PassiveSystem':
|
||||
return ` /**
|
||||
* 被动系统不主动处理实体
|
||||
* 通常用于响应事件或被其他系统调用
|
||||
*/
|
||||
public processEntity(entity: Entity): void {
|
||||
${this.generateProcessingLogic(requiredComponents)}
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动触发处理
|
||||
*/
|
||||
public trigger(): void {
|
||||
for (const entity of this.entities) {
|
||||
this.processEntity(entity);
|
||||
}
|
||||
}`;
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
private generateProcessingLogic(requiredComponents: string[]): string {
|
||||
if (requiredComponents.length === 0) {
|
||||
return ' // 添加处理逻辑';
|
||||
}
|
||||
|
||||
const componentVars = requiredComponents.map((comp: string) => {
|
||||
const varName = comp.replace('Component', '').toLowerCase();
|
||||
return ` const ${varName} = entity.getComponent(${comp});`;
|
||||
}).join('\n');
|
||||
|
||||
const nullCheck = requiredComponents.map((comp: string) => {
|
||||
const varName = comp.replace('Component', '').toLowerCase();
|
||||
return varName;
|
||||
}).join(' && ');
|
||||
|
||||
return `${componentVars}
|
||||
|
||||
if (${nullCheck}) {
|
||||
// 添加处理逻辑
|
||||
}`;
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@
|
||||
import packageJSON from '../package.json';
|
||||
import { exec } from 'child_process';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { readFileSync, outputFile } from 'fs-extra';
|
||||
import { join } from 'path';
|
||||
import { TemplateGenerator } from './TemplateGenerator';
|
||||
import { CodeGenerator } from './CodeGenerator';
|
||||
|
||||
/**
|
||||
* @en Registration method for the main process of Extension
|
||||
@@ -120,16 +122,28 @@ export const methods: { [key: string]: (...any: any) => any } = {
|
||||
* 打开文档
|
||||
*/
|
||||
'open-documentation'() {
|
||||
// 使用系统默认命令打开链接
|
||||
const url = 'https://github.com/esengine/ecs-framework/blob/master/README.md';
|
||||
exec(`start "" "${url}"`, (error) => {
|
||||
if (error) {
|
||||
console.error('Failed to open documentation:', error);
|
||||
Editor.Dialog.info('打开文档', {
|
||||
detail: `请手动访问以下链接查看文档:\n\n${url}`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// 使用Electron的shell模块打开外部链接(推荐方法)
|
||||
const { shell } = require('electron');
|
||||
shell.openExternal(url);
|
||||
console.log('Documentation link opened successfully');
|
||||
} catch (error) {
|
||||
console.error('Failed to open documentation with shell.openExternal, trying exec:', error);
|
||||
|
||||
// 备用方法:使用系统命令
|
||||
exec(`start "" "${url}"`, (execError) => {
|
||||
if (execError) {
|
||||
console.error('Failed to open documentation with exec:', execError);
|
||||
Editor.Dialog.info('打开文档', {
|
||||
detail: `请手动访问以下链接查看文档:\n\n${url}`,
|
||||
});
|
||||
} else {
|
||||
console.log('Documentation link opened successfully with exec');
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -198,56 +212,59 @@ export const methods: { [key: string]: (...any: any) => any } = {
|
||||
},
|
||||
|
||||
/**
|
||||
* 打开设置
|
||||
* 打开GitHub仓库
|
||||
*/
|
||||
'open-settings'() {
|
||||
console.log('Opening ECS Framework settings panel...');
|
||||
'open-github'() {
|
||||
const url = 'https://github.com/esengine/ecs-framework';
|
||||
|
||||
try {
|
||||
// 正确的打开特定面板的方法
|
||||
Editor.Panel.open(packageJSON.name + '.settings');
|
||||
console.log('Settings panel opened successfully');
|
||||
// 使用Electron的shell模块打开外部链接(推荐方法)
|
||||
const { shell } = require('electron');
|
||||
shell.openExternal(url);
|
||||
console.log('GitHub link opened successfully');
|
||||
} catch (error) {
|
||||
console.error('Failed to open settings panel:', error);
|
||||
Editor.Dialog.error('打开设置失败', {
|
||||
detail: `无法打开设置面板:\n\n${error}\n\n请尝试重启Cocos Creator编辑器。`,
|
||||
console.error('Failed to open GitHub with shell.openExternal, trying exec:', error);
|
||||
|
||||
// 备用方法:使用系统命令
|
||||
exec(`start "" "${url}"`, (execError) => {
|
||||
if (execError) {
|
||||
console.error('Failed to open GitHub with exec:', execError);
|
||||
Editor.Dialog.info('打开GitHub', {
|
||||
detail: `请手动访问以下链接:\n\n${url}`,
|
||||
});
|
||||
} else {
|
||||
console.log('GitHub link opened successfully with exec');
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 项目分析(预留)
|
||||
* 打开QQ群
|
||||
*/
|
||||
'analyze-project'() {
|
||||
Editor.Dialog.info('项目分析', {
|
||||
detail: '项目分析功能开发中...\n\n将在下个版本提供以下分析功能:\n• ECS架构合理性分析\n• 性能瓶颈检测\n• 组件使用统计\n• 系统执行效率分析\n• 内存使用优化建议',
|
||||
buttons: ['好的'],
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件库(预留)
|
||||
*/
|
||||
'open-component-library'() {
|
||||
Editor.Dialog.info('组件库', {
|
||||
detail: '组件库功能开发中...\n\n将在下个版本提供:\n• 常用组件模板库\n• 系统模板库\n• 一键生成组件代码\n• 社区组件分享\n• 组件文档和示例',
|
||||
buttons: ['好的'],
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 打开GitHub仓库
|
||||
*/
|
||||
'open-github'() {
|
||||
const url = 'https://github.com/esengine/ecs-framework';
|
||||
// 在Windows上使用正确的start命令语法
|
||||
exec(`start "" "${url}"`, (error) => {
|
||||
if (error) {
|
||||
console.error('Failed to open GitHub:', error);
|
||||
Editor.Dialog.info('打开GitHub', {
|
||||
detail: `请手动访问以下链接:\n\n${url}`,
|
||||
});
|
||||
}
|
||||
});
|
||||
'open-qq-group'() {
|
||||
const url = 'https://qm.qq.com/cgi-bin/qm/qr?k=1DMoPJEsY5xUpTAcmjIHK8whgHJHYQTL&authKey=%2FklVb3S0Momc1q1J%2FWHncuwMVHGrDbwV1Y6gAfa5e%2FgHCvyYUL2gpA6hSOU%2BVSa5&noverify=0&group_code=481923584';
|
||||
|
||||
try {
|
||||
// 使用Electron的shell模块打开外部链接(推荐方法)
|
||||
const { shell } = require('electron');
|
||||
shell.openExternal(url);
|
||||
console.log('QQ group link opened successfully');
|
||||
} catch (error) {
|
||||
console.error('Failed to open QQ group with shell.openExternal, trying exec:', error);
|
||||
|
||||
// 备用方法:使用系统命令
|
||||
exec(`start "" "${url}"`, (execError) => {
|
||||
if (execError) {
|
||||
console.error('Failed to open QQ group with exec:', execError);
|
||||
Editor.Dialog.info('加入QQ群', {
|
||||
detail: `请手动访问以下链接加入QQ群:\n\n${url}\n\n或手动搜索QQ群号:481923584`,
|
||||
});
|
||||
} else {
|
||||
console.log('QQ group link opened successfully with exec');
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -268,36 +285,18 @@ export const methods: { [key: string]: (...any: any) => any } = {
|
||||
},
|
||||
|
||||
/**
|
||||
* 处理设置更新
|
||||
* 打开代码生成器面板
|
||||
*/
|
||||
'settings-updated'(settings: any) {
|
||||
console.log('ECS Framework settings updated:', settings);
|
||||
|
||||
// 这里可以根据设置更新做一些处理
|
||||
// 比如重新配置框架、更新性能监控等
|
||||
|
||||
// 示例:根据设置更新性能监控
|
||||
if (settings?.performance?.enableMonitoring) {
|
||||
console.log('Performance monitoring enabled with thresholds:', {
|
||||
warning: settings.performance.warningThreshold,
|
||||
critical: settings.performance.criticalThreshold,
|
||||
memoryWarning: settings.performance.memoryWarningMB,
|
||||
memoryCritical: settings.performance.memoryCriticalMB
|
||||
});
|
||||
}
|
||||
|
||||
// 示例:根据设置更新调试模式
|
||||
if (settings?.debugging?.enableDebugMode) {
|
||||
console.log('Debug mode enabled with log level:', settings.debugging.logLevel);
|
||||
}
|
||||
|
||||
// 示例:根据设置更新事件系统
|
||||
if (settings?.events?.enableEventSystem) {
|
||||
console.log('Event system configured:', {
|
||||
asyncEvents: settings.events.enableAsyncEvents,
|
||||
batching: settings.events.enableEventBatching,
|
||||
batchSize: settings.events.batchSize,
|
||||
maxListeners: settings.events.maxEventListeners
|
||||
'open-generator'() {
|
||||
console.log('Opening ECS Framework code generator panel...');
|
||||
try {
|
||||
// 正确的打开特定面板的方法
|
||||
Editor.Panel.open(packageJSON.name + '.generator');
|
||||
console.log('Generator panel opened successfully');
|
||||
} catch (error) {
|
||||
console.error('Failed to open generator panel:', error);
|
||||
Editor.Dialog.error('打开代码生成器失败', {
|
||||
detail: `无法打开代码生成器面板:\n\n${error}\n\n请尝试重启Cocos Creator编辑器。`,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { readFileSync } from 'fs-extra';
|
||||
import { join } from 'path';
|
||||
import { createApp, App, defineComponent, ref, reactive, onMounted, onUnmounted } from 'vue';
|
||||
import { WebSocketServer } from 'ws';
|
||||
import { WebSocketServer, WebSocket } from 'ws';
|
||||
import { IncomingMessage } from 'http';
|
||||
|
||||
const panelDataMap = new WeakMap<any, App>();
|
||||
|
||||
@@ -15,7 +16,7 @@ interface GameInstance {
|
||||
lastUpdateTime: number;
|
||||
isActive: boolean;
|
||||
debugData?: any;
|
||||
ws?: any; // WebSocket连接
|
||||
ws?: WebSocket; // WebSocket连接
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +137,7 @@ class ECSDebugServer {
|
||||
try {
|
||||
this.wss = new WebSocketServer({ port: this.port });
|
||||
|
||||
this.wss.on('connection', (ws, req) => {
|
||||
this.wss.on('connection', (ws: WebSocket, req: IncomingMessage) => {
|
||||
const instanceId = this.generateInstanceId();
|
||||
const instance: GameInstance = {
|
||||
id: instanceId,
|
||||
@@ -151,7 +152,7 @@ class ECSDebugServer {
|
||||
this.gameInstances.set(instanceId, instance);
|
||||
console.log(`[ECS Debug Server] New instance connected: ${instance.name}`);
|
||||
|
||||
ws.on('message', (data) => {
|
||||
ws.on('message', (data: Buffer) => {
|
||||
try {
|
||||
const message = JSON.parse(data.toString());
|
||||
this.handleMessage(instanceId, message);
|
||||
@@ -168,7 +169,7 @@ class ECSDebugServer {
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('error', (error) => {
|
||||
ws.on('error', (error: Error) => {
|
||||
console.error(`[ECS Debug Server] WebSocket error for ${instanceId}:`, error);
|
||||
});
|
||||
|
||||
|
||||
@@ -462,22 +462,18 @@ module.exports = Editor.Panel.define({
|
||||
});
|
||||
};
|
||||
|
||||
const openSettings = () => {
|
||||
Editor.Message.send('cocos-ecs-extension', 'open-settings');
|
||||
};
|
||||
|
||||
const openProjectAnalysis = () => {
|
||||
Editor.Message.send('cocos-ecs-extension', 'open-project-analysis');
|
||||
};
|
||||
|
||||
const openComponentLibrary = () => {
|
||||
Editor.Message.send('cocos-ecs-extension', 'open-component-library');
|
||||
};
|
||||
|
||||
const openGithub = () => {
|
||||
Editor.Message.send('cocos-ecs-extension', 'open-github');
|
||||
};
|
||||
|
||||
const joinQQGroup = () => {
|
||||
Editor.Message.send('cocos-ecs-extension', 'open-qq-group');
|
||||
};
|
||||
|
||||
const openGenerator = () => {
|
||||
Editor.Message.send('cocos-ecs-extension', 'open-generator');
|
||||
};
|
||||
|
||||
// 组件挂载后检测状态
|
||||
onMounted(() => {
|
||||
setupMessageListeners();
|
||||
@@ -510,10 +506,9 @@ module.exports = Editor.Panel.define({
|
||||
checkForUpdates,
|
||||
openDocumentation,
|
||||
createEcsTemplate,
|
||||
openSettings,
|
||||
openProjectAnalysis,
|
||||
openComponentLibrary,
|
||||
openGithub
|
||||
openGithub,
|
||||
joinQQGroup,
|
||||
openGenerator
|
||||
};
|
||||
},
|
||||
template: readFileSync(join(__dirname, '../../../static/template/vue/welcome.html'), 'utf-8'),
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
import { readFileSync } from 'fs-extra';
|
||||
import { join } from 'path';
|
||||
import * as path from 'path';
|
||||
import { createApp, App, defineComponent, ref, reactive } from 'vue';
|
||||
import { CodeGenerator } from '../../CodeGenerator';
|
||||
|
||||
const panelDataMap = new WeakMap<any, App>();
|
||||
|
||||
module.exports = Editor.Panel.define({
|
||||
listeners: {
|
||||
show() { },
|
||||
hide() { },
|
||||
},
|
||||
template: `<div id="app"></div>`,
|
||||
style: readFileSync(join(__dirname, '../../../static/style/generator/index.css'), 'utf-8'),
|
||||
$: {
|
||||
app: '#app',
|
||||
},
|
||||
ready() {
|
||||
if (this.$.app) {
|
||||
const app = createApp(defineComponent({
|
||||
setup() {
|
||||
const featureName = ref('');
|
||||
const options = reactive({
|
||||
generateComponent: true,
|
||||
generateSystem: false
|
||||
});
|
||||
|
||||
// 组件选项
|
||||
const componentOptions = reactive({
|
||||
includeComments: true,
|
||||
addProperties: []
|
||||
});
|
||||
|
||||
// 系统选项
|
||||
const systemOptions = reactive({
|
||||
systemType: 'EntitySystem' as 'EntitySystem' | 'ProcessingSystem' | 'IntervalSystem' | 'PassiveSystem',
|
||||
includeComments: true,
|
||||
requiredComponents: [],
|
||||
filterByComponent: true
|
||||
});
|
||||
|
||||
// 系统类型定义
|
||||
const systemTypes = [
|
||||
{
|
||||
value: 'EntitySystem',
|
||||
name: 'EntitySystem',
|
||||
icon: '🔄',
|
||||
description: '批量处理实体,适合需要遍历多个实体的逻辑',
|
||||
usage: '适用场景:移动系统、渲染系统、物理碰撞系统'
|
||||
},
|
||||
{
|
||||
value: 'ProcessingSystem',
|
||||
name: 'ProcessingSystem',
|
||||
icon: '⚡',
|
||||
description: '执行全局逻辑,不依赖特定实体',
|
||||
usage: '适用场景:输入处理、音效管理、场景切换'
|
||||
},
|
||||
{
|
||||
value: 'IntervalSystem',
|
||||
name: 'IntervalSystem',
|
||||
icon: '⏰',
|
||||
description: '按时间间隔执行,可控制执行频率',
|
||||
usage: '适用场景:AI决策、状态保存、定时清理'
|
||||
},
|
||||
{
|
||||
value: 'PassiveSystem',
|
||||
name: 'PassiveSystem',
|
||||
icon: '🎯',
|
||||
description: '被动响应,需要手动调用或事件触发',
|
||||
usage: '适用场景:技能释放、道具使用、特殊效果'
|
||||
}
|
||||
];
|
||||
|
||||
const isGenerating = ref(false);
|
||||
const previewCode = ref('');
|
||||
const showPreview = ref(false);
|
||||
|
||||
// 选择系统类型
|
||||
const selectSystemType = (type: string) => {
|
||||
systemOptions.systemType = type as any;
|
||||
updatePreview();
|
||||
};
|
||||
|
||||
// 生成代码
|
||||
const generateCode = async () => {
|
||||
if (!featureName.value.trim()) {
|
||||
Editor.Dialog.warn('请输入功能名称', {
|
||||
detail: '请先输入一个有效的功能名称,例如:Health、Movement、Combat等'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!options.generateComponent && !options.generateSystem) {
|
||||
Editor.Dialog.warn('请选择生成内容', {
|
||||
detail: '请至少选择一种要生成的代码类型(组件或系统)'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
isGenerating.value = true;
|
||||
|
||||
try {
|
||||
const projectPath = Editor.Project.path;
|
||||
const ecsDir = path.join(projectPath, 'assets', 'scripts', 'ecs');
|
||||
|
||||
// 检查ECS目录是否存在
|
||||
const fs = require('fs');
|
||||
if (!fs.existsSync(ecsDir)) {
|
||||
Editor.Dialog.warn('ECS目录不存在', {
|
||||
detail: '请先创建ECS模板后再生成代码。\n\n您可以在欢迎面板中点击"创建ECS模板"来创建基础结构。',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const codeGenerator = new CodeGenerator();
|
||||
const generatedFiles: string[] = [];
|
||||
const baseName = featureName.value.trim();
|
||||
|
||||
// 生成组件
|
||||
if (options.generateComponent) {
|
||||
const componentDir = path.join(ecsDir, 'components');
|
||||
await codeGenerator.generateComponent(baseName, componentDir, componentOptions);
|
||||
generatedFiles.push(`📦 组件: ${baseName}Component.ts`);
|
||||
}
|
||||
|
||||
// 生成系统
|
||||
if (options.generateSystem) {
|
||||
const systemDir = path.join(ecsDir, 'systems');
|
||||
// 如果选择了组件过滤且生成了组件,自动添加组件过滤
|
||||
const requiredComponents = (systemOptions.filterByComponent && options.generateComponent) ?
|
||||
[`${baseName}Component`] : [];
|
||||
|
||||
const systemOpts = {
|
||||
...systemOptions,
|
||||
requiredComponents
|
||||
};
|
||||
|
||||
await codeGenerator.generateSystem(
|
||||
baseName,
|
||||
systemDir,
|
||||
systemOpts
|
||||
);
|
||||
generatedFiles.push(`⚙️ 系统: ${baseName}System.ts`);
|
||||
}
|
||||
|
||||
// 成功提示
|
||||
Editor.Dialog.info('代码生成成功', {
|
||||
detail: `✅ ${baseName} 功能代码已生成完成!\n\n生成的文件:\n${generatedFiles.join('\n')}\n\n请刷新资源管理器查看新创建的文件。`
|
||||
});
|
||||
|
||||
// 清空输入
|
||||
featureName.value = '';
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to generate code:', error);
|
||||
Editor.Dialog.error('代码生成失败', {
|
||||
detail: `生成代码时发生错误:\n\n${error}`
|
||||
});
|
||||
} finally {
|
||||
isGenerating.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 预览代码
|
||||
const previewGeneration = () => {
|
||||
if (!featureName.value.trim()) {
|
||||
showPreview.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const baseName = featureName.value.trim();
|
||||
let preview = `将要生成的文件:\n\n`;
|
||||
|
||||
if (options.generateComponent) {
|
||||
preview += `📦 组件: ${baseName}Component.ts\n`;
|
||||
preview += ` - 位置: assets/scripts/ecs/components/\n`;
|
||||
preview += ` - 基础组件模板\n\n`;
|
||||
}
|
||||
|
||||
if (options.generateSystem) {
|
||||
const selectedType = systemTypes.find(t => t.value === systemOptions.systemType);
|
||||
preview += `⚙️ 系统: ${baseName}System.ts\n`;
|
||||
preview += ` - 位置: assets/scripts/ecs/systems/\n`;
|
||||
preview += ` - 类型: ${selectedType?.name || systemOptions.systemType}\n`;
|
||||
|
||||
if (systemOptions.filterByComponent && options.generateComponent) {
|
||||
preview += ` - 过滤组件: ${baseName}Component\n`;
|
||||
} else if (systemOptions.filterByComponent) {
|
||||
preview += ` - 组件过滤: 需要手动配置\n`;
|
||||
} else {
|
||||
preview += ` - 组件过滤: 无\n`;
|
||||
}
|
||||
preview += `\n`;
|
||||
}
|
||||
|
||||
previewCode.value = preview;
|
||||
showPreview.value = true;
|
||||
};
|
||||
|
||||
// 监听功能名称变化
|
||||
const updatePreview = () => {
|
||||
if (featureName.value.trim()) {
|
||||
previewGeneration();
|
||||
} else {
|
||||
showPreview.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
featureName,
|
||||
options,
|
||||
componentOptions,
|
||||
systemOptions,
|
||||
systemTypes,
|
||||
isGenerating,
|
||||
previewCode,
|
||||
showPreview,
|
||||
generateCode,
|
||||
updatePreview,
|
||||
selectSystemType
|
||||
};
|
||||
},
|
||||
template: readFileSync(join(__dirname, '../../../static/template/generator/index.html'), 'utf-8')
|
||||
}));
|
||||
|
||||
app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('ui-');
|
||||
app.mount(this.$.app);
|
||||
panelDataMap.set(this, app);
|
||||
}
|
||||
},
|
||||
beforeClose() { },
|
||||
close() {
|
||||
const app = panelDataMap.get(this);
|
||||
if (app) {
|
||||
app.unmount();
|
||||
panelDataMap.delete(this);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1,370 +0,0 @@
|
||||
import { readFileSync } from 'fs-extra';
|
||||
import { join } from 'path';
|
||||
import { createApp, App, defineComponent, ref, onMounted, reactive } from 'vue';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const panelDataMap = new WeakMap<any, App>();
|
||||
|
||||
/**
|
||||
* ECS框架设置配置接口
|
||||
*/
|
||||
interface ECSSettings {
|
||||
// 代码生成设置
|
||||
codeGeneration: {
|
||||
template: 'typescript' | 'javascript';
|
||||
useStrictMode: boolean;
|
||||
generateComments: boolean;
|
||||
generateImports: boolean;
|
||||
componentSuffix: string;
|
||||
systemSuffix: string;
|
||||
indentStyle: 'spaces' | 'tabs';
|
||||
indentSize: number;
|
||||
};
|
||||
|
||||
// 性能监控设置
|
||||
performance: {
|
||||
enableMonitoring: boolean;
|
||||
warningThreshold: number; // 执行时间警告阈值(ms)
|
||||
criticalThreshold: number; // 执行时间严重阈值(ms)
|
||||
memoryWarningMB: number; // 内存警告阈值(MB)
|
||||
memoryCriticalMB: number; // 内存严重阈值(MB)
|
||||
maxRecentSamples: number; // 性能采样数量
|
||||
enableFpsMonitoring: boolean;
|
||||
targetFps: number;
|
||||
};
|
||||
|
||||
// 调试设置
|
||||
debugging: {
|
||||
enableDebugMode: boolean;
|
||||
showEntityCount: boolean;
|
||||
showSystemExecutionTime: boolean;
|
||||
enablePerformanceWarnings: boolean;
|
||||
logLevel: 'none' | 'error' | 'warn' | 'info' | 'debug';
|
||||
enableDetailedLogs: boolean;
|
||||
};
|
||||
|
||||
// 编辑器集成
|
||||
editor: {
|
||||
autoRefreshAssets: boolean;
|
||||
showWelcomePanelOnStartup: boolean;
|
||||
enableAutoUpdates: boolean;
|
||||
updateChannel: 'stable' | 'beta' | 'alpha';
|
||||
enableNotifications: boolean;
|
||||
};
|
||||
|
||||
// 项目模板设置
|
||||
template: {
|
||||
defaultEntityName: string;
|
||||
defaultComponentName: string;
|
||||
defaultSystemName: string;
|
||||
createExampleFiles: boolean;
|
||||
includeDocumentation: boolean;
|
||||
useFactoryPattern: boolean;
|
||||
};
|
||||
|
||||
// 事件系统设置
|
||||
events: {
|
||||
enableEventSystem: boolean;
|
||||
defaultEventPriority: number;
|
||||
enableAsyncEvents: boolean;
|
||||
enableEventBatching: boolean;
|
||||
batchSize: number;
|
||||
batchDelay: number; // ms
|
||||
maxEventListeners: number;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认设置
|
||||
*/
|
||||
const defaultSettings: ECSSettings = {
|
||||
codeGeneration: {
|
||||
template: 'typescript',
|
||||
useStrictMode: true,
|
||||
generateComments: true,
|
||||
generateImports: true,
|
||||
componentSuffix: 'Component',
|
||||
systemSuffix: 'System',
|
||||
indentStyle: 'spaces',
|
||||
indentSize: 4
|
||||
},
|
||||
performance: {
|
||||
enableMonitoring: true,
|
||||
warningThreshold: 16.67, // 60fps
|
||||
criticalThreshold: 33.33, // 30fps
|
||||
memoryWarningMB: 100,
|
||||
memoryCriticalMB: 200,
|
||||
maxRecentSamples: 60,
|
||||
enableFpsMonitoring: true,
|
||||
targetFps: 60
|
||||
},
|
||||
debugging: {
|
||||
enableDebugMode: true,
|
||||
showEntityCount: true,
|
||||
showSystemExecutionTime: true,
|
||||
enablePerformanceWarnings: true,
|
||||
logLevel: 'info',
|
||||
enableDetailedLogs: false
|
||||
},
|
||||
editor: {
|
||||
autoRefreshAssets: true,
|
||||
showWelcomePanelOnStartup: true,
|
||||
enableAutoUpdates: false,
|
||||
updateChannel: 'stable',
|
||||
enableNotifications: true
|
||||
},
|
||||
template: {
|
||||
defaultEntityName: 'GameEntity',
|
||||
defaultComponentName: 'CustomComponent',
|
||||
defaultSystemName: 'CustomSystem',
|
||||
createExampleFiles: true,
|
||||
includeDocumentation: true,
|
||||
useFactoryPattern: true
|
||||
},
|
||||
events: {
|
||||
enableEventSystem: true,
|
||||
defaultEventPriority: 0,
|
||||
enableAsyncEvents: true,
|
||||
enableEventBatching: false,
|
||||
batchSize: 10,
|
||||
batchDelay: 16,
|
||||
maxEventListeners: 100
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取设置文件路径
|
||||
*/
|
||||
function getSettingsPath(): string {
|
||||
const projectPath = Editor.Project.path;
|
||||
return path.join(projectPath, '.ecs-framework-settings.json');
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载设置
|
||||
*/
|
||||
function loadSettings(): ECSSettings {
|
||||
try {
|
||||
const settingsPath = getSettingsPath();
|
||||
if (fs.existsSync(settingsPath)) {
|
||||
const data = fs.readFileSync(settingsPath, 'utf-8');
|
||||
const loadedSettings = JSON.parse(data);
|
||||
// 合并默认设置,确保所有字段都存在
|
||||
return deepMerge(defaultSettings, loadedSettings);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to load ECS settings:', error);
|
||||
}
|
||||
return JSON.parse(JSON.stringify(defaultSettings));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存设置
|
||||
*/
|
||||
function saveSettings(settings: ECSSettings): boolean {
|
||||
try {
|
||||
const settingsPath = getSettingsPath();
|
||||
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to save ECS settings:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 深度合并对象
|
||||
*/
|
||||
function deepMerge(target: any, source: any): any {
|
||||
if (source === null || typeof source !== 'object') return source;
|
||||
if (target === null || typeof target !== 'object') return source;
|
||||
|
||||
const result = { ...target };
|
||||
|
||||
for (const key in source) {
|
||||
if (source.hasOwnProperty(key)) {
|
||||
if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
|
||||
result[key] = deepMerge(target[key], source[key]);
|
||||
} else {
|
||||
result[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置为默认设置
|
||||
*/
|
||||
function resetToDefaults(): ECSSettings {
|
||||
return JSON.parse(JSON.stringify(defaultSettings));
|
||||
}
|
||||
|
||||
module.exports = Editor.Panel.define({
|
||||
listeners: {
|
||||
show() { console.log('ECS Settings Panel Show'); },
|
||||
hide() { console.log('ECS Settings Panel Hide'); },
|
||||
},
|
||||
template: `<div id="app"></div>`,
|
||||
style: readFileSync(join(__dirname, '../../../static/style/settings/index.css'), 'utf-8'),
|
||||
$: {
|
||||
app: '#app',
|
||||
},
|
||||
ready() {
|
||||
if (this.$.app) {
|
||||
// 不要直接设置HTML内容,让Vue来处理
|
||||
const app = createApp(defineComponent({
|
||||
setup() {
|
||||
const settings = reactive(loadSettings());
|
||||
const isDirty = ref(false);
|
||||
const saving = ref(false);
|
||||
const lastSaved = ref('');
|
||||
|
||||
// 监听设置变化
|
||||
const markDirty = () => {
|
||||
isDirty.value = true;
|
||||
};
|
||||
|
||||
// 保存设置
|
||||
const saveCurrentSettings = async () => {
|
||||
saving.value = true;
|
||||
try {
|
||||
const success = saveSettings(settings);
|
||||
if (success) {
|
||||
isDirty.value = false;
|
||||
lastSaved.value = new Date().toLocaleTimeString();
|
||||
|
||||
// 通知主进程设置已更新
|
||||
Editor.Message.send('cocos-ecs-extension', 'settings-updated', settings);
|
||||
|
||||
Editor.Dialog.info('设置保存', {
|
||||
detail: '✅ ECS框架设置已成功保存!',
|
||||
});
|
||||
} else {
|
||||
Editor.Dialog.error('保存失败', {
|
||||
detail: '❌ 保存设置时发生错误,请检查文件权限。',
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Save settings error:', error);
|
||||
Editor.Dialog.error('保存失败', {
|
||||
detail: `❌ 保存设置时发生错误:\n\n${error}`,
|
||||
});
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 重置设置
|
||||
const resetSettings = () => {
|
||||
Editor.Dialog.warn('重置设置', {
|
||||
detail: '⚠️ 您确定要重置所有设置为默认值吗?\n\n此操作无法撤销。',
|
||||
buttons: ['重置', '取消'],
|
||||
}).then((result: any) => {
|
||||
if (result.response === 0) {
|
||||
const defaults = resetToDefaults();
|
||||
Object.assign(settings, defaults);
|
||||
isDirty.value = true;
|
||||
|
||||
Editor.Dialog.info('设置重置', {
|
||||
detail: '✅ 设置已重置为默认值,请点击保存按钮确认更改。',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 导出设置
|
||||
const exportSettings = () => {
|
||||
try {
|
||||
const dataStr = JSON.stringify(settings, null, 2);
|
||||
const blob = new Blob([dataStr], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
// 创建下载链接
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'ecs-framework-settings.json';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
Editor.Dialog.info('导出成功', {
|
||||
detail: '✅ 设置已导出到下载文件夹。',
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Export settings error:', error);
|
||||
Editor.Dialog.error('导出失败', {
|
||||
detail: `❌ 导出设置时发生错误:\n\n${error}`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 导入设置
|
||||
const importSettings = () => {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.accept = '.json';
|
||||
input.style.display = 'none';
|
||||
|
||||
input.onchange = (e: any) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = (event) => {
|
||||
try {
|
||||
const importedSettings = JSON.parse(event.target?.result as string);
|
||||
const mergedSettings = deepMerge(defaultSettings, importedSettings);
|
||||
Object.assign(settings, mergedSettings);
|
||||
isDirty.value = true;
|
||||
|
||||
Editor.Dialog.info('导入成功', {
|
||||
detail: '✅ 设置已导入,请检查并保存。',
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Import settings error:', error);
|
||||
Editor.Dialog.error('导入失败', {
|
||||
detail: `❌ 导入设置文件时发生错误:\n\n${error}\n\n请确保文件格式正确。`,
|
||||
});
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
};
|
||||
|
||||
document.body.appendChild(input);
|
||||
input.click();
|
||||
document.body.removeChild(input);
|
||||
};
|
||||
|
||||
return {
|
||||
settings,
|
||||
isDirty,
|
||||
saving,
|
||||
lastSaved,
|
||||
markDirty,
|
||||
saveCurrentSettings,
|
||||
resetSettings,
|
||||
exportSettings,
|
||||
importSettings
|
||||
};
|
||||
},
|
||||
template: readFileSync(join(__dirname, '../../../static/template/settings/index.html'), 'utf-8'),
|
||||
}));
|
||||
|
||||
app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('ui-');
|
||||
app.mount(this.$.app);
|
||||
panelDataMap.set(this, app);
|
||||
}
|
||||
},
|
||||
beforeClose() { },
|
||||
close() {
|
||||
const app = panelDataMap.get(this);
|
||||
if (app) {
|
||||
app.unmount();
|
||||
panelDataMap.delete(this);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -356,7 +356,41 @@
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* 响应式布局优化 */
|
||||
/* action-card样式 */
|
||||
.action-card.special {
|
||||
background: linear-gradient(135deg, var(--color-primary-fill) 0%, var(--color-focus-fill) 100%);
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.action-card.special h3 {
|
||||
color: var(--color-primary-contrast);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.action-card.special p {
|
||||
color: var(--color-primary-contrast);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.action-card.special:hover {
|
||||
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-focus-border) 100%);
|
||||
border-color: var(--color-focus-border);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.action-card.special .icon {
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.1); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
/* 响应式布局 */
|
||||
@media (max-width: 600px) {
|
||||
.welcome-container {
|
||||
padding: 16px;
|
||||
@@ -377,7 +411,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 确保按钮文本不被截断 */
|
||||
.management-buttons ui-button {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -0,0 +1,378 @@
|
||||
/* ECS代码生成器样式 */
|
||||
.ecs-generator {
|
||||
height: 100%;
|
||||
background: var(--color-panel-bg);
|
||||
color: var(--color-text-normal);
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.generator-container {
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 头部样式 */
|
||||
.generator-header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
padding: 16px;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 16px;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.generator-header h1 {
|
||||
margin: 0 0 6px 0;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.generator-header p {
|
||||
margin: 0;
|
||||
opacity: 0.9;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* 表单区域 */
|
||||
.generator-form {
|
||||
background: var(--color-area-bg);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 6px;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.form-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 16px;
|
||||
color: var(--color-text-normal);
|
||||
}
|
||||
|
||||
/* 输入字段 */
|
||||
.input-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-normal);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.feature-input {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 4px;
|
||||
background: var(--color-panel-bg);
|
||||
color: var(--color-text-normal);
|
||||
box-sizing: border-box;
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.feature-input:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.input-hint {
|
||||
margin-top: 6px;
|
||||
font-size: 12px;
|
||||
color: var(--color-text-contrast-weakest);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* 选项组 */
|
||||
.options-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.option-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.option-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* 复选框样式 */
|
||||
.checkbox-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.checkbox-wrapper input[type="checkbox"] {
|
||||
margin-right: 8px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.option-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-normal);
|
||||
}
|
||||
|
||||
.option-description {
|
||||
margin-left: 24px;
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--color-text-contrast-weakest);
|
||||
}
|
||||
|
||||
/* 系统配置区域 */
|
||||
.system-config {
|
||||
margin-top: 16px;
|
||||
padding: 16px;
|
||||
background: var(--color-panel-bg);
|
||||
border: 1px solid var(--color-border-soft);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.config-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.config-section:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.config-label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-normal);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.filter-option {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* 系统类型卡片 */
|
||||
.system-type-cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.system-card {
|
||||
padding: 16px;
|
||||
border: 2px solid var(--color-border);
|
||||
border-radius: 8px;
|
||||
background: var(--color-area-bg);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.system-card:hover {
|
||||
border-color: #667eea;
|
||||
background: var(--color-panel-bg);
|
||||
}
|
||||
|
||||
.system-card.active {
|
||||
border-color: #667eea;
|
||||
background: var(--color-panel-bg);
|
||||
box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.system-card.active::after {
|
||||
content: '✓';
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 12px;
|
||||
color: #667eea;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
font-size: 20px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-normal);
|
||||
}
|
||||
|
||||
.card-description {
|
||||
font-size: 13px;
|
||||
color: var(--color-text-contrast-weak);
|
||||
margin-bottom: 6px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.card-usage {
|
||||
font-size: 12px;
|
||||
color: var(--color-text-contrast-weakest);
|
||||
font-style: italic;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* 系统类型选择 */
|
||||
.system-type-group {
|
||||
margin-left: 24px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.system-type-select {
|
||||
padding: 6px 8px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 4px;
|
||||
background: var(--color-panel-bg);
|
||||
color: var(--color-text-normal);
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 预览区域 */
|
||||
.preview-section {
|
||||
background: var(--color-area-bg);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 6px;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
flex: 1;
|
||||
min-height: 200px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.preview-title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
color: var(--color-text-normal);
|
||||
}
|
||||
|
||||
.preview-content {
|
||||
flex: 1;
|
||||
background: var(--color-panel-bg);
|
||||
border: 1px solid var(--color-border-soft);
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
color: var(--color-text-contrast-weak);
|
||||
overflow-y: auto;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* 操作按钮区域 */
|
||||
.action-section {
|
||||
background: var(--color-area-bg);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 6px;
|
||||
padding: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.generate-btn {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.generate-btn:hover:not(:disabled) {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.generate-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.btn-icon.spinning {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* 滚动条样式 */
|
||||
.generator-container::-webkit-scrollbar,
|
||||
.preview-content::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.generator-container::-webkit-scrollbar-track,
|
||||
.preview-content::-webkit-scrollbar-track {
|
||||
background: var(--color-area-bg);
|
||||
}
|
||||
|
||||
.generator-container::-webkit-scrollbar-thumb,
|
||||
.preview-content::-webkit-scrollbar-thumb {
|
||||
background: var(--color-border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.generator-container::-webkit-scrollbar-thumb:hover,
|
||||
.preview-content::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--color-border-emphasis);
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 600px) {
|
||||
.generator-container {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.generator-header h1 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.feature-input {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,353 +0,0 @@
|
||||
/* ECS Framework 设置面板样式 */
|
||||
.settings-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--color-normal-fill);
|
||||
font-family: var(--font-family);
|
||||
}
|
||||
|
||||
/* 头部样式 */
|
||||
.settings-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
padding: 16px 20px;
|
||||
background: var(--color-info-fill);
|
||||
border-bottom: 1px solid var(--color-normal-border);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.header-title h1 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--color-default-text);
|
||||
}
|
||||
|
||||
.header-title p {
|
||||
margin: 4px 0 0 0;
|
||||
font-size: 12px;
|
||||
color: var(--color-focus-text);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.header-actions ui-button {
|
||||
min-width: 80px;
|
||||
height: 28px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* 保存按钮状态 */
|
||||
.save-button.dirty {
|
||||
background: var(--color-warn-fill) !important;
|
||||
border-color: var(--color-warn-border) !important;
|
||||
color: var(--color-warn-text) !important;
|
||||
}
|
||||
|
||||
.save-button.saving {
|
||||
background: var(--color-info-fill) !important;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* 图标动画 */
|
||||
.spin {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* 状态栏 */
|
||||
.status-bar {
|
||||
padding: 8px 20px;
|
||||
background: var(--color-success-fill);
|
||||
border-bottom: 1px solid var(--color-normal-border);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 12px;
|
||||
color: var(--color-success-text);
|
||||
}
|
||||
|
||||
/* 设置内容区域 */
|
||||
.settings-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding: 0 20px 20px 20px;
|
||||
max-height: calc(100vh - 140px); /* 确保有固定的滚动区域 */
|
||||
scroll-behavior: smooth; /* 平滑滚动 */
|
||||
}
|
||||
|
||||
/* 设置分组 */
|
||||
.settings-section {
|
||||
margin-bottom: 32px;
|
||||
background: var(--color-default-fill);
|
||||
border: 1px solid var(--color-normal-border);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
padding: 16px 20px;
|
||||
background: var(--color-focus-fill);
|
||||
border-bottom: 1px solid var(--color-normal-border);
|
||||
}
|
||||
|
||||
.section-header h2 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--color-default-text);
|
||||
}
|
||||
|
||||
.section-header p {
|
||||
margin: 4px 0 0 0;
|
||||
font-size: 12px;
|
||||
color: var(--color-focus-text);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 设置网格 */
|
||||
.settings-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 16px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* 设置项 */
|
||||
.setting-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.setting-item label {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--color-default-text);
|
||||
}
|
||||
|
||||
.setting-item ui-input,
|
||||
.setting-item ui-select,
|
||||
.setting-item ui-num-input {
|
||||
width: 100%;
|
||||
height: 26px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* 复选框项样式 */
|
||||
.checkbox-item {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.checkbox-item ui-checkbox {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 全宽设置项 */
|
||||
.setting-item.full-width {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
/* 底部区域 */
|
||||
.settings-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 20px;
|
||||
background: var(--color-focus-fill);
|
||||
border-top: 1px solid var(--color-normal-border);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.footer-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 11px;
|
||||
color: var(--color-focus-text);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.footer-info ui-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.footer-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dirty-indicator {
|
||||
font-size: 11px;
|
||||
color: var(--color-warn-text);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.settings-header {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.settings-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.settings-footer {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: stretch;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* 深色主题支持 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.settings-container {
|
||||
background: #2c2c2c;
|
||||
}
|
||||
|
||||
.settings-section {
|
||||
background: #3c3c3c;
|
||||
border-color: #555;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
background: #404040;
|
||||
border-color: #555;
|
||||
}
|
||||
|
||||
.settings-header {
|
||||
background: #333;
|
||||
border-color: #555;
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
background: #2d5a2d;
|
||||
}
|
||||
|
||||
.settings-footer {
|
||||
background: #333;
|
||||
border-color: #555;
|
||||
}
|
||||
}
|
||||
|
||||
/* 优化滚动条样式 */
|
||||
.settings-content::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.settings-content::-webkit-scrollbar-track {
|
||||
background: var(--color-normal-fill);
|
||||
border-radius: 5px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.settings-content::-webkit-scrollbar-thumb {
|
||||
background: var(--color-focus-border);
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.2s ease;
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.settings-content::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--color-warn-border);
|
||||
}
|
||||
|
||||
.settings-content::-webkit-scrollbar-thumb:active {
|
||||
background: var(--color-danger-border);
|
||||
}
|
||||
|
||||
/* 表单元素统一样式 */
|
||||
.setting-item ui-input,
|
||||
.setting-item ui-select,
|
||||
.setting-item ui-num-input {
|
||||
border: 1px solid var(--color-normal-border);
|
||||
border-radius: 4px;
|
||||
padding: 4px 8px;
|
||||
background: var(--color-default-fill);
|
||||
color: var(--color-default-text);
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.setting-item ui-input:focus,
|
||||
.setting-item ui-select:focus,
|
||||
.setting-item ui-num-input:focus {
|
||||
border-color: var(--color-focus-border);
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
/* 复选框样式 */
|
||||
.setting-item ui-checkbox {
|
||||
font-size: 12px;
|
||||
color: var(--color-default-text);
|
||||
}
|
||||
|
||||
/* 按钮样式覆盖 */
|
||||
.header-actions .export-button {
|
||||
background: var(--color-info-fill);
|
||||
border-color: var(--color-info-border);
|
||||
color: var(--color-info-text);
|
||||
}
|
||||
|
||||
.header-actions .import-button {
|
||||
background: var(--color-warn-fill);
|
||||
border-color: var(--color-warn-border);
|
||||
color: var(--color-warn-text);
|
||||
}
|
||||
|
||||
.header-actions .reset-button {
|
||||
background: var(--color-danger-fill);
|
||||
border-color: var(--color-danger-border);
|
||||
color: var(--color-danger-text);
|
||||
}
|
||||
|
||||
/* 工具提示样式 */
|
||||
.setting-item[title] {
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* 加载状态 */
|
||||
.loading-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 3px solid var(--color-normal-border);
|
||||
border-top: 3px solid var(--color-focus-border);
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<div class="ecs-generator">
|
||||
<div class="generator-container">
|
||||
<!-- 头部区域 -->
|
||||
<div class="generator-header">
|
||||
<h1>🛠️ ECS 代码生成器</h1>
|
||||
<p>输入功能名称,快速生成组件和系统代码</p>
|
||||
</div>
|
||||
|
||||
<!-- 表单区域 -->
|
||||
<div class="generator-form">
|
||||
<div class="form-title">📝 基础设置</div>
|
||||
|
||||
<!-- 功能名称输入 -->
|
||||
<div class="input-group">
|
||||
<label class="input-label">功能名称</label>
|
||||
<input
|
||||
v-model="featureName"
|
||||
@input="updatePreview"
|
||||
type="text"
|
||||
class="feature-input"
|
||||
placeholder="例如:Health、Movement、Combat"
|
||||
maxlength="50"
|
||||
/>
|
||||
<div class="input-hint">
|
||||
💡 使用英文名称,首字母大写,例如:Health、Movement、Combat
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 生成选项 -->
|
||||
<div class="options-group">
|
||||
<label class="input-label">生成内容</label>
|
||||
|
||||
<div class="option-item">
|
||||
<label class="checkbox-wrapper">
|
||||
<input type="checkbox" v-model="options.generateComponent" @change="updatePreview">
|
||||
<span class="option-title">📦 生成组件 (Component)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="option-description" v-if="options.generateComponent">
|
||||
创建基础组件类,包含reset()方法和基本结构
|
||||
</div>
|
||||
|
||||
<div class="option-item">
|
||||
<label class="checkbox-wrapper">
|
||||
<input type="checkbox" v-model="options.generateSystem" @change="updatePreview">
|
||||
<span class="option-title">⚙️ 生成系统 (System)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="option-description" v-if="options.generateSystem">
|
||||
创建处理组件的系统类,包含完整的生命周期方法
|
||||
</div>
|
||||
|
||||
<!-- 系统详细配置 -->
|
||||
<div class="system-config" v-if="options.generateSystem">
|
||||
<!-- 组件过滤选项 -->
|
||||
<div class="config-section">
|
||||
<label class="config-label">🔍 组件过滤</label>
|
||||
<div class="filter-option">
|
||||
<label class="checkbox-wrapper">
|
||||
<input type="checkbox" v-model="systemOptions.filterByComponent" @change="updatePreview">
|
||||
<span class="option-title">过滤包含组件的实体</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="option-description" v-if="systemOptions.filterByComponent">
|
||||
系统只处理包含指定组件的实体。如果勾选了"生成组件",会自动过滤{{featureName}}Component
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 系统类型选择 -->
|
||||
<div class="config-section">
|
||||
<label class="config-label">🎯 系统类型</label>
|
||||
<div class="system-type-cards">
|
||||
<div
|
||||
v-for="type in systemTypes"
|
||||
:key="type.value"
|
||||
class="system-card"
|
||||
:class="{ active: systemOptions.systemType === type.value }"
|
||||
@click="selectSystemType(type.value)">
|
||||
<div class="card-header">
|
||||
<span class="card-icon">{{ type.icon }}</span>
|
||||
<span class="card-title">{{ type.name }}</span>
|
||||
</div>
|
||||
<div class="card-description">{{ type.description }}</div>
|
||||
<div class="card-usage">{{ type.usage }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 预览区域 -->
|
||||
<div class="preview-section" v-if="showPreview">
|
||||
<div class="preview-title">👀 生成预览</div>
|
||||
<div class="preview-content">{{ previewCode }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 生成按钮 -->
|
||||
<div class="action-section">
|
||||
<button
|
||||
class="generate-btn"
|
||||
:disabled="isGenerating || (!options.generateComponent && !options.generateSystem) || !featureName.trim()"
|
||||
@click="generateCode">
|
||||
<span class="btn-icon" :class="{ spinning: isGenerating }">
|
||||
{{ isGenerating ? '⏳' : '🚀' }}
|
||||
</span>
|
||||
{{ isGenerating ? '生成中...' : '生成代码' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,322 +0,0 @@
|
||||
<div id="app">
|
||||
<div class="settings-container">
|
||||
<!-- 头部 -->
|
||||
<div class="settings-header">
|
||||
<div class="header-title">
|
||||
<h1>🔧 ECS Framework 设置</h1>
|
||||
<p>配置ECS框架的行为和性能选项</p>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<ui-button class="save-button" :class="{ dirty: isDirty, saving: saving }"
|
||||
@click="saveCurrentSettings" :disabled="saving">
|
||||
<ui-icon value="confirm" v-if="!saving"></ui-icon>
|
||||
<ui-icon value="loading" class="spin" v-if="saving"></ui-icon>
|
||||
{{ saving ? '保存中...' : (isDirty ? '保存 *' : '保存') }}
|
||||
</ui-button>
|
||||
<ui-button class="export-button" @click="exportSettings">
|
||||
<ui-icon value="download"></ui-icon>
|
||||
导出
|
||||
</ui-button>
|
||||
<ui-button class="import-button" @click="importSettings">
|
||||
<ui-icon value="upload"></ui-icon>
|
||||
导入
|
||||
</ui-button>
|
||||
<ui-button class="reset-button" @click="resetSettings">
|
||||
<ui-icon value="reset"></ui-icon>
|
||||
重置
|
||||
</ui-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 状态栏 -->
|
||||
<div class="status-bar" v-if="lastSaved">
|
||||
<span class="status-text">最后保存: {{ lastSaved }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 设置内容 -->
|
||||
<div class="settings-content">
|
||||
<!-- 代码生成设置 -->
|
||||
<div class="settings-section">
|
||||
<div class="section-header">
|
||||
<h2>📝 代码生成设置</h2>
|
||||
<p>配置自动生成代码的格式和选项</p>
|
||||
</div>
|
||||
<div class="settings-grid">
|
||||
<div class="setting-item">
|
||||
<label>模板语言</label>
|
||||
<ui-select v-model="settings.codeGeneration.template" @change="markDirty">
|
||||
<option value="typescript">TypeScript</option>
|
||||
<option value="javascript">JavaScript</option>
|
||||
</ui-select>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>组件后缀</label>
|
||||
<ui-input v-model="settings.codeGeneration.componentSuffix"
|
||||
@change="markDirty" placeholder="Component"></ui-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>系统后缀</label>
|
||||
<ui-input v-model="settings.codeGeneration.systemSuffix"
|
||||
@change="markDirty" placeholder="System"></ui-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>缩进风格</label>
|
||||
<ui-select v-model="settings.codeGeneration.indentStyle" @change="markDirty">
|
||||
<option value="spaces">空格</option>
|
||||
<option value="tabs">制表符</option>
|
||||
</ui-select>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>缩进大小</label>
|
||||
<ui-num-input v-model="settings.codeGeneration.indentSize"
|
||||
@change="markDirty" :min="1" :max="8"></ui-num-input>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.codeGeneration.useStrictMode" @change="markDirty">
|
||||
启用严格模式
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.codeGeneration.generateComments" @change="markDirty">
|
||||
生成注释
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.codeGeneration.generateImports" @change="markDirty">
|
||||
自动添加导入语句
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 性能监控设置 -->
|
||||
<div class="settings-section">
|
||||
<div class="section-header">
|
||||
<h2>⚡ 性能监控设置</h2>
|
||||
<p>配置性能监控和优化建议</p>
|
||||
</div>
|
||||
<div class="settings-grid">
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.performance.enableMonitoring" @change="markDirty">
|
||||
启用性能监控
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.performance.enableFpsMonitoring" @change="markDirty">
|
||||
启用FPS监控
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>目标FPS</label>
|
||||
<ui-num-input v-model="settings.performance.targetFps"
|
||||
@change="markDirty" :min="30" :max="120"></ui-num-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>执行时间警告阈值 (ms)</label>
|
||||
<ui-num-input v-model="settings.performance.warningThreshold"
|
||||
@change="markDirty" :min="1" :max="100" :step="0.1"></ui-num-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>执行时间严重阈值 (ms)</label>
|
||||
<ui-num-input v-model="settings.performance.criticalThreshold"
|
||||
@change="markDirty" :min="1" :max="200" :step="0.1"></ui-num-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>内存警告阈值 (MB)</label>
|
||||
<ui-num-input v-model="settings.performance.memoryWarningMB"
|
||||
@change="markDirty" :min="10" :max="1000"></ui-num-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>内存严重阈值 (MB)</label>
|
||||
<ui-num-input v-model="settings.performance.memoryCriticalMB"
|
||||
@change="markDirty" :min="50" :max="2000"></ui-num-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>性能采样数量</label>
|
||||
<ui-num-input v-model="settings.performance.maxRecentSamples"
|
||||
@change="markDirty" :min="10" :max="300"></ui-num-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 调试设置 -->
|
||||
<div class="settings-section">
|
||||
<div class="section-header">
|
||||
<h2>🐛 调试设置</h2>
|
||||
<p>配置调试模式和日志选项</p>
|
||||
</div>
|
||||
<div class="settings-grid">
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.debugging.enableDebugMode" @change="markDirty">
|
||||
启用调试模式
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.debugging.showEntityCount" @change="markDirty">
|
||||
显示实体数量
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.debugging.showSystemExecutionTime" @change="markDirty">
|
||||
显示系统执行时间
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.debugging.enablePerformanceWarnings" @change="markDirty">
|
||||
启用性能警告
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.debugging.enableDetailedLogs" @change="markDirty">
|
||||
启用详细日志
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>日志级别</label>
|
||||
<ui-select v-model="settings.debugging.logLevel" @change="markDirty">
|
||||
<option value="none">无</option>
|
||||
<option value="error">错误</option>
|
||||
<option value="warn">警告</option>
|
||||
<option value="info">信息</option>
|
||||
<option value="debug">调试</option>
|
||||
</ui-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 编辑器集成设置 -->
|
||||
<div class="settings-section">
|
||||
<div class="section-header">
|
||||
<h2>⚙️ 编辑器集成</h2>
|
||||
<p>配置与Cocos Creator的集成选项</p>
|
||||
</div>
|
||||
<div class="settings-grid">
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.editor.autoRefreshAssets" @change="markDirty">
|
||||
自动刷新资源
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.editor.showWelcomePanelOnStartup" @change="markDirty">
|
||||
启动时显示欢迎面板
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.editor.enableAutoUpdates" @change="markDirty">
|
||||
启用自动更新
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.editor.enableNotifications" @change="markDirty">
|
||||
启用通知
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>更新频道</label>
|
||||
<ui-select v-model="settings.editor.updateChannel" @change="markDirty">
|
||||
<option value="stable">稳定版</option>
|
||||
<option value="beta">测试版</option>
|
||||
<option value="alpha">开发版</option>
|
||||
</ui-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 项目模板设置 -->
|
||||
<div class="settings-section">
|
||||
<div class="section-header">
|
||||
<h2>📁 项目模板设置</h2>
|
||||
<p>配置生成项目模板的默认选项</p>
|
||||
</div>
|
||||
<div class="settings-grid">
|
||||
<div class="setting-item">
|
||||
<label>默认实体名称</label>
|
||||
<ui-input v-model="settings.template.defaultEntityName"
|
||||
@change="markDirty" placeholder="GameEntity"></ui-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>默认组件名称</label>
|
||||
<ui-input v-model="settings.template.defaultComponentName"
|
||||
@change="markDirty" placeholder="CustomComponent"></ui-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>默认系统名称</label>
|
||||
<ui-input v-model="settings.template.defaultSystemName"
|
||||
@change="markDirty" placeholder="CustomSystem"></ui-input>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.template.createExampleFiles" @change="markDirty">
|
||||
创建示例文件
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.template.includeDocumentation" @change="markDirty">
|
||||
包含文档
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.template.useFactoryPattern" @change="markDirty">
|
||||
使用工厂模式
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 事件系统设置 -->
|
||||
<div class="settings-section">
|
||||
<div class="section-header">
|
||||
<h2>📡 事件系统设置</h2>
|
||||
<p>配置事件系统的行为和性能</p>
|
||||
</div>
|
||||
<div class="settings-grid">
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.events.enableEventSystem" @change="markDirty">
|
||||
启用事件系统
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.events.enableAsyncEvents" @change="markDirty">
|
||||
启用异步事件
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item checkbox-item">
|
||||
<ui-checkbox v-model="settings.events.enableEventBatching" @change="markDirty">
|
||||
启用事件批处理
|
||||
</ui-checkbox>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>默认事件优先级</label>
|
||||
<ui-num-input v-model="settings.events.defaultEventPriority"
|
||||
@change="markDirty" :min="-100" :max="100"></ui-num-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>批处理大小</label>
|
||||
<ui-num-input v-model="settings.events.batchSize"
|
||||
@change="markDirty" :min="1" :max="100"></ui-num-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>批处理延迟 (ms)</label>
|
||||
<ui-num-input v-model="settings.events.batchDelay"
|
||||
@change="markDirty" :min="1" :max="1000"></ui-num-input>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label>最大事件监听器数</label>
|
||||
<ui-num-input v-model="settings.events.maxEventListeners"
|
||||
@change="markDirty" :min="10" :max="1000"></ui-num-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部提示 -->
|
||||
<div class="settings-footer">
|
||||
<div class="footer-info">
|
||||
<ui-icon value="info"></ui-icon>
|
||||
<span>设置将保存到项目目录的 .ecs-framework-settings.json 文件中</span>
|
||||
</div>
|
||||
<div class="footer-actions">
|
||||
<span class="dirty-indicator" v-if="isDirty">● 有未保存的更改</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -100,7 +100,7 @@
|
||||
<p v-else>安装@esengine/ecs-framework到当前项目</p>
|
||||
</div>
|
||||
|
||||
<div class="action-card" :class="{ disabled: !ecsInstalled }" @click="openDocumentation">
|
||||
<div class="action-card" @click="openDocumentation">
|
||||
<h3>
|
||||
<span class="icon">📚</span>
|
||||
查看文档
|
||||
@@ -134,36 +134,29 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="action-card" @click="openSettings">
|
||||
<!-- 代码生成工具区域 -->
|
||||
<div class="actions-section" v-if="ecsInstalled">
|
||||
<div class="status-title">🛠️ 代码生成工具</div>
|
||||
|
||||
<div class="action-card special" @click="openGenerator">
|
||||
<h3>
|
||||
<span class="icon">⚙️</span>
|
||||
插件设置
|
||||
<span class="icon">🚀</span>
|
||||
代码生成器
|
||||
</h3>
|
||||
<p>配置ECS插件的各项设置和偏好</p>
|
||||
<p>一站式代码生成工具,输入功能名称快速生成组件和系统代码</p>
|
||||
</div>
|
||||
|
||||
<div class="action-card" @click="openProjectAnalysis">
|
||||
<h3>
|
||||
<span class="icon">📊</span>
|
||||
项目分析
|
||||
</h3>
|
||||
<p>分析当前项目的ECS使用情况和性能建议</p>
|
||||
</div>
|
||||
|
||||
<div class="action-card" @click="openComponentLibrary">
|
||||
<h3>
|
||||
<span class="icon">🧩</span>
|
||||
组件库
|
||||
</h3>
|
||||
<p>浏览和管理项目中的ECS组件</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部信息 -->
|
||||
<div class="footer">
|
||||
<p>ECS Framework Plugin v{{pluginVersion}} | 基于Vue 3.x构建</p>
|
||||
<p>更多信息请访问: <a href="#" @click="openGithub">GitHub Repository</a></p>
|
||||
<p>
|
||||
更多信息请访问: <a href="#" @click="openGithub">GitHub Repository</a> |
|
||||
<a href="#" @click="joinQQGroup">💬 加入QQ群交流</a>
|
||||
</p>
|
||||
<p v-if="lastCheckTime" class="last-check">最后检查时间: {{lastCheckTime}}</p>
|
||||
</div>
|
||||
</div>
|
||||
6
extensions/cocos/cocos-ecs/package-lock.json
generated
6
extensions/cocos/cocos-ecs/package-lock.json
generated
@@ -10,9 +10,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@esengine/ecs-framework": {
|
||||
"version": "2.1.19",
|
||||
"resolved": "https://registry.npmjs.org/@esengine/ecs-framework/-/ecs-framework-2.1.19.tgz",
|
||||
"integrity": "sha512-yS6g1Swdd/FvnIrdmaxBh6ml5r+Oh4edIhGwVfEbzQMHUmrZQbva7/NGyOhTsJ6qsIGVyNin8o46tTud2YCj4g==",
|
||||
"version": "2.1.20",
|
||||
"resolved": "https://registry.npmjs.org/@esengine/ecs-framework/-/ecs-framework-2.1.20.tgz",
|
||||
"integrity": "sha512-L6PJ1uoXIttzjYt66shZPdmJ4lU38SyqRnEcVJexcR+V6iyQ/U7H8yjvQjeTIlBb0u7JDBEC6a8B4Cr6VlsF9Q==",
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { ComponentPool } from '../ComponentPool';
|
||||
export { ComponentPool, ComponentPoolManager } from '../ComponentPool';
|
||||
export { ComponentStorage } from '../ComponentStorage';
|
||||
Reference in New Issue
Block a user