添加Cocos Creator ECS编辑器插件:完整的框架管理和模板生成功能

This commit is contained in:
YHH
2025-06-16 18:32:44 +08:00
parent d9ef0b587e
commit 103f773286
34 changed files with 3007 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
[InternetShortcut]
URL=https://docs.cocos.com/creator/manual/en/scripting/setup.html#custom-script-template

24
extensions/cocos/cocos-ecs/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
#///////////////////////////
# Cocos Creator 3D Project
#///////////////////////////
library/
temp/
local/
build/
profiles/
native
#//////////////////////////
# NPM
#//////////////////////////
node_modules/
#//////////////////////////
# VSCode
#//////////////////////////
.vscode/
#//////////////////////////
# WebStorm
#//////////////////////////
.idea/

View File

@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "e7a0c4c4-f555-4dc5-be34-83ae26b4eb35",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,434 @@
[
{
"__type__": "cc.SceneAsset",
"_name": "scene",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"scene": {
"__id__": 1
}
},
{
"__type__": "cc.Scene",
"_name": "scene",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [
{
"__id__": 2
},
{
"__id__": 5
}
],
"_active": true,
"_components": [],
"_prefab": null,
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"autoReleaseAssets": false,
"_globals": {
"__id__": 7
},
"_id": "ff354f0b-c2f5-4dea-8ffb-0152d175d11c"
},
{
"__type__": "cc.Node",
"_name": "Main Light",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 3
}
],
"_prefab": null,
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": -0.06397656665577071,
"y": -0.44608233363525845,
"z": -0.8239028751062036,
"w": -0.3436591377065261
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": -117.894,
"y": -194.909,
"z": 38.562
},
"_id": "c0y6F5f+pAvI805TdmxIjx"
},
{
"__type__": "cc.DirectionalLight",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": null,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 250,
"b": 240,
"a": 255
},
"_useColorTemperature": false,
"_colorTemperature": 6550,
"_staticSettings": {
"__id__": 4
},
"_visibility": -325058561,
"_illuminanceHDR": 65000,
"_illuminance": 65000,
"_illuminanceLDR": 1.6927083333333335,
"_shadowEnabled": false,
"_shadowPcf": 0,
"_shadowBias": 0.00001,
"_shadowNormalBias": 0,
"_shadowSaturation": 1,
"_shadowDistance": 50,
"_shadowInvisibleOcclusionRange": 200,
"_csmLevel": 4,
"_csmLayerLambda": 0.75,
"_csmOptimizationMode": 2,
"_csmAdvancedOptions": false,
"_csmLayersTransition": false,
"_csmTransitionRange": 0.05,
"_shadowFixedArea": false,
"_shadowNear": 0.1,
"_shadowFar": 10,
"_shadowOrthoSize": 5,
"_id": "597uMYCbhEtJQc0ffJlcgA"
},
{
"__type__": "cc.StaticLightSettings",
"_baked": false,
"_editorOnly": false,
"_castShadow": false
},
{
"__type__": "cc.Node",
"_name": "Main Camera",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 6
}
],
"_prefab": null,
"_lpos": {
"__type__": "cc.Vec3",
"x": -10,
"y": 10,
"z": 10
},
"_lrot": {
"__type__": "cc.Quat",
"x": -0.27781593346944056,
"y": -0.36497167621709875,
"z": -0.11507512748638377,
"w": 0.8811195706053617
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1073741824,
"_euler": {
"__type__": "cc.Vec3",
"x": -35,
"y": -45,
"z": 0
},
"_id": "c9DMICJLFO5IeO07EPon7U"
},
{
"__type__": "cc.Camera",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 5
},
"_enabled": true,
"__prefab": null,
"_projection": 1,
"_priority": 0,
"_fov": 45,
"_fovAxis": 0,
"_orthoHeight": 10,
"_near": 1,
"_far": 1000,
"_color": {
"__type__": "cc.Color",
"r": 51,
"g": 51,
"b": 51,
"a": 255
},
"_depth": 1,
"_stencil": 0,
"_clearFlags": 14,
"_rect": {
"__type__": "cc.Rect",
"x": 0,
"y": 0,
"width": 1,
"height": 1
},
"_aperture": 19,
"_shutter": 7,
"_iso": 0,
"_screenScale": 1,
"_visibility": 1822425087,
"_targetTexture": null,
"_postProcess": null,
"_usePostProcess": false,
"_cameraType": -1,
"_trackingType": 0,
"_id": "7dWQTpwS5LrIHnc1zAPUtf"
},
{
"__type__": "cc.SceneGlobals",
"ambient": {
"__id__": 8
},
"shadows": {
"__id__": 9
},
"_skybox": {
"__id__": 10
},
"fog": {
"__id__": 11
},
"octree": {
"__id__": 12
},
"skin": {
"__id__": 13
},
"lightProbeInfo": {
"__id__": 14
},
"postSettings": {
"__id__": 15
},
"bakedWithStationaryMainLight": false,
"bakedWithHighpLightmap": false
},
{
"__type__": "cc.AmbientInfo",
"_skyColorHDR": {
"__type__": "cc.Vec4",
"x": 0.2,
"y": 0.5,
"z": 0.8,
"w": 0.520833125
},
"_skyColor": {
"__type__": "cc.Vec4",
"x": 0.2,
"y": 0.5,
"z": 0.8,
"w": 0.520833125
},
"_skyIllumHDR": 20000,
"_skyIllum": 20000,
"_groundAlbedoHDR": {
"__type__": "cc.Vec4",
"x": 0.2,
"y": 0.2,
"z": 0.2,
"w": 1
},
"_groundAlbedo": {
"__type__": "cc.Vec4",
"x": 0.2,
"y": 0.2,
"z": 0.2,
"w": 1
},
"_skyColorLDR": {
"__type__": "cc.Vec4",
"x": 0.452588,
"y": 0.607642,
"z": 0.755699,
"w": 0
},
"_skyIllumLDR": 0.8,
"_groundAlbedoLDR": {
"__type__": "cc.Vec4",
"x": 0.618555,
"y": 0.577848,
"z": 0.544564,
"w": 0
}
},
{
"__type__": "cc.ShadowsInfo",
"_enabled": false,
"_type": 0,
"_normal": {
"__type__": "cc.Vec3",
"x": 0,
"y": 1,
"z": 0
},
"_distance": 0,
"_planeBias": 1,
"_shadowColor": {
"__type__": "cc.Color",
"r": 76,
"g": 76,
"b": 76,
"a": 255
},
"_maxReceived": 4,
"_size": {
"__type__": "cc.Vec2",
"x": 1024,
"y": 1024
}
},
{
"__type__": "cc.SkyboxInfo",
"_envLightingType": 0,
"_envmapHDR": {
"__uuid__": "d032ac98-05e1-4090-88bb-eb640dcb5fc1@b47c0",
"__expectedType__": "cc.TextureCube"
},
"_envmap": {
"__uuid__": "d032ac98-05e1-4090-88bb-eb640dcb5fc1@b47c0",
"__expectedType__": "cc.TextureCube"
},
"_envmapLDR": {
"__uuid__": "6f01cf7f-81bf-4a7e-bd5d-0afc19696480@b47c0",
"__expectedType__": "cc.TextureCube"
},
"_diffuseMapHDR": null,
"_diffuseMapLDR": null,
"_enabled": true,
"_useHDR": true,
"_editableMaterial": null,
"_reflectionHDR": null,
"_reflectionLDR": null,
"_rotationAngle": 0
},
{
"__type__": "cc.FogInfo",
"_type": 0,
"_fogColor": {
"__type__": "cc.Color",
"r": 200,
"g": 200,
"b": 200,
"a": 255
},
"_enabled": false,
"_fogDensity": 0.3,
"_fogStart": 0.5,
"_fogEnd": 300,
"_fogAtten": 5,
"_fogTop": 1.5,
"_fogRange": 1.2,
"_accurate": false
},
{
"__type__": "cc.OctreeInfo",
"_enabled": false,
"_minPos": {
"__type__": "cc.Vec3",
"x": -1024,
"y": -1024,
"z": -1024
},
"_maxPos": {
"__type__": "cc.Vec3",
"x": 1024,
"y": 1024,
"z": 1024
},
"_depth": 8
},
{
"__type__": "cc.SkinInfo",
"_enabled": true,
"_blurRadius": 0.01,
"_sssIntensity": 3
},
{
"__type__": "cc.LightProbeInfo",
"_giScale": 1,
"_giSamples": 1024,
"_bounces": 2,
"_reduceRinging": 0,
"_showProbe": true,
"_showWireframe": true,
"_showConvex": false,
"_data": null,
"_lightProbeSphereVolume": 1
},
{
"__type__": "cc.PostSettingsInfo",
"_toneMappingType": 0
}
]

