mirror of
https://github.com/storytold/bevy-mocap.git
synced 2026-10-09 00:09:45 +00:00
early passing tests
This commit is contained in:
+64
-13
@@ -5,12 +5,11 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub struct MorphID {
|
pub struct MorphID {
|
||||||
id: usize,
|
pub id: usize,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||||
pub struct RelativeFrameTime(f32);
|
pub struct RelativeFrameTime(pub f32);
|
||||||
|
|
||||||
impl MorphID {
|
impl MorphID {
|
||||||
pub fn new(id: usize) -> Self {
|
pub fn new(id: usize) -> Self {
|
||||||
@@ -22,20 +21,21 @@ impl MorphID {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct CSVFrame {
|
pub struct CSVFrame {
|
||||||
timestamp: RelativeFrameTime,
|
pub timestamp: RelativeFrameTime,
|
||||||
morphs: HashMap<MorphID, f32>,
|
pub morphs: HashMap<MorphID, f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct CSVAnimation {
|
pub struct CSVAnimation {
|
||||||
frames: Vec<CSVFrame>,
|
pub frames: Vec<CSVFrame>,
|
||||||
morph_names: Vec<String>
|
pub morph_names: Vec<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug)]
|
||||||
pub enum CSVParseError {
|
pub enum CSVParseError {
|
||||||
NoData
|
NoData,
|
||||||
|
InvalidCSV(csv::Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for CSVParseError {
|
impl std::fmt::Display for CSVParseError {
|
||||||
@@ -46,9 +46,46 @@ impl std::fmt::Display for CSVParseError {
|
|||||||
|
|
||||||
impl std::error::Error for CSVParseError {}
|
impl std::error::Error for CSVParseError {}
|
||||||
|
|
||||||
|
const TIMECODE_COLUMN_ID : usize = 0;
|
||||||
|
const MORPH_COLUMNS_START_ID : usize = 2;
|
||||||
|
|
||||||
impl CSVAnimation {
|
impl CSVAnimation {
|
||||||
pub fn parse(csv: &str) -> Result<CSVAnimation, CSVParseError> {
|
pub fn parse(csv: &str) -> Result<CSVAnimation, CSVParseError> {
|
||||||
Err(CSVParseError::NoData)
|
if csv.is_empty() {
|
||||||
|
return Err(CSVParseError::NoData);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buffer = csv.as_bytes();
|
||||||
|
|
||||||
|
let mut csv_content = csv::ReaderBuilder::new().has_headers(false).from_reader(buffer);
|
||||||
|
|
||||||
|
let mut records = csv_content.records();
|
||||||
|
|
||||||
|
let first_row = match records.next() {
|
||||||
|
Some(Ok(v)) => v,
|
||||||
|
Some(Err(e)) => {
|
||||||
|
return Err(CSVParseError::InvalidCSV(e));
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
return Err(CSVParseError::NoData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let morph_names = first_row.iter().enumerate().filter_map(|(i, v)| if i >= MORPH_COLUMNS_START_ID { Some(v.trim().to_string()) } else { None }).collect();
|
||||||
|
|
||||||
|
for result in csv_content.records() {
|
||||||
|
let record = match result {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(error) => {
|
||||||
|
return Err(CSVParseError::InvalidCSV(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(CSVAnimation {
|
||||||
|
frames: vec![],
|
||||||
|
morph_names,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +94,21 @@ mod tests {
|
|||||||
use crate::{CSVAnimation, CSVParseError};
|
use crate::{CSVAnimation, CSVParseError};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn given_no_data_the_csv_doesnt_parse() {
|
fn given_no_data_it_emits_a_no_data_error() {
|
||||||
assert_eq!(CSVAnimation::parse("").err().unwrap(), CSVParseError::NoData)
|
assert!(matches!(CSVAnimation::parse("").err().unwrap(), CSVParseError::NoData))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn given_an_invalid_csv_it_emits_an_invalid_csv_error() {
|
||||||
|
assert!(matches!(CSVAnimation::parse("an invalid csv file
|
||||||
|
seems to be here... right now?
|
||||||
|
I wonder, will it be caught"), Err(CSVParseError::InvalidCSV(_))))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn given_a_header_row_it_sets_correct_headers() {
|
||||||
|
let result = CSVAnimation::parse("timecode, blendshapecount, shape_1, shape_2").unwrap();
|
||||||
|
assert_eq!(result.morph_names.get(0).unwrap(), "shape_1");
|
||||||
|
assert_eq!(result.morph_names.get(1).unwrap(), "shape_2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user