pen.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. use std::{
  2. fmt::Debug,
  3. fs::File,
  4. io::{Cursor, Read, Write},
  5. path::PathBuf,
  6. };
  7. use binrw::{BinRead, BinWrite, BinWriterExt, FilePtr64};
  8. use diff::Diff;
  9. use crate::{
  10. field_of::FieldOf,
  11. types::{Bool, Field, Rgba, WString, WobbleType, F64, U32},
  12. };
  13. #[derive(BinRead, Debug)]
  14. pub struct PenHeader {
  15. pub pen_count: u32,
  16. #[br(args {
  17. inner: binrw::args! {
  18. pen_count
  19. }
  20. })]
  21. pub data: FilePtr64<Pens>,
  22. }
  23. // Manually implement BinWrite as FilePtr does not support serialization
  24. // See: https://github.com/jam1garner/binrw/issues/4
  25. impl BinWrite for PenHeader {
  26. type Args<'a> = ();
  27. fn write_options<W: std::io::prelude::Write + std::io::prelude::Seek>(
  28. &self,
  29. writer: &mut W,
  30. endian: binrw::Endian,
  31. args: Self::Args<'_>,
  32. ) -> binrw::prelude::BinResult<()> {
  33. let pen_count: u32 = self.data.pens.len().try_into().unwrap();
  34. pen_count.write_options(writer, endian, args)?;
  35. // Write address of data, which is placed after this field
  36. let data_offset: u64 = writer.stream_position().unwrap() + 8;
  37. data_offset.write_options(writer, endian, args)?;
  38. self.data.pens.write_options(writer, endian, args)
  39. }
  40. }
  41. #[derive(BinRead, BinWrite, Debug, Diff, PartialEq)]
  42. #[diff(attr(
  43. #[derive(Debug, PartialEq)]
  44. ))]
  45. #[br(import {pen_count: u32})]
  46. pub struct Pens {
  47. #[br(count = pen_count)]
  48. pub pens: Vec<Pen>,
  49. }
  50. #[cfg_attr(feature = "default-debug", derive(Debug))]
  51. #[derive(BinRead, BinWrite, Clone, Diff, PartialEq)]
  52. #[diff(attr(
  53. #[derive(Debug, PartialEq)]
  54. ))]
  55. #[brw(magic(236u32))] // Number of fields within this struct
  56. pub struct Pen {
  57. pub color: FieldOf<Rgba>,
  58. pub name: WString,
  59. pub disabled: Bool,
  60. pub use_default: Bool,
  61. pub loop_count: U32,
  62. pub speed: F64, // Changes with wobble relative speed
  63. pub power: F64,
  64. pub frequency: U32,
  65. _unknown_1: Field,
  66. pub start_tc: U32,
  67. pub end_tc: U32,
  68. pub polygon_tc: U32,
  69. pub jump_speed: F64,
  70. _unknown_2: [Field; 10],
  71. pub laser_off_tc: U32,
  72. pub wave: U32, // Only available if continue_mode is false
  73. _unknown_3: Field,
  74. pub wobble_enable: U32,
  75. pub wobble_diameter: F64,
  76. pub wobble_distance: F64,
  77. _unknown_4: [Field; 8],
  78. pub min_jump_tc: U32,
  79. pub max_jump_tc: U32,
  80. pub jump_limit: F64,
  81. _unknown_5: [Field; 2],
  82. pub frequency_2: F64,
  83. _unknown_6: [Field; 152],
  84. pub wobble_type: FieldOf<WobbleType>,
  85. pub continue_mode: U32,
  86. _unknown_7: [Field; 12],
  87. pub wobble_diameter_2: F64, // Only with wobble type ellipse
  88. _unknown_8: [Field; 26],
  89. }
  90. impl Pen {
  91. pub fn read_from_file(path: &PathBuf) -> Self {
  92. let mut input: File = File::open(path).expect("Failed to open input file");
  93. let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
  94. input
  95. .read_to_end(buffer.get_mut())
  96. .expect("Failed to read input file");
  97. Pen::read_le(&mut buffer).expect("Failed to deserialize input as object")
  98. }
  99. pub fn write_to_file(&self, path: &PathBuf) {
  100. let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
  101. buffer.write_le(self).expect("Failed to serialize object");
  102. let mut output: File = File::create(path).expect("Failed to open output file");
  103. output
  104. .write_all(buffer.into_inner().as_slice())
  105. .expect("Failed to write to output file");
  106. }
  107. }
  108. // Custom Debug implementation to only print known fields
  109. #[cfg(not(feature = "default-debug"))]
  110. impl Debug for Pen {
  111. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  112. f.debug_struct("Pen")
  113. .field("color", &self.color)
  114. .field("name", &self.name)
  115. .field("disabled", &self.disabled)
  116. .field("use_default", &self.use_default)
  117. .field("loop_count", &self.loop_count)
  118. .field("speed", &self.speed)
  119. .field("power", &self.power)
  120. .field("frequency", &self.frequency)
  121. .field("start_tc", &self.start_tc)
  122. .field("end_tc", &self.end_tc)
  123. .field("polygon_tc", &self.polygon_tc)
  124. .field("jump_speed", &self.jump_speed)
  125. .field("laser_off_tc", &self.laser_off_tc)
  126. .field("wave", &self.wave)
  127. .field("wobble_enable", &self.wobble_enable)
  128. .field("wobble_diameter", &self.wobble_diameter)
  129. .field("wobble_distance", &self.wobble_distance)
  130. .field("min_jump_tc", &self.min_jump_tc)
  131. .field("max_jump_tc", &self.max_jump_tc)
  132. .field("jump_limit", &self.jump_limit)
  133. .field("frequency_2", &self.frequency_2)
  134. .field("wobble_type", &self.wobble_type)
  135. .field("continue_mode", &self.continue_mode)
  136. .field("wobble_diameter_2", &self.wobble_diameter_2)
  137. .finish()
  138. }
  139. }