View File

@@ -0,0 +1,11 @@
{
"ver": "1.1.50",
"importer": "scene",
"imported": true,
"uuid": "ff354f0b-c2f5-4dea-8ffb-0152d175d11c",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "1bf5f009-19d9-42b9-b6bb-b44efe349b09",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,81 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"description": "面板数据 / Panel data",
"additionalProperties": false,
"patternProperties": {
"^[a-zA-Z0-9_-]+$": {
"type": "object",
"description": "面板名 / Panel name",
"properties": {
"title": {
"type": "string",
"default": "Default Panel",
"description": "面板标题,支持 i18n:key / Panel title, support for i18n:key (required)"
},
"main": {
"type": "string",
"default": "dist/panels/default/index.js",
"description": "入口函数 / Entry function (required)"
},
"icon": {
"type": "string",
"description": "面板图标存放相对目录 / Relative directory for panel icon storage"
},
"type": {
"type": "string",
"enum": ["dockable", "simple"],
"default": "dockable",
"description": "面板类型dockable | simple / Panel type (dockable | simple)"
},
"flags": {
"type": "object",
"properties": {
"resizable": {
"type": "boolean",
"default": true,
"description": "是否可以改变大小,默认 true / Whether the size can be changed, default true"
},
"save": {
"type": "boolean",
"default": true,
"description": "是否需要保存,默认 false / Whether to save, default false"
},
"alwaysOnTop": {
"type": "boolean",
"default": true,
"description": "是否保持顶层显示,默认 false / Whether to keep the top level display, default false"
}
}
},
"size": {
"type": "object",
"description": "面板大小信息 / Panel size information",
"properties": {
"min-width": {
"type": "number",
"default": 200,
"description": "面板最小宽度 / Minimum panel width"
},
"min-height": {
"type": "number",
"default": 200,
"description": "面板最小高度 / Minimum panel height"
},
"width": {
"type": "number",
"default": 400,
"description": " 面板默认宽度 / Panel Default Width"
},
"height": {
"type": "number",
"default": 600,
"description": "面板默认高度 / Panel Default Height"
}
}
}
},
"required": ["title", "main"]
}
}
}

View File

@@ -0,0 +1,9 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"description": "其他扩展插件的扩展配置 / Extended configuration for other extension plugins",
"properties": {
},
"required": []
}

View File

@@ -0,0 +1,64 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"description": "插件定义文件 / Extension definition file",
"properties": {
"author": {
"type": "string",
"description": "作者 / Author",
"default": "Cocos Creator Developer"
},
"contributions": {
"$ref": "./contributions/index.json"
},
"dependencies": {
"type": "object",
"description": "发布时所需的依赖库 / Dependencies required for publishing"
},
"description": {
"type": "string",
"description": "简要介绍扩展关键特性、用途,支持 i18n / Brief introduction of the key features and uses of the extension, supporting i18n"
},
"devDependencies": {
"type": "object",
"description": "开发时所需的依赖库 / Dependencies required for development"
},
"editor": {
"type": "string",
"description": "支持的 Cocos Creator 编辑器版本,支持 semver 格式 / Supported Cocos Creator editor version, supporting semver format"
},
"main": {
"type": "string",
"description": "入口函数 / Entry function",
"default": "./dist/index.js"
},
"name": {
"type": "string",
"description": "不能以 _ 或 . 开头、不能含有大写字母,也不能含有 URL 的非法字符例如 .、' 和 ,。 / Cannot start with _ or., cannot contain uppercase letters, and cannot contain URL illegal characters such as.,'and,",
"default": "Custom Extension"
},
"package_version": {
"type": "number",
"description": "扩展系统预留版本号 / Extension system reserved version number",
"default": 2
},
"panels": {
"$ref": "./base/panels.json"
},
"scripts": {
"type": "object",
"description": "NPM 脚本 / NPM scripts"
},
"version": {
"type": "string",
"description": "版本号字符串 / Version number string",
"default": "1.0.0"
}
},
"required": [
"author",
"name",
"package_version",
"version"
]
}

View File

@@ -0,0 +1,25 @@
# Project Title
An extension that shows how to open and communicate with the panel through messages and menus.
The panel is based on Vue3.x.
## Development Environment
Node.js
## Install
```bash
# Install dependent modules
npm install
# build
npm run build
```
## Usage
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.
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`.

View File

@@ -0,0 +1,24 @@
# 项目简介
一份包含面板的扩展,该面板基于 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` 方法。

View File

@@ -0,0 +1,22 @@
{
"$schema": "https://schemastore.azurewebsites.net/schemas/json/tsconfig.json",
"compilerOptions": {
"target": "ES2017",
"module": "CommonJS",
"moduleResolution": "node",
"inlineSourceMap": true,
"inlineSources": true,
"esModuleInterop": true,
"skipLibCheck": true,
"strict": true,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"outDir": "./dist",
"rootDir": "./source",
"types": [
"node",
"@cocos/creator-types/editor",
]
}
}

View File

@@ -0,0 +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"};

View File

@@ -0,0 +1 @@
"use strict";module.exports={open_panel:"默认面板",send_to_panel:"发送消息给面板",description:"含有一个基于Vue3.x开发的面板的扩展"};

View File

