aada 0.1.0

纯 Rust 的 2D 骨骼动画引擎,兼容 Spine 4.x 导出格式(JSON + atlas)。求解到分层 Mesh 与各 Mesh 渲染设置为止,之后交给渲染器。
Documentation
//! 渲染负载:引擎输出的网格数据(`Vec<MeshPayload>`),供渲染系统消费。

use glam::{Affine2, Vec2};

use crate::data::runtime::mesh::MeshIdx;

/// 渲染负载的用途
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PayloadUsage {
    /// 普通网格
    Mesh(MeshIdx),
    /// 开始一个裁剪区域(positions 为变形后的裁剪多边形顶点)
    ///
    /// 渲染层应从此负载开始裁剪,直到对应的 ClipEnd;嵌套裁剪取交集
    ClipStart { id: MeshIdx },
    /// 结束一个裁剪区域(与 ClipStart 的 id 配对)
    ClipEnd { id: MeshIdx },
}

/// 运行时向外输出的网格数据
///
/// 实际输出应当为一个 MeshPayload 列表,供渲染系统使用
///
/// 每个 MeshPayload 对应于一个独立的网格对象
///
/// 渲染顺序:列表中靠后的 MeshPayload 会覆盖靠前的,即靠后的 MeshPayload 渲染在前面
///
/// 例如:[mesh_a, mesh_b] 则 mesh_b 会覆盖在 mesh_a 前面
///
/// 注意:本系统为单纹理设计,所有 MeshPayload 共享同一纹理。
///
/// 未来可能添加新字段以支持其他功能
///
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct MeshPayload {
    /// 用途:普通网格 / 裁剪开始 / 裁剪结束
    pub usage: PayloadUsage,
    /// 所属 slot,渲染层用它确定绘制顺序(排序规则由引擎保证,与列表顺序一致)
    pub slot: crate::data::runtime::slot::SlotIdx,
    /// 顶点 UV 坐标,以局部纹理坐标形式存储,必须使用 uv_transform 进行变换后才能用于采样
    pub uvs: Vec<Vec2>,
    /// 顶点位置,以模型空间坐标形式存储,不含深度信息
    /// - 普通网格:蒙皮变形后的网格顶点
    /// - ClipStart:变形后的裁剪多边形顶点(渲染层直接使用,不需要三角形)
    pub positions: Vec<Vec2>,
    /// 三角形索引
    pub indices: Vec<u32>,
    /// 乘性顶点颜色(RGBA,范围 \[0,1\]),用于与纹理颜色相乘
    pub tint_color: [f32; 4],
    /// UV 变换矩阵
    pub uv_transform: Affine2,
}

impl MeshPayload {
    /// 构造一个渲染负载(字段随 [MeshPayload] 的扩展而扩展)
    pub fn new(
        usage: PayloadUsage,
        slot: crate::data::runtime::slot::SlotIdx,
        positions: Vec<Vec2>,
        uvs: Vec<Vec2>,
        indices: Vec<u32>,
        tint_color: [f32; 4],
        uv_transform: Affine2,
    ) -> Self {
        Self {
            usage,
            slot,
            positions,
            uvs,
            indices,
            tint_color,
            uv_transform,
        }
    }
}