# Figma to Cocos Creator

将 Figma 设计稿转换为 Cocos Creator 2.x Prefab 文件，支持按照 [Figma 节点层级与命名规范](packages/Figma%20节点层级与命名规范.md) 自动处理通用组件和自定义内容。

## 功能特性

- 解析 Figma 文件结构，1:1 还原 UI 布局到 Cocos Prefab
- 自动下载图片资源并生成 `.meta` 文件
- 识别 `common` / `custom` 节点，资源分目录导出
- `_merge` 后缀节点自动合并导出为单张图片
- `btn_` 前缀节点自动添加 `cc.Button` 组件
- 不可见节点直接忽略（不生成 prefab 节点，不导出资源）
- 多状态子节点（`sp_selected`/`sp_error`/`sp_disabled`/`sp_pressed`，含 `_merge` 后缀变体）自动设为 `active=false`
- `multi_xxxx_copy` 占位节点只导出空节点（保留坐标），不递归子节点、不导出资源；兼容数字后缀如 `multi_grid_copy_1`
- 图片 Sprite 使用 SIMPLE 类型 + RAW 尺寸模式（`_sizeMode=2`）+ 不勾选 Trim（`_isTrimmedMode=false`）；Meta 文件保持 `trimType=auto`
- 默认字体映射 FZCuYuan-M03S → `c257f605-daaf-42be-9822-47d6f7c4080a`
- 支持 Web UI、命令行、Cocos Creator 插件三种使用方式

## 项目结构

```
figma-to-cocos/
├── packages/
│   ├── core/           # 核心转换库
│   ├── cli/            # 命令行工具
│   └── web/            # Web UI 服务
├── .env.example        # 环境变量示例
└── package.json        # monorepo 根配置
```

## 安装与构建

```bash
cd figma-to-cocos
npm install
npm run build
```

## 获取 Figma Token