@@ -0,0 +1,287 @@
{
"name": "cocos-ecs-extension",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cocos-ecs-extension",
"version": "1.0.0",
"hasInstallScript": true,
"dependencies": {
"fs-extra": "^10.0.0",
"vue": "^3.1.4"
},
"devDependencies": {
"@cocos/creator-types": "^3.8.6",
"@types/fs-extra": "^9.0.5",
"@types/node": "^18.17.1",
"typescript": "^5.8.2"
}
},
"node_modules/@babel/parser": {
"version": "7.23.0",
"license": "MIT",
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@cocos/creator-types": {
"version": "3.8.6",
"resolved": "https://registry.npmjs.org/@cocos/creator-types/-/creator-types-3.8.6.tgz",
"integrity": "sha512-hyZ4aoqqLxoRtKbBLSJM5RgtK3oGOlTEryHDcyH4znq3h9cFk+MSbQC2aJHvK5/bMlJzsZ641/hD77RGSrvo8Q==",
"dev": true
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"license": "MIT"
},
"node_modules/@types/fs-extra": {
"version": "9.0.13",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz",
"integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/node": {
"version": "18.19.111",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.111.tgz",
"integrity": "sha512-90sGdgA+QLJr1F9X79tQuEut0gEYIfkX9pydI4XGRgvFo9g2JWswefI+WUSUHPYVBHYSEfTEqBxA5hQvAZB3Mw==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/@vue/compiler-core": {
"version": "3.3.4",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.21.3",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.3.4",
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.3.4",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.20.15",
"@vue/compiler-core": "3.3.4",
"@vue/compiler-dom": "3.3.4",
"@vue/compiler-ssr": "3.3.4",
"@vue/reactivity-transform": "3.3.4",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.0",
"postcss": "^8.1.10",
"source-map-js": "^1.0.2"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.3.4",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/reactivity": {
"version": "3.3.4",
"license": "MIT",
"dependencies": {
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/reactivity-transform": {
"version": "3.3.4",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.20.15",
"@vue/compiler-core": "3.3.4",
"@vue/shared": "3.3.4",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.0"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.3.4",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.3.4",
"@vue/shared": "3.3.4"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.3.4",
"license": "MIT",
"dependencies": {
"@vue/runtime-core": "3.3.4",
"@vue/shared": "3.3.4",
"csstype": "^3.1.1"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.3.4",
"license": "MIT",
"dependencies": {
"@vue/compiler-ssr": "3.3.4",
"@vue/shared": "3.3.4"
},
"peerDependencies": {
"vue": "3.3.4"
}
},
"node_modules/@vue/shared": {
"version": "3.3.4",
"license": "MIT"
},
"node_modules/csstype": {
"version": "3.1.2",
"license": "MIT"
},
"node_modules/estree-walker": {
"version": "2.0.2",
"license": "MIT"
},
"node_modules/fs-extra": {
"version": "10.1.0",
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"license": "ISC"
},
"node_modules/jsonfile": {
"version": "6.1.0",
"license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/magic-string": {
"version": "0.30.3",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
},
"engines": {
"node": ">=12"
}
},
"node_modules/nanoid": {
"version": "3.3.6",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/picocolors": {
"version": "1.0.0",
"license": "ISC"
},
"node_modules/postcss": {
"version": "8.4.30",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/source-map-js": {
"version": "1.0.2",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true
},
"node_modules/universalify": {
"version": "2.0.0",
"license": "MIT",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/vue": {
"version": "3.3.4",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.3.4",
"@vue/compiler-sfc": "3.3.4",
"@vue/runtime-dom": "3.3.4",
"@vue/server-renderer": "3.3.4",
"@vue/shared": "3.3.4"
}
}
}
}

View File

@@ -0,0 +1,103 @@
{
"$schema": "./@types/schema/package/index.json",
"package_version": 2,
"name": "cocos-ecs-extension",
"version": "1.0.0",
"author": "esengine",
"editor": ">=3.8.6",
"scripts": {
"preinstall": "node ./scripts/preinstall.js",
"build": "npx tsc"
},
"description": "i18n:cocos-ecs-extension.description",
"main": "./dist/main.js",
"dependencies": {
"vue": "^3.1.4",
"fs-extra": "^10.0.0"
},
"devDependencies": {
"@cocos/creator-types": "^3.8.6",
"@types/fs-extra": "^9.0.5",
"@types/node": "^18.17.1",
"typescript": "^5.8.2"
},
"panels": {
"default": {
"title": "ECS Framework - 欢迎面板",
"type": "dockable",
"main": "dist/panels/default",
"size": {
"min-width": 450,
"min-height": 600,
"width": 850,
"height": 800
}
}
},
"contributions": {
"menu": [
{
"path": "i18n:menu.panel/ECS Framework",
"label": "欢迎面板",
"message": "open-panel"
},
{
"path": "i18n:menu.develop/ECS Framework",
"label": "ECS 开发工具",
"message": "open-panel"
}
],
"messages": {
"open-panel": {
"methods": [
"openPanel"
]
},
"install-ecs-framework": {
"methods": [
"install-ecs-framework"
]
},
"update-ecs-framework": {
"methods": [
"update-ecs-framework"
]
},
"uninstall-ecs-framework": {
"methods": [
"uninstall-ecs-framework"
]
},
"open-documentation": {
"methods": [
"open-documentation"
]
},
"create-ecs-template": {
"methods": [
"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"
]
}
}
}
}

View File

@@ -0,0 +1 @@
const readFileSync=require("fs")["readFileSync"],join=require("path")["join"],spawnSync=require("child_process")["spawnSync"],PATH={packageJSON:join(__dirname,"../package.json")};function checkCreatorTypesVersion(e){var o="win32"===process.platform?"npm.cmd":"npm";let n=spawnSync(o,["view","@cocos/creator-types","versions"]).stdout.toString();try{n=JSON.parse(listString)}catch(e){}return!!n.includes(e)}try{const e=readFileSync(PATH.packageJSON,"utf8"),f=JSON.parse(e),g=f.devDependencies["@cocos/creator-types"].replace(/^[^\d]+/,"");checkCreatorTypesVersion(g)||(console.log("Warning:"),console.log(" @en"),console.log(" Version check of @cocos/creator-types failed."),console.log(` The definition of ${g} has not been released yet. Please export the definition to the ./node_modules directory by selecting "Developer -> Export Interface Definition" in the menu of the Creator editor.`),console.log(" The definition of the corresponding version will be released on npm after the editor is officially released."),console.log(" @zh"),console.log(" @cocos/creator-types 版本检查失败。"),console.log(` ${g} 定义还未发布,请先通过 Creator 编辑器菜单 "开发者 -> 导出接口定义",导出定义到 ./node_modules 目录。`),console.log(" 对应版本的定义会在编辑器正式发布后同步发布到 npm 上。"))}catch(e){console.error(e)}

View File

@@ -0,0 +1,403 @@
import * as path from 'path';
import * as fs from 'fs';
/**
* ECS启动模板生成器
* 生成最基础的ECS框架启动模板不包含业务逻辑
*/
export class TemplateGenerator {
private projectPath: string;
private ecsDir: string;
constructor(projectPath: string) {
this.projectPath = projectPath;
this.ecsDir = path.join(projectPath, 'assets', 'scripts', 'ecs');
}
/**
* 检查是否已经存在ECS模板
*/
public checkTemplateExists(): boolean {
return fs.existsSync(this.ecsDir);
}
/**
* 获取已存在的文件列表
*/
public getExistingFiles(): string[] {
if (!this.checkTemplateExists()) return [];
const files: string[] = [];
this.scanDirectory(this.ecsDir, '', files);
return files;
}
private scanDirectory(dirPath: string, relativePath: string, files: string[]): void {
if (!fs.existsSync(dirPath)) return;
const items = fs.readdirSync(dirPath);
for (const item of items) {
const fullPath = path.join(dirPath, item);
const relativeFilePath = relativePath ? `${relativePath}/${item}` : item;
if (fs.statSync(fullPath).isDirectory()) {
this.scanDirectory(fullPath, relativeFilePath, files);
} else {
files.push(relativeFilePath);
}
}
}
/**
* 删除现有的ECS模板
*/
public removeExistingTemplate(): void {
if (fs.existsSync(this.ecsDir)) {
fs.rmSync(this.ecsDir, { recursive: true, force: true });
console.log('Removed existing ECS template');
}
}
/**
* 创建ECS启动模板
*/
public createTemplate(): void {
// 创建目录结构
this.createDirectories();
// 创建ECS启动管理器
this.createECSManager();
// 创建基础游戏场景
this.createBaseGameScene();
// 创建README文档
this.createReadme();
console.log('ECS启动模板创建成功');
}
/**
* 创建目录结构
*/
private createDirectories(): void {
const dirs = [
this.ecsDir,
path.join(this.ecsDir, 'scenes'),
path.join(this.ecsDir, 'components'),
path.join(this.ecsDir, 'systems')
];
dirs.forEach(dir => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
console.log(`Created directory: ${path.relative(this.projectPath, dir)}`);
}
});
}
/**
* 创建ECS管理器
*/
private createECSManager(): void {
this.writeFile(path.join(this.ecsDir, 'ECSManager.ts'), `import { Core } from '@esengine/ecs-framework';
import { Component, _decorator } from 'cc';
import { GameScene } from './scenes/GameScene';
const { ccclass, property } = _decorator;
/**
* ECS管理器 - Cocos Creator组件
* 将此组件添加到场景中的任意节点上即可启动ECS框架
*
* 使用说明:
* 1. 在Cocos Creator场景中创建一个空节点
* 2. 将此ECSManager组件添加到该节点
* 3. 运行场景即可自动启动ECS框架
*/
@ccclass('ECSManager')
export class ECSManager extends Component {
@property({
tooltip: '是否启用调试模式(建议开发阶段开启)'
})
public debugMode: boolean = true;
private isInitialized: boolean = false;
/**
* 组件启动时初始化ECS
*/
start() {
this.initializeECS();
}
/**
* 初始化ECS框架
*/
private initializeECS(): void {
if (this.isInitialized) return;
console.log('🎮 正在初始化ECS框架...');
try {
// 1. 创建Core实例
Core.create(this.debugMode);
// 2. 创建游戏场景
const gameScene = new GameScene();
// 3. 设置为当前场景会自动调用scene.begin()
Core.scene = gameScene;
this.isInitialized = true;
console.log('✅ ECS框架初始化成功');
console.log('📖 请查看 assets/scripts/ecs/README.md 了解如何添加组件和系统');
} catch (error) {
console.error('❌ ECS框架初始化失败:', error);
}
}
/**
* 每帧更新ECS框架
*/
update(deltaTime: number) {
if (this.isInitialized) {
// 更新ECS核心系统
Core.update(deltaTime);
}
}
/**
* 组件销毁时清理ECS
*/
onDestroy() {
if (this.isInitialized) {
console.log('🧹 清理ECS框架...');
// ECS框架会自动处理场景清理
this.isInitialized = false;
}
}
}
`);
}
/**
* 创建基础游戏场景
*/
private createBaseGameScene(): void {
this.writeFile(path.join(this.ecsDir, 'scenes', 'GameScene.ts'), `import { Scene } from '@esengine/ecs-framework';
/**
* 游戏场景
*
* 这是您的主游戏场景。在这里可以:
* - 添加游戏系统
* - 创建初始实体
* - 设置场景参数
*/
export class GameScene extends Scene {
/**
* 场景初始化
* 在场景创建时调用,用于设置基础配置
*/
public initialize(): void {
super.initialize();
// 设置场景名称
this.name = "MainGameScene";
console.log('🎯 游戏场景已创建');
// TODO: 在这里添加您的游戏系统
// 例如this.addEntityProcessor(new MovementSystem());
// TODO: 在这里创建初始实体
// 例如this.createEntity("Player");
}
/**
* 场景开始运行
* 在场景开始时调用,用于执行启动逻辑
*/
public onStart(): void {
super.onStart();
console.log('🚀 游戏场景已启动');
// TODO: 在这里添加场景启动逻辑
// 例如创建UI、播放音乐、初始化游戏状态等
}
/**
* 场景卸载
* 在场景结束时调用,用于清理资源
*/
public unload(): void {
console.log('🛑 游戏场景已结束');
// TODO: 在这里添加清理逻辑
// 例如:清理缓存、释放资源等
super.unload();
}
}
`);
}
/**
* 创建README文档
*/
private createReadme(): void {
this.writeFile(path.join(this.ecsDir, 'README.md'), `# ECS框架启动模板
欢迎使用ECS框架这是一个最基础的启动模板帮助您快速开始ECS项目开发。
## 📁 项目结构
\`\`\`
ecs/
├── components/ # 组件目录(请在此添加您的组件)
├── systems/ # 系统目录(请在此添加您的系统)
├── scenes/ # 场景目录
│ └── GameScene.ts # 主游戏场景
├── ECSManager.ts # ECS管理器组件
└── README.md # 本文档
\`\`\`
## 🚀 快速开始
### 1. 启动ECS框架
ECS框架已经配置完成您只需要
1. 在Cocos Creator中打开您的场景
2. 创建一个空节点(例如命名为"ECSManager"
3. 将 \`ECSManager\` 组件添加到该节点
4. 运行场景ECS框架将自动启动
### 2. 查看控制台输出
如果一切正常,您将在控制台看到:
\`\`\`
🎮 正在初始化ECS框架...
🎯 游戏场景已创建
✅ ECS框架初始化成功
🚀 游戏场景已启动
\`\`\`
## 📚 下一步开发
### 创建您的第一个组件
\`components/\` 目录下创建组件:
\`\`\`typescript
// components/PositionComponent.ts
import { Component } from '@esengine/ecs-framework';
import { Vec3 } from 'cc';
export class PositionComponent extends Component {
public position: Vec3 = new Vec3();
constructor(x: number = 0, y: number = 0, z: number = 0) {
super();
this.position.set(x, y, z);
}
}
\`\`\`
### 创建您的第一个系统
\`systems/\` 目录下创建系统:
\`\`\`typescript
// systems/MovementSystem.ts
import { EntitySystem, Entity, Matcher } from '@esengine/ecs-framework';
import { PositionComponent } from '../components/PositionComponent';
export class MovementSystem extends EntitySystem {
constructor() {
super(Matcher.empty().all(PositionComponent));
}
protected process(entities: Entity[]): void {
for (const entity of entities) {
const position = entity.getComponent(PositionComponent);
if (position) {
// TODO: 在这里编写移动逻辑
console.log(\`实体 \${entity.name} 位置: \${position.position}\`);
}
}
}
}
\`\`\`
### 在场景中注册系统
\`scenes/GameScene.ts\`\`initialize()\` 方法中添加:
\`\`\`typescript
import { MovementSystem } from '../systems/MovementSystem';
public initialize(): void {
super.initialize();
this.name = "MainGameScene";
// 添加系统
this.addEntityProcessor(new MovementSystem());
// 创建测试实体
const testEntity = this.createEntity("TestEntity");
testEntity.addComponent(new PositionComponent(0, 0, 0));
}
\`\`\`
## 🔗 学习资源
- [ECS框架完整文档](https://github.com/esengine/ecs-framework)
- [ECS概念详解](https://github.com/esengine/ecs-framework/blob/master/docs/concepts-explained.md)
- [新手教程](https://github.com/esengine/ecs-framework/blob/master/docs/beginner-tutorials.md)
- [组件设计指南](https://github.com/esengine/ecs-framework/blob/master/docs/component-design-guide.md)
- [系统开发指南](https://github.com/esengine/ecs-framework/blob/master/docs/system-guide.md)
## 💡 开发提示
1. **组件只存储数据**:避免在组件中编写复杂逻辑
2. **系统处理逻辑**:所有业务逻辑应该在系统中实现
3. **使用Matcher过滤实体**系统通过Matcher指定需要处理的实体类型
4. **性能优化**:大量实体时考虑使用位掩码查询和组件索引
## ❓ 常见问题
### Q: 如何创建实体?
A: 在场景中使用 \`this.createEntity("实体名称")\`
### Q: 如何给实体添加组件?
A: 使用 \`entity.addComponent(new YourComponent())\`
### Q: 如何获取实体的组件?
A: 使用 \`entity.getComponent(YourComponent)\`
### Q: 如何删除实体?
A: 使用 \`entity.destroy()\`\`this.destroyEntity(entity)\`
---
🎮 **开始您的ECS开发之旅吧**
如有问题请查阅官方文档或提交Issue。
`);
}
/**
* 写入文件
*/
private writeFile(filePath: string, content: string): void {
fs.writeFileSync(filePath, content, 'utf8');
console.log(`Created file: ${path.relative(this.projectPath, filePath)}`);
}
}

