index.js
3.38 KB
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
81
82
83
84
85
86
87
88
89
90
// index.js — @drama/rig 唯一公共面(§3 契约)。
//
// 职责:汇总 rigs/clips/poses 三类纯数据,做「命名姿势覆盖同名内置 clip」的合并,深冻结,
// 暴露查询函数与轨道元数据。**无任何求值 / 插值 / 渲染逻辑**(那些全在 @drama/core)。
//
// 不可变性约定:采用「方案 A —— 返回深冻结(Object.freeze 递归)的共享常量」。
// 零拷贝、调用方误改即抛(严格模式)/ 静默失败(非严格)。
// core 侧约定不修改 rig 返回的数据(增量算在 core 内部临时结构里),故方案 A 足够。
// 形状契约 typedef 经公共面再导出,供下游 `import('@drama/rig').RigDefinition` 等消费
// (@drama/core / @drama/render-pixi 基于此对齐,详见 types.js)。
/**
* @typedef {import('./types.js').RigDefinition} RigDefinition
* @typedef {import('./types.js').Bone} Bone
* @typedef {import('./types.js').Slot} Slot
* @typedef {import('./types.js').AnimationClip} AnimationClip
* @typedef {import('./types.js').Keyframe} Keyframe
* @typedef {import('./types.js').NamedPose} NamedPose
*/
import { RIGS } from './rigs/index.js'
import { CLIPS, TRACKS as _TRACKS, TRACK_BONES as _TRACK_BONES, TRACK_DEFAULTS as _TRACK_DEFAULTS } from './clips/index.js'
import { POSES } from './poses.js'
/**
* 递归深冻结一个普通对象/数组(就地冻结,纯数据无循环引用)。
* @template {unknown} T
* @param {T} obj
* @returns {T}
*/
function deepFreeze(obj) {
if (obj === null || typeof obj !== 'object' || Object.isFrozen(obj)) return obj
for (const value of Object.values(/** @type {Record<string, unknown>} */ (obj))) {
deepFreeze(value)
}
return Object.freeze(obj)
}
// —— 合并:命名姿势覆盖同名内置 clip(验收 §2.4:调用方拿到合并后结果,无需自己 merge)——
/** @type {Record<string, import('./types.js').AnimationClip>} */
const MERGED_CLIPS = deepFreeze({ ...CLIPS, ...POSES })
/** @type {Record<string, import('./types.js').NamedPose>} */
const FROZEN_POSES = deepFreeze({ ...POSES })
/** @type {Record<string, import('./types.js').RigDefinition>} */
const FROZEN_RIGS = deepFreeze({ ...RIGS })
/** 有序轨道:['base','lower_body','arm_l','arm_r','head']。 @type {string[]} */
export const TRACKS = deepFreeze([..._TRACKS])
/** 各 track 拥有的 bone 子集(互不相交)。 @type {Record<string, string[]>} */
export const TRACK_BONES = deepFreeze({ ..._TRACK_BONES })
/** 无指定动作时回落的默认 clip id。 @type {Record<string, string>} */
export const TRACK_DEFAULTS = deepFreeze({ ..._TRACK_DEFAULTS })
/**
* 取骨架定义。未知 id 返回 null(不抛)。
* @param {string} id
* @returns {import('./types.js').RigDefinition|null}
*/
export function getRig(id) {
return FROZEN_RIGS[id] ?? null
}
/**
* 取内置动作库全集(含命名姿势合并后结果)。
* @returns {Record<string, import('./types.js').AnimationClip>}
*/
export function getClips() {
return MERGED_CLIPS
}
/**
* 取命名姿势集。
* @returns {Record<string, import('./types.js').NamedPose>}
*/
export function getPoses() {
return FROZEN_POSES
}
/**
* 取单个 clip(含命名姿势,姿势覆盖同名内置)。未知 id 返回 null。
* @param {string} id
* @returns {import('./types.js').AnimationClip|null}
*/
export function getClip(id) {
return MERGED_CLIPS[id] ?? null
}