Files
SpineParticlesWeb/网页粒子系统阶段八.md
T
2026-08-29 21:36:04 +08:00

574 lines
20 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.
# 网页粒子系统 · 阶段八
> 阶段定位:**Spine 骨骼选择、粒子独立骨骼跟随、对象显隐、编辑效率与画布参考功能定版**
> 完成日期:2026-08-29
> 工程目录:`/Users/tianmokeji/Desktop/SpineParticle`
> 技术栈:Vue 3 + TypeScript + Pinia + PixiJS 7 + Spine Runtime 4.2 + Vite
---
## 一、阶段结论
阶段八在阶段七 Spine 资源加载和统一时间轴的基础上,完成了骨骼选择到粒子发射器跟随的完整工作流。粒子系统现在可以分别绑定不同 Spine 对象中的不同骨骼,绑定关系彼此独立,并具备目标失效后的自动回退机制。
本阶段同时把场景对象显隐改为对象级控制,并为后续导出建立了粒子系统“所属动画”数据模型。
本阶段主要完成:
1. 将界面中的“骨架”术语统一为 `Spine`
2. 为 Spine 层级树增加骨骼选择、清除选择、搜索和折叠操作;
3. 在画布中显示当前选中骨骼的位置;
4. 实现粒子发射器跟随 Spine 骨骼;
5. 支持位移、旋转、缩放偏移以及本地/世界空间;
6. 修复 Spine 旋转和缩放被错误传递给粒子的问题;
7. 让多个粒子系统的 Spine 与骨骼绑定彼此独立;
8. 实现目标 Spine 或骨骼失效后的自动回退;
9. 为场景中的粒子、碰撞体、路径和 Spine 增加独立显隐按钮;
10. 移除系统设置中的全局 Spine 资源显示开关;
11. 为时间轴增加 Spine 预览动画快捷选择;
12. 将时间轴“动画”升级为粒子系统“所属动画”管理;
13. 支持所属动画新增、重命名、删除和最少一个动画保护;
14. 移除画布右上角重复的秒数显示;
15. 增加 Spine 资源文件夹一键加载;
16. 修复统计数字、帧数和所属动画菜单的显示稳定性;
17. 为四类场景对象增加独立复制功能;
18. 增加画布背景图上传、偏移、透明度和清除功能;
19. 完成 Spine 4.2 与背景图测试资源下的交互及生产构建验证。
---
## 二、Spine 术语与对象界面
### 2.1 术语统一
面向用户的场景对象术语统一使用 `Spine`,不再把资源对象简称为“骨架”。
主要界面名称包括:
- `Spine`
- `Spine 属性`
- `Spine 名称`
- `Spine 资源`
- `Spine 动画`
- `启用 Spine` 相关提示;
- 场景对象类型 `Spine`
“骨骼”一词只用于 Spine 资源内部真实的 bone 层级和粒子系统生成的骨骼数据,避免与整个 Spine 场景对象混淆。
### 2.2 画布时间文字清理
画布右上角原有的 `t=0.00s` 文字只是当前时间的重复调试显示。当前帧、总帧数和播放状态已经由底部时间轴完整表达,因此本阶段将该文字移除。
---
## 三、Spine 骨骼层级树
### 3.1 骨骼选择
Spine 资源加载成功后,层级树中的每个骨骼都可以点击选择:
- 当前骨骼使用高亮行显示;
- 默认不选择任何骨骼;
- 同一时间只保留一个层级树骨骼作为“当前选中骨骼”;
- 再次点击同一骨骼可以取消选择;
- 选择另一个 Spine 中的骨骼时,会清除之前的临时层级树选择。
层级树标题旁显示自适应宽度的选择按钮:
```text
未选择时:当前骨骼:未选择
已选择时:清除选中骨骼:boneName
```
点击已选择状态的按钮可以清除层级树选择。按钮宽度会根据骨骼名称和可用空间自动调整,名称过长时使用省略显示。
### 3.2 名称搜索
层级树增加骨骼名称搜索框:
- 输入名称片段即可过滤骨骼;
- 搜索不区分大小写;
- 支持一键清空搜索内容;
- 没有匹配结果时显示空状态提示;
- 搜索只改变显示结果,不修改骨骼数据或当前绑定。
### 3.3 折叠与展开
保留并完善阶段七的层级操作:
- 单独折叠或展开父骨骼;
- 全部折叠;
- 全部展开;
- 搜索状态下直接展示名称匹配结果;
- 长列表在固定区域内滚动。
### 3.4 画布骨骼点预览
在层级树选择骨骼后,画布会立即绘制该骨骼的世界位置点,不需要先开启粒子跟随。
该预览用于确认:
- 是否选择了正确骨骼;
- 骨骼当前动画位置是否正确;
- Spine 对象自身位移、旋转和缩放后的世界位置是否正确;
- 粒子发射器后续应绑定的位置。
清除层级树选择后,单纯的选择预览点会消失;已经绑定到粒子系统的骨骼目标仍按绑定关系保留。
---
## 四、粒子发射器骨骼跟随
### 4.1 跟随模式
开启“发射器跟随”后,跟随模式包括:
| 模式 | 行为 |
|---|---|
| 无 | 不使用路径或骨骼跟随 |
| 跟随路径 | 使用场景路径对象驱动发射器 |
| 选中的骨骼 | 把当前粒子系统绑定到层级树当前选中的 Spine 骨骼 |
只有层级树存在有效选中骨骼时,才可以新建骨骼绑定。已经完成骨骼绑定的粒子系统会继续保留该模式,即使之后清除了层级树临时选择。
### 4.2 一次绑定原则
层级树的“当前选中骨骼”只是一个待绑定目标。选择“选中的骨骼”时,会把以下信息一次性写入当前粒子系统:
```text
emitterFollowSpineId
emitterFollowBoneName
```
绑定完成后,后续在层级树中选择其他骨骼不会自动覆盖已有绑定。
面板显示的是当前粒子系统实际保存的目标:
```text
跟随目标:SpineSkeleton1 / root
```
如果层级树当前选择与已绑定目标不同,面板显示“重新绑定当前选中骨骼”按钮。只有主动点击该按钮,当前粒子系统才会改绑到新目标。
### 4.3 多粒子系统独立绑定
每个粒子系统独立保存自己的 Spine ID 和骨骼名称,因此支持:
- 粒子系统 A 跟随 Spine A 的骨骼 `hand_l`
- 粒子系统 B 跟随 Spine A 的骨骼 `hand_r`
- 粒子系统 C 跟随 Spine B 的骨骼 `weapon`
- 各粒子系统使用不同的偏移和空间模式;
- 修改其中一个粒子系统的目标不会影响其他系统。
运行时逐个读取粒子系统自身保存的目标,并从对应 Spine 运行时对象中查询骨骼世界位置,不再使用全局骨骼目标覆盖全部粒子系统。
### 4.4 参数
骨骼绑定成功后显示:
| 参数 | 默认值 | 说明 |
|---|---:|---|
| 跟随空间 | 世界空间 | 控制已出生粒子是否继续随目标移动 |
| 位移偏移 X / Y | 0 / 0 | 在骨骼世界位置上叠加位置偏移 |
| 旋转偏移 | 0° | 使用粒子系统自身旋转基础上的附加角度 |
| 缩放偏移 X / Y | 1 / 1 | 使用粒子系统自身缩放基础上的倍率 |
绑定没有成功时不会再出现只有“选中的骨骼”下拉值、下方却完全空白的状态。面板会提示尚未绑定有效骨骼,并在存在层级树选择时提供明确的绑定按钮。
### 4.5 本地空间与世界空间
| 空间 | 行为 |
|---|---|
| 本地空间 | 整个粒子发射器随骨骼位置移动,已出生粒子继续随发射器移动 |
| 世界空间 | 只移动新粒子的生成位置,已经出生的粒子保留在生成时的世界位置 |
两种空间只改变粒子位置的跟随判定,不会因为切换空间而改变粒子本身的尺寸。
### 4.6 Spine 变换继承规则
骨骼跟随只读取目标骨骼的世界位置,不继承以下变换:
- Spine 对象的旋转;
- Spine 对象的缩放;
- Spine 骨骼自身的旋转;
- Spine 骨骼自身的缩放。
粒子的旋转和缩放始终来自粒子系统自己的根变换及骨骼跟随偏移参数。因此在世界空间与本地空间之间切换时,粒子大小不会因 Spine 或骨骼缩放而变化。
### 4.7 目标失效回退
每个粒子系统持续校验自己保存的目标。以下情况会使绑定失效:
- 目标 Spine 对象被删除;
- 目标 Spine 资源被清空;
- 重新加载资源后原骨骼名称不存在;
- 配置中的 Spine ID 或骨骼名称无效。
失效后只重置受影响的粒子系统:
```text
emitterFollowMode = none
emitterFollowSpineId = 0
emitterFollowBoneName = ''
```
单纯清除层级树的“当前选中骨骼”不会解除已有绑定,因为骨骼本身仍然存在。
---
## 五、场景对象独立显隐
### 5.1 对象级小眼睛
场景对象列表中的每个对象右侧增加小眼睛按钮:
- 粒子系统;
- 碰撞体;
- 路径;
- Spine。
点击后只切换该对象的 `visible` 状态。新建对象默认显示;旧场景或热更新对象缺少该字段时自动补为显示。
### 5.2 显隐与启用分离
`visible` 只控制编辑器画布显示,不代替对象原有的 `enabled` 或功能开关。
隐藏对象时:
- 不绘制对象主体;
- 不绘制该对象的变换工具;
- 不绘制其发射点、路径锚点、碰撞体轮廓或选择辅助图形;
- 隐藏粒子系统时同时隐藏粒子骨骼调试线;
- 隐藏 Spine 时隐藏 Spine 资源和选择预览点。
隐藏对象不会:
- 停止粒子模拟;
- 关闭碰撞体的实际碰撞;
- 使路径跟随失效;
- 破坏粒子系统保存的骨骼绑定;
- 修改时间轴时长或导出配置。
因此“小眼睛”是编辑器可见性控制,“启用”仍是对象功能状态,两者语义独立。
### 5.3 移除全局 Spine 显示开关
系统设置中的“启用 Spine 资源显示”已移除。每个 Spine 对象使用自己的小眼睛控制显示,不再通过一个全局开关同时隐藏全部 Spine。
该变更替代了阶段七文档中的全局 Spine 显示设置设计。
---
## 六、时间轴 Spine 预览动画
时间轴控制栏新增“Spine 预览动画”下拉框,与 Spine 属性面板中的动画选择并存。
规则如下:
- 当前选中 Spine 有动画时,优先控制当前 Spine;
- 当前对象不是 Spine 时,使用场景中第一个包含动画的 Spine;
- 下拉项显示动画名称和真实时长;
- 切换后同步更新 Spine 属性面板;
- 切换动画后重新计算时间轴总长度并回到第 0 帧;
- 没有可用 Spine 动画时下拉框置灰。
该功能只提供快捷预览入口,不改变 Spine 动画自身非循环、由编辑器统一时间轴驱动的规则。
---
## 七、粒子系统所属动画
### 7.1 数据语义
时间轴原有的“动画”字段改为“所属动画”。它表示当前粒子系统在后续导出结构中归属于哪个动画,而不是当前 Spine 的预览动画。
每个粒子系统新增独立的动画归属字段:
```text
ParticleSystem.animation
```
项目时间轴状态保存可用动画名称列表:
```text
TimelineState.animations
```
默认状态为:
```text
动画列表:['animation']
新粒子系统所属动画:animation
```
### 7.2 动画管理
点击“所属动画”下拉按钮后可以:
- 查看全部动画名称;
- 修改当前粒子系统所属动画;
- 新增动画;
- 重命名当前动画;
- 删除当前动画。
新增动画自动使用不重复的英文名称:
```text
animation2
animation3
...
```
新增后,当前粒子系统自动归入新动画。
### 7.3 重命名与删除规则
动画名称:
- 不能为空;
- 不能与已有动画重名;
- 最长输入限制为 64 个字符;
- 重命名后,所有引用旧名称的粒子系统同步更新。
删除动画时:
- 如果仍有其他动画,引用被删除动画的粒子系统自动归入相邻的剩余动画;
- 当前选择同步切换到回退动画;
- 动画列表至少保留一个项目;
- 只剩一个动画时删除按钮禁用。
### 7.4 多粒子系统
不同粒子系统可以归属不同动画,例如:
```text
ParticleSystem1 -> idle
ParticleSystem2 -> attack
ParticleSystem3 -> hit
```
切换场景对象中的粒子系统后,时间轴“所属动画”会显示该系统自己的归属,不会覆盖其他粒子系统。
当前阶段只建立动画归属关系,尚未按所属动画过滤时间轴轨道或执行最终导出。
---
## 八、数据与兼容性
### 8.1 新增字段
场景对象新增:
```text
ParticleSystem.visible
ParticleSystem.animation
CollisionBody.visible
ScenePath.visible
SpineSceneObject.visible
```
时间轴新增:
```text
TimelineState.animations
```
粒子发射器沿用并完善:
```text
emitterFollowSpineId
emitterFollowBoneName
emitterFollowBoneOffsetX
emitterFollowBoneOffsetY
emitterFollowBoneRotation
emitterFollowBoneScaleX
emitterFollowBoneScaleY
```
### 8.2 旧数据迁移
开发热更新或旧场景缺少字段时:
- 场景对象默认补为显示;
- 动画列表默认补为 `['animation']`
- 粒子系统缺少或引用无效所属动画时归入 `animation`
- 骨骼跟随字段通过 `ensureEmitterConfig()` 补齐;
- 骨骼目标不存在时自动回到无跟随模式。
系统设置中的旧 `showSpineResources` 字段不再参与界面和运行时显示判断。
---
## 九、编辑效率与画布参考功能
### 9.1 Spine 文件夹一键加载
Spine 资源面板在原有骨架数据、Atlas 和纹理分别选择的方式之外,增加文件夹加载入口。
选择文件夹后会自动识别:
- 一个 `.json``.skel` 骨架数据文件;
- 一个 `.atlas` 图集文件;
- 文件夹中的 `.png``.jpg``.jpeg``.webp` 纹理;
- Atlas 实际引用的多张纹理页面。
识别完成后直接执行与原三步选择相同的 Spine 4.2 加载流程,保留原有分文件选择方式作为兼容入口。
### 9.2 当前场景对象独立复制
场景对象标题栏在 `Spine` 后增加 `+Copy` 按钮。按钮读取场景树当前选中项,支持复制:
- 粒子系统;
- 碰撞体;
- 路径;
- Spine。
复制完成后,新对象自动成为当前选中对象,并使用不重复名称:
```text
ParticleSystem1 Copy
ParticleSystem1 Copy 2
...
```
复制规则如下:
- 面板参数、曲线、标签、路径点和 Spine 元数据进行深度复制;
- 修改副本参数不会反向修改原对象;
- 粒子录制帧属于运行时缓存,不复制旧缓存,由副本按照相同配置重新生成;
- Spine 层级树的临时骨骼选择不复制,副本默认不选中骨骼;
- 已加载的 Spine 解析结果和纹理作为只读资源安全共享;
- Spine 资源注册表使用引用计数,删除任一副本不会提前销毁其他副本仍在使用的纹理;
- 粒子系统原有的 Spine 骨骼跟随目标、所属动画和全部效果参数保持不变。
当场景树不存在有效选中对象时,`+Copy` 自动置灰。
### 9.3 时间轴与统计显示稳定性
本阶段补充修复了以下界面问题:
- 画布左下角系统数量和粒子骨骼数量使用固定宽度与等宽数字,单位数和多位数切换时不再推动后方文字;
- 粒子骨骼数量保持左对齐,数值区域位置固定;
- 时间轴当前帧与总帧作为一个整体固定显示,不再被布局拆开;
- 非循环播放到末帧后再次播放会从头开始;
- 再次播放时,粒子活动数量和粒子骨骼数量持续按当前回放帧更新,不再停留在第一次播放结果;
- “所属动画”菜单改为向上展开,避免靠近屏幕底部时被裁切;
- 修复向上菜单因时间轴父级裁切和层级关系导致点击无效的问题。
### 9.4 画布背景图
画布顶部工具栏增加“背景图”按钮。下拉面板提供:
| 控件 | 行为 |
|---|---|
| 上传图像 / 更换图像 | 选择 `.png``.jpg``.jpeg``.webp` 图片 |
| 清除背景 | 移除当前背景并释放纹理资源 |
| X / Y | 调整背景在画布世界坐标中的位置偏移 |
| 透明度 | 在 0%~100% 范围内调整背景显示透明度 |
背景图片锚点位于图片中心,使用与其他场景对象一致的世界坐标方向,并跟随画布整体缩放和平移。
背景 Sprite 是 `world` 容器中的第一个绘制节点,因此显示优先级低于:
- Spine
- 粒子系统;
- 碰撞体;
- 路径;
- 发射点、变换工具和其他画布辅助图形。
背景图只用于编辑器预览,不参与粒子碰撞、路径采样、时间轴长度或导出数据计算。
“清除背景”在没有图片时置灰。执行清除后:
```text
背景资源:无
X / Y0 / 0
透明度:100%
```
同时撤销临时对象 URL 并释放 PixiJS 纹理,避免反复更换或清除图片产生资源泄漏。
项目中的测试图片为:
```text
public/background/bg.png
```
---
## 十、验证结果
本阶段使用 `public/spine/` 中的 Spine 4.2 测试资源完成验证:
- `bingo.json`
- `bingo.atlas`
- `bingo.png`
- `bingo_2.png`
已验证:
- Spine 骨骼名称搜索、折叠、选择和清除;
- 层级树选择后立即绘制骨骼位置点;
- 选择 `root` 后,骨骼跟随空间和偏移参数正常显示;
- 层级树改选 `zong` 后,已有 `root` 绑定保持不变;
- 点击重新绑定后,当前粒子系统单独切换为 `zong`
- 多粒子系统配置独立保存 Spine ID 和骨骼名称;
- 骨骼目标失效检测及无跟随回退逻辑;
- 本地空间和世界空间不继承 Spine/骨骼旋转与缩放;
- 粒子、碰撞体、路径和 Spine 小眼睛状态切换;
- 全局 Spine 显示设置已经移除;
- Spine 预览动画下拉框与属性面板同步;
- 所属动画默认 `animation`
- 所属动画新增、重命名和删除;
- 删除最后一个动画被禁止;
- 两个粒子系统分别保存 `animation``animation2`
- Spine 文件夹选择可以一次识别骨架数据、Atlas 和多纹理资源;
- `+Copy` 可以分别复制粒子、碰撞体、路径和 Spine;
- 修改粒子副本名称后,原粒子系统名称保持不变;
- Spine 副本可以安全共享已加载资源;
- 背景图下拉面板正常显示上传、清除、X/Y 和透明度控件;
- `public/background/bg.png` 可以成功加载到画布底层;
- 背景图 X/Y 偏移与透明度可以实时调整;
- 未加载背景时“清除背景”按钮正确置灰;
- 统计数字和时间轴帧数显示不再因位数变化产生布局跳动;
- 页面交互过程中无控制台错误;
- `npm run build` 生产构建通过;
- `git diff --check` 通过。
构建仍存在 Vite 主产物超过 500 kB 的体积提示,不影响构建结果和本阶段功能。
---
## 十一、当前限制
1. Spine 资源仍通过本地文件选择器加载,刷新后需要重新选择;
2. Spine 皮肤、插槽、约束和动画混合尚未开放;
3. 骨骼跟随当前只使用骨骼位置,不提供继承骨骼旋转或缩放的可选模式;
4. 骨骼跟随目标使用 Spine ID 和骨骼名称,工程保存与导入格式尚未落地;
5. 所属动画当前只保存分组关系,尚未影响时间轴轨道筛选、播放范围或导出结果;
6. 场景对象小眼睛状态尚未纳入持久化工程文件;
7. Spine 预览动画当前一次控制一个预览对象,尚未提供多 Spine 联动选择界面;
8. 主包仍包含 Spine 运行时和主要编辑器模块,尚未进行动态拆包;
9. 背景图片来自浏览器本地文件选择,刷新页面后需要重新上传;
10. 背景图当前只提供位置和透明度,不提供旋转、缩放、适配画布或锁定操作;
11. 背景图仅用于编辑器显示,尚未纳入工程保存格式和最终导出;
12. 场景对象复制当前在内存场景中完成,工程保存与跨项目粘贴仍待后续实现。
---
## 十二、阶段九建议
1. 建立正式场景工程保存格式,持久化对象显隐、所属动画和骨骼绑定;
2. 实现项目打开、保存、另存为和自动恢复;
3. 把 Spine、Atlas 和纹理复制到工程资源目录并建立相对路径引用;
4. 实现按“所属动画”筛选时间轴轨道和播放范围;
5. 设计导出数据结构,输出动画列表、粒子系统归属和 Spine 骨骼绑定;
6. 为骨骼跟随增加可选的旋转继承、缩放继承和轴向过滤;
7. 增加 Spine 皮肤、插槽和动画混合控制;
8. 建立多 Spine、多粒子系统、多骨骼绑定的自动回归测试;
9. 对 Spine 面板和曲线编辑器进行动态加载,降低主包体积;
10. 补充资源丢失、骨骼改名和动画删除后的导入迁移提示;
11. 将背景图路径、位置和透明度纳入工程文件,并支持重新定位丢失资源;
12. 为背景图增加适配画布、原始尺寸、缩放和锁定操作;
13. 为场景对象复制增加撤销/重做,以及跨工程复制粘贴支持。