View File

@@ -0,0 +1,245 @@
// @ts-ignore
import packageJSON from '../package.json';
import { exec } from 'child_process';
import * as path from 'path';
import { readFileSync, outputFile } from 'fs-extra';
import { join } from 'path';
import { TemplateGenerator } from './TemplateGenerator';
/**
* @en Registration method for the main process of Extension
* @zh 为扩展的主进程的注册方法
*/
export const methods: { [key: string]: (...any: any) => any } = {
/**
* @en A method that can be triggered by message
* @zh 通过 message 触发的方法
*/
openPanel() {
Editor.Panel.open(packageJSON.name);
},
/**
* 安装ECS Framework
*/
'install-ecs-framework'() {
const projectPath = Editor.Project.path;
const command = 'npm install @esengine/ecs-framework';
console.log(`Installing ECS Framework to project: ${projectPath}`);
console.log(`Command: ${command}`);
exec(command, { cwd: projectPath }, (error, stdout, stderr) => {
console.log('Install stdout:', stdout);
console.log('Install stderr:', stderr);
if (error) {
console.error('Installation failed:', error);
} else {
console.log('Installation completed successfully');
// 验证安装是否成功
const nodeModulesPath = path.join(projectPath, 'node_modules', '@esengine', 'ecs-framework');
const installSuccess = require('fs').existsSync(nodeModulesPath);
if (installSuccess) {
console.log('ECS Framework installed successfully');
} else {
console.warn('ECS Framework directory not found after install');
}
}
});
},
/**
* 更新ECS Framework
*/
'update-ecs-framework'(targetVersion?: string) {
const projectPath = Editor.Project.path;
const version = targetVersion ? `@${targetVersion}` : '@latest';
const command = `npm install @esengine/ecs-framework${version}`;
console.log(`Updating ECS Framework to ${version} in project: ${projectPath}`);
console.log(`Command: ${command}`);
exec(command, { cwd: projectPath }, (error, stdout, stderr) => {
console.log('Update stdout:', stdout);
console.log('Update stderr:', stderr);
if (error) {
console.error('Update failed:', error);
} else {
console.log('Update completed successfully');
// 验证更新是否成功
const nodeModulesPath = path.join(projectPath, 'node_modules', '@esengine', 'ecs-framework');
const updateSuccess = require('fs').existsSync(nodeModulesPath);
if (updateSuccess) {
console.log(`ECS Framework updated successfully to ${version}`);
} else {
console.warn('ECS Framework directory not found after update');
}
}
});
},
/**
* 卸载ECS Framework
*/
'uninstall-ecs-framework'() {
const projectPath = Editor.Project.path;
const command = 'npm uninstall @esengine/ecs-framework';
console.log(`Uninstalling ECS Framework from project: ${projectPath}`);
console.log(`Command: ${command}`);
exec(command, { cwd: projectPath }, (error, stdout, stderr) => {
console.log('Uninstall stdout:', stdout);
console.log('Uninstall stderr:', stderr);
if (error) {
console.error('Uninstall failed:', error);
} else {
console.log('Uninstall completed successfully');
// 检查是否真的卸载了
const nodeModulesPath = path.join(projectPath, 'node_modules', '@esengine', 'ecs-framework');
const stillExists = require('fs').existsSync(nodeModulesPath);
if (stillExists) {
console.warn('ECS Framework directory still exists after uninstall');
} else {
console.log('ECS Framework uninstalled successfully');
}
}
});
},
/**
* 打开文档
*/
'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}`,
});
}
});
},
/**
* 创建ECS模板
*/
'create-ecs-template'() {
const projectPath = Editor.Project.path;
console.log(`Creating ECS template in project: ${projectPath}`);
try {
const templateGenerator = new TemplateGenerator(projectPath);
// 检查是否已存在模板
if (templateGenerator.checkTemplateExists()) {
const existingFiles = templateGenerator.getExistingFiles();
const fileList = existingFiles.length > 0 ? existingFiles.join('\n• ') : '未检测到具体文件';
Editor.Dialog.warn('模板已存在', {
detail: `检测到已存在ECS模板包含以下文件\n\n• ${fileList}\n\n是否要覆盖现有模板`,
buttons: ['覆盖', '取消'],
}).then((result: any) => {
if (result.response === 0) {
// 用户选择覆盖
console.log('User chose to overwrite existing template');
templateGenerator.removeExistingTemplate();
templateGenerator.createTemplate();
Editor.Dialog.info('模板创建成功', {
detail: '✅ ECS项目模板已覆盖并重新创建完成\n\n已为您的Cocos Creator项目生成了完整的ECS架构模板包括\n\n' +
'• 位置、速度、Cocos节点组件\n' +
'• 移动系统和节点同步系统\n' +
'• 实体工厂和场景管理器\n' +
'• ECS管理器组件(可直接添加到节点)\n' +
'• 完整的使用文档\n\n' +
'请刷新资源管理器查看新创建的文件。',
});
} else {
console.log('User cancelled template creation');
}
});
return;
}
// 创建新模板
templateGenerator.createTemplate();
console.log('ECS template created successfully');
Editor.Dialog.info('模板创建成功', {
detail: '✅ ECS项目模板已创建完成\n\n已为您的Cocos Creator项目生成了完整的ECS架构模板包括\n\n' +
'• 位置、速度、Cocos节点组件\n' +
'• 移动系统和节点同步系统\n' +
'• 实体工厂和场景管理器\n' +
'• ECS管理器组件(可直接添加到节点)\n' +
'• 完整的使用文档\n\n' +
'请刷新资源管理器查看新创建的文件。',
});
} catch (error) {
console.error('Failed to create ECS template:', error);
const errorMessage = error instanceof Error ? error.message : String(error);
Editor.Dialog.error('模板创建失败', {
detail: `创建ECS模板时发生错误\n\n${errorMessage}\n\n请检查项目权限和目录结构。`,
});
}
},
/**
* 打开设置
*/
'open-settings'() {
Editor.Dialog.info('插件设置', {
detail: '设置面板开发中...\n\n将在下个版本提供完整的插件配置功能。\n\n预计功能\n• 代码生成模板配置\n• 性能监控设置\n• 自动更新设置\n• 开发工具偏好',
buttons: ['好的'],
});
},
/**
* 项目分析(预留)
*/
'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: ['好的'],
});
},
};
/**
* @en Method triggered when the extension is started
* @zh 启动扩展时触发的方法
*/
export function load() {
console.log('ECS Framework Extension loaded');
}
/**
* @en Method triggered when uninstalling the extension
* @zh 卸载扩展时触发的方法
*/
export function unload() {
console.log('ECS Framework Extension unloaded');
}

