123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- use std::{
- fs::File,
- io::{Cursor, Read, Write},
- path::PathBuf,
- };
- use binrw::{BinRead, BinWriterExt};
- use ezcad::pen::Pen;
- use log::debug;
- use serde::{Deserialize, Serialize};
- const SPEED_MIN: f64 = 0.0;
- const SPEED_MAX: f64 = 100000.0;
- const POWER_MIN: f64 = 0.0;
- const POWER_MAX: f64 = 100.0;
- const FREQUENCY_MIN: u32 = 1000;
- const FREQUENCY_MAX: u32 = 999000;
- #[derive(Debug, Serialize, Deserialize)]
- #[serde(rename_all = "PascalCase")]
- pub struct Patch {
- color: Option<(u8, u8, u8)>,
- enabled: Option<bool>,
- loop_count: Option<u32>,
- speed: Option<f64>,
- power: Option<f64>,
- frequency: Option<u32>,
- }
- impl Patch {
- fn patch(&self, id: usize, pens: &mut Vec<Pen>) {
- let to_patch: &mut Pen = pens.get_mut(id).expect("Invalid pen index");
- if let Some(color) = self.color {
- debug!("Patching color for pen #{}: {:?}", id, color);
- *to_patch.color = color.into()
- }
- if let Some(enabled) = self.enabled {
- debug!("Patching enablement for pen #{}: {}", id, enabled);
- *to_patch.disabled = !enabled as u32;
- }
- if let Some(loop_count) = self.loop_count {
- debug!("Patching loop count for pen #{}: {}", id, loop_count);
- assert!(loop_count > 0, "Pen loop count must be greater than zero");
- *to_patch.loop_count = loop_count;
- }
- if let Some(speed) = self.speed {
- debug!("Patching speed for pen #{}: {}", id, speed);
- assert!(
- speed > SPEED_MIN && speed <= SPEED_MAX,
- "Pen speed must be between {} and {}",
- SPEED_MIN,
- SPEED_MAX
- );
- *to_patch.speed = speed;
- }
- if let Some(power) = self.power {
- debug!("Patching power for pen #{}: {}", id, power);
- assert!(
- power > POWER_MIN && power <= POWER_MAX,
- "Pen power must be between {} and {}",
- POWER_MIN,
- POWER_MAX
- );
- *to_patch.power = power;
- }
- if let Some(frequency) = self.frequency {
- debug!("Patching frequency for pen #{}: {}", id, frequency);
- assert!(
- frequency >= FREQUENCY_MIN && frequency <= FREQUENCY_MAX,
- "Pen frequency must be between {} and {}",
- FREQUENCY_MIN,
- FREQUENCY_MAX
- );
- *to_patch.frequency = frequency;
- *to_patch.frequency_2 = frequency.try_into().unwrap();
- }
- // Always enable custom settings for pen
- *to_patch.use_default = 0;
- }
- }
- #[derive(Debug, Serialize, Deserialize)]
- #[serde(rename_all = "PascalCase")]
- pub struct PatchPen {
- pen: usize,
- #[serde(flatten)]
- patch: Patch,
- }
- impl PatchPen {
- pub fn patch(&self, pens: &mut Vec<Pen>) {
- self.patch.patch(self.pen, pens);
- }
- }
- #[derive(Debug, Serialize, Deserialize)]
- #[serde(rename_all = "PascalCase")]
- pub struct ClonePen {
- from: usize,
- to: usize,
- #[serde(flatten)]
- patch: Option<Patch>,
- }
- impl ClonePen {
- pub fn clone(&self, pens: &mut Vec<Pen>) {
- debug!("Cloning pen #{} to #{}", self.from, self.to);
- assert!(
- self.to > self.from,
- "Target pen must be greater than source pen"
- );
- // Clone pen
- let src: Pen = pens.get(self.from).expect("Invalid pen index").clone();
- let dst: &mut Pen = pens.get_mut(self.to).expect("Invalid pen index");
- *dst = src;
- // Patch pen if needed
- if let Some(patch) = &self.patch {
- patch.patch(self.to, pens);
- }
- }
- }
- #[derive(Debug, Serialize, Deserialize)]
- pub enum PatternField {
- Loops(i32),
- Speed(f64),
- Power(f64),
- Frequency(i32),
- }
- #[derive(Debug, Serialize, Deserialize)]
- #[serde(rename_all = "PascalCase")]
- pub struct PatternPen {
- from: usize,
- to: usize,
- field: PatternField,
- }
- impl PatternPen {
- pub fn pattern(&self, pens: &mut Vec<Pen>) {
- debug!("Patterning from pen #{} to #{}", self.from, self.to);
- assert!(
- self.to > self.from,
- "Target pen(s) must be greater than source pen"
- );
- // Obtain settings from first pen
- let src: Pen = pens.get(self.from).expect("Invalid pen index").clone();
- let mut setting: PatternField = match self.field {
- PatternField::Loops(_) => {
- debug!(
- "Initial loop count from pen #{}: {}",
- self.from, *src.loop_count
- );
- PatternField::Loops((*src.loop_count).try_into().unwrap())
- }
- PatternField::Speed(_) => {
- debug!("Initial speed from pen #{}: {}", self.from, *src.speed);
- PatternField::Speed(*src.speed)
- }
- PatternField::Power(_) => {
- debug!("Initial power from pen #{}: {}", self.from, *src.power);
- PatternField::Power(*src.power)
- }
- PatternField::Frequency(_) => {
- debug!(
- "Initial frequency from pen #{}: {}",
- self.from, *src.frequency
- );
- PatternField::Frequency((*src.frequency).try_into().unwrap())
- }
- };
- for dst in (self.from..=self.to).skip(1) {
- // Clone to target pen
- let pen: &mut Pen = pens.get_mut(dst).expect("Invalid pen index");
- *pen = src.clone();
- // Calculate new setting
- setting = match (setting, &self.field) {
- (PatternField::Loops(prev), PatternField::Loops(incr)) => {
- let value: i32 = prev + incr;
- debug!("Patching loop count for pen #{}: {}", dst, value);
- assert!(value > 0, "Pen loop count must be greater than zero");
- PatternField::Loops(value)
- }
- (PatternField::Speed(prev), PatternField::Speed(incr)) => {
- let value: f64 = prev + incr;
- debug!("Patching speed for pen #{}: {}", dst, value);
- assert!(
- value > SPEED_MIN && value <= SPEED_MAX,
- "Pen speed must be between {} and {}",
- SPEED_MIN,
- SPEED_MAX
- );
- PatternField::Speed(value)
- }
- (PatternField::Power(prev), PatternField::Power(incr)) => {
- let value: f64 = prev + incr;
- debug!("Patching power for pen #{}: {}", dst, value);
- assert!(
- value > POWER_MIN && value <= POWER_MAX,
- "Pen power must be between {} and {}",
- POWER_MIN,
- POWER_MAX
- );
- PatternField::Power(value)
- }
- (PatternField::Frequency(prev), PatternField::Frequency(incr)) => {
- let value: i32 = prev + incr;
- debug!("Patching frequency for pen #{}: {}", dst, value);
- assert!(
- value >= FREQUENCY_MIN.try_into().unwrap()
- && value <= FREQUENCY_MAX.try_into().unwrap(),
- "Pen frequency must be between {} and {}",
- FREQUENCY_MIN,
- FREQUENCY_MAX
- );
- PatternField::Frequency(value)
- }
- _ => unreachable!(),
- };
- // Patch updated value
- match setting {
- PatternField::Loops(x) => *pen.loop_count = x.try_into().unwrap(),
- PatternField::Speed(x) => *pen.speed = x,
- PatternField::Power(x) => *pen.power = x,
- PatternField::Frequency(x) => {
- *pen.frequency = x.try_into().unwrap();
- *pen.frequency_2 = x.try_into().unwrap();
- }
- }
- // Always enable custom settings for pen
- *pen.use_default = 0;
- }
- }
- }
- #[derive(Debug, Serialize, Deserialize)]
- #[serde(rename_all = "PascalCase")]
- pub struct ImportExportPen {
- index: usize,
- path: PathBuf,
- }
- impl ImportExportPen {
- pub fn export(&self, pens: &mut Vec<Pen>) {
- debug!(
- "Exporting pen #{} to '{}'",
- self.index,
- self.path.to_string_lossy()
- );
- let pen = pens.get(self.index).expect("Invalid pen index");
- let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
- buffer.write_le(pen).expect("Failed to serialize pen");
- let mut output: File = File::create(&self.path).expect("Failed to open output file");
- output
- .write_all(buffer.into_inner().as_slice())
- .expect("Failed to write to output file");
- }
- pub fn import(&self, pens: &mut Vec<Pen>) {
- debug!(
- "Importing pen #{} from '{}'",
- self.index,
- self.path.to_string_lossy()
- );
- let mut input: File = File::open(&self.path).expect("Failed to open input file");
- let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
- input
- .read_to_end(buffer.get_mut())
- .expect("Failed to read input file");
- let pen: Pen = Pen::read_le(&mut buffer).expect("Failed to deserialize input as pen");
- let dst: &mut Pen = pens.get_mut(self.index).expect("Invalid pen index");
- *dst = pen;
- }
- }
|