1. 登录 [Figma](https://www.figma.com)
2. 进入 Settings → Account → Personal access tokens
3. 点击 Create a new personal access token
4. 复制生成的 Token

配置方式（二选一）：

```bash
# 方式一：写入 .env 文件
cp .env.example .env
# 编辑 .env，填入 Token：
# FIGMA_TOKEN=figd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# 方式二：直接设置环境变量
export FIGMA_TOKEN=figd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

---

## 方式一：命令行（CLI）

### 基本用法

从 Figma 复制 Frame 的链接（右键 Frame → Copy link），链接中会包含 `node-id` 参数：

```bash
npx -y figma-to-cocos convert "https://www.figma.com/design/ABCDEF/MyFile?node-id=1:2" --prefab-name G3L3_2_1
```

这会：

1. 通过 Figma API 获取 `node-id=1:2` 对应的 Frame 数据
2. 递归解析所有子节点，生成 Prefab JSON
3. 下载所有图片资源（矢量、图片填充、背景等）
4. 输出到 `./output/` 目录，资源放在 `image/{prefabName}/` 下

### 指定输出目录

```bash
npx -y figma-to-cocos convert "https://..." --prefab-name G3L3_2_1 -o ./my-project/assets
```

### 使用 Token 参数（不用环境变量时）

```bash
npx -y figma-to-cocos convert "https://..." --prefab-name G3L3_2_1 -t figd_xxxxxxxx
```

### 调整图片导出倍率

默认 1x，即 Figma 中 100×100 的节点导出为 100×100 px 的图片：

```bash
# 1x - 原始尺寸（默认）
npx -y figma-to-cocos convert "https://..." --prefab-name G3L3_2_1 -s 1

# 2x - 两倍尺寸
npx -y figma-to-cocos convert "https://..." --prefab-name G3L3_2_1 -s 2

# 3x - 三倍尺寸
npx -y figma-to-cocos convert "https://..." --prefab-name G3L3_2_1 -s 3
```

### 切换图片格式

```bash
# PNG（默认）
npx -y figma-to-cocos convert "https://..." --prefab-name G3L3_2_1 -f png

# JPG
npx -y figma-to-cocos convert "https://..." --prefab-name G3L3_2_1 -f jpg
```

### 跳过图片下载

只生成 Prefab 结构，不下载图片（调试用）：

```bash
npx -y figma-to-cocos convert "https://..." --prefab-name G3L3_2_1 --no-images
```

### 自动合并参数

当节点总数超过阈值时，深度超过指定值的子树会被合并导出为单张图片：

```bash
npx -y figma-to-cocos convert "https://..." --prefab-name G3L3_2_1 --merge-threshold 500 --merge-depth 8
```

### 解析 URL（调试用）

不做转换，只解析链接中的 fileKey 和 nodeId：

```bash
npx -y figma-to-cocos parse-url "https://www.figma.com/design/ABCDEF/MyFile?node-id=1-2"
# File Key: ABCDEF
# Node ID: 1:2
```

### 完整参数列表

| 参数                    | 说明                                                  | 默认值     |
| ----------------------- | ----------------------------------------------------- | ---------- |
| `<url>`                 | Figma 文件链接（必填），建议带 `?node-id=` 指定 Frame | —          |
| `--prefab-name <name>`  | Prefab 名称（必填），用于资源子目录 `image/{name}/`   | —          |
| `-o, --output <dir>`    | 输出目录                                              | `./output` |
| `-t, --token <token>`   | Figma Token，也可通过 `FIGMA_TOKEN` 环境变量设置      | —          |
| `-s, --scale <n>`       | 图片导出倍率，可选 1 / 2 / 3                          | `1`        |
| `-f, --format <fmt>`    | 图片格式，可选 png / jpg                              | `png`      |
| `--no-images`           | 跳过图片下载                                          | `false`    |
| `--merge-threshold <n>` | 自动合并节点数阈值                                    | `999`      |
| `--merge-depth <n>`     | 自动合并深度阈值                                      | `10`       |

### 完整示例

```bash
# 典型用法：转换一个 step Frame，1x PNG，输出到项目资源目录
export FIGMA_TOKEN=figd_xxxxxxxx
npx -y figma-to-cocos convert \
  "https://www.figma.com/design/ABCDEF/au25g3w2model1?node-id=1:2" \
  --prefab-name G3L3_2_1 \
  -o ./cocos-project/assets/courses/au25g3w2model1 \
  -s 1 \
  -f png
```

---

## 方式二：Web UI

```bash
npm run start:web
# 访问 http://localhost:3000
```

1. 输入 Figma Token 连接
2. 输入 Team ID（默认 `1243029000772724234`）加载项目列表
3. 选择文件 → 选择 Frame
4. 填写 **Prefab 名称**（必填，用于资源子目录命名）
5. 配置转换选项，点击开始转换
6. 下载 ZIP 文件（命名为 `{Frame名}_{时间戳}.zip`）

---

## 输出目录结构

```
output/
├── prefab/
│   ├── au25g3w2model1_step_1.prefab
│   └── au25g3w2model1_step_1.prefab.meta
└── image/
    └── au25g3w2model1_step_1/   ← 按 prefab 名分目录
        ├── common/              ← common 节点下的图片资源
        │   ├── bg_title.png
        │   └── bg_title.png.meta
        ├── custom/              ← custom 节点下的图片资源
        │   ├── sp_apple.png
        │   └── sp_apple.png.meta
        ├── other.png            ← 不在 common/custom 下的资源
        └── other.png.meta
```

## 节点转换规则

| Figma 节点 | Cocos 组件 | 触发条件 |
| --- | --- | --- |
| Frame/Group | `cc.Node` | 容器节点，递归处理子节点 |
| Text | `cc.Label` | 文本图层 |
| 矢量形状 | `cc.Sprite` | Rectangle、Ellipse、Vector 等，导出为 PNG |
| 图片填充 | `cc.Sprite` | fills 中包含 IMAGE 类型 |
| 渐变/阴影 | `cc.Sprite` | 导出为图片 |
| `*_merge` 节点 | `cc.Sprite` | 名称以 `_merge` 结尾，整体导出为一张图片，prefab 中去掉后缀 |
| `btn_*` 节点 | `cc.Button` | 名称以 `btn_` 开头，自动添加 Button 组件 |
| `visible=false` | —（忽略） | 不可见节点直接跳过，不生成 prefab 节点，不导出资源 |
| `sp_selected/sp_error/sp_disabled/sp_pressed` | `active=false` | 多状态子节点默认非激活（兼容 `_merge` 后缀） |
| `multi_*_copy` / `multi_*_copy_N` | `cc.Node`（空） | 占位节点，只保留坐标和尺寸，不导出子节点和资源，后续流程替换 |

## API 使用

```typescript
import { FigmaToCocosConverter } from '@figma-to-cocos/core';

const converter = new FigmaToCocosConverter('your_figma_token');

const result = await converter.convert({
    fileKey: 'ABCDEF',
    nodeId: '1:2',
    outputDir: './output',
    prefabName: 'G3L3_2_1', // 必填，资源输出到 image/G3L3_2_1/
    downloadImages: true,
    imageScale: 2,
    imageFormat: 'png',
    autoMergeThreshold: 999,
    autoMergeDepth: 10
});

if (result.success) {
    console.log('Prefab:', result.prefabPath);
    console.log('Node:', result.nodeName);
    console.log('Assets:', result.assets.length);
}
```

## License

MIT