View File

@@ -0,0 +1,533 @@
/* eslint-disable vue/one-component-per-file */
import { readFileSync } from 'fs-extra';
import { join } from 'path';
import { createApp, App, defineComponent, ref, onMounted } from 'vue';
import * as fs from 'fs';
import * as path from 'path';
import { exec } from 'child_process';
const panelDataMap = new WeakMap<any, App>();
/**
* 检测ECS框架安装状态的工具函数
*/
async function checkEcsFrameworkStatus(projectPath: string) {
const packageJsonPath = path.join(projectPath, 'package.json');
const nodeModulesPath = path.join(projectPath, 'node_modules', '@esengine', 'ecs-framework');
try {
// 检查package.json是否存在
const packageJsonExists = fs.existsSync(packageJsonPath);
if (!packageJsonExists) {
return {
packageJsonExists: false,
ecsInstalled: false,
ecsVersion: null
};
}
// 读取package.json
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
// 检查依赖中是否包含ECS框架
const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
const ecsInDeps = dependencies['@esengine/ecs-framework'];
// 检查node_modules中是否实际安装了ECS框架
const ecsActuallyInstalled = fs.existsSync(nodeModulesPath);
let ecsVersion = null;
if (ecsActuallyInstalled) {
try {
const ecsPackageJson = JSON.parse(
fs.readFileSync(path.join(nodeModulesPath, 'package.json'), 'utf-8')
);
ecsVersion = ecsPackageJson.version;
} catch (e) {
console.warn('Unable to read ECS framework version:', e);
}
}
return {
packageJsonExists: true,
ecsInstalled: ecsActuallyInstalled && !!ecsInDeps,
ecsVersion,
declaredVersion: ecsInDeps
};
} catch (error) {
console.error('Error checking ECS framework status:', error);
return {
packageJsonExists: false,
ecsInstalled: false,
ecsVersion: null
};
}
}
/**
* 检测ECS模板状态
*/
function checkEcsTemplateStatus(projectPath: string) {
const ecsDir = path.join(projectPath, 'assets', 'scripts', 'ecs');
try {
if (!fs.existsSync(ecsDir)) {
return {
templateExists: false,
existingFiles: []
};
}
// 扫描ECS目录中的文件
const existingFiles: string[] = [];
function scanDirectory(dirPath: string, relativePath: string = '') {
if (!fs.existsSync(dirPath)) return;
const items = fs.readdirSync(dirPath);
for (const item of items) {
const fullPath = path.join(dirPath, item);
const relativeFilePath = relativePath ? `${relativePath}/${item}` : item;
if (fs.statSync(fullPath).isDirectory()) {
scanDirectory(fullPath, relativeFilePath);
} else {
existingFiles.push(relativeFilePath);
}
}
}
scanDirectory(ecsDir);
return {
templateExists: existingFiles.length > 0,
existingFiles
};
} catch (error) {
console.error('Error checking ECS template status:', error);
return {
templateExists: false,
existingFiles: []
};
}
}
/**
* 获取ECS框架的最新版本
*/
function getLatestEcsVersion(): Promise<string | null> {
return new Promise((resolve) => {
exec('npm view @esengine/ecs-framework version', (error, stdout) => {
if (error) {
console.warn('Failed to get latest version:', error);
resolve(null);
} else {
resolve(stdout.trim());
}
});
});
}
/**
* 获取Node.js版本
*/
function getNodeVersion(): Promise<string> {
return new Promise((resolve) => {
exec('node --version', (error, stdout) => {
if (error) {
resolve('未知');
} else {
resolve(stdout.trim().replace('v', ''));
}
});
});
}
/**
* 比较版本号
*/
function compareVersions(current: string, latest: string): boolean {
try {
const currentParts = current.split('.').map(Number);
const latestParts = latest.split('.').map(Number);
for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
const currentPart = currentParts[i] || 0;
const latestPart = latestParts[i] || 0;
if (latestPart > currentPart) {
return true; // 有更新
} else if (latestPart < currentPart) {
return false; // 当前版本更新
}
}
return false; // 版本相同
} catch (error) {
console.warn('Version comparison failed:', error);
return false;
}
}
/**
* @zh 如果希望兼容 3.3 之前的版本可以使用下方的代码
* @en You can add the code below if you want compatibility with versions prior to 3.3
*/
// Editor.Panel.define = Editor.Panel.define || function(options: any) { return options }
module.exports = Editor.Panel.define({
listeners: {
show() { console.log('ECS Welcome Panel Show'); },
hide() { console.log('ECS Welcome Panel Hide'); },
},
template: readFileSync(join(__dirname, '../../../static/template/default/index.html'), 'utf-8'),
style: readFileSync(join(__dirname, '../../../static/style/default/index.css'), 'utf-8'),
$: {
app: '#app',
},
methods: {
/**
* 向主进程发送消息的方法
*/
sendToMain(message: string, ...args: any[]) {
Editor.Message.send('cocos-ecs-extension', message, ...args);
}
},
ready() {
if (this.$.app) {
const app = createApp({});
app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('ui-');
// ECS欢迎组件
app.component('EcsWelcome', defineComponent({
setup() {
// 响应式状态
const checkingStatus = ref(true);
const ecsInstalled = ref(false);
const ecsVersion = ref<string | null>(null);
const latestVersion = ref<string | null>(null);
const hasUpdate = ref(false);
const packageJsonExists = ref(false);
const nodeVersion = ref('检测中...');
const pluginVersion = ref('1.0.0');
const lastCheckTime = ref<string | null>(null);
// ECS模板状态
const templateExists = ref(false);
const existingFiles = ref<string[]>([]);
// 操作状态
const installing = ref(false);
const updating = ref(false);
const uninstalling = ref(false);
// 操作状态显示
const showOperationStatus = ref(false);
const operationStatusType = ref('loading');
const operationStatusMessage = ref('');
const operationStatusDetails = ref('');
// 显示操作状态
const setOperationStatus = (type: string, message: string, details?: string) => {
showOperationStatus.value = true;
operationStatusType.value = type;
operationStatusMessage.value = message;
operationStatusDetails.value = details || '';
// 自动隐藏成功和警告消息
if (type === 'success' || type === 'warning') {
setTimeout(() => {
showOperationStatus.value = false;
}, 5000);
}
};
// 获取状态图标
const getStatusIcon = (type: string) => {
switch (type) {
case 'loading': return '⏳';
case 'success': return '✅';
case 'error':
case 'failed': return '❌';
case 'warning': return '⚠️';
default: return '';
}
};
// 监听来自主进程的消息 - 暂时注释掉,使用定时刷新
const setupMessageListeners = () => {
// TODO: 使用正确的消息监听API
console.log('Message listeners setup - using polling instead');
};
// 定时检查状态(用于检测操作完成)
let statusCheckInterval: any = null;
const startStatusPolling = () => {
if (statusCheckInterval) clearInterval(statusCheckInterval);
statusCheckInterval = setInterval(() => {
if (installing.value || updating.value || uninstalling.value) {
checkStatus();
}
}, 3000); // 每3秒检查一次
};
const stopStatusPolling = () => {
if (statusCheckInterval) {
clearInterval(statusCheckInterval);
statusCheckInterval = null;
}
};
// 检测状态的方法
const checkStatus = async () => {
checkingStatus.value = true;
try {
// 获取当前项目路径
const projectPath = Editor.Project.path;
// 检测ECS框架状态
const status = await checkEcsFrameworkStatus(projectPath);
const prevInstalled = ecsInstalled.value;
const prevVersion = ecsVersion.value;
packageJsonExists.value = status.packageJsonExists;
ecsInstalled.value = status.ecsInstalled;
ecsVersion.value = status.ecsVersion;
// 检测ECS模板状态
const templateStatus = checkEcsTemplateStatus(projectPath);
templateExists.value = templateStatus.templateExists;
existingFiles.value = templateStatus.existingFiles;
// 检测操作完成
if (installing.value) {
if (status.ecsInstalled && !prevInstalled) {
installing.value = false;
setOperationStatus('success', 'ECS Framework 安装成功!');
stopStatusPolling();
} else if (!status.ecsInstalled) {
// 可能还在安装中,继续等待
}
}
if (updating.value) {
if (status.ecsVersion && status.ecsVersion !== prevVersion) {
updating.value = false;
setOperationStatus('success', `ECS Framework 更新成功到 v${status.ecsVersion}`);
stopStatusPolling();
}
}
if (uninstalling.value) {
if (!status.ecsInstalled && prevInstalled) {
uninstalling.value = false;
setOperationStatus('success', 'ECS Framework 卸载成功!');
stopStatusPolling();
}
}
// 获取Node.js版本
nodeVersion.value = await getNodeVersion();
// 检查更新
if (ecsInstalled.value && ecsVersion.value) {
await checkForUpdates();
}
// 更新检查时间
lastCheckTime.value = new Date().toLocaleString();
} catch (error) {
console.error('Status check failed:', error);
// 如果检查失败,停止操作状态
if (installing.value || updating.value || uninstalling.value) {
installing.value = false;
updating.value = false;
uninstalling.value = false;
setOperationStatus('error', '状态检查失败,请手动验证操作结果');
stopStatusPolling();
}
} finally {
checkingStatus.value = false;
}
};
// 检查更新
const checkForUpdates = async () => {
if (!ecsInstalled.value || !ecsVersion.value) {
setOperationStatus('warning', '请先安装 ECS Framework');
return;
}
try {
setOperationStatus('loading', '正在检查更新...');
const latest = await getLatestEcsVersion();
if (latest) {
latestVersion.value = latest;
const needsUpdate = compareVersions(ecsVersion.value, latest);
hasUpdate.value = needsUpdate;
if (needsUpdate) {
setOperationStatus('success', `发现新版本v${latest}当前v${ecsVersion.value}`);
} else {
setOperationStatus('success', `已是最新版本v${ecsVersion.value}`);
}
} else {
setOperationStatus('warning', '无法获取最新版本信息,请检查网络连接');
}
// 更新检查时间
lastCheckTime.value = new Date().toLocaleString();
} catch (error) {
console.warn('Failed to check updates:', error);
setOperationStatus('error', '检查更新失败,请检查网络连接');
}
};
// 操作方法
const installEcsFramework = () => {
if (!packageJsonExists.value || installing.value) return;
Editor.Dialog.info('安装 ECS Framework', {
detail: '即将安装@esengine/ecs-framework到当前项目...',
buttons: ['确定', '取消'],
default: 0,
}).then((result) => {
if (result.response === 0) {
installing.value = true;
setOperationStatus('loading', '正在安装 ECS Framework...');
startStatusPolling();
// 发送安装命令到主进程
Editor.Message.send('cocos-ecs-extension', 'install-ecs-framework');
}
});
};
const updateEcsFramework = () => {
if (!hasUpdate.value || updating.value) return;
Editor.Dialog.info('更新 ECS Framework', {
detail: `即将更新ECS框架从 v${ecsVersion.value} 到 v${latestVersion.value}`,
buttons: ['确定', '取消'],
default: 0,
}).then((result) => {
if (result.response === 0) {
updating.value = true;
setOperationStatus('loading', `正在更新 ECS Framework 到 v${latestVersion.value}...`);
startStatusPolling();
Editor.Message.send('cocos-ecs-extension', 'update-ecs-framework', latestVersion.value);
}
});
};
const uninstallEcsFramework = () => {
if (uninstalling.value) return;
Editor.Dialog.warn('卸载 ECS Framework', {
detail: '确定要卸载ECS框架吗这将删除项目中的ECS框架依赖。',
buttons: ['确定卸载', '取消'],
default: 1,
}).then((result) => {
if (result.response === 0) {
uninstalling.value = true;
setOperationStatus('loading', '正在卸载 ECS Framework...');
startStatusPolling();
Editor.Message.send('cocos-ecs-extension', 'uninstall-ecs-framework');
}
});
};
const openDocumentation = () => {
if (!ecsInstalled.value) return;
Editor.Message.send('cocos-ecs-extension', 'open-documentation');
};
const createEcsTemplate = () => {
if (!ecsInstalled.value || templateExists.value) return;
Editor.Dialog.info('创建 ECS 模板', {
detail: '即将创建基础的ECS项目结构和启动代码...',
buttons: ['确定', '取消'],
default: 0,
}).then((result) => {
if (result.response === 0) {
Editor.Message.send('cocos-ecs-extension', 'create-ecs-template');
}
});
};
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');
};
// 组件挂载后检测状态
onMounted(() => {
setupMessageListeners();
checkStatus();
});
return {
checkingStatus,
ecsInstalled,
ecsVersion,
latestVersion,
hasUpdate,
packageJsonExists,
nodeVersion,
pluginVersion,
lastCheckTime,
templateExists,
existingFiles,
installing,
updating,
uninstalling,
showOperationStatus,
operationStatusType,
operationStatusMessage,
operationStatusDetails,
getStatusIcon,
installEcsFramework,
updateEcsFramework,
uninstallEcsFramework,
checkForUpdates,
openDocumentation,
createEcsTemplate,
openSettings,
openProjectAnalysis,
openComponentLibrary,
openGithub
};
},
template: readFileSync(join(__dirname, '../../../static/template/vue/welcome.html'), 'utf-8'),
}));
app.mount(this.$.app);
panelDataMap.set(this, app);
}
},
beforeClose() { },
close() {
const app = panelDataMap.get(this);
if (app) {
app.unmount();
}
},
});

