1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//! # aada —— 纯 Rust 的 2D 骨骼动画引擎库
//!
//! 兼容 [Spine](https://esotericsoftware.com/spine) 4.x 导出格式(JSON + atlas)。本库只负责
//! **求解到"分层 Mesh + 各 Mesh 渲染设置"为止**,之后的绘制交给渲染器(bevy 集成在独立的
//! `aada-bevy` crate 中)。无渲染器依赖,仅依赖 `glam` / `serde`。
//!
//! ## 架构
//!
//! - `cacl`:纯计算(仿射矩阵、贝塞尔曲线采样),与数据无关。
//! - `data::store`:导入层。把 spine JSON / atlas 解析为可 serde 序列化的中间结构,
//! 再经 `to_rt()` 转成运行时索引化数据。
//! - `data::runtime`:运行时层。索引化的静态数据集合 + 每帧引擎管线。
//! - `custom_index` / `vec_map` / `utils` / `error`:索引容器与通用工具。
//!
//! 核心设计:**解析期一次性把名称解析为强类型索引**(`BoneIdx` / `SlotIdx` / `MeshIdx` /
//! `SkinIdx` / `AnimIdx` 等),运行时零字符串查找、全部走索引。静态数据(骨骼层级、皮肤、
//! 网格、动画)与可变状态([`data::runtime::skeleton::Pose`] 每帧变换、约束状态)分离。
//!
//! ## 快速开始
//!
//! ```no_run
//! use aada::prelude::*;
//!
//! // 1. 构建运行时(spine JSON + atlas 文本)
//! let (rt, _pages) = build_rt(
//! &"{\"skeleton\":{}}".to_string(),
//! &"example.png\nsize: 1024, 1024".to_string(),
//! )
//! .unwrap();
//!
//! // 2. 按名称取索引(之后全走索引)
//! let anim = rt.animates.get_index("walk").unwrap();
//! let skin = rt.skins.get_index("default").unwrap();
//!
//! // 3. 每帧走分步管线(config 跨帧复用,连续时间采样 O(1) 加速),
//! // 中间可插入自定义逻辑(如约束前操纵骨骼、覆盖约束参数)
//! let mut config = AnimateConfig::new();
//! for t in 0..60 {
//! let sampled = rt.sample(anim, &mut config, t as f32 / 60.0);
//! let mut pose = rt.pose_from_sample(&sampled); // 可在此修改 pose(约束前骨骼操纵)
//! let state = rt.constraint_state(&sampled); // 可在此覆盖约束参数
//! rt.apply_constraint_state(&mut pose, &state);
//! let payloads = rt.build_payloads(&[skin], &sampled, &mut pose);
//! // payloads: Vec<MeshPayload>,顺序即渲染顺序(靠后覆盖靠前)
//! }
//! ```