@esengine/cocos-nexus
Version:
类似Unity Odin Inspector的Cocos Creator插件开发框架 - 用TypeScript完全重新定义插件UI开发体验
1,651 lines (1,598 loc) • 309 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('reflect-metadata'), require('fs'), require('path'), require('@/UI')) :
typeof define === 'function' && define.amd ? define(['reflect-metadata', 'fs', 'path', '@/UI'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.CocosNexus = factory(null, global.require$$0, global.require$$1, global.require$$4));
})(this, (function (reflectMetadata, require$$0, require$$1, require$$4) { 'use strict';
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var dist = {};
var NexusPlugin = {};
var Types = {};
var hasRequiredTypes;
function requireTypes () {
if (hasRequiredTypes) return Types;
hasRequiredTypes = 1;
Object.defineProperty(Types, "__esModule", { value: true });
Types.NEXUS_THEME_METADATA = Types.NEXUS_PROPERTY_METADATA = Types.NEXUS_COMPONENT_METADATA = Types.NEXUS_PANEL_METADATA = Types.NEXUS_PLUGIN_METADATA = void 0;
// 装饰器元数据
Types.NEXUS_PLUGIN_METADATA = Symbol('nexus:plugin');
Types.NEXUS_PANEL_METADATA = Symbol('nexus:panel');
Types.NEXUS_COMPONENT_METADATA = Symbol('nexus:component');
Types.NEXUS_PROPERTY_METADATA = Symbol('nexus:property');
Types.NEXUS_THEME_METADATA = Symbol('nexus:theme');
return Types;
}
var NexusExtension = {};
var NexusAutoWatcher = {};
var hasRequiredNexusAutoWatcher;
function requireNexusAutoWatcher () {
if (hasRequiredNexusAutoWatcher) return NexusAutoWatcher;
hasRequiredNexusAutoWatcher = 1;
/**
* @fileoverview Nexus自动文件监听器 - 高性能零配置文件监听系统
* @description 提供高性能的文件监听功能,包含防抖机制、智能过滤、性能监控和内存优化
*
* @author ESEngine Team
* @version 2.1.0
* @since 1.0.0
* @license MIT
*
* @example
* ```typescript
* const watcher = NexusAutoWatcher.getInstance();
* watcher.start();
*
* // 获取性能指标
* const metrics = watcher.getPerformanceMetrics();
* console.log('监听性能:', metrics);
*
* // 自定义过滤规则
* watcher.addFilterRule(/\.test\.ts$/, 'exclude', 10);
* ```
*/
var __createBinding = (NexusAutoWatcher && NexusAutoWatcher.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (NexusAutoWatcher && NexusAutoWatcher.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (NexusAutoWatcher && NexusAutoWatcher.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(NexusAutoWatcher, "__esModule", { value: true });
NexusAutoWatcher.AutoWatcher = NexusAutoWatcher.NexusAutoWatcher = NexusAutoWatcher.SmartFileFilter = void 0;
const fs = __importStar(require$$0);
const path = __importStar(require$$1);
/**
* 智能文件过滤器
*
* @description 提供基于规则的文件过滤功能,支持自定义过滤条件和优先级
* @class SmartFileFilter
* @since 2.1.0
*/
class SmartFileFilter {
/**
* 构造函数,初始化默认过滤规则
*
* @since 2.1.0
*/
constructor() {
this.filterRules = [];
this.cache = new Map();
this.cacheHits = 0;
this.cacheTotal = 0;
this.initializeDefaultRules();
}
/**
* 初始化默认过滤规则
*
* @private
* @since 2.1.0
*/
initializeDefaultRules() {
// 包含规则
this.addRule(/\.ts$/, 'include', 100, 'TypeScript源文件');
this.addRule(/\.js$/, 'include', 90, 'JavaScript源文件');
this.addRule(/\.json$/, 'include', 80, 'JSON配置文件');
// 排除规则
this.addRule(/node_modules/, 'exclude', 200, '排除node_modules');
this.addRule(/\.d\.ts$/, 'exclude', 150, '排除类型声明文件');
this.addRule(/\.git/, 'exclude', 180, '排除Git文件');
this.addRule(/dist\/|build\/|out\//, 'exclude', 170, '排除构建输出');
this.addRule(/\.log$/, 'exclude', 160, '排除日志文件');
this.addRule(/\.tmp$|\.temp$/, 'exclude', 140, '排除临时文件');
}
/**
* 添加过滤规则
*
* @param pattern 正则表达式模式
* @param action 动作类型
* @param priority 优先级(数字越大优先级越高)
* @param description 规则描述
*
* @since 2.1.0
*/
addRule(pattern, action, priority = 0, description) {
this.filterRules.push({ pattern, action, priority, description });
this.filterRules.sort((a, b) => b.priority - a.priority);
this.clearCache();
}
/**
* 移除过滤规则
*
* @param pattern 要移除的规则模式
* @returns 是否成功移除
*
* @since 2.1.0
*/
removeRule(pattern) {
const index = this.filterRules.findIndex(rule => rule.pattern.source === pattern.source);
if (index > -1) {
this.filterRules.splice(index, 1);
this.clearCache();
return true;
}
return false;
}
/**
* 检查文件是否应该被处理
*
* @param filePath 文件路径
* @returns 是否应该处理
*
* @since 2.1.0
*/
shouldProcess(filePath) {
this.cacheTotal++;
// 检查缓存
if (this.cache.has(filePath)) {
this.cacheHits++;
return this.cache.get(filePath);
}
// 应用过滤规则
let result = false; // 默认不处理
for (const rule of this.filterRules) {
if (rule.pattern.test(filePath)) {
result = rule.action === 'include';
break;
}
}
// 缓存结果
this.cache.set(filePath, result);
// 限制缓存大小
if (this.cache.size > 1000) {
this.clearCache();
}
return result;
}
/**
* 获取缓存命中率
*
* @returns 缓存命中率 (0-1)
*
* @since 2.1.0
*/
getCacheHitRate() {
return this.cacheTotal > 0 ? this.cacheHits / this.cacheTotal : 0;
}
/**
* 清理缓存
*
* @since 2.1.0
*/
clearCache() {
this.cache.clear();
this.cacheHits = 0;
this.cacheTotal = 0;
}
/**
* 获取所有过滤规则
*
* @returns 过滤规则数组
*
* @since 2.1.0
*/
getRules() {
return [...this.filterRules];
}
}
NexusAutoWatcher.SmartFileFilter = SmartFileFilter;
/**
* Nexus自动文件监听器
*
* @description 提供高性能的零配置文件监听功能,包含:
* - 防抖机制和性能优化
* - 智能文件过滤系统
* - 内存管理和监控
* - 详细的性能指标
*
* @class NexusAutoWatcher
* @since 1.0.0
* @version 2.1.0
*
* @example
* ```typescript
* const watcher = NexusAutoWatcher.getInstance();
*
* // 启动监听
* watcher.start();
*
* // 添加自定义过滤规则
* watcher.addFilterRule(/\.spec\.ts$/, 'exclude', 120);
*
* // 获取性能指标
* const metrics = watcher.getPerformanceMetrics();
* console.log('平均响应时间:', metrics.averageResponseTime);
*
* // 停止监听
* watcher.stop();
* ```
*/
let NexusAutoWatcher$1 = class NexusAutoWatcher {
/**
* 私有构造函数(单例模式)
*
* @private
* @since 1.0.0
*/
constructor() {
this.watchers = [];
this.debounceTimers = new Map();
this.isWatching = false;
this.processingQueue = new Map();
/** 自动监听器配置 */
this.config = {
enabled: true,
debounceTime: 300,
autoStart: true,
maxFiles: 10000,
memoryThreshold: 100
};
this.fileFilter = new SmartFileFilter();
this.performanceMetrics = this.initializeMetrics();
this.setupMemoryMonitoring();
if (this.config.autoStart && typeof process !== 'undefined') {
setTimeout(() => this.start(), 1000);
}
}
/**
* 获取单例实例
*
* @returns NexusAutoWatcher实例
* @since 1.0.0
*/
static getInstance() {
if (!NexusAutoWatcher.instance) {
NexusAutoWatcher.instance = new NexusAutoWatcher();
}
return NexusAutoWatcher.instance;
}
/**
* 初始化性能指标
*
* @private
* @returns 初始化的性能指标
* @since 2.1.0
*/
initializeMetrics() {
return {
watchCount: 0,
processCount: 0,
filteredCount: 0,
averageResponseTime: 0,
lastTriggerTime: 0,
memoryUsage: 0,
watchedDirectories: 0,
cacheHitRate: 0
};
}
/**
* 设置内存监控
*
* @private
* @since 2.1.0
*/
setupMemoryMonitoring() {
if (typeof process !== 'undefined') {
setInterval(() => {
const memUsage = process.memoryUsage();
this.performanceMetrics.memoryUsage = memUsage.heapUsed / 1024 / 1024;
// 检查内存阈值
if (this.performanceMetrics.memoryUsage > (this.config.memoryThreshold || 100)) {
this.performMemoryOptimization();
}
}, 5000);
}
}
/**
* 执行内存优化
*
* @private
* @since 2.1.0
*/
performMemoryOptimization() {
console.warn('🔥 内存使用过高,执行优化...');
// 清理防抖定时器
this.clearAllTimers();
// 清理文件过滤器缓存
this.fileFilter.clearCache();
// 清理处理队列
this.processingQueue.clear();
// 触发垃圾回收
if (commonjsGlobal.gc) {
commonjsGlobal.gc();
}
console.log('✅ 内存优化完成');
}
/**
* 启动自动监听
*
* @description 在错误隔离环境中启动文件监听,确保监听器错误不会影响主程序
* @public
* @since 1.0.0
*/
start() {
if (!this.config.enabled || this.isWatching)
return;
console.log('🚀 Nexus自动监听器启动 - 零配置高性能文件监听!');
try {
const srcPath = this.findSourceDirectory();
if (srcPath) {
this.watchDirectory(srcPath);
this.isWatching = true;
this.performanceMetrics.watchedDirectories = 1;
console.log(`👁️ 正在监听: ${srcPath}`);
console.log('✨ 文件变化将自动触发重新生成,享受零配置开发体验!');
console.log(`📊 性能优化已启用 - 防抖: ${this.config.debounceTime}ms`);
}
}
catch (error) {
console.error('❌ 启动自动监听失败:', error);
}
}
/**
* 停止监听
*
* @description 停止所有文件监听并清理资源
* @public
* @since 1.0.0
*/
stop() {
if (!this.isWatching)
return;
this.watchers.forEach(watcher => watcher.close());
this.watchers = [];
this.clearAllTimers();
this.processingQueue.clear();
this.isWatching = false;
this.performanceMetrics.watchedDirectories = 0;
console.log('🛑 Nexus自动监听器已停止');
}
/**
* 查找源代码目录
*
* @private
* @returns 源代码目录路径或null
* @since 1.0.0
*/
findSourceDirectory() {
const possiblePaths = [
path.join(process.cwd(), 'src'),
path.join(process.cwd(), 'plugins'),
path.join(process.cwd(), 'panels'),
process.cwd()
];
for (const dirPath of possiblePaths) {
if (fs.existsSync(dirPath)) {
return dirPath;
}
}
return null;
}
/**
* 监听目录
*
* @private
* @param dirPath 目录路径
* @since 1.0.0
*/
watchDirectory(dirPath) {
try {
const watcher = fs.watch(dirPath, { recursive: true }, (eventType, filename) => {
if (!filename)
return;
const filePath = path.join(dirPath, filename);
this.handleFileChange(filePath, eventType);
});
this.watchers.push(watcher);
}
catch (error) {
console.error(`❌ 监听目录失败: ${dirPath}`, error);
}
}
/**
* 处理文件变化
*
* @private
* @param filePath 文件路径
* @param eventType 事件类型
* @since 1.0.0
*/
handleFileChange(filePath, eventType) {
const startTime = performance.now();
this.performanceMetrics.watchCount++;
// 智能过滤
if (!this.fileFilter.shouldProcess(filePath)) {
this.performanceMetrics.filteredCount++;
return;
}
// 防抖处理
const timer = this.debounceTimers.get(filePath);
if (timer)
clearTimeout(timer);
this.debounceTimers.set(filePath, setTimeout(() => {
this.processFileChange(filePath, eventType, startTime);
this.debounceTimers.delete(filePath);
}, this.config.debounceTime));
}
/**
* 处理文件变化(防抖后)
*
* @private
* @param filePath 文件路径
* @param eventType 事件类型
* @param startTime 开始时间
* @since 1.0.0
*/
processFileChange(filePath, eventType, startTime) {
try {
// 检查文件是否存在
if (!fs.existsSync(filePath)) {
if (eventType === 'rename') {
console.log(`📁 文件已删除: ${path.basename(filePath)}`);
}
return;
}
const content = fs.readFileSync(filePath, 'utf-8');
// 检查是否是Nexus文件
if (this.isNexusFile(content)) {
console.log(`🔄 检测到Nexus文件变化: ${path.basename(filePath)}`);
this.regeneratePlugin(filePath, content);
this.performanceMetrics.processCount++;
}
// 更新性能指标
const endTime = performance.now();
const responseTime = endTime - startTime;
this.updatePerformanceMetrics(responseTime);
}
catch (error) {
console.error(`❌ 处理文件变化失败: ${filePath}`, error);
}
}
/**
* 更新性能指标
*
* @private
* @param responseTime 响应时间
* @since 2.1.0
*/
updatePerformanceMetrics(responseTime) {
this.performanceMetrics.lastTriggerTime = Date.now();
this.performanceMetrics.averageResponseTime =
(this.performanceMetrics.averageResponseTime + responseTime) / 2;
this.performanceMetrics.cacheHitRate = this.fileFilter.getCacheHitRate();
}
/**
* 检查是否是Nexus文件
*
* @private
* @param content 文件内容
* @returns 是否是Nexus文件
* @since 1.0.0
*/
isNexusFile(content) {
return content.includes('@Plugin') ||
content.includes('@Panel') ||
content.includes('extends NexusPlugin') ||
content.includes('extends NexusPanel');
}
/**
* 重新生成插件
*
* @private
* @param filePath 文件路径
* @param content 文件内容
* @since 1.0.0
*/
regeneratePlugin(filePath, content) {
try {
const pluginName = this.extractPluginName(content) || path.basename(filePath, '.ts');
const outputDir = this.getOutputDirectory();
if (!outputDir) {
console.log('📝 未找到输出目录,跳过文件生成');
return;
}
// 确保输出目录存在
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
// 生成主文件
const mainContent = this.generateMainFile(content);
const mainPath = path.join(outputDir, 'main.ts');
fs.writeFileSync(mainPath, mainContent, 'utf-8');
// 生成package.json
const packageContent = this.generatePackageJson(pluginName);
const packagePath = path.join(outputDir, 'package.json');
fs.writeFileSync(packagePath, packageContent, 'utf-8');
console.log(`✅ 自动重新生成完成: ${pluginName}`);
console.log(`📁 输出目录: ${outputDir}`);
}
catch (error) {
console.error('❌ 重新生成插件失败:', error);
}
}
/**
* 提取插件名称
*
* @private
* @param content 文件内容
* @returns 插件名称或null
* @since 1.0.0
*/
extractPluginName(content) {
const match = content.match(/@Plugin\s*\(\s*\{[^}]*name\s*:\s*['"](.*?)['"][^}]*\}/);
return match ? match[1] : null;
}
/**
* 获取输出目录
*
* @private
* @returns 输出目录路径或null
* @since 1.0.0
*/
getOutputDirectory() {
const possibleDirs = [
path.join(process.cwd(), 'dist'),
path.join(process.cwd(), 'build'),
path.join(process.cwd(), 'output'),
path.join(process.cwd(), 'generated')
];
for (const dir of possibleDirs) {
if (fs.existsSync(dir)) {
return dir;
}
}
// 如果都不存在,创建默认的dist目录
const defaultDir = path.join(process.cwd(), 'dist');
return defaultDir;
}
/**
* 生成主文件内容
*
* @private
* @param sourceContent 源文件内容
* @returns 生成的主文件内容
* @since 1.0.0
*/
generateMainFile(sourceContent) {
const pluginName = this.extractPluginName(sourceContent) || 'UnknownPlugin';
return `// 自动生成的插件主文件
// 生成时间: ${new Date().toISOString()}
// 源文件: ${sourceContent.split('\n')[0]}
import { NexusPlugin } from '@esengine/cocos-nexus';
${sourceContent}
// 导出插件实例
export default new ${pluginName}();
`;
}
/**
* 生成package.json内容
*
* @private
* @param pluginName 插件名称
* @returns 生成的package.json内容
* @since 1.0.0
*/
generatePackageJson(pluginName) {
const packageConfig = {
name: pluginName.toLowerCase(),
version: '1.0.0',
description: `${pluginName} - Nexus Plugin`,
main: './main.js',
contributions: {
profile: {
editor: {
label: pluginName,
icon: './icon.png'
}
}
},
engines: {
'cocos-creator': '>=3.3.0'
},
nexus: {
generated: true,
timestamp: new Date().toISOString()
}
};
return JSON.stringify(packageConfig, null, 2);
}
/**
* 清理所有定时器
*
* @private
* @since 1.0.0
*/
clearAllTimers() {
for (const timer of this.debounceTimers.values()) {
clearTimeout(timer);
}
this.debounceTimers.clear();
}
/**
* 添加文件过滤规则
*
* @param pattern 正则表达式模式
* @param action 过滤动作
* @param priority 优先级
* @param description 规则描述
*
* @public
* @since 2.1.0
*/
addFilterRule(pattern, action, priority = 0, description) {
this.fileFilter.addRule(pattern, action, priority, description);
}
/**
* 移除文件过滤规则
*
* @param pattern 要移除的规则模式
* @returns 是否成功移除
*
* @public
* @since 2.1.0
*/
removeFilterRule(pattern) {
return this.fileFilter.removeRule(pattern);
}
/**
* 获取监听状态
*
* @returns 监听状态对象
* @since 1.0.0
*/
getStatus() {
return {
watching: this.isWatching,
watchedDirectories: this.watchers.length,
config: { ...this.config }
};
}
/**
* 获取性能监控数据
*
* @returns 性能监控数据
* @since 2.1.0
*/
getPerformanceMetrics() {
return { ...this.performanceMetrics };
}
/**
* 重置性能监控数据
*
* @since 2.1.0
*/
resetPerformanceMetrics() {
this.performanceMetrics = this.initializeMetrics();
this.fileFilter.clearCache();
}
/**
* 打印性能报告
*
* @since 2.1.0
*/
printPerformanceReport() {
const metrics = this.performanceMetrics;
const efficiency = metrics.watchCount > 0 ?
((metrics.watchCount - metrics.filteredCount) / metrics.watchCount * 100).toFixed(1) : 0;
console.group('🚀 NexusAutoWatcher 性能报告');
console.log(`监听触发次数: ${metrics.watchCount}`);
console.log(`文件处理次数: ${metrics.processCount}`);
console.log(`过滤掉的文件: ${metrics.filteredCount}`);
console.log(`过滤效率: ${efficiency}%`);
console.log(`平均响应时间: ${metrics.averageResponseTime.toFixed(2)}ms`);
console.log(`缓存命中率: ${(metrics.cacheHitRate * 100).toFixed(1)}%`);
console.log(`内存使用量: ${metrics.memoryUsage.toFixed(2)}MB`);
console.log(`监听目录数: ${metrics.watchedDirectories}`);
console.groupEnd();
}
/**
* 更新配置
*
* @param newConfig 新配置
* @since 1.0.0
*/
updateConfig(newConfig) {
this.config = { ...this.config, ...newConfig };
// 如果监听状态发生变化,重新启动
if (newConfig.enabled !== undefined) {
if (newConfig.enabled && !this.isWatching) {
this.start();
}
else if (!newConfig.enabled && this.isWatching) {
this.stop();
}
}
}
/**
* 获取所有过滤规则
*
* @returns 过滤规则数组
* @since 2.1.0
*/
getFilterRules() {
return this.fileFilter.getRules();
}
/**
* 清理缓存
*
* @since 2.1.0
*/
clearCache() {
this.fileFilter.clearCache();
}
};
NexusAutoWatcher.NexusAutoWatcher = NexusAutoWatcher$1;
// 便捷导出
NexusAutoWatcher.AutoWatcher = NexusAutoWatcher$1.getInstance();
return NexusAutoWatcher;
}
var hasRequiredNexusExtension;
function requireNexusExtension () {
if (hasRequiredNexusExtension) return NexusExtension;
hasRequiredNexusExtension = 1;
Object.defineProperty(NexusExtension, "__esModule", { value: true });
NexusExtension.NexusExtension = void 0;
const NexusAutoWatcher_1 = requireNexusAutoWatcher();
/**
* Nexus扩展管理器
* 用于集成到Cocos Creator的扩展系统
*/
let NexusExtension$1 = class NexusExtension {
constructor() {
this.plugins = new Map();
this.panels = new Map();
}
static get Instance() {
if (!NexusExtension.instance) {
NexusExtension.instance = new NexusExtension();
}
return NexusExtension.instance;
}
/**
* 注册插件
*/
registerPlugin(plugin) {
const name = plugin.getName();
if (this.plugins.has(name)) {
console.warn(`Plugin ${name} is already registered`);
return;
}
this.plugins.set(name, plugin);
plugin.onLoad();
console.log(`Plugin ${name} registered successfully`);
}
/**
* 注册面板
*/
registerPanel(name, panel) {
if (this.panels.has(name)) {
console.warn(`Panel ${name} is already registered`);
return;
}
this.panels.set(name, panel);
console.log(`Panel ${name} registered successfully`);
}
/**
* 获取插件
*/
getPlugin(name) {
return this.plugins.get(name);
}
/**
* 获取面板
*/
getPanel(name) {
return this.panels.get(name);
}
/**
* 获取所有插件
*/
getAllPlugins() {
return Array.from(this.plugins.values());
}
/**
* 获取所有面板
*/
getAllPanels() {
return Array.from(this.panels.values());
}
/**
* 卸载插件
*/
unregisterPlugin(name) {
const plugin = this.plugins.get(name);
if (plugin) {
plugin.onUnload();
this.plugins.delete(name);
console.log(`Plugin ${name} unregistered successfully`);
}
}
/**
* 卸载面板
*/
unregisterPanel(name) {
const panel = this.panels.get(name);
if (panel) {
panel.onDestroy();
this.panels.delete(name);
console.log(`Panel ${name} unregistered successfully`);
}
}
/**
* 启动扩展系统
*/
static async start() {
console.log('🚀 启动 Nexus 扩展系统...');
try {
// 启动自动文件监听器
console.log('📡 启动自动文件监听器...');
NexusAutoWatcher_1.AutoWatcher.start();
console.log('✅ Nexus 扩展系统已启动');
console.log('🎉 零配置开发体验已激活 - 无需手动运行watch命令!');
}
catch (error) {
console.error('❌ 启动扩展系统失败:', error);
throw error;
}
}
/**
* 停止扩展系统
*/
static async stop() {
console.log('🛑 停止 Nexus 扩展系统...');
try {
// 停止自动文件监听器
NexusAutoWatcher_1.AutoWatcher.stop();
console.log('✅ Nexus 扩展系统已停止');
}
catch (error) {
console.error('❌ 停止扩展系统失败:', error);
throw error;
}
}
/**
* 创建标准的Cocos面板定义
* 这是核心功能:将Nexus面板转换为Cocos面板
*/
createCocosPanel(nexusPanel, panelName) {
nexusPanel.getConfig();
// 生成面板HTML模板
const template = `
<div id="nexus-panel-${panelName}" style="width: 100%; height: 100%; overflow: auto;">
<div id="nexus-content-${panelName}" style="padding: 10px; height: 100%; box-sizing: border-box;"></div>
</div>
`;
// 生成面板CSS样式
const style = this.generatePanelStyles(panelName);
// 生成面板选择器
const $ = {
content: `#nexus-content-${panelName}`
};
// 生成面板方法
const methods = {
ready() {
console.log(`Nexus面板 ${panelName} 准备就绪`);
// 初始化面板
nexusPanel.onInit();
// 设置容器
const container = document.querySelector(`#nexus-content-${panelName}`);
if (container) {
nexusPanel.setContainer(container);
// 开始渲染循环
const renderLoop = () => {
if (nexusPanel) {
nexusPanel.render();
}
requestAnimationFrame(renderLoop);
};
renderLoop();
}
},
close() {
console.log(`Nexus面板 ${panelName} 关闭`);
nexusPanel.onDestroy();
}
};
// 返回完整的面板定义
const panelDefinition = {
template,
style,
$,
methods
};
return panelDefinition;
}
/**
* 生成面板样式
*/
generatePanelStyles(panelName) {
return `
#nexus-panel-${panelName} {
background-color: #f0f0f0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 14px;
color: #333;
}
.nexus-label {
margin: 4px 0;
padding: 2px 4px;
display: block;
}
.nexus-button {
margin: 2px;
padding: 6px 12px;
border: 1px solid #d0d0d0;
border-radius: 4px;
background-color: #fff;
cursor: pointer;
font-size: 14px;
transition: all 0.2s;
}
.nexus-button:hover {
background-color: #e8e8e8;
border-color: #b0b0b0;
}
.nexus-button:active {
background-color: #d0d0d0;
transform: translateY(1px);
}
.nexus-textfield {
margin: 2px;
padding: 6px 8px;
border: 1px solid #d0d0d0;
border-radius: 4px;
font-size: 14px;
width: 100%;
box-sizing: border-box;
}
.nexus-textfield:focus {
outline: none;
border-color: #007acc;
box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2);
}
.nexus-toggle-container {
display: flex;
align-items: center;
margin: 4px 0;
}
.nexus-toggle {
margin-right: 8px;
}
.nexus-dropdown {
margin: 2px;
padding: 6px 8px;
border: 1px solid #d0d0d0;
border-radius: 4px;
font-size: 14px;
background-color: #fff;
cursor: pointer;
}
.nexus-slider {
margin: 4px 0;
width: 100%;
}
.nexus-separator {
margin: 8px 0;
height: 1px;
background-color: #e0e0e0;
}
.nexus-tab-group {
display: flex;
margin: 4px 0;
border-bottom: 1px solid #e0e0e0;
}
.nexus-tab {
padding: 8px 16px;
cursor: pointer;
border: none;
background: none;
font-size: 14px;
transition: all 0.2s;
}
.nexus-tab:hover {
background-color: #f0f0f0;
}
.nexus-tab.active {
background-color: #007acc;
color: white;
}
`;
}
/**
* 生成Cocos Creator扩展的main.ts
*/
generateMainTs() {
const methods = [];
const imports = [];
// 生成面板相关方法
this.panels.forEach((panel, name) => {
const methodName = `open${name.charAt(0).toUpperCase() + name.slice(1)}`;
methods.push(`
'${methodName}'() {
Editor.Panel.open('${name}');
}`);
});
// 生成插件相关方法
this.plugins.forEach((plugin) => {
const config = plugin.getConfig();
if (config.menu) {
config.menu.forEach((menu) => {
methods.push(`
'${menu.action}'() {
// 插件方法实现
console.log('执行插件方法: ${menu.action}');
}`);
});
}
});
return `
import { NexusExtension } from '@esengine/cocos-nexus';
${imports.join('\n')}
export const methods = {${methods.join(',\n')}
};
export function load() {
console.log('Nexus Extension loaded');
}
export function unload() {
console.log('Nexus Extension unloaded');
}
`;
}
/**
* 生成面板文件内容
* 这是关键功能:自动生成符合Cocos标准的面板文件
*/
generatePanelFile(nexusPanel, panelName) {
const className = nexusPanel.constructor.name;
return `
import { ${className} } from '../${className}';
let panel: ${className} | null = null;
const template = \`
<div id="nexus-panel-${panelName}" style="width: 100%; height: 100%; overflow: auto;">
<div id="nexus-content-${panelName}" style="padding: 10px; height: 100%; box-sizing: border-box;"></div>
</div>
\`;
const style = \`
${this.generatePanelStyles(panelName)}
\`;
const $ = {
content: '#nexus-content-${panelName}'
};
const methods = {
ready() {
console.log('Nexus面板 ${panelName} 准备就绪');
try {
// 创建面板实例
panel = new ${className}({
title: "${nexusPanel.getConfig().title}",
width: ${nexusPanel.getConfig().width},
height: ${nexusPanel.getConfig().height},
dockable: ${nexusPanel.getConfig().dockable},
resizable: ${nexusPanel.getConfig().resizable}
});
// 初始化面板
panel.onInit();
// 设置容器
const container = document.querySelector('#nexus-content-${panelName}') as HTMLElement;
if (container) {
panel.setContainer(container);
// 开始渲染循环
const renderLoop = () => {
if (panel) {
panel.render();
}
requestAnimationFrame(renderLoop);
};
renderLoop();
}
} catch (error) {
console.error('面板初始化失败:', error);
}
},
close() {
console.log('Nexus面板 ${panelName} 关闭');
try {
if (panel) {
panel.onDestroy();
panel = null;
}
} catch (error) {
console.error('面板关闭失败:', error);
}
}
};
// 使用正确的 Editor.Panel.define() 格式导出面板定义
module.exports = Editor.Panel.define({
template,
style,
$,
methods
});
`;
}
/**
* 自动化插件集成
* 这是你需要的核心功能:让插件遵循你的规范
*/
integratePlugin(plugin) {
const config = plugin.getConfig();
const result = {
mainTs: '',
panelFiles: new Map(),
packageJson: {}
};
// 生成main.ts
result.mainTs = this.generatePluginMainTs(plugin);
// 生成面板文件
if (config.panels) {
Object.entries(config.panels).forEach(([panelName, panelConfig]) => {
const panel = this.panels.get(panelName);
if (panel) {
result.panelFiles.set(panelName, this.generatePanelFile(panel, panelName));
}
});
}
// 生成package.json配置
result.packageJson = this.generatePackageJson(plugin);
return result;
}
/**
* 生成插件的main.ts文件
*/
generatePluginMainTs(plugin) {
const config = plugin.getConfig();
const className = plugin.constructor.name;
const methods = [];
// 生成菜单方法
if (config.menu) {
config.menu.forEach((menu) => {
methods.push(`
'${menu.action}'() {
if (pluginInstance) {
// 调用插件方法
console.log('执行插件方法: ${menu.action}');
}
}`);
});
}
// 生成面板打开方法
if (config.panels) {
Object.keys(config.panels).forEach((panelName) => {
const methodName = `open-${panelName}-panel`;
methods.push(`
'${methodName}'() {
Editor.Panel.open('${config.name}.${panelName}');
}`);
});
}
return `
import { ${className} } from './${className}';
let pluginInstance: ${className} | null = null;
export const methods = {${methods.join(',')}
};
export function load() {
console.log('${config.name} 插件加载');
pluginInstance = new ${className}();
}
export function unload() {
console.log('${config.name} 插件卸载');
if (pluginInstance) {
pluginInstance.onUnload();
pluginInstance = null;
}
}
`;
}
/**
* 生成package.json配置
*/
generatePackageJson(plugin) {
const config = plugin.getConfig();
const packageJson = {
name: config.name,
package_version: 2,
version: config.version,
description: config.description,
author: config.author,
editor: ">=3.8.0",
main: "./dist/main.js",
panels: {},
contributions: {
menu: [],
messages: {}
}
};
// 生成菜单配置
if (config.menu) {
packageJson.contributions.menu = config.menu.map(menu => ({
path: menu.path,
label: menu.label,
message: menu.action
}));
// 生成消息配置
config.menu.forEach(menu => {
packageJson.contributions.messages[menu.action] = {
methods: [menu.action]
};
});
}
// 生成面板配置
if (config.panels) {
Object.entries(config.panels).forEach(([panelName, panelConfig]) => {
packageJson.panels[panelName] = {
title: panelConfig.title,
type: panelConfig.dockable !== false ? "dockable" : "simple",
main: `./dist/${panelName}`,
size: {
"min-width": Math.max(300, panelConfig.minWidth || 300),
"min-height": Math.max(200, panelConfig.minHeight || 200),
"width": panelConfig.width || 600,
"height": panelConfig.height || 400
}
};
});
}
return packageJson;
}
};
NexusExtension.NexusExtension = NexusExtension$1;
return NexusExtension;
}
var NexusThemeManager = {};
var hasRequiredNexusThemeManager;
function requireNexusThemeManager () {
if (hasRequiredNexusThemeManager) return NexusThemeManager;
hasRequiredNexusThemeManager = 1;
Object.defineProperty(NexusThemeManager, "__esModule", { value: true });
NexusThemeManager.ThemeManager = NexusThemeManager.NexusThemeManager = void 0;
/**
* Nexus主题管理器
* 负责主题注册、切换、CSS变量管理等
*/
let NexusThemeManager$1 = class NexusThemeManager {
constructor() {
this.themes = new Map();
this.currentTheme = 'default';
this.cssVariables = new Map();
this.styleElement = null;
this.initializeDefaultThemes();
this.createStyleElement();
}
static getInstance() {
if (!NexusThemeManager.instance) {
NexusThemeManager.instance = new NexusThemeManager();
}
return NexusThemeManager.instance;
}
/**
* 初始化默认主题
*/
initializeDefaultThemes() {
// 默认主题
this.registerTheme('default', {
name: 'Default',
colors: {
primary: '#2563eb',
primaryDark: '#1d4ed8',
secondary: '#64748b',
secondaryDark: '#475569',
background: '#ffffff',
surface: '#f8fafc',
surfaceVariant: '#e2e8f0',
text: '#1e293b',
textSecondary: '#64748b',
textOnPrimary: '#ffffff',
border: '#e2e8f0',
borderLight: '#f1f5f9',
success: '#22c55e',
warning: '#f59e0b',
error: '#ef4444',
info: '#3b82f6',
},
spacing: {
xs: 4,
sm: 8,
md: 16,
lg: 24,
xl: 32,
},
fonts: {
primary: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
secondary: 'Georgia, "Times New Roman", serif',
mono: 'Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace',
},
fontSize: {
xs: 12,
sm: 14,
md: 16,
lg: 18,
xl: 20,
},
borderRadius: {
sm: 4,
md: 8,
lg: 12,
},
shadows: {
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
},
animations: {
duration: {
fast: 150,
normal: 250,
slow: 400,
},
easing: {
ease: 'cubic-bezier(0.4, 0, 0.2, 1)',
easeIn: 'cubic-bezier(0.4, 0, 1, 1)',
easeOut: 'cubic-bezier(0, 0, 0.2, 1)',
easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)',
},
},
});
// 暗色主题
this.registerTheme('dark', {
name: 'Dark',
colors: {
primary: '#3b82f6',
primaryDark: '#2563eb',
secondary: '#64748b',
secondaryDark: '#475569',
background: '#0f172a',
surface: '#1e293b',
surfaceVariant: '#334155',
text: '#f1f5f9',
textSecondary: '#94a3b8',
textOnPrimary: '#ffffff',
border: '#334155',
borderLight: '#475569',
success: '#22c55e',
warning: '#f59e0b',
error: '#ef4444',
info: '#3b82f6',
},
spacing: {
xs: 4,
sm: 8,
md: 16,
lg: 24,
xl: 32,
},
fonts: {
primary: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
secondary: 'Georgia, "Times New Roman", serif',
mono: 'Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace',
},
fontSize: {
xs: 12,
sm: 14,
md: 16,
lg: 18,
xl: 20,
},
borderRadius: {
sm: 4,
md: 8,
lg: 12,
},
shadows: {
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.3)',
md: '0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3)',
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3)',
},
animations: {
duration: {
fast: 150,
normal: 250,
slow: 400,
},
easing: {
ease: 'cubic-bezier(0.4, 0, 0.2, 1)',
easeIn: 'cubic-bezier(0.4, 0, 1, 1)',
easeOut: 'cubic-bezier(0, 0, 0.2, 1)',
easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)',
},
},
});
// Cocos Creator主题
this.registerTheme('cocos', {
name: 'Cocos Creator',
colors: {
primary: '#ff6b35',
primaryDark: '#e55a2b',
secondary: '#2c3e50',
secondaryDark: '#1a252f',
background: '#2c3e50',
surface: '#34495e',
surfaceVariant: '#4a5f7a',
text: '#ecf0f1',
textSecondary: '#95a5a6',
textOnPrimary: '#ffffff',
border: '#4a5f7a',
borderLight: '#5d6d7e',
success: '#27ae60',
warning: '#f39c12',
error: '#e74c3c',
info: '#3498db',
},
spacing: {
xs: 4,
sm: 8,
md: 16,
lg: 24,
xl: 32,
},
fonts: {
primary: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
secondary: 'Georgia, "Times New Roman", serif',
mono: 'Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace',
},
fontSize: {
xs: 12,
sm: 14,
md: 16,
lg: 18,
xl: 20,
},
borderRadius: {
sm: 4,
md: 8,
lg: 12,
},
shadows: {
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.3)',
md: '0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3)',
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3)',
},
animations: {
duration: {
fast: 150,
normal: 250,
slow: 400,
},
easing: {
ease: 'cubic-bezier(0.4, 0, 0.2, 1)',
easeIn: 'cubic-bezier(0.4, 0, 1, 1)',
easeOut: 'cubic-bezier(0, 0, 0.2, 1)',
easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)',
},
},
});
}
/**
* 创建样式元素
*/
createStyleElement() {
if (typeof document === 'undefined')
return;
this.styleElement = document.createElement('style');
this.styleElement.setAttribute('data-nexus-theme', 'true');
document.head.appendChild(this.styleElement);
}
/**
* 注册主题
*/
registerTheme(name, theme) {
this.themes.set(name, theme);
console.log(`主题 "${name}" 已注册`);
}
/**
* 获取主题
*/
getTheme(name) {
return this.themes.get(name);
}
/**
* 获取当前主题
*/
getCurrentTheme() {
return this.themes.get(this.currentTheme);
}
/**
* 获取所有主题名称
*/
getThemeNames() {
return Array.from(this.themes.keys());
}
/**
* 切换主题
*/
setTheme(name) {
const theme = this.themes.get(name);
if (!theme) {
console.error(`主题 "${name}" 不存在`);
return false;
}
this.currentTheme = name;
this.updateCSSVariables(theme);
// 触发主题变更事件
this.dispatchThemeChangeEvent(name, theme);
console.log(`主题已切换为 "${name}"`);
return true;
}
/**
* 更新CSS变量
*/
updateCSSVariables(theme) {
if (!this.styleElement)
return;
const variables = this.generateCSSVariables(theme);
this.styleElement.textContent = `:root {\n${variables}\n}`;
}
/**
* 生成CSS变量
*/
generateCSSVariables(theme) {
const variables = [];
// 颜色变量
Object.entries(theme.colors).forEach(([key, value]) => {
variables.push(` --nexus-color-${this.kebabCase(key)}: ${value};`);
});
// 间距变量
Object.entries(theme.spacing).forEach(([key, value]) => {
variables.push(` --nexus-spacing-${key}: ${value}px;`);
});
// 字体变量
Object.entries(theme.fonts).forEach(([key, value]) => {
variables.push(` --nexus-font-${key}: ${value};`);
});
// 字体大小变量
Object.entries(theme.fontSize).forEach(([key, value]) => {
variables.push(` --nexus-font-size-${key}: ${value}px;`);
});
// 圆角变量
Object.entries(theme.borderRadius).forEach(([key, value]) => {
variables.push(` --nexus-border-radius-${key}: ${value}px;`);
});
// 阴影变量
Object.entries(theme.shadows).forEach(([key, value]) => {
varia