View File

@@ -0,0 +1,450 @@
#text {
color: var(--color-normal-contrast-weakest);
margin: auto;
width: 180px;
}
.counter {
text-align: center;
}
.ecs-welcome-panel {
height: 100%;
background: var(--color-panel-bg);
color: var(--color-text-normal);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
overflow: hidden;
}
.welcome-container {
padding: 16px;
height: 100%;
display: flex;
flex-direction: column;
overflow-y: auto;
overflow-x: hidden;
max-height: 100vh;
box-sizing: border-box;
}
.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;
}
.header h1 {
margin: 0 0 6px 0;
font-size: 20px;
font-weight: 600;
}
.header p {
margin: 0;
opacity: 0.9;
font-size: 13px;
}
.status-section {
background: var(--color-area-bg);
border: 1px solid var(--color-border);
border-radius: 6px;
padding: 14px;
margin-bottom: 14px;
flex-shrink: 0;
}
.status-title {
font-size: 15px;
font-weight: 600;
margin-bottom: 10px;
color: var(--color-text-normal);
}
.status-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid var(--color-border-soft);
flex-wrap: wrap;
gap: 8px;
}
.status-item:last-child {
border-bottom: none;
}
.status-label {
color: var(--color-text-contrast-weakest);
flex: 1;
min-width: 200px;
}
.status-badge {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
white-space: nowrap;
}
.status-badge.installed {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.status-badge.not-installed {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.status-badge.checking {
background: #fff3cd;
color: #856404;
border: 1px solid #ffeaa7;
}
.version-info {
font-family: 'Courier New', monospace;
font-size: 11px;
color: var(--color-text-contrast-weak);
}
.update-hint {
color: #ff6b35;
font-size: 10px;
font-weight: 600;
margin-left: 8px;
display: block;
margin-top: 2px;
}
.management-buttons {
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 8px;
}
.management-buttons ui-button {
width: 100%;
min-height: 32px;
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 8px 12px;
}
.management-buttons ui-button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.management-buttons ui-button.green {
background-color: #28a745;
color: white;
border: 1px solid #28a745;
}
.management-buttons ui-button.red {
background-color: #dc3545;
color: white;
border: 1px solid #dc3545;
}
.management-buttons ui-button.blue {
background-color: #007bff;
color: white;
border: 1px solid #007bff;
}
.operation-status {
padding: 12px;
border-radius: 6px;
margin-top: 8px;
}
.operation-status.loading {
background: #fff3cd;
border: 1px solid #ffeaa7;
color: #856404;
}
.operation-status.success {
background: #d4edda;
border: 1px solid #c3e6cb;
color: #155724;
}
.operation-status.error,
.operation-status.failed {
background: #f8d7da;
border: 1px solid #f5c6cb;
color: #721c24;
}
.operation-status.warning {
background: #fff3cd;
border: 1px solid #ffeaa7;
color: #856404;
}
.status-content {
display: flex;
align-items: center;
gap: 8px;
}
.status-icon {
font-size: 16px;
}
.status-text {
flex: 1;
font-weight: 500;
}
.status-details {
margin-top: 8px;
font-size: 11px;
opacity: 0.8;
white-space: pre-line;
}
.actions-section {
background: var(--color-area-bg);
border: 1px solid var(--color-border);
border-radius: 6px;
padding: 14px;
margin-bottom: 14px;
flex-shrink: 0;
}
.action-card {
background: var(--color-neutral-bg);
border: 1px solid var(--color-border);
border-radius: 6px;
padding: 12px;
margin-bottom: 10px;
cursor: pointer;
transition: all 0.2s ease;
}
.action-card:last-child {
margin-bottom: 0;
}
.action-card h3 {
margin: 0 0 6px 0;
font-size: 14px;
font-weight: 600;
color: var(--color-text-normal);
display: flex;
align-items: center;
gap: 8px;
}
.action-card p {
margin: 0;
font-size: 12px;
color: var(--color-text-contrast-weakest);
line-height: 1.4;
}
.footer {
background: var(--color-area-bg);
border: 1px solid var(--color-border);
border-radius: 6px;
padding: 12px;
margin-top: 8px;
text-align: center;
font-size: 11px;
color: var(--color-text-contrast-weak);
flex-shrink: 0;
}
.footer a {
color: var(--color-primary);
text-decoration: none;
}
.footer a:hover {
text-decoration: underline;
}
.last-check {
margin-top: 4px;
font-size: 10px;
opacity: 0.7;
}
.loading-spinner {
display: inline-block;
width: 14px;
height: 14px;
border: 2px solid var(--color-border);
border-top: 2px solid var(--color-primary);
border-radius: 50%;
animation: spin 1s linear infinite;
margin-right: 6px;
vertical-align: middle;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.icon {
margin-right: 8px;
font-size: 16px;
}
/* 优化滚动条样式 */
.welcome-container::-webkit-scrollbar {
width: 8px;
}
.welcome-container::-webkit-scrollbar-track {
background: var(--color-area-bg);
border-radius: 4px;
}
.welcome-container::-webkit-scrollbar-thumb {
background: var(--color-border-emphasis);
border-radius: 4px;
opacity: 0.5;
}
.welcome-container::-webkit-scrollbar-thumb:hover {
background: var(--color-border-emphasis-strong);
opacity: 0.8;
}
/* 状态切换动画 */
.status-badge {
transition: all 0.3s ease;
}
.action-card {
transform: translateY(0);
transition: all 0.2s ease;
}
.action-card:hover:not(.disabled) {
background: var(--color-area-bg-hover);
border-color: var(--color-primary-highlight);
transform: translateY(-1px);
}
.action-card.disabled {
opacity: 0.5;
cursor: not-allowed;
}
.action-card.disabled:hover {
background: var(--color-neutral-bg);
border-color: var(--color-border);
transform: none;
}
/* 响应式布局优化 */
@media (max-width: 600px) {
.welcome-container {
padding: 16px;
}
.header h1 {
font-size: 20px;
}
.status-item {
flex-direction: column;
align-items: flex-start;
}
.status-label {
min-width: auto;
margin-bottom: 4px;
}
}
/* 确保按钮文本不被截断 */
.management-buttons ui-button {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* 现有文件信息样式 */
.existing-files-info {
margin-top: 12px;
padding: 10px;
background: var(--color-area-bg);
border: 1px solid var(--color-border);
border-radius: 4px;
font-size: 11px;
}
.files-summary {
font-weight: 600;
color: var(--color-text-normal);
margin-bottom: 8px;
padding-bottom: 6px;
border-bottom: 1px solid var(--color-border);
}
.files-list,
.files-overflow {
max-height: 120px;
overflow-y: auto;
}
.file-item {
padding: 2px 0;
color: var(--color-text-contrast-weak);
font-family: var(--font-mono);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.more-files {
padding: 4px 0;
color: var(--color-text-contrast-weakest);
font-style: italic;
border-top: 1px solid var(--color-border);
margin-top: 4px;
padding-top: 6px;
}
/* 文件列表滚动条样式 */
.files-list::-webkit-scrollbar,
.files-overflow::-webkit-scrollbar {
width: 6px;
}
.files-list::-webkit-scrollbar-track,
.files-overflow::-webkit-scrollbar-track {
background: var(--color-area-bg);
border-radius: 3px;
}
.files-list::-webkit-scrollbar-thumb,
.files-overflow::-webkit-scrollbar-thumb {
background: var(--color-border);
border-radius: 3px;
}
.files-list::-webkit-scrollbar-thumb:hover,
.files-overflow::-webkit-scrollbar-thumb:hover {
background: var(--color-border-emphasis);
}

View File

@@ -0,0 +1,5 @@
<div class="ecs-welcome-panel">
<div id="app">
<ecs-welcome></ecs-welcome>
</div>
</div>

View File

@@ -0,0 +1,6 @@
<div class="counter">
<h2> {{counter}}</h2>
<ui-button class="blue"
@click="addition">+</ui-button>
<ui-button @click="subtraction">-</ui-button>
</div>

View File

@@ -0,0 +1,169 @@
<div class="welcome-container">
<!-- 头部欢迎区域 -->
<div class="header">
<h1>🎮 ECS Framework for Cocos Creator</h1>
<p>高性能实体组件系统框架</p>
</div>
<!-- 操作状态显示区域 -->
<div class="status-section" v-if="showOperationStatus">
<div class="status-title">📋 操作状态</div>
<div class="operation-status" :class="operationStatusType">
<div class="status-content">
<span v-if="operationStatusType === 'loading'" class="loading-spinner"></span>
<span class="status-icon">{{ getStatusIcon(operationStatusType) }}</span>
<span class="status-text">{{ operationStatusMessage }}</span>
</div>
<div v-if="operationStatusDetails" class="status-details">
{{ operationStatusDetails }}
</div>
</div>
</div>
<!-- 安装状态检测区域 -->
<div class="status-section">
<div class="status-title">📦 安装状态检测</div>
<div class="status-item">
<span class="status-label">ECS Framework (@esengine/ecs-framework)</span>
<div v-if="checkingStatus" class="status-badge checking">
<span class="loading-spinner"></span>检测中...
</div>
<div v-else-if="ecsInstalled" class="status-badge installed">
✅ 已安装 <span class="version-info">v{{ecsVersion}}</span>
<span v-if="hasUpdate" class="update-hint">有新版本v{{latestVersion}}</span>
</div>
<div v-else class="status-badge not-installed">
❌ 未安装
</div>
</div>
<div class="status-item">
<span class="status-label">项目package.json</span>
<div v-if="packageJsonExists" class="status-badge installed">
✅ 存在
</div>
<div v-else class="status-badge not-installed">
❌ 不存在
</div>
</div>
<div class="status-item">
<span class="status-label">Node.js环境</span>
<div class="status-badge installed">
✅ v{{nodeVersion}}
</div>
</div>
</div>
<!-- ECS框架管理区域 -->
<div class="status-section" v-if="ecsInstalled">
<div class="status-title">🔧 ECS Framework 管理</div>
<div class="management-buttons">
<ui-button
class="green"
:disabled="!hasUpdate || updating"
@click="updateEcsFramework">
<span v-if="updating" class="loading-spinner"></span>
{{ updating ? '更新中...' : (hasUpdate ? `更新到 v${latestVersion}` : '已是最新版本') }}
</ui-button>
<ui-button
class="red"
:disabled="uninstalling"
@click="uninstallEcsFramework">
<span v-if="uninstalling" class="loading-spinner"></span>
{{ uninstalling ? '卸载中...' : '卸载 ECS Framework' }}
</ui-button>
<ui-button
class="blue"
@click="checkForUpdates">
🔄 检查更新
</ui-button>
</div>
</div>
<!-- 快速操作区域 -->
<div class="actions-section">
<div class="status-title">🚀 快速开始</div>
<div class="action-card" :class="{ disabled: !packageJsonExists || installing }" @click="installEcsFramework">
<h3>
<span class="icon">📥</span>
{{ ecsInstalled ? '重新安装 ECS Framework' : '安装 ECS Framework' }}
</h3>
<p v-if="installing">正在安装中,请稍候...</p>
<p v-else-if="!packageJsonExists">请先确保项目有package.json文件</p>
<p v-else-if="ecsInstalled">重新安装当前版本的ECS框架</p>
<p v-else>安装@esengine/ecs-framework到当前项目</p>
</div>
<div class="action-card" :class="{ disabled: !ecsInstalled }" @click="openDocumentation">
<h3>
<span class="icon">📚</span>
查看文档
</h3>
<p>打开ECS框架完整使用文档和教程</p>
</div>
<div class="action-card" :class="{ disabled: !ecsInstalled || templateExists }" @click="createEcsTemplate">
<h3>
<span class="icon">🛠️</span>
创建ECS模板
</h3>
<p v-if="!ecsInstalled">请先安装 ECS Framework</p>
<p v-else-if="templateExists">⚠️ ECS模板已存在避免覆盖现有代码</p>
<p v-else>生成基础的ECS项目结构和启动代码</p>
<div v-if="templateExists && existingFiles.length > 0" class="existing-files-info">
<div class="files-summary">
检测到 {{existingFiles.length}} 个已存在的文件
</div>
<div class="files-list" v-if="existingFiles.length <= 10">
<div v-for="file in existingFiles" :key="file" class="file-item">
📄 {{file}}
</div>
</div>
<div v-else class="files-overflow">
<div v-for="file in existingFiles.slice(0, 8)" :key="file" class="file-item">
📄 {{file}}
</div>
<div class="more-files">... 还有 {{existingFiles.length - 8}} 个文件</div>
</div>
</div>
</div>
<div class="action-card" @click="openSettings">
<h3>
<span class="icon">⚙️</span>
插件设置
</h3>
<p>配置ECS插件的各项设置和偏好</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 v-if="lastCheckTime" class="last-check">最后检查时间: {{lastCheckTime}}</p>
</div>
</div>

View File

@@ -0,0 +1,11 @@
{
"extends": "./base.tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./source",
"types": [
"node",
"@cocos/creator-types/editor",
]
}
}

View File

@@ -0,0 +1,21 @@
{
"name": "cocos-ecs",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cocos-ecs",
"dependencies": {
"@esengine/ecs-framework": "^2.1.19"
}
},
"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==",
"engines": {
"node": ">=16.0.0"
}
}
}
}

View File

@@ -0,0 +1,10 @@
{
"name": "cocos-ecs",
"uuid": "e17e4eb7-dfe2-4f87-b77d-13c36da216e3",
"creator": {
"version": "3.8.6"
},
"dependencies": {
"@esengine/ecs-framework": "^2.1.19"
}
}

View File

@@ -0,0 +1,3 @@
{
"__version__": "1.3.9"
}

View File

@@ -0,0 +1,3 @@
{
"__version__": "1.0.1"
}

View File

@@ -0,0 +1,3 @@
{
"__version__": "1.0.12"
}

View File

@@ -0,0 +1,23 @@
{
"__version__": "1.0.1",
"information": {
"customSplash": {
"id": "customSplash",
"label": "customSplash",
"enable": false,
"customSplash": {
"complete": false,
"form": "https://creator-api.cocos.com/api/form/show?"
}
},
"removeSplash": {
"id": "removeSplash",
"label": "removeSplash",
"enable": false,
"removeSplash": {
"complete": false,
"form": "https://creator-api.cocos.com/api/form/show?"
}
}
}
}

View File

@@ -0,0 +1,3 @@
{
"__version__": "1.0.4"
}

View File

@@ -0,0 +1,3 @@
{
"__version__": "1.0.6"
}

View File

@@ -0,0 +1,9 @@
{
/* Base configuration. Do not edit this field. */
"extends": "./temp/tsconfig.cocos.json",
/* Add your custom configuration here. */
"compilerOptions": {
"strict": false
}
}