live2d_parser/cubism_v1/moc/
pivots.rs

1use crate::{
2    cubism_v1::moc::{MocObject, MocReader, ObjectData},
3    L2Error,
4};
5use serde::{Deserialize, Serialize};
6use tracing::{debug, info, trace, warn};
7
8#[derive(Debug, Serialize, Deserialize)]
9pub struct PivotManager {
10    pub items: Vec<Pivot>,
11}
12
13#[derive(Debug, Serialize, Deserialize)]
14pub struct Pivot {
15    pub id: String,
16    pub count: u32,
17    pub values: Vec<f32>,
18}
19
20impl MocObject for PivotManager {
21    fn read_object(reader: &MocReader) -> Result<Self, L2Error>
22    where
23        Self: Sized,
24    {
25        let o: ObjectData = reader.read()?;
26        Ok(Self { items: o.as_pivots() })
27    }
28}
29
30impl MocObject for Vec<Pivot> {
31    fn read_object(reader: &MocReader) -> Result<Self, L2Error>
32    where
33        Self: Sized,
34    {
35        let count = reader.read_var()?;
36        let mut pivots = Vec::with_capacity(count as usize);
37        for _ in 0..count {
38            pivots.push(reader.read()?);
39        }
40        Ok(pivots)
41    }
42}
43
44impl MocObject for Pivot {
45    fn read_object(reader: &MocReader) -> Result<Self, L2Error>
46    where
47        Self: Sized,
48    {
49        let id = reader.read()?;
50        let count: i32 = reader.read()?;
51        let values: ObjectData = reader.read()?;
52        Ok(Self {
53            id,
54            count: count as u32,
55            // 似乎总是 f32[3], 暂未发现反例
56            values: values.as_f32_array(),
57        })
58    }
59}
60
61impl ObjectData {
62    pub fn as_pivots(self) -> Vec<Pivot> {
63        match self {
64            ObjectData::Null => Vec::new(),
65            ObjectData::ObjectArray(o) => o.into_iter().map(|x| x.as_pivots()).flatten().collect(),
66            ObjectData::Pivot(v) => vec![v],
67            ObjectData::PivotManager(v) => v.items,
68            s => {
69                warn!("ObjectData::as_pivots() called on non-pivot object {s:?}");
70                vec![]
71            }
72        }
73    }
74}