Добавил Cocos Code Mode

This commit is contained in:
ftc
2026-09-13 09:43:24 +03:00
parent f0e745a734
commit ec44436c26
54 changed files with 7663 additions and 0 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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"]
}
}
}
@@ -0,0 +1,7 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"description": "其他扩展插件的扩展配置 / Extended configuration for other extension plugins",
"properties": {},
"required": []
}
@@ -0,0 +1,59 @@
{
"$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"]
}
+219
View File
@@ -0,0 +1,219 @@
# Code Mode for Cocos Creator
**Code Mode** turns the Cocos Creator Editor into an AI-controllable tool. It runs an HTTP server inside the editor that exposes scene manipulation, asset management, and property inspection as structured tool calls via [UTCP Protocol](https://www.utcp.io/) — letting AI agents build, inspect, and modify Cocos Creator projects the same way a developer would through the UI.
These tools are combined in [UTCP Code Mode](https://github.com/universal-tool-calling-protocol/code-mode/) environment to achieve maximum performance and token efficiency for AI agents, letting them call the tools in isolated JS sandbox.
## Tools
![Tools <> UI Mapping](tools_screenshot.jpg)
| Category | Tools | Purpose |
|----------|-------|---------|
| **Scene** | `nodeGetTree`, `nodeGetAtPath`, `nodeCreate`, `nodeCreatePrimitive`, `nodeOperate` | Navigate and build scene hierarchy |
| **Components** | `nodeComponentsGet`, `nodeComponentAdd`, `nodeComponentRemove`, `nodeGetAvailableComponentTypes` | Attach, remove, and discover components |
| **Inspector** | `inspectorGetInstanceDefinition`, `inspectorGetSettingsDefinition`, `inspectorGetInstanceProperties`, `inspectorGetSettingsProperties`, `inspectorSetInstanceProperties`, `inspectorSetSettingsProperties` | Introspect types and read/write properties |
| **Assets** | `assetGetTree`, `assetGetAtPath`, `assetCreate`, `assetImport`, `assetOperate`, `assetGetPreview` | Browse, create, and manage project assets |
| **Editor** | `editorOperate`, `editorGetLogs`, `editorGetScenePreview` | Control editor state and capture previews |
## How It Works
**Code Mode** follows a **discover, then act** pattern. AI agents never guess at property names or component structures — they query for the real definitions first.
```
1. Get the scene tree → find the node you need
2. Get its type definition → learn its actual properties
3. Set properties by name → make precise changes
```
### Example
```typescript
// Find the camera node
const tree = CocosEditor.nodeGetTree({});
const cameraRef = tree.children[0].components[0]; // component reference
// Discover what properties Camera has
const def = CocosEditor.inspectorGetInstanceDefinition({ reference: cameraRef });
// → "export class Camera { fov: number; near: number; far: number; ... }"
// Set multiple properties in one call
CocosEditor.inspectorSetInstanceProperties({
reference: cameraRef,
propertyPaths: ["fov", "near", "far"],
values: [60, 0.1, 1000]
});
```
## Architecture
### Tool Execution
The extension runs an Express.js HTTP server on a configurable port (default: auto-assigned). Tool handlers execute asynchronously using Cocos Creator's Editor Message API — all editor interactions go through `Editor.Message.request`, which marshals calls to the appropriate editor subsystem.
- **Read tools** (GET) — query scene state and return structured data immediately.
- **Write tools** (POST) — mutate scene state and call `Editor.Message.request('scene', 'snapshot')` to register the change as an undoable step.
This means AI agents can safely chain read calls and batch writes without blocking the editor.
### Tool Discovery
Tools are TypeScript class methods decorated with `@utcpTool`. The `ToolRegistry` collects them at startup, builds JSON schemas from the inline definitions, and serves a UTCP manual at the `/utcp` endpoint.
```typescript
export class SceneTools {
@utcpTool(
'nodeGetTree',
'Get the hierarchy tree of specific node or scene root if no reference is provided.',
{
type: 'object',
properties: {
reference: InstanceReferenceSchema
}
},
SceneTreeItemSchema, "GET", ['scene', 'graph', 'node', 'hierarchy', 'tree']
)
async nodeGetTree(args: { reference?: IInstanceReference }): Promise<ISceneTreeItem> {
// ...
}
}
```
### Instance References
Nodes, components, and assets are passed around as lightweight UUID-based handles:
```typescript
{ id: "a1b2c3d4-...", type: "cc.Camera" }
```
Returned by tree queries, component lookups, and creation tools. Passed back to any tool that needs to target a specific object.
### TypeScript Definitions
Code Mode dynamically generates TypeScript class definitions from the live editor property dump. When an AI agent calls `inspectorGetInstanceDefinition`, it receives a complete TypeScript class with the correct field names, types, enums, and decorator hints — including `@property` attributes like `min`, `max`, `unit`, and `tooltip`.
```typescript
// Example output for a Transform-like node
export class Node {
readonly uuid: string;
/** World position */
worldPosition: Vec3;
/** World rotation (euler angles) */
worldRotation: Vec3;
worldScale: Vec3;
active: boolean;
}
```
Components without special handling are reflected automatically from the serialized property dump. Common Cocos math types (`Vec2`, `Vec3`, `Vec4`, `Color`, `Rect`, `Quat`, `Mat4`, `Gradient`, etc.) are always available via `inspectorGetSettingsDefinition({ settingsType: 'CommonTypes' })`.
### Settings Inspection
Two special settings types can be inspected and modified directly:
- **`CurrentSceneGlobals`** — ambient light, skybox, shadows, and other scene-level rendering settings.
- **`ProjectSettings`** — engine and project configuration.
## Installation
### From release
1. Download last release from this repository.
2. Open Cocos Creator, go to **Extension → Extension Manager**, and click `Import Extension File(.zip)` button (icon with arrow).
3. Select the downloaded zip file.
4. The UTCP server starts automatically and registers itself in `~/.utcp_config.json` by default.
### Build from source
1. Clone this repository.
2. Install `node` and `npm`.
3. run
```bash
git clone https://github.com/romarogov/cocos-code-mode.git
cd cocos-code-mode
npm i
npm run package
```
4. If everything builds fine, `cocos-code-mode.zip` file should appear in repository root.
5. Install it in Cocos Creator with **Extension Manager**.
## Adding Custom Tools
You should add custom tools right in extension package and build it from source as described above.
Implementation example:
```typescript
import { utcpTool } from './utcp/decorators';
export class MyTools {
@utcpTool(
'myCustomTool',
'Describe what this tool does',
{
type: 'object',
properties: {
input: { type: 'string' },
count: { type: 'number', default: 10 }
},
required: ['input']
},
{ type: 'object', properties: { result: { type: 'string' } } },
"POST",
['custom', 'tags']
)
async myCustomTool(args: { input: string, count?: number }): Promise<{ result: string }> {
// Implementation
}
}
```
Register the class by importing it in `utcp-server.ts`. Tools are served automatically at startup. No additional registration needed.
## UTCP Call Templates Configuration
The extension provides a **Configuration** panel accessible from the **Code Mode** top menu. It shows the current server port, the path to the UTCP config file, and lets you manage additional UTCP call templates to connect other UTCP-compatible tool providers (including MCP servers) into the same Code Mode execution context.
You can find Call Template structures in [UTCP documentation](https://www.utcp.io/protocols):
- [MCP Call Template](https://utcp.io/protocols/mcp#call-template-structure)
- [HTTP Call Template](https://utcp.io/protocols/http#call-template-structure) ([Streamable](https://utcp.io/protocols/http#call-template-structure), [SSE](https://utcp.io/protocols/http#call-template-structure))
- [CLI Call Template](https://utcp.io/protocols/cli#call-template-structure)
- [Text Call Template](http://utcp.io/protocols/text#call-template-structure)
The extension automatically maintains a `CocosEditor` entry in UTCP Config pointing to the running server port.
## Integration
Code Mode works with any UTCP-compatible client, including the [Code Mode MCP server](https://github.com/universal-tool-calling-protocol/code-mode/?tab=readme-ov-file#even-easier-ready-to-use-mcp-server) for AI assistants.
### MCP Server Config
```json
{
"mcpServers": {
"code-mode": {
"command": "npx",
"args": ["@utcp/code-mode-mcp"],
"env": {
"UTCP_CONFIG_FILE": "~/.utcp_config.json"
}
}
}
}
```
### Claude Code Configuration
To set up a Claude Code agent to use Code Mode, open your project and run:
Linux/MacOS:
``` bash
claude mcp add --transport stdio --env UTCP_CONFIG_FILE="~/.utcp_config.json" -- code-mode npx @utcp/code-mode-mcp
```
Windows:
``` powershell
claude mcp add --transport stdio --env UTCP_CONFIG_FILE="%userprofile%/.utcp_config.json" -- code-mode cmd /c npx @utcp/code-mode-mcp
```
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+39
View File
@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ToolRegistry = void 0;
exports.utcpTool = utcpTool;
class ToolRegistry {
static register(options) {
this.tools.set(options.tool.name, options);
}
static getTools() {
return Array.from(this.tools.values());
}
}
exports.ToolRegistry = ToolRegistry;
ToolRegistry.tools = new Map();
function utcpTool(name, description, inputs, outputs, httpMethod, tags = []) {
return function (target, propertyKey, descriptor) {
if (!descriptor)
return;
ToolRegistry.register({
method: descriptor.value,
target,
tool: {
name,
description,
inputs,
outputs,
tags,
tool_call_template: {
call_template_type: "http",
http_method: httpMethod,
request_body_format: "json",
url: `/tools/${name}`,
content_type: "application/json"
},
}
});
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb3JhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS91dGNwL2RlY29yYXRvcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBcUJBLDRCQXVCQztBQW5DRCxNQUFhLFlBQVk7SUFHckIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFxQjtRQUNqQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBRUQsTUFBTSxDQUFDLFFBQVE7UUFDWCxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQzNDLENBQUM7O0FBVEwsb0NBVUM7QUFUa0Isa0JBQUssR0FBOEIsSUFBSSxHQUFHLEVBQUUsQ0FBQztBQVdoRSxTQUFnQixRQUFRLENBQUMsSUFBWSxFQUFFLFdBQW1CLEVBQUUsTUFBa0IsRUFBRSxPQUFtQixFQUFFLFVBQXVELEVBQUUsT0FBaUIsRUFBRTtJQUM3SyxPQUFPLFVBQVUsTUFBVyxFQUFFLFdBQW1CLEVBQUUsVUFBK0I7UUFDOUUsSUFBSSxDQUFDLFVBQVU7WUFBRSxPQUFPO1FBRXhCLFlBQVksQ0FBQyxRQUFRLENBQUM7WUFDbEIsTUFBTSxFQUFFLFVBQVUsQ0FBQyxLQUFLO1lBQ3hCLE1BQU07WUFDTixJQUFJLEVBQUU7Z0JBQ0YsSUFBSTtnQkFDSixXQUFXO2dCQUNYLE1BQU07Z0JBQ04sT0FBTztnQkFDUCxJQUFJO2dCQUNKLGtCQUFrQixFQUFFO29CQUNoQixrQkFBa0IsRUFBRSxNQUFNO29CQUMxQixXQUFXLEVBQUUsVUFBVTtvQkFDdkIsbUJBQW1CLEVBQUUsTUFBTTtvQkFDM0IsR0FBRyxFQUFFLFVBQVUsSUFBSSxFQUFFO29CQUNyQixZQUFZLEVBQUUsa0JBQWtCO2lCQUNmO2FBQ3hCO1NBQ0osQ0FBQyxDQUFDO0lBQ1AsQ0FBQyxDQUFDO0FBQ04sQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBDYWxsVGVtcGxhdGUgfSBmcm9tICdAdXRjcC9odHRwJztcbmltcG9ydCB7IEpzb25TY2hlbWEsIFRvb2wgfSBmcm9tICdAdXRjcC9zZGsnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFRvb2xNZXRhZGF0YSB7XG4gICAgbWV0aG9kOiBGdW5jdGlvbjtcbiAgICB0YXJnZXQ6IGFueTtcbiAgICB0b29sOiBUb29sO1xufVxuXG5leHBvcnQgY2xhc3MgVG9vbFJlZ2lzdHJ5IHtcbiAgICBwcml2YXRlIHN0YXRpYyB0b29sczogTWFwPHN0cmluZywgVG9vbE1ldGFkYXRhPiA9IG5ldyBNYXAoKTtcblxuICAgIHN0YXRpYyByZWdpc3RlcihvcHRpb25zOiBUb29sTWV0YWRhdGEpIHtcbiAgICAgICAgdGhpcy50b29scy5zZXQob3B0aW9ucy50b29sLm5hbWUsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXRUb29scygpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy50b29scy52YWx1ZXMoKSk7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdXRjcFRvb2wobmFtZTogc3RyaW5nLCBkZXNjcmlwdGlvbjogc3RyaW5nLCBpbnB1dHM6IEpzb25TY2hlbWEsIG91dHB1dHM6IEpzb25TY2hlbWEsIGh0dHBNZXRob2Q6ICdHRVQnIHwgJ1BPU1QnIHwgJ1BVVCcgfCAnREVMRVRFJyB8ICdQQVRDSCcsIHRhZ3M6IHN0cmluZ1tdID0gW10pIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldDogYW55LCBwcm9wZXJ0eUtleTogc3RyaW5nLCBkZXNjcmlwdG9yPzogUHJvcGVydHlEZXNjcmlwdG9yKSB7XG4gICAgICAgIGlmICghZGVzY3JpcHRvcikgcmV0dXJuO1xuXG4gICAgICAgIFRvb2xSZWdpc3RyeS5yZWdpc3Rlcih7XG4gICAgICAgICAgICBtZXRob2Q6IGRlc2NyaXB0b3IudmFsdWUsXG4gICAgICAgICAgICB0YXJnZXQsXG4gICAgICAgICAgICB0b29sOiB7XG4gICAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbixcbiAgICAgICAgICAgICAgICBpbnB1dHMsXG4gICAgICAgICAgICAgICAgb3V0cHV0cyxcbiAgICAgICAgICAgICAgICB0YWdzLFxuICAgICAgICAgICAgICAgIHRvb2xfY2FsbF90ZW1wbGF0ZToge1xuICAgICAgICAgICAgICAgICAgICBjYWxsX3RlbXBsYXRlX3R5cGU6IFwiaHR0cFwiLFxuICAgICAgICAgICAgICAgICAgICBodHRwX21ldGhvZDogaHR0cE1ldGhvZCxcbiAgICAgICAgICAgICAgICAgICAgcmVxdWVzdF9ib2R5X2Zvcm1hdDogXCJqc29uXCIsXG4gICAgICAgICAgICAgICAgICAgIHVybDogYC90b29scy8ke25hbWV9YCxcbiAgICAgICAgICAgICAgICAgICAgY29udGVudF90eXBlOiBcImFwcGxpY2F0aW9uL2pzb25cIlxuICAgICAgICAgICAgICAgIH0gYXMgSHR0cENhbGxUZW1wbGF0ZSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcbn1cbiJdfQ==
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,37 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GetPropertiesTool = void 0;
const decorators_1 = require("../decorators");
const schemas_1 = require("../schemas");
const tools_utils_1 = require("../utils/tools-utils");
class GetPropertiesTool {
async inspectorGetSettingsProperties(params) {
return await this.inspectorGetProperties({ reference: { id: params.settingsType } });
}
async inspectorGetProperties(args) {
const info = await tools_utils_1.ToolsUtils.inspectInstance(args.reference.id);
if (!info) {
throw new Error(`Target ${args.reference.id} not found or not supported.`);
}
const { props, type, assetInfo } = info;
if (!props) {
throw new Error(`Could not retrieve properties for ${type} (${args.reference.id}).`);
}
const parsedProps = tools_utils_1.ToolsUtils.unwrapProperties(props);
return { dump: parsedProps };
}
}
exports.GetPropertiesTool = GetPropertiesTool;
__decorate([
(0, decorators_1.utcpTool)("inspectorGetSettingsProperties", "Gets plain object of properties for the specific settings.", { type: 'object', properties: { settingsType: { type: 'string', enum: ['CurrentSceneGlobals', 'ProjectSettings'] } }, required: ['settingsType'] }, { type: 'object', properties: { dump: { type: 'object' } }, required: ['dump'] }, "GET", ['inspect', 'scene', 'properties', 'settings', 'config', 'dump'])
], GetPropertiesTool.prototype, "inspectorGetSettingsProperties", null);
__decorate([
(0, decorators_1.utcpTool)("inspectorGetInstanceProperties", "Gets plain object of properties, with no serialization info for any instance (scene node, component, asset).", { type: 'object', properties: { reference: schemas_1.InstanceReferenceSchema }, required: ['reference'] }, { type: 'object', properties: { dump: { type: 'object' } }, required: ['dump'] }, "GET", ['inspect', 'properties', 'dump', 'instance', 'node', 'component', 'asset', 'data'])
], GetPropertiesTool.prototype, "inspectorGetProperties", null);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LXByb3BlcnRpZXMtdG9vbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NvdXJjZS91dGNwL3Rvb2xzL2dldC1wcm9wZXJ0aWVzLXRvb2wudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUEsOENBQXlDO0FBQ3pDLHdDQUF5RTtBQUN6RSxzREFBa0Q7QUFFbEQsTUFBYSxpQkFBaUI7SUFRcEIsQUFBTixLQUFLLENBQUMsOEJBQThCLENBQUMsTUFBZ0M7UUFDakUsT0FBTyxNQUFNLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pGLENBQUM7SUFRSyxBQUFOLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxJQUF1QztRQUNoRSxNQUFNLElBQUksR0FBRyxNQUFNLHdCQUFVLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDakUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1IsTUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSw4QkFBOEIsQ0FBQyxDQUFDO1FBQy9FLENBQUM7UUFFRCxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsR0FBRyxJQUFJLENBQUM7UUFDeEMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1QsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQ0FBcUMsSUFBSSxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN6RixDQUFDO1FBRUQsTUFBTSxXQUFXLEdBQUcsd0JBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUV2RCxPQUFPLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxDQUFDO0lBQ2pDLENBQUM7Q0FDSjtBQWpDRCw4Q0FpQ0M7QUF6QlM7SUFOTCxJQUFBLHFCQUFRLEVBQ0wsZ0NBQWdDLEVBQ2hDLDREQUE0RCxFQUM1RCxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLEVBQUUsWUFBWSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUNsSixFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUcsQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUM3Sjt1RUFHQTtBQVFLO0lBTkwsSUFBQSxxQkFBUSxFQUNMLGdDQUFnQyxFQUNoQyw4R0FBOEcsRUFDOUcsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxFQUFFLFNBQVMsRUFBRSxpQ0FBdUIsRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQy9GLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRyxDQUFDLFNBQVMsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FDaEw7K0RBZUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB1dGNwVG9vbCB9IGZyb20gJy4uL2RlY29yYXRvcnMnO1xuaW1wb3J0IHsgSUluc3RhbmNlUmVmZXJlbmNlLCBJbnN0YW5jZVJlZmVyZW5jZVNjaGVtYSB9IGZyb20gJy4uL3NjaGVtYXMnO1xuaW1wb3J0IHsgVG9vbHNVdGlscyB9IGZyb20gJy4uL3V0aWxzL3Rvb2xzLXV0aWxzJztcblxuZXhwb3J0IGNsYXNzIEdldFByb3BlcnRpZXNUb29sIHtcblxuICAgIEB1dGNwVG9vbChcbiAgICAgICAgXCJpbnNwZWN0b3JHZXRTZXR0aW5nc1Byb3BlcnRpZXNcIixcbiAgICAgICAgXCJHZXRzIHBsYWluIG9iamVjdCBvZiBwcm9wZXJ0aWVzIGZvciB0aGUgc3BlY2lmaWMgc2V0dGluZ3MuXCIsXG4gICAgICAgIHsgdHlwZTogJ29iamVjdCcsIHByb3BlcnRpZXM6IHsgc2V0dGluZ3NUeXBlOiB7IHR5cGU6ICdzdHJpbmcnLCBlbnVtOiBbJ0N1cnJlbnRTY2VuZUdsb2JhbHMnLCAnUHJvamVjdFNldHRpbmdzJ10gfSB9LCByZXF1aXJlZDogWydzZXR0aW5nc1R5cGUnXSB9LFxuICAgICAgICB7IHR5cGU6ICdvYmplY3QnLCBwcm9wZXJ0aWVzOiB7IGR1bXA6IHsgdHlwZTogJ29iamVjdCcgfSB9LCByZXF1aXJlZDogWydkdW1wJ10gfSwgXCJHRVRcIiwgIFsnaW5zcGVjdCcsICdzY2VuZScsICdwcm9wZXJ0aWVzJywgJ3NldHRpbmdzJywgJ2NvbmZpZycsICdkdW1wJ11cbiAgICApXG4gICAgYXN5bmMgaW5zcGVjdG9yR2V0U2V0dGluZ3NQcm9wZXJ0aWVzKHBhcmFtczogeyBzZXR0aW5nc1R5cGU6IHN0cmluZyB9KTogUHJvbWlzZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuaW5zcGVjdG9yR2V0UHJvcGVydGllcyh7IHJlZmVyZW5jZTogeyBpZDogcGFyYW1zLnNldHRpbmdzVHlwZSB9IH0pO1xuICAgIH1cblxuICAgIEB1dGNwVG9vbChcbiAgICAgICAgXCJpbnNwZWN0b3JHZXRJbnN0YW5jZVByb3BlcnRpZXNcIixcbiAgICAgICAgXCJHZXRzIHBsYWluIG9iamVjdCBvZiBwcm9wZXJ0aWVzLCB3aXRoIG5vIHNlcmlhbGl6YXRpb24gaW5mbyBmb3IgYW55IGluc3RhbmNlIChzY2VuZSBub2RlLCBjb21wb25lbnQsIGFzc2V0KS5cIixcbiAgICAgICAgeyB0eXBlOiAnb2JqZWN0JywgcHJvcGVydGllczogeyByZWZlcmVuY2U6IEluc3RhbmNlUmVmZXJlbmNlU2NoZW1hIH0sIHJlcXVpcmVkOiBbJ3JlZmVyZW5jZSddIH0sXG4gICAgICAgIHsgdHlwZTogJ29iamVjdCcsIHByb3BlcnRpZXM6IHsgZHVtcDogeyB0eXBlOiAnb2JqZWN0JyB9IH0sIHJlcXVpcmVkOiBbJ2R1bXAnXSB9LCBcIkdFVFwiLCAgWydpbnNwZWN0JywgJ3Byb3BlcnRpZXMnLCAnZHVtcCcsICdpbnN0YW5jZScsICdub2RlJywgJ2NvbXBvbmVudCcsICdhc3NldCcsICdkYXRhJ11cbiAgICApXG4gICAgYXN5bmMgaW5zcGVjdG9yR2V0UHJvcGVydGllcyhhcmdzOiB7IHJlZmVyZW5jZTogSUluc3RhbmNlUmVmZXJlbmNlIH0pOiBQcm9taXNlPHsgZHVtcDogYW55IH0+IHtcbiAgICAgICAgY29uc3QgaW5mbyA9IGF3YWl0IFRvb2xzVXRpbHMuaW5zcGVjdEluc3RhbmNlKGFyZ3MucmVmZXJlbmNlLmlkKTtcbiAgICAgICAgaWYgKCFpbmZvKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRhcmdldCAke2FyZ3MucmVmZXJlbmNlLmlkfSBub3QgZm91bmQgb3Igbm90IHN1cHBvcnRlZC5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgcHJvcHMsIHR5cGUsIGFzc2V0SW5mbyB9ID0gaW5mbztcbiAgICAgICAgaWYgKCFwcm9wcykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgcmV0cmlldmUgcHJvcGVydGllcyBmb3IgJHt0eXBlfSAoJHthcmdzLnJlZmVyZW5jZS5pZH0pLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcGFyc2VkUHJvcHMgPSBUb29sc1V0aWxzLnVud3JhcFByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgIHJldHVybiB7IGR1bXA6IHBhcnNlZFByb3BzIH07XG4gICAgfVxufVxuXG4iXX0=
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseAssetImporter = void 0;
class BaseAssetImporter {
get className() {
// Default: Capitalize name + AssetImporter (e.g. image -> ImageAssetImporter)
return this.name.charAt(0).toUpperCase() + this.name.slice(1) + 'AssetImporter';
}
async setProperty(assetInfo, path, value) {
console.warn(`[BaseAssetImporter] setProperty not implemented for ${this.name}`);
return false;
}
}
exports.BaseAssetImporter = BaseAssetImporter;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1pbXBvcnRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NvdXJjZS91dGNwL3V0aWxzL2Fzc2V0LWltcG9ydGVycy9iYXNlLWltcG9ydGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQTZCQSxNQUFzQixpQkFBaUI7SUFHbkMsSUFBSSxTQUFTO1FBQ1QsOEVBQThFO1FBQzlFLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsZUFBZSxDQUFDO0lBQ3BGLENBQUM7SUFJRCxLQUFLLENBQUMsV0FBVyxDQUFDLFNBQXFCLEVBQUUsSUFBWSxFQUFFLEtBQVU7UUFDN0QsT0FBTyxDQUFDLElBQUksQ0FBQyx1REFBdUQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDakYsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztDQUNKO0FBZEQsOENBY0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJQXNzZXRJbmZvIH0gZnJvbSBcIkBjb2Nvcy9jcmVhdG9yLXR5cGVzL2VkaXRvci9wYWNrYWdlcy9hc3NldC1kYi9AdHlwZXMvcHVibGljXCI7XG5pbXBvcnQgeyBJUHJvcGVydHlWYWx1ZVR5cGUgfSBmcm9tICdAY29jb3MvY3JlYXRvci10eXBlcy9lZGl0b3IvcGFja2FnZXMvc2NlbmUvQHR5cGVzL3B1YmxpYyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUFzc2V0SW1wb3J0ZXIge1xuICAgIC8qKlxuICAgICAqIFRoZSBpbXBvcnRlciBuYW1lIHRoaXMgaGFuZGxlciBzdXBwb3J0cyAoZS5nLiAnbWF0ZXJpYWwnLCAndGV4dHVyZScsICd0eXBlc2NyaXB0JylcbiAgICAgKi9cbiAgICBuYW1lOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgXCJGYWtlXCIgQ2xhc3MgTmFtZSBmb3IgdGhpcyBpbXBvcnRlciAoZS5nLiAnTWF0ZXJpYWxBc3NldEltcG9ydGVyJylcbiAgICAgKi9cbiAgICBjbGFzc05hbWU6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGFjdHVhbCBwcm9wZXJ0aWVzIG9mIHRoZSBhc3NldCwgY29uZm9ybWluZyB0byB0aGUgZGVmaW5pdGlvblxuICAgICAqIEBwYXJhbSBhc3NldEluZm8gVGhlIGFzc2V0IGluZm8gb2JqZWN0IGZyb20gYXNzZXQtZGJcbiAgICAgKi9cbiAgICBnZXRQcm9wZXJ0aWVzKGFzc2V0SW5mbzogSUFzc2V0SW5mbyk6IFByb21pc2U8eyBba2V5OiBzdHJpbmddOiBJUHJvcGVydHlWYWx1ZVR5cGUgfT47XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGEgcHJvcGVydHkgb24gdGhlIGFzc2V0XG4gICAgICogQHBhcmFtIGFzc2V0SW5mbyBUaGUgYXNzZXQgaW5mbyBvYmplY3QgZnJvbSBhc3NldC1kYlxuICAgICAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXRcbiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldFxuICAgICAqL1xuICAgIHNldFByb3BlcnR5KGFzc2V0SW5mbzogSUFzc2V0SW5mbywgcGF0aDogc3RyaW5nLCB2YWx1ZTogYW55KTogUHJvbWlzZTxib29sZWFuPjtcbn1cblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VBc3NldEltcG9ydGVyIGltcGxlbWVudHMgSUFzc2V0SW1wb3J0ZXIge1xuICAgIGFic3RyYWN0IG5hbWU6IHN0cmluZztcbiAgICBcbiAgICBnZXQgY2xhc3NOYW1lKCk6IHN0cmluZyB7XG4gICAgICAgIC8vIERlZmF1bHQ6IENhcGl0YWxpemUgbmFtZSArIEFzc2V0SW1wb3J0ZXIgKGUuZy4gaW1hZ2UgLT4gSW1hZ2VBc3NldEltcG9ydGVyKVxuICAgICAgICByZXR1cm4gdGhpcy5uYW1lLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgdGhpcy5uYW1lLnNsaWNlKDEpICsgJ0Fzc2V0SW1wb3J0ZXInO1xuICAgIH1cblxuICAgIGFic3RyYWN0IGdldFByb3BlcnRpZXMoYXNzZXRJbmZvOiBJQXNzZXRJbmZvKTogUHJvbWlzZTx7IFtrZXk6IHN0cmluZ106IElQcm9wZXJ0eVZhbHVlVHlwZSB9PjtcblxuICAgIGFzeW5jIHNldFByb3BlcnR5KGFzc2V0SW5mbzogSUFzc2V0SW5mbywgcGF0aDogc3RyaW5nLCB2YWx1ZTogYW55KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIGNvbnNvbGUud2FybihgW0Jhc2VBc3NldEltcG9ydGVyXSBzZXRQcm9wZXJ0eSBub3QgaW1wbGVtZW50ZWQgZm9yICR7dGhpcy5uYW1lfWApO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufVxuXG4iXX0=
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FbxImporter = void 0;
const model_base_importer_1 = require("./model-base-importer");
class FbxImporter extends model_base_importer_1.ModelBaseImporter {
constructor() {
super(...arguments);
this.name = 'fbx';
}
addSpecificUserData(userData, container) {
const fbx = userData.fbx || {};
container.animationBakeRate = {
value: fbx.animationBakeRate,
type: 'Enum',
enumList: [
{ name: 'Auto', value: 0 },
{ name: 'BakeRate24', value: 24 },
{ name: 'BakeRate25', value: 25 },
{ name: 'BakeRate30', value: 30 },
{ name: 'BakeRate60', value: 60 }
],
tooltip: 'Specify the animation bake sample rate in frames per second (fps).'
};
container.preferLocalTimeSpan = {
value: !!fbx.preferLocalTimeSpan,
type: 'Boolean',
tooltip: 'When exporting FBX animations, whether prefer to use the time range recorded in FBX file.<br>If one is not preferred, or one is invalid for use, the time range is robustly calculated.<br>Some FBX generators may not export this information.'
};
container.smartMaterialEnabled = {
value: !!fbx.smartMaterialEnabled,
type: 'Boolean',
tooltip: 'Convert DCC materials to engine builtin materials which match the internal lighting model.'
};
container.legacyFbxImporter = {
value: !!userData.legacyFbxImporter,
type: 'Boolean',
};
}
}
exports.FbxImporter = FbxImporter;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmJ4LWltcG9ydGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc291cmNlL3V0Y3AvdXRpbHMvYXNzZXQtaW1wb3J0ZXJzL2ZieC1pbXBvcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrREFBMEQ7QUFHMUQsTUFBYSxXQUFZLFNBQVEsdUNBQWlCO0lBQWxEOztRQUNJLFNBQUksR0FBRyxLQUFLLENBQUM7SUFtQ2pCLENBQUM7SUFqQ2EsbUJBQW1CLENBQUMsUUFBYSxFQUFFLFNBQXVDO1FBQ2hGLE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDO1FBRS9CLFNBQVMsQ0FBQyxpQkFBaUIsR0FBRztZQUMxQixLQUFLLEVBQUUsR0FBRyxDQUFDLGlCQUFpQjtZQUM1QixJQUFJLEVBQUUsTUFBTTtZQUNaLFFBQVEsRUFBRTtnQkFDTixFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRTtnQkFDMUIsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUU7Z0JBQ2pDLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFO2dCQUNqQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRTtnQkFDakMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUU7YUFDcEM7WUFDRCxPQUFPLEVBQUUsb0VBQW9FO1NBQ2hGLENBQUM7UUFFRixTQUFTLENBQUMsbUJBQW1CLEdBQUc7WUFDNUIsS0FBSyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsbUJBQW1CO1lBQ2hDLElBQUksRUFBRSxTQUFTO1lBQ2YsT0FBTyxFQUFFLGlQQUFpUDtTQUM3UCxDQUFDO1FBRUYsU0FBUyxDQUFDLG9CQUFvQixHQUFHO1lBQzVCLEtBQUssRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLG9CQUFvQjtZQUNqQyxJQUFJLEVBQUUsU0FBUztZQUNmLE9BQU8sRUFBRSw0RkFBNEY7U0FDekcsQ0FBQztRQUVGLFNBQVMsQ0FBQyxpQkFBaUIsR0FBRztZQUN6QixLQUFLLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxpQkFBaUI7WUFDbkMsSUFBSSxFQUFFLFNBQVM7U0FDbkIsQ0FBQztJQUNOLENBQUM7Q0FDSjtBQXBDRCxrQ0FvQ0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNb2RlbEJhc2VJbXBvcnRlciB9IGZyb20gJy4vbW9kZWwtYmFzZS1pbXBvcnRlcic7XG5pbXBvcnQgeyBJUHJvcGVydHkgfSBmcm9tICdAY29jb3MvY3JlYXRvci10eXBlcy9lZGl0b3IvcGFja2FnZXMvc2NlbmUvQHR5cGVzL3B1YmxpYyc7XG5cbmV4cG9ydCBjbGFzcyBGYnhJbXBvcnRlciBleHRlbmRzIE1vZGVsQmFzZUltcG9ydGVyIHtcbiAgICBuYW1lID0gJ2ZieCc7XG5cbiAgICBwcm90ZWN0ZWQgYWRkU3BlY2lmaWNVc2VyRGF0YSh1c2VyRGF0YTogYW55LCBjb250YWluZXI6IHsgW2tleTogc3RyaW5nXTogSVByb3BlcnR5IH0pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZmJ4ID0gdXNlckRhdGEuZmJ4IHx8IHt9O1xuICAgICAgICBcbiAgICAgICAgY29udGFpbmVyLmFuaW1hdGlvbkJha2VSYXRlID0ge1xuICAgICAgICAgICAgdmFsdWU6IGZieC5hbmltYXRpb25CYWtlUmF0ZSxcbiAgICAgICAgICAgIHR5cGU6ICdFbnVtJyxcbiAgICAgICAgICAgIGVudW1MaXN0OiBbXG4gICAgICAgICAgICAgICAgeyBuYW1lOiAnQXV0bycsIHZhbHVlOiAwIH0sXG4gICAgICAgICAgICAgICAgeyBuYW1lOiAnQmFrZVJhdGUyNCcsIHZhbHVlOiAyNCB9LFxuICAgICAgICAgICAgICAgIHsgbmFtZTogJ0Jha2VSYXRlMjUnLCB2YWx1ZTogMjUgfSxcbiAgICAgICAgICAgICAgICB7IG5hbWU6ICdCYWtlUmF0ZTMwJywgdmFsdWU6IDMwIH0sXG4gICAgICAgICAgICAgICAgeyBuYW1lOiAnQmFrZVJhdGU2MCcsIHZhbHVlOiA2MCB9XG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgdG9vbHRpcDogJ1NwZWNpZnkgdGhlIGFuaW1hdGlvbiBiYWtlIHNhbXBsZSByYXRlIGluIGZyYW1lcyBwZXIgc2Vjb25kIChmcHMpLidcbiAgICAgICAgfTtcblxuICAgICAgICBjb250YWluZXIucHJlZmVyTG9jYWxUaW1lU3BhbiA9IHtcbiAgICAgICAgICAgIHZhbHVlOiAhIWZieC5wcmVmZXJMb2NhbFRpbWVTcGFuLFxuICAgICAgICAgICAgdHlwZTogJ0Jvb2xlYW4nLFxuICAgICAgICAgICAgdG9vbHRpcDogJ1doZW4gZXhwb3J0aW5nIEZCWCBhbmltYXRpb25zLCB3aGV0aGVyIHByZWZlciB0byB1c2UgdGhlIHRpbWUgcmFuZ2UgcmVjb3JkZWQgaW4gRkJYIGZpbGUuPGJyPklmIG9uZSBpcyBub3QgcHJlZmVycmVkLCBvciBvbmUgaXMgaW52YWxpZCBmb3IgdXNlLCB0aGUgdGltZSByYW5nZSBpcyByb2J1c3RseSBjYWxjdWxhdGVkLjxicj5Tb21lIEZCWCBnZW5lcmF0b3JzIG1heSBub3QgZXhwb3J0IHRoaXMgaW5mb3JtYXRpb24uJ1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnRhaW5lci5zbWFydE1hdGVyaWFsRW5hYmxlZCA9IHtcbiAgICAgICAgICAgICB2YWx1ZTogISFmYnguc21hcnRNYXRlcmlhbEVuYWJsZWQsXG4gICAgICAgICAgICAgdHlwZTogJ0Jvb2xlYW4nLFxuICAgICAgICAgICAgIHRvb2x0aXA6ICdDb252ZXJ0IERDQyBtYXRlcmlhbHMgdG8gZW5naW5lIGJ1aWx0aW4gbWF0ZXJpYWxzIHdoaWNoIG1hdGNoIHRoZSBpbnRlcm5hbCBsaWdodGluZyBtb2RlbC4nXG4gICAgICAgIH07XG5cbiAgICAgICAgY29udGFpbmVyLmxlZ2FjeUZieEltcG9ydGVyID0ge1xuICAgICAgICAgICAgIHZhbHVlOiAhIXVzZXJEYXRhLmxlZ2FjeUZieEltcG9ydGVyLFxuICAgICAgICAgICAgIHR5cGU6ICdCb29sZWFuJyxcbiAgICAgICAgfTtcbiAgICB9XG59XG4iXX0=
@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GltfImporter = void 0;
const model_base_importer_1 = require("./model-base-importer");
class GltfImporter extends model_base_importer_1.ModelBaseImporter {
constructor() {
super(...arguments);
this.name = 'gltf';
}
addSpecificUserData(userData, container) {
// GLTF specific properties if any
}
}
exports.GltfImporter = GltfImporter;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2x0Zi1pbXBvcnRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NvdXJjZS91dGNwL3V0aWxzL2Fzc2V0LWltcG9ydGVycy9nbHRmLWltcG9ydGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLCtEQUEwRDtBQUcxRCxNQUFhLFlBQWEsU0FBUSx1Q0FBaUI7SUFBbkQ7O1FBQ0ksU0FBSSxHQUFHLE1BQU0sQ0FBQztJQUtsQixDQUFDO0lBSGEsbUJBQW1CLENBQUMsUUFBYSxFQUFFLFNBQXVDO1FBQ2hGLGtDQUFrQztJQUN0QyxDQUFDO0NBQ0o7QUFORCxvQ0FNQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE1vZGVsQmFzZUltcG9ydGVyIH0gZnJvbSAnLi9tb2RlbC1iYXNlLWltcG9ydGVyJztcbmltcG9ydCB7IElQcm9wZXJ0eSB9IGZyb20gJ0Bjb2Nvcy9jcmVhdG9yLXR5cGVzL2VkaXRvci9wYWNrYWdlcy9zY2VuZS9AdHlwZXMvcHVibGljJztcblxuZXhwb3J0IGNsYXNzIEdsdGZJbXBvcnRlciBleHRlbmRzIE1vZGVsQmFzZUltcG9ydGVyIHtcbiAgICBuYW1lID0gJ2dsdGYnO1xuXG4gICAgcHJvdGVjdGVkIGFkZFNwZWNpZmljVXNlckRhdGEodXNlckRhdGE6IGFueSwgY29udGFpbmVyOiB7IFtrZXk6IHN0cmluZ106IElQcm9wZXJ0eSB9KTogdm9pZCB7XG4gICAgICAgIC8vIEdMVEYgc3BlY2lmaWMgcHJvcGVydGllcyBpZiBhbnlcbiAgICB9XG59XG4iXX0=
File diff suppressed because one or more lines are too long
@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImporterManager = void 0;
class ImporterManager {
static getInstance() {
if (!this._instance) {
this._instance = new ImporterManager();
}
return this._instance;
}
constructor() {
this._importers = new Map();
}
registerImporter(importer) {
this._importers.set(importer.name, importer);
}
getImporter(name) {
return this._importers.get(name);
}
hasImporter(name) {
return this._importers.has(name);
}
}
exports.ImporterManager = ImporterManager;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1wb3J0ZXItbWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NvdXJjZS91dGNwL3V0aWxzL2Fzc2V0LWltcG9ydGVycy9pbXBvcnRlci1tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLE1BQWEsZUFBZTtJQUlqQixNQUFNLENBQUMsV0FBVztRQUNyQixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUMzQyxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQzFCLENBQUM7SUFFRDtRQVRRLGVBQVUsR0FBZ0MsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQVNyQyxDQUFDO0lBRWpCLGdCQUFnQixDQUFDLFFBQXdCO1FBQzVDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDakQsQ0FBQztJQUVNLFdBQVcsQ0FBQyxJQUFZO1FBQzNCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVNLFdBQVcsQ0FBQyxJQUFZO1FBQzNCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDckMsQ0FBQztDQUNKO0FBeEJELDBDQXdCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElBc3NldEltcG9ydGVyIH0gZnJvbSAnLi9iYXNlLWltcG9ydGVyJztcblxuZXhwb3J0IGNsYXNzIEltcG9ydGVyTWFuYWdlciB7XG4gICAgcHJpdmF0ZSBzdGF0aWMgX2luc3RhbmNlOiBJbXBvcnRlck1hbmFnZXI7XG4gICAgcHJpdmF0ZSBfaW1wb3J0ZXJzOiBNYXA8c3RyaW5nLCBJQXNzZXRJbXBvcnRlcj4gPSBuZXcgTWFwKCk7XG5cbiAgICBwdWJsaWMgc3RhdGljIGdldEluc3RhbmNlKCk6IEltcG9ydGVyTWFuYWdlciB7XG4gICAgICAgIGlmICghdGhpcy5faW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHRoaXMuX2luc3RhbmNlID0gbmV3IEltcG9ydGVyTWFuYWdlcigpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9pbnN0YW5jZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKCkge31cblxuICAgIHB1YmxpYyByZWdpc3RlckltcG9ydGVyKGltcG9ydGVyOiBJQXNzZXRJbXBvcnRlcikge1xuICAgICAgICB0aGlzLl9pbXBvcnRlcnMuc2V0KGltcG9ydGVyLm5hbWUsIGltcG9ydGVyKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0SW1wb3J0ZXIobmFtZTogc3RyaW5nKTogSUFzc2V0SW1wb3J0ZXIgfCB1bmRlZmluZWQge1xuICAgICAgICByZXR1cm4gdGhpcy5faW1wb3J0ZXJzLmdldChuYW1lKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaGFzSW1wb3J0ZXIobmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pbXBvcnRlcnMuaGFzKG5hbWUpO1xuICAgIH1cbn1cbiJdfQ==
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,57 @@
"use strict";
// Removed IInspectorProperty-related transformation methods.
/*
export class InspectorUtils {
static localize(text: string | undefined): string | undefined {
if (!text) return text;
if (text.length === 0) return undefined;
if (text.startsWith('i18n:')) {
// @ts-ignore
return Editor.I18n.t(text.replace('i18n:', ''));
}
return text;
}
static isPrimitiveType(type: string | undefined): boolean {
if (!type) return false;
return ['Number', 'Integer', 'String', 'Boolean', 'Enum', 'BitMask', 'Float',
'cc.Vec2', 'cc.Vec3', 'cc.Vec4', 'cc.Color', 'cc.Size', 'cc.Rect', 'cc.Quat'].includes(type);
}
static cleanResult(obj: any): any {
if (Array.isArray(obj)) {
return obj.map(v => this.cleanResult(v));
} else if (obj !== null && typeof obj === 'object') {
const newObj: any = {};
for (const key in obj) {
const val = this.cleanResult(obj[key]);
if (val !== undefined) {
newObj[key] = val;
}
}
return newObj;
}
return obj;
}
static parsePropertySet(container: any, excludeKeys: string[] = [], simple: boolean = false, depth: number = 0): any {
if (!container) return {};
const props: any = {};
for (const key in container) {
if (excludeKeys.includes(key)) continue;
const prop = container[key];
if ('visible' in prop && !prop.visible) continue;
if (prop && typeof prop === 'object' && 'value' in prop) {
props[key] = prop.value;
} else {
props[key] = prop;
}
}
return props;
}
}
*/
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zcGVjdG9yLXV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc291cmNlL3V0Y3AvdXRpbHMvaW5zcGVjdG9yLXV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSw2REFBNkQ7QUFDN0Q7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBcURFIiwic291cmNlc0NvbnRlbnQiOlsiLy8gUmVtb3ZlZCBJSW5zcGVjdG9yUHJvcGVydHktcmVsYXRlZCB0cmFuc2Zvcm1hdGlvbiBtZXRob2RzLlxuLypcbmV4cG9ydCBjbGFzcyBJbnNwZWN0b3JVdGlscyB7XG5cbiAgICBzdGF0aWMgbG9jYWxpemUodGV4dDogc3RyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgaWYgKCF0ZXh0KSByZXR1cm4gdGV4dDtcbiAgICAgICAgaWYgKHRleHQubGVuZ3RoID09PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBpZiAodGV4dC5zdGFydHNXaXRoKCdpMThuOicpKSB7XG4gICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICByZXR1cm4gRWRpdG9yLkkxOG4udCh0ZXh0LnJlcGxhY2UoJ2kxOG46JywgJycpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGV4dDtcbiAgICB9XG5cbiAgICBzdGF0aWMgaXNQcmltaXRpdmVUeXBlKHR5cGU6IHN0cmluZyB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoIXR5cGUpIHJldHVybiBmYWxzZTtcbiAgICAgICAgcmV0dXJuIFsnTnVtYmVyJywgJ0ludGVnZXInLCAnU3RyaW5nJywgJ0Jvb2xlYW4nLCAnRW51bScsICdCaXRNYXNrJywgJ0Zsb2F0JyxcbiAgICAgICAgICAgICAgICAnY2MuVmVjMicsICdjYy5WZWMzJywgJ2NjLlZlYzQnLCAnY2MuQ29sb3InLCAnY2MuU2l6ZScsICdjYy5SZWN0JywgJ2NjLlF1YXQnXS5pbmNsdWRlcyh0eXBlKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY2xlYW5SZXN1bHQob2JqOiBhbnkpOiBhbnkge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgICAgICAgICByZXR1cm4gb2JqLm1hcCh2ID0+IHRoaXMuY2xlYW5SZXN1bHQodikpO1xuICAgICAgICB9IGVsc2UgaWYgKG9iaiAhPT0gbnVsbCAmJiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgY29uc3QgbmV3T2JqOiBhbnkgPSB7fTtcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbCA9IHRoaXMuY2xlYW5SZXN1bHQob2JqW2tleV0pO1xuICAgICAgICAgICAgICAgIGlmICh2YWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBuZXdPYmpba2V5XSA9IHZhbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3T2JqO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvYmo7XG4gICAgfVxuXG4gICAgc3RhdGljIHBhcnNlUHJvcGVydHlTZXQoY29udGFpbmVyOiBhbnksIGV4Y2x1ZGVLZXlzOiBzdHJpbmdbXSA9IFtdLCBzaW1wbGU6IGJvb2xlYW4gPSBmYWxzZSwgZGVwdGg6IG51bWJlciA9IDApOiBhbnkge1xuICAgICAgICBpZiAoIWNvbnRhaW5lcikgcmV0dXJuIHt9O1xuICAgICAgICBjb25zdCBwcm9wczogYW55ID0ge307XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIGNvbnRhaW5lcikge1xuICAgICAgICAgICAgaWYgKGV4Y2x1ZGVLZXlzLmluY2x1ZGVzKGtleSkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBjb25zdCBwcm9wID0gY29udGFpbmVyW2tleV07XG4gICAgICAgICAgICBpZiAoJ3Zpc2libGUnIGluIHByb3AgJiYgIXByb3AudmlzaWJsZSkgY29udGludWU7XG4gICAgICAgICAgICBpZiAocHJvcCAmJiB0eXBlb2YgcHJvcCA9PT0gJ29iamVjdCcgJiYgJ3ZhbHVlJyBpbiBwcm9wKSB7XG4gICAgICAgICAgICAgICAgcHJvcHNba2V5XSA9IHByb3AudmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHByb3BzW2tleV0gPSBwcm9wO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwcm9wcztcbiAgICB9XG59XG5cbiovIl19
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
"use strict"; module.exports = { open_panel: "Configuration", description: "Cocos Creator MCP Integration for AI Code Mode" };
+1
View File
@@ -0,0 +1 @@
"use strict"; module.exports = { open_panel: "配置", description: "Cocos Creator MCP Integration for AI Code Mode" };
File diff suppressed because it is too large Load Diff
+100
View File
@@ -0,0 +1,100 @@
{
"$schema": "./@types/schema/package/index.json",
"package_version": 2,
"name": "cocos-code-mode",
"version": "1.0.0",
"author": "Roman Rogov",
"editor": ">=3.8.7",
"scripts": {
"preinstall": "node ./scripts/preinstall.js",
"build": "npx tsc",
"package": "npm run build && node ./scripts/package.js"
},
"description": "i18n:cocos-code-mode.description",
"main": "./dist/main.js",
"dependencies": {
"@types/sharp": "^0.31.1",
"@utcp/http": "^1.1.0",
"@utcp/sdk": "^1.1.0",
"cors": "^2.8.6",
"express": "^5.2.1",
"fs-extra": "^10.0.0",
"sharp": "^0.34.5",
"zod": "^4.2.1"
},
"devDependencies": {
"@cocos/creator-types": "^3.8.7",
"@types/cors": "^2.8.19",
"@types/express": "^5.0.6",
"@types/fs-extra": "^9.0.5",
"@types/node": "^18.17.1",
"typescript": "^5.8.2"
},
"panels": {
"configuration": {
"title": "Configuration",
"type": "dockable",
"main": "dist/panels/configuration",
"size": {
"min-width": 400,
"min-height": 300,
"width": 1024,
"height": 600
}
},
"preview": {
"title": "Asset Preview",
"type": "dockable",
"main": "dist/panels/preview",
"size": {
"min-width": 200,
"min-height": 200,
"width": 400,
"height": 400
}
}
},
"contributions": {
"scene": {
"script": "./dist/scene.js"
},
"menu": [
{
"path": "Code Mode",
"label": "i18n:cocos-code-mode.open_panel",
"message": "open-panel"
}
],
"messages": {
"open-panel": {
"methods": [
"openPanel"
]
},
"open-preview-panel": {
"methods": [
"openPreviewPanel"
]
},
"preview-asset": {
"methods": [
"preview.previewAsset"
]
},
"generate-preview": {
"methods": [
"preview.generatePreview"
]
},
"restart-server": {
"methods": [
"restartServer"
]
}
}
},
"creator": {
"version": "3.8.7"
},
"uuid": "b401b190-c2a1-4149-9250-a0ed22e1968b"
}
@@ -0,0 +1,104 @@
.panel {
display: flex;
flex-direction: column;
height: 100%;
padding: 10px;
gap: 10px;
overflow-y: auto;
}
ui-prop-split {
--ui-prop-margin-left: 24px;
--ui-prop-label-width-min: 60px;
--ui-prop-label-width-max: 289px;
--left-width: 38.2%;
}
.section {
margin-bottom: 10px;
}
.desc-container {
padding: 5px 10px;
color: var(--color-text-normal);
opacity: 0.8;
margin-bottom: 5px;
}
.code-container {
margin-top: 5px;
}
.list-container {
padding: 0;
max-height: 400px;
overflow-y: auto;
margin-bottom: 15px;
}
.bridge-item-section {
margin-bottom: 5px;
border: 1px solid var(--color-normal-border-weak);
border-radius: 4px;
overflow: hidden;
}
.bridge-item-content {
padding: 10px;
background: var(--color-normal-fill-calmer);
}
.bridge-actions {
display: flex;
justify-content: flex-end;
margin-top: 5px;
}
.actions.right {
display: flex;
justify-content: flex-end;
margin-top: 5px;
}
ui-button.blue {
color: white;
}
ui-button.green {
color: white;
}
ui-prop {
margin-top: 10px;
}
.transparent {
background: transparent;
border: none;
}
.group-header {
font-weight: bold;
color: var(--color-text-normal);
margin-bottom: 5px;
margin-top: 10px;
padding-left: 5px;
}
.mt-10 {
margin-top: 10px;
}
.add-template-container {
padding: 0 5px;
}
ui-prop ui-button {
margin-left: 10px;
}
#save-utcp-path-btn {
max-width: 24px;
padding: 0 4px;
height: 24px;
}
@@ -0,0 +1,15 @@
.panel {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
background-color: #252526;
}
#preview-container {
flex: 1;
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
}
@@ -0,0 +1,48 @@
<ui-prop-split class="panel" position="38.2" indent="24px" min-limit="60px,85px">
<!-- Port Section -->
<ui-section class="config" header="Server Configuration" expand>
<ui-prop>
<ui-label slot="label" class="label">Server Port</ui-label>
<ui-num-input slot="content" id="port-input" value="3000" step="1"></ui-num-input>
<ui-button slot="content" id="save-port-btn" class="blue">Update</ui-button>
</ui-prop>
</ui-section>
<!-- UTCP Config Section -->
<ui-section class="config" header="UTCP Configuration" expand>
<ui-prop>
<ui-label slot="label" class="label">Config Path</ui-label>
<ui-input slot="content" id="utcp-config-path" class="flex-1"></ui-input>
<ui-button type="icon" slot="content" id="save-utcp-path-btn" class="green"><ui-icon
value="check"></ui-icon></ui-button>
</ui-prop>
<div class="group-header">Bridge Templates</div>
<div id="bridge-container" class="list-container">
<!-- Templates injected here -->
</div>
<div class="group-header mt-10">Add New Template</div>
<div class="add-template-container">
<ui-textarea id="new-template-json" placeholder="UTCP Call Template" rows="5"></ui-textarea>
<div class="actions right">
<ui-button id="add-bridge-btn" class="green">
<ui-icon value="add"></ui-icon> Add Template
</ui-button>
</div>
</div>
</ui-section>
<!-- MCP Integration Section -->
<ui-section class="config" header="MCP Agent Integration" expand>
<div class="desc-container">
<span class="desc">Configure your AI agent by adding this server to MCP config
config. Config example:</span>
</div>
<div class="code-container">
<ui-code language="json" id="mcp-config-code"></ui-code>
</div>
</ui-section>
</ui-prop-split>
@@ -0,0 +1,3 @@
<div class="panel">
<div id="preview-container"></div>
</div>