UNPKG

@esengine/cocos-nexus

Version:

类似Unity Odin Inspector的Cocos Creator插件开发框架 - 用TypeScript完全重新定义插件UI开发体验

1,707 lines (1,653 loc) 300 kB
'use strict'; require('reflect-metadata'); var require$$0 = require('fs'); var require$$1 = require('path'); var require$$4 = require('@/UI'); 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]) => { variables.push(` --nexus-shadow-${key}: ${value};`); }); // 动画变量 Object.entries(theme.animations.duration).forEach(([key, value]) => { variables.push(` --nexus-duration-${key}: ${value}ms;`); }); Object.entries(theme.animations.easing).forEach(([key, value]) => { variables.push(` --nexus-easing-${key}: ${value};`); }); return variables.join('\n'); } /** * 将驼峰命名转换为kebab-case */ kebabCase(str) { return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); } /** * 触发主题变更事件 */ dispatchThemeChangeEvent(themeName, theme) { if (typeof window !== 'undefined' && window.dispatchEvent) { const event = new CustomEvent('nexus-theme-change', { detail: { themeName, theme } }); window.dispatchEvent(event); } } /** * 获取CSS变量值 */ getCSSVariable(name) { if (typeof document === 'undefined') return ''; const value = getComputedStyle(document.documentElement).getPropertyValue(`--nexus-${name}`); return value.trim(); } /** * 设置CSS变量 */ setCSSVariable(name, value) { if (typeof document === 'undefined') return; document.documentElement.style.setProperty(`--nexus-${name}`, value); } /** * 获取主题变量 */ getThemeVariables(themeName) { const theme = themeName ? this.getTheme(themeName) : this.getCurrentTheme(); if (!theme) return {}; const variables = {}; // 展开所有主题属性为平面变量 Object.entries(theme.colors).forEach(([key, value]) => { variables[`color-${this.kebabCase(key)}`]