You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 line
4.3KB

  1. use regex::{Regex, RegexBuilder, Captures};
  2. use std::sync::RwLock;
  3. use crate::instruction::{Instruction, InstructionType, Vector3, CameraData};
  4. lazy_static!{
  5. static ref REGEX_CACHE: RwLock<RegexPatterns> = RwLock::new(RegexPatterns{
  6. single_instruction: RegexBuilder::new(r"(\w+)\s*\((\d+(?:\.\d+)?),?\s*(\d+(?:\.\d+)?),?\s*(\d+(?:\.\d+)?)(?:,?\s*(\d+(?:\.\d+)?))?\s*\)").case_insensitive(true).build().unwrap(),
  7. //multi_instruction: RegexBuilder::new("").case_insensitive(true).build().unwrap(),
  8. });
  9. }
  10. struct RegexPatterns {
  11. single_instruction: Regex,
  12. }
  13. impl Instruction {
  14. pub fn parse_line(line: &str) -> Result<Instruction, String> {
  15. let cache_lock = REGEX_CACHE.read().unwrap();
  16. if count(line, '(') > 1 {
  17. // do multi parsing
  18. let mut instructions = Vec::<InstructionType>::new();
  19. for capture in cache_lock.single_instruction.captures_iter(line) {
  20. let ins = Self::parse_single(&capture)?;
  21. instructions.push(ins);
  22. }
  23. return Ok(Instruction {
  24. instr: InstructionType::Multi{instructions},
  25. start: 0.0,
  26. progress: 0.0,
  27. base: CameraData::default(),
  28. })
  29. } else {
  30. // assume single instruction on line
  31. if let Some(captures) = cache_lock.single_instruction.captures(line) {
  32. let instr = Self::parse_single(&captures)?;
  33. return Ok(Instruction {
  34. instr,
  35. start: 0.0,
  36. progress: 0.0,
  37. base: CameraData::default(),
  38. })
  39. } else {
  40. return Err("Invalid line".to_string());
  41. }
  42. }
  43. }
  44. fn parse_single(c: &Captures) -> Result<InstructionType, String> {
  45. let name = c.get(1).unwrap().as_str();
  46. let param1 = c.get(2).unwrap().as_str().parse::<f64>().unwrap();
  47. let param2 = c.get(3).unwrap().as_str().parse::<f64>().unwrap();
  48. let param3 = c.get(4).unwrap().as_str().parse::<f64>().unwrap();
  49. // optional 4th param
  50. // let param4 = c.get(5).unwrap().as_str().parse::<f64>();
  51. match name.to_uppercase().as_str() {
  52. "TRACK" => {
  53. if let Some(param4) = c.get(5) {
  54. Ok(InstructionType::Track {
  55. vector: Vector3{x: param1, y: param2, z: param3},
  56. time: param4.as_str().parse::<f64>().unwrap(),
  57. })
  58. } else {
  59. Ok(InstructionType::Track {
  60. vector: Vector3{x: param1, y: param2, z: param3},
  61. time: 0.0,
  62. })
  63. }
  64. },
  65. "MOVE" => Ok(InstructionType::Move {
  66. vector: Vector3{x: param1, y: param2, z: param3},
  67. }),
  68. "ROTATE" => {
  69. if let Some(param4) = c.get(5) {
  70. Ok(InstructionType::Rotate {
  71. vector: Vector3{x: param1, y: param2, z: param3},
  72. time: param4.as_str().parse::<f64>().unwrap(),
  73. })
  74. } else {
  75. Ok(InstructionType::Track {
  76. vector: Vector3{x: param1, y: param2, z: param3},
  77. time: 0.0,
  78. })
  79. }
  80. },
  81. "LOOK" => Ok(InstructionType::Look {
  82. vector: Vector3{x: param1, y: param2, z: param3},
  83. }),
  84. _ => Err(format!("Invalid instruction {}", name))
  85. }
  86. }
  87. pub fn start(&mut self, now: f64, base: CameraData) {
  88. self.start = now;
  89. self.base = base;
  90. }
  91. pub fn lerp(&mut self, now: f64) -> CameraData {
  92. self.progress += now;
  93. match self.instr {
  94. InstructionType::Look {..} | InstructionType::Move {..} => self.instr.lerp(self.start, now),
  95. InstructionType::Track {..} | InstructionType::Rotate {..} | InstructionType::Multi{..} => self.base + self.instr.lerp(self.start, now),
  96. }
  97. }
  98. pub fn done(&self) -> bool {
  99. !(self.progress < (self.start + self.instr.time()))
  100. }
  101. }
  102. // string helper functions
  103. fn count(target: &str, chr: char) -> usize {
  104. let mut times: usize = 0;
  105. for c in target.chars() {
  106. if chr == c {
  107. times+=1;
  108. }
  109. }
  110. times
  111. }