# Ep.18 — Customizing 03: 命名规范 & 团队模板

https://youtu.be/pwvMbO_Y36k

如果无法访问 YouTube，可在 **Bilibili** 搜索 OtakuSolutions 频道观看相关内容。


本文档说明如何将 BipedPlus 命名调整为工作室规范，并**保存为可重复使用的 common 模板**。

> 如果无法访问 YouTube，可在 **Bilibili** 搜索 OtakuSolutions 频道观看相关内容。

## 1. 为什么需要

当 BipedPlus 默认命名（`Skin_*`、`Ctrl_*`、`Bip001`）与团队规则不匹配时，工作流程就会受阻。
可以进行重命名——关键是**将结果保存为模板，避免每次重复操作**。

## 2. 完整流程

![BipedPlus Naming & Template Pipeline](./pipeline.png)

## 3. 命名变更的允许范围和注意事项

| 类型 | 内容 |
|------|------|
| ✅ 可以更改 | Biped 名称、Skin 骨骼名称（与引擎骨骼名对应）、控制器前缀、层显示名称 |
| ⚠️ 注意 | 使用**统一批量规则**重命名，避免破坏 Hierarchy / Constraint / Space |
| ❌ 禁止省略 Fix Missing | 重命名后不执行 Fix Missing 将导致 Mirror / Picker / Reset 失效 |

## 4. Fix Missing — 重命名后保持系统同步

名称更改后，INFO 记录的旧名称会不匹配，导致 **Missing** 错误。

| 概念 | 说明 |
|------|------|
| **Seed** | 即使节点被重命名，也能识别该节点的唯一地址值 |
| **Fix Missing** | 利用 Seed 重新链接重命名后节点的功能 |

**操作步骤**：Rig Info → Load → 检查 Missing → 执行 Fix Missing → 确认镜像更新 → 通过 Ani Utils 验证

## 5. 自定义层名称

层设置 → **Edit Name** → 新建预设（团队/产品名）→ 添加前缀/后缀 → **Apply to Rename**
保持 Hierarchy 中的角色分类不变——只将**显示标签**改为符合团队规范的名称。

## 6. 保存为 common 模板

| 步骤 | 内容 |
|------|------|
| 1 | 打开建模场景（或新建文件） |
| 2 | **Merge** — `common/BP_Human_Template.max` 中的所有节点 |
| 3 | BipedPlus **Scan** — 确认 INFO / 镜像等已保留 |
| 4 | 按角色调整 Figure / 比例等 |
| 5 | 保存到角色文件夹 → 分发给动画团队（使用 Player 工作） |

```
共享_绑定/
├── character_A/
├── character_B/
└── common/
    └── BP_Human_Template.max   ← 已配置命名、层级和 INFO 的主模板
```

## 7. Picker 的例外

| | INFO / Ani Utils（Fix Missing 后） | Picker |
|--|-----------------------------------|--------|
| 重命名后 | 可恢复 | **基于名称**——布局可能失效 |

**推荐**：在命名和模板确定后，用新命名重建 Picker，并与模板 `.max` 一起分发给团队。
Picker 文件位置在 BipedPlus **Settings** 中查看。

## 8. 检查清单

- [ ] 团队的 bone / Ctrl / Layer 命名规则已文档化
- [ ] 使用批量重命名脚本（或团队脚本）
- [ ] 重命名后：验证 Fix Missing + Mirror / Reset
- [ ] `common/` 模板 `.max` 存在于共享文件夹中
- [ ] 新角色使用 Merge → Scan 工作流程
- [ ] Picker 已按最终命名规范重建
- [ ] 动画团队使用 Player 和**相同的安装程序**


### Example Rename Script (handle 2-pass)

Edit `NODE_RENAME_MAP` to match your team's rules. Run in Max Script Editor after Build.

```python
# -*- coding: utf-8 -*-
"""BipedPlus naming example (handle 2-pass, short version)"""

import pymxs
rt = pymxs.runtime

NODE_RENAME_MAP = [
    ("Bip001",          "Bip009"),
    ("Bip001 Pelvis",   "Bip009 Pelvis"),
    ("Ctrl_Head",       "CTL_Head"),
    ("Skin_Spine1",     "Bip001_Spine1"),
    ("Skin_L_Hand",     "Bip001_L_Hand"),
]

def rename_nodes_by_handle(rename_map=None):
    mapping = rename_map if rename_map is not None else NODE_RENAME_MAP
    if not mapping:
        raise ValueError("NODE_RENAME_MAP is empty.")

    # Phase 1 — collect handles
    collected = []
    for src, dst in mapping:
        node = rt.getNodeByName(src)
        if node is None:
            print(f"[SKIP] {src}")
            continue
        collected.append((int(node.handle), src, dst))

    if not collected:
        raise ValueError("No rename targets found in scene.")

    # Phase 2 — apply
    for handle, src, dst in collected:
        node = rt.maxOps.getNodeByHandle(handle)
        if node is None:
            raise RuntimeError(f"handle={handle} restore failed ({src} → {dst})")
        node.name = dst
        print(f"[OK] {src} → {dst}")

    print(f"Done ({len(collected)} ok). Next: Rig Info → Fix Missing")

if __name__ == "__main__":
    rename_nodes_by_handle()
```

> After running: Rig Info → Fix Missing → verify Mirror / Reset.