pen.rs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. use std::path::PathBuf;
  2. use ezcad::{pen::Pen, types::Rgba};
  3. use log::debug;
  4. use serde::{Deserialize, Serialize};
  5. const SPEED_MIN: f64 = 0.0;
  6. const SPEED_MAX: f64 = 100000.0;
  7. const POWER_MIN: f64 = 0.0;
  8. const POWER_MAX: f64 = 100.0;
  9. const FREQUENCY_MIN: u32 = 1000;
  10. const FREQUENCY_MAX: u32 = 999000;
  11. #[derive(Debug, Serialize, Deserialize)]
  12. #[serde(rename_all = "PascalCase")]
  13. pub struct Patch {
  14. color: Option<(u8, u8, u8)>,
  15. enabled: Option<bool>,
  16. loop_count: Option<u32>,
  17. speed: Option<f64>,
  18. power: Option<f64>,
  19. frequency: Option<u32>,
  20. }
  21. impl Patch {
  22. fn patch(&self, pen: &mut Pen) {
  23. self.color.map(|color| {
  24. debug!("Patching pen color to {:?}", color);
  25. *pen.color = color.into()
  26. });
  27. self.enabled.map(|enabled| {
  28. debug!("Patching pen enablement to {}", enabled);
  29. *pen.disabled = !enabled as u32;
  30. });
  31. self.loop_count.map(|loop_count| {
  32. debug!("Patching pen loop count to {}", loop_count);
  33. assert!(loop_count > 0, "Pen loop count must be greater than zero");
  34. *pen.loop_count = loop_count;
  35. });
  36. self.speed.map(|speed| {
  37. debug!("Patching pen speed {}", speed);
  38. assert!(
  39. speed > SPEED_MIN && speed <= SPEED_MAX,
  40. "Pen speed must be between {} and {}",
  41. SPEED_MIN,
  42. SPEED_MAX
  43. );
  44. *pen.speed = speed;
  45. });
  46. self.power.map(|power| {
  47. debug!("Patching pen power {}", power);
  48. assert!(
  49. power > POWER_MIN && power <= POWER_MAX,
  50. "Pen power must be between {} and {}",
  51. POWER_MIN,
  52. POWER_MAX
  53. );
  54. *pen.power = power;
  55. });
  56. self.frequency.map(|frequency| {
  57. debug!("Patching pen frequency {}", frequency);
  58. assert!(
  59. frequency >= FREQUENCY_MIN && frequency <= FREQUENCY_MAX,
  60. "Pen frequency must be between {} and {}",
  61. FREQUENCY_MIN,
  62. FREQUENCY_MAX
  63. );
  64. *pen.frequency = frequency;
  65. *pen.frequency_2 = frequency.try_into().unwrap();
  66. });
  67. // Always enable custom settings for pen
  68. *pen.use_default = 0;
  69. }
  70. }
  71. #[derive(Debug, Serialize, Deserialize)]
  72. #[serde(rename_all = "PascalCase")]
  73. pub struct PatchPen {
  74. pen: usize,
  75. #[serde(flatten)]
  76. patch: Patch,
  77. }
  78. impl PatchPen {
  79. pub fn patch(&self, pens: &mut Vec<Pen>) {
  80. debug!("Patching pen #{}", self.pen);
  81. let pen: &mut Pen = pens.get_mut(self.pen).expect("Invalid pen index");
  82. self.patch.patch(pen);
  83. }
  84. }
  85. #[derive(Debug, Serialize, Deserialize)]
  86. #[serde(rename_all = "PascalCase")]
  87. pub struct ClonePen {
  88. from: usize,
  89. to: usize,
  90. inclusive: Option<bool>,
  91. #[serde(flatten)]
  92. patch: Option<Patch>,
  93. }
  94. impl ClonePen {
  95. pub fn clone(&self, pens: &mut Vec<Pen>) {
  96. debug!(
  97. "Cloning pen #{} to #{}{}",
  98. self.from,
  99. self.to,
  100. match self.inclusive {
  101. Some(true) => format!("(inclusive)"),
  102. _ => format!(""),
  103. }
  104. );
  105. // Clone pen
  106. let src: Pen = pens.get(self.from).expect("Invalid pen index").clone();
  107. match self.inclusive {
  108. Some(true) => {
  109. assert!(
  110. self.to > self.from,
  111. "Target pen(s) must be greater than source pen"
  112. );
  113. // Clone pen (randomize color)
  114. for idx in (self.from..=self.to).skip(1) {
  115. let dst: &mut Pen = pens.get_mut(idx).expect("Invalid pen index");
  116. *dst = src.clone();
  117. *dst.color = Rgba::random().into();
  118. // Patch pen if needed
  119. self.patch.as_ref().map(|patch| {
  120. debug!("Patching pen #{}", idx);
  121. patch.patch(dst);
  122. });
  123. }
  124. }
  125. _ => {
  126. let dst: &mut Pen = pens.get_mut(self.to).expect("Invalid pen index");
  127. *dst = src;
  128. // Patch pen if needed
  129. self.patch.as_ref().map(|patch| {
  130. debug!("Patching pen #{}", self.to);
  131. patch.patch(dst);
  132. });
  133. }
  134. }
  135. }
  136. }
  137. #[derive(Debug, Serialize, Deserialize)]
  138. pub enum PatternField {
  139. Loops(i32),
  140. Speed(f64),
  141. Power(f64),
  142. Frequency(i32),
  143. }
  144. impl PatternField {
  145. pub fn pattern(&self, pens: &mut dyn Iterator<Item = (usize, &mut Pen)>) {
  146. // Obtain settings from source (first) pen
  147. let (src_idx, src) = pens.next().expect("Pattern must involve at least one pen");
  148. let mut setting: PatternField = match self {
  149. PatternField::Loops(_) => {
  150. debug!(
  151. "Initial loop count from pen #{} is {}",
  152. src_idx, *src.loop_count
  153. );
  154. PatternField::Loops((*src.loop_count).try_into().unwrap())
  155. }
  156. PatternField::Speed(_) => {
  157. debug!("Initial speed from pen #{} is {}", src_idx, *src.speed);
  158. PatternField::Speed(*src.speed)
  159. }
  160. PatternField::Power(_) => {
  161. debug!("Initial power from pen #{} is {}", src_idx, *src.power);
  162. PatternField::Power(*src.power)
  163. }
  164. PatternField::Frequency(_) => {
  165. debug!(
  166. "Initial frequency from pen #{} is {}",
  167. src_idx, *src.frequency
  168. );
  169. PatternField::Frequency((*src.frequency).try_into().unwrap())
  170. }
  171. };
  172. for (idx, dst) in pens {
  173. // Calculate new setting
  174. setting = match (setting, self) {
  175. (PatternField::Loops(prev), PatternField::Loops(incr)) => {
  176. let value: i32 = prev + incr;
  177. debug!("Patching loop count for pen #{} to {}", idx, value);
  178. assert!(value > 0, "Pen loop count must be greater than zero");
  179. PatternField::Loops(value)
  180. }
  181. (PatternField::Speed(prev), PatternField::Speed(incr)) => {
  182. let value: f64 = prev + incr;
  183. debug!("Patching speed for pen #{} to {}", idx, value);
  184. assert!(
  185. value > SPEED_MIN && value <= SPEED_MAX,
  186. "Pen speed must be between {} and {}",
  187. SPEED_MIN,
  188. SPEED_MAX
  189. );
  190. PatternField::Speed(value)
  191. }
  192. (PatternField::Power(prev), PatternField::Power(incr)) => {
  193. let value: f64 = prev + incr;
  194. debug!("Patching power for pen #{} to {}", idx, value);
  195. assert!(
  196. value > POWER_MIN && value <= POWER_MAX,
  197. "Pen power must be between {} and {}",
  198. POWER_MIN,
  199. POWER_MAX
  200. );
  201. PatternField::Power(value)
  202. }
  203. (PatternField::Frequency(prev), PatternField::Frequency(incr)) => {
  204. let value: i32 = prev + incr;
  205. debug!("Patching frequency for pen #{} to {}", idx, value);
  206. assert!(
  207. value >= FREQUENCY_MIN.try_into().unwrap()
  208. && value <= FREQUENCY_MAX.try_into().unwrap(),
  209. "Pen frequency must be between {} and {}",
  210. FREQUENCY_MIN,
  211. FREQUENCY_MAX
  212. );
  213. PatternField::Frequency(value)
  214. }
  215. _ => unreachable!(),
  216. };
  217. // Patch updated value
  218. match setting {
  219. PatternField::Loops(x) => *dst.loop_count = x.try_into().unwrap(),
  220. PatternField::Speed(x) => *dst.speed = x,
  221. PatternField::Power(x) => *dst.power = x,
  222. PatternField::Frequency(x) => {
  223. *dst.frequency = x.try_into().unwrap();
  224. *dst.frequency_2 = x.try_into().unwrap();
  225. }
  226. }
  227. // Always enable custom settings for pen
  228. *dst.use_default = 0;
  229. }
  230. }
  231. }
  232. #[derive(Debug, Serialize, Deserialize)]
  233. #[serde(rename_all = "PascalCase")]
  234. pub struct PatternPen {
  235. index: usize,
  236. count: usize,
  237. field: PatternField,
  238. }
  239. impl PatternPen {
  240. pub fn pattern(&self, pens: &mut Vec<Pen>) {
  241. debug!(
  242. "Patterning from pen #{} to #{}",
  243. self.index,
  244. self.index + self.count - 1
  245. );
  246. self.field.pattern(
  247. &mut pens
  248. .iter_mut()
  249. .enumerate()
  250. .skip(self.index)
  251. .take(self.count),
  252. )
  253. }
  254. }
  255. #[derive(Debug, Serialize, Deserialize)]
  256. #[serde(rename_all = "PascalCase")]
  257. pub struct ImportExportPen {
  258. index: usize,
  259. path: PathBuf,
  260. }
  261. impl ImportExportPen {
  262. pub fn export(&self, pens: &mut Vec<Pen>) {
  263. debug!(
  264. "Exporting pen #{} to '{}'",
  265. self.index,
  266. self.path.to_string_lossy()
  267. );
  268. let pen = pens.get(self.index).expect("Invalid pen index");
  269. pen.write_to_file(&self.path);
  270. }
  271. pub fn import(&self, pens: &mut Vec<Pen>) {
  272. debug!(
  273. "Importing pen #{} from '{}'",
  274. self.index,
  275. self.path.to_string_lossy()
  276. );
  277. let pen: Pen = Pen::read_from_file(&self.path);
  278. let dst: &mut Pen = pens.get_mut(self.index).expect("Invalid pen index");
  279. *dst = pen;
  280. }
  281. }