// 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} */ (obj))) { deepFreeze(value) } return Object.freeze(obj) } // —— 合并:命名姿势覆盖同名内置 clip(验收 §2.4:调用方拿到合并后结果,无需自己 merge)—— /** @type {Record} */ const MERGED_CLIPS = deepFreeze({ ...CLIPS, ...POSES }) /** @type {Record} */ const FROZEN_POSES = deepFreeze({ ...POSES }) /** @type {Record} */ const FROZEN_RIGS = deepFreeze({ ...RIGS }) /** 有序轨道:['base','lower_body','arm_l','arm_r','head']。 @type {string[]} */ export const TRACKS = deepFreeze([..._TRACKS]) /** 各 track 拥有的 bone 子集(互不相交)。 @type {Record} */ export const TRACK_BONES = deepFreeze({ ..._TRACK_BONES }) /** 无指定动作时回落的默认 clip id。 @type {Record} */ 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} */ export function getClips() { return MERGED_CLIPS } /** * 取命名姿势集。 * @returns {Record} */ 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 }