Files
ChildHood/tools/world-sketcher/README.md
T
starmen1265 c509223e08 feat(world-sketcher): 新增本地服务器、标签显示和README重写
- 新增 server.py + start.bat: 本地保存/加载服务器
- sketch.html: 切换层级时自动绘制元素标签
- L1 显示区域名称+地形标高,L2 显示建筑名称+高度
- 保存优先POST到服务器,加载优先从output/读取
- 命名弹窗区分'地形标高'和'建筑高度'
- README 全面重写:双模式启动、文件结构、API端点、高度语义
2026-06-10 15:49:12 +08:00

239 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# World Layout Sketcher — 世界布局草图工具
> 在场景概念与关卡执行案之间,提供可视化布局沟通工具。
> 用颜色画笔绘制世界布局 → AI 解读 → 双方确认 → 产出执行案。
---
## 快速开始
### 方式一:本地服务器(推荐)
保存/加载直接读写 `output/` 目录,无需手动下载。
1. 双击 `start.bat`
2. 浏览器自动打开 `http://localhost:8765/sketch.html`
3. 开始绘制,点"保存"直接存入 `output/`
> 需要 Python 3。关闭终端窗口即可停止服务器。
### 方式二:直接打开 HTML
双击 `sketch.html` 在浏览器中打开(推荐 Chrome / Edge)。
- 保存时通过浏览器下载 ZIP 文件
- 加载时通过浏览器文件选择器选择 ZIP
> **注意**:直接打开 HTML 时加载独立的 `.json` 文件**不会恢复画布位图**——位图数据存储在 ZIP 包内的 PNG 文件中,必须加载 `.zip` 文件才能完整恢复。
---
## 文件结构
```
world-sketcher/
├── start.bat ← 启动脚本(双击运行)
├── server.py ← 本地保存/加载服务器
├── sketch.html ← 主工具(单文件,浏览器运行)
├── README.md
└── output/ ← 保存/加载目录
├── 迈皋桥-scene.zip ← 完整场景包(JSON + 所有 PNG)
├── 迈皋桥-scene.json ← 结构化数据(不含位图)
├── 迈皋桥-L1-drawing.png # L1 画布像素数据
├── 迈皋桥-L1-overview-preview.png # L1 合并预览
└── 迈皋桥-L2-*-drawing.png # L2 各区域画布数据
```
---
## 基本操作
1. 左侧设置**场景名称**和**世界尺寸**(米)
2. 选择画笔,在画布上绘制
3. **双击** 已绘制区域 → 弹出命名对话框:
- 输入名称(如"家"、"小卖部")
- **L1 区域**:设置**地形标高**(米,可为负值表示洼地)
- **L2 建筑**:设置**建筑高度**(米)
- 勾选**连通到**其他已命名区域(建立连接关系)
- 勾选「可进入」→ 创建下级详图(L1 → L2)
4. 保存 → 存入 `output/`(服务器模式)或浏览器下载(离线模式)
### 画布标签
- **L1 层**:显示区域名称 + 地形标高(如 `棚户区 (标高2m)`)
- **L2 层**:显示建筑名称 + 建筑高度(如 `棚户1 (3m)`)
- 标高为 0 时不显示高度
---
## 三级层次
| 层级 | 范围 | 绘制内容 | 说明 |
|------|------|---------|------|
| **L1** 场景总览 | ≤1km | 大区域、主干道、河流 | 鸟瞰全局,定位区域关系 |
| **L2** 区域详图 | ≤300m | 建筑、内部道路、绿化、水体 | 每个区域的详细布局 |
| **L3** 建筑内部 | 预留 | 拖放细节资产 | 未来版本 |
### 导航方式
- L1 画布上,双击已命名的区域并勾选「可进入」
- 左侧元素列表中点击 **"进入 →"**
- 面包屑导航点击 **"场景总览"** 返回上级
- 返回 L1 时,L2 的绘制内容会自动合成回 L1 对应区域
---
## 画笔图例
| 画笔 | 颜色 | 用途 | 对应 UE 材质 | 可用层级 | 高度含义 |
|------|------|------|-------------|---------|---------|
| 道路 Road | 灰 `#909090` | 道路、马路、小路 | MI_DevGray | L1/L2 | — |
| 建筑 Building | 橙 `#E07020` | 建筑物 | MI_DevOrange | L2 | 建筑高度 |
| 水域 Water | 天蓝 `#40A0D0` | 河流、水塘、水体 | MI_DevSkyBlue | L1/L2 | — |
| 植被 Greenery | 绿 `#40B040` | 树木、草地、绿化带 | MI_DevGreen | L2 | 2m |
| 不可通行 Blocked | 棕 `#A07040` | 山体、围墙、不可达区域 | MI_DevBrown | L1/L2 | 3m |
| 区域 Zone | 红 `#D04040` | 区域边界、地块划分 | MI_DevRed | L1 | 地形标高 |
| 橡皮擦 Eraser | — | 擦除 | — | L1/L2 | — |
---
## 快捷键
| 操作 | 快捷键 |
|------|--------|
| 画笔工具 | P |
| 橡皮擦工具 | E |
| 撤销 | Ctrl+Z |
| 重做 | Ctrl+Y |
| 网格开关 | G |
---
## 坐标系
- **原点**:画布左下角(西南角)
- **X+**:向右(东)
- **Y+**:向上(北)
- **单位**:厘米(与 UE5 一致,1 uu = 1 cm)
- 画布顶部 = 世界最大 Y,画布底部 = 世界 Y=0
状态栏实时显示鼠标位置的像素坐标和世界坐标。
---
## 输出格式
### scene.json 结构
```json
{
"scene_name": "迈皋桥",
"version": "v02",
"created": "2026-06-09T16:46:32",
"origin": "SW corner, X+ East, Y+ North",
"brush_legend": {
"#D04040": { "type": "zone", "label": "区域 Zone", "mi_material": "MI_DevRed" }
},
"levels": {
"L1": {
"world_size_m": [500, 400],
"canvas_size_px": [1000, 800],
"scale_m_per_px": 0.5,
"elements": [
{
"id": "el_001", "type": "zone", "name": "棚户区",
"height_m": 2, "connections": ["el_002"],
"has_detail": true, "detail_ref": "L2-el_001"
}
],
"regions": [
{
"id": "r_001", "type": "zone", "name": "棚户区",
"bounds_world_m": [5.0, 5.0, 120.0, 95.0],
"area_px": 15000
}
],
"image_file": "迈皋桥-L1-drawing.png",
"l1_base_file": null
},
"L2-el_001": {
"world_size_m": [80, 60],
"elements": [
{ "id": "el_010", "type": "building", "name": "棚户1", "height_m": 3 }
],
"image_file": "迈皋桥-L2-el_001-drawing.png",
"l1_base_file": "迈皋桥-L2-el_001-l1base.png",
"parent_level": "L1",
"parent_element": "el_001"
}
}
}
```
### 高度字段语义
| 层级 | 元素类型 | `height_m` 含义 | 用途 |
|------|---------|----------------|------|
| L1 | zone(区域) | **地形标高** | 地面海拔相对高度,0=基准面,负值=洼地 |
| L2 | building(建筑) | **建筑高度** | 建筑物垂直高度 |
| L1/L2 | blocked(不可通行) | **障碍高度** | 围墙/山体等垂直尺度 |
---
## 本地服务器
`server.py` 提供三个 HTTP 端点,供 `sketch.html` 直接读写 `output/` 目录:
| 端点 | 方法 | 说明 |
|------|------|------|
| `/list` | GET | 列出 `output/` 下所有 `.json` / `.zip` 文件 |
| `/load/<filename>` | GET | 从 `output/` 读取指定文件 |
| `/save` | POST (multipart) | 接收文件并保存到 `output/` |
服务器运行时,sketch.html 自动检测并使用服务器模式;未运行时自动回退到浏览器下载/文件选择。
手动启动:
```bash
python server.py # 默认端口 8765
python server.py 9000 # 自定义端口
```
---
## 工作流集成
在关卡设计流程中的位置:
```
场景概念 (场景-vXX.md)
↓
【World Layout Sketcher】 ← 本工具
↓
AI 布局解读文档 (场景名-layout-vXX.md)
↓ 用户确认
关卡执行案 (关卡-vXX-执行案.md)
↓
搭建指南 → Level Builder → UE5 关卡
```
### AI 解读流程
1. 用户在工具中画好布局,命名区域,设置标高/高度和连通关系,保存
2. AI 读取 JSON 中的 elements + regions + connections + height_m
3. AI 交叉参考场景设计案的氛围描述,将 JSON 数据与场景概念建立映射
4. AI 产出结构化布局解读 Markdown(区域表、连通关系、标高、待确认问题)
5. 用户确认后,策划基于解读文档产出关卡执行案
> PNG 文件用于画布的保存/加载和人工预览。AI 分析以 JSON 结构化数据为准,不依赖 PNG 像素分析。
---
## 设计原则
- **预定义画笔**:无自由拾色器,保证每个像素都映射到已知地形类型
- **结构化数据优先**:标高、高度和连通关系由用户直接输入,AI 无需从图像推断
- **层次化设计**:L1 定大局,L2 定细节,L3 预留
- **人机共读**:PNG 供人视觉确认,JSON 供 AI 和程序化解析
- **材质一致**:画笔颜色直接映射 UE5 的 MI_Dev* 标识色材质
- **离线优先**:单 HTML 文件即可使用,服务器仅为便利增强