|
@@ -1,484 +1,484 @@
|
|
|
-use std::fmt::{Debug, Display};
|
|
|
-
|
|
|
-use crate::{
|
|
|
- array_of::ArrayOf,
|
|
|
- field_of::FieldOf,
|
|
|
- types::{Coordinate, Field, F64, U32},
|
|
|
-};
|
|
|
-use binrw::{binrw, BinRead, BinWrite};
|
|
|
-use diff::Diff;
|
|
|
-use modular_bitfield::{
|
|
|
- bitfield,
|
|
|
- specifiers::{B1, B18},
|
|
|
-};
|
|
|
-use serde::{Deserialize, Serialize};
|
|
|
-
|
|
|
-use super::{line::Lines, Object, ObjectCore, Translate};
|
|
|
-
|
|
|
-#[bitfield(bits = 32)]
|
|
|
-#[derive(BinRead, BinWrite, Copy, Clone, Debug, Default, Diff, PartialEq)]
|
|
|
-#[diff(attr(
|
|
|
- #[derive(Debug, PartialEq)]
|
|
|
-))]
|
|
|
-#[br(map = Self::from_bytes)]
|
|
|
-#[bw(map = |&x| Self::into_bytes(x))]
|
|
|
-pub struct HatchFlag {
|
|
|
- pub all_calc: B1,
|
|
|
- pub follow_edge_once: B1,
|
|
|
- pub continuous_pattern: B1, // Hatch type 3 when combined with bidirectional_pattern
|
|
|
- pub bidirectional_pattern: B1, // Hatch type 1
|
|
|
- pub ring_pattern: B1, // Hatch type 2
|
|
|
- #[skip]
|
|
|
- __: B1,
|
|
|
- pub auto_rotate_hatch_angle: B1,
|
|
|
- pub average_distribute_line: B1,
|
|
|
- #[skip]
|
|
|
- __: B1,
|
|
|
- pub gong_pattern: B1, // Hatch type 4 when combined with bidirectional_pattern
|
|
|
- pub cross_hatch: B1,
|
|
|
- pub background_pattern: B1, // Hatch type 5, must set all_calc as well
|
|
|
- pub fill_pattern: B1, // Hatch type 6 when combined with continuous_pattern and bidirectional_pattern
|
|
|
- pub zigzag_pattern: B1, // Hatch type 7
|
|
|
- #[skip]
|
|
|
- __: B18,
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(Copy, Clone, Debug, Serialize, Deserialize, strum::Display)]
|
|
|
-pub enum HatchPattern {
|
|
|
- Directional,
|
|
|
- Bidirectional,
|
|
|
- Ring,
|
|
|
- Continuous,
|
|
|
- Gong,
|
|
|
- Background,
|
|
|
- Fill,
|
|
|
- Zigzag,
|
|
|
-}
|
|
|
-
|
|
|
-impl From<HatchPattern> for HatchFlag {
|
|
|
- fn from(value: HatchPattern) -> Self {
|
|
|
- let mut ret = Self::new();
|
|
|
- match value {
|
|
|
- HatchPattern::Directional => (),
|
|
|
- HatchPattern::Bidirectional => ret.set_bidirectional_pattern(1),
|
|
|
- HatchPattern::Ring => ret.set_ring_pattern(1),
|
|
|
- HatchPattern::Continuous => {
|
|
|
- ret.set_bidirectional_pattern(1);
|
|
|
- ret.set_continuous_pattern(1);
|
|
|
- }
|
|
|
- HatchPattern::Gong => {
|
|
|
- ret.set_bidirectional_pattern(1);
|
|
|
- ret.set_gong_pattern(1);
|
|
|
- }
|
|
|
- HatchPattern::Background => {
|
|
|
- ret.set_background_pattern(1);
|
|
|
- ret.set_all_calc(1);
|
|
|
- }
|
|
|
- HatchPattern::Fill => ret.set_fill_pattern(1),
|
|
|
- HatchPattern::Zigzag => ret.set_zigzag_pattern(1),
|
|
|
- }
|
|
|
- ret
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl From<HatchFlag> for HatchPattern {
|
|
|
- fn from(value: HatchFlag) -> Self {
|
|
|
- if value.ring_pattern() != 0 {
|
|
|
- HatchPattern::Ring
|
|
|
- } else if value.background_pattern() != 0 {
|
|
|
- HatchPattern::Background
|
|
|
- } else if value.fill_pattern() != 0 {
|
|
|
- HatchPattern::Fill
|
|
|
- } else if value.zigzag_pattern() != 0 {
|
|
|
- HatchPattern::Zigzag
|
|
|
- } else if value.gong_pattern() != 0 {
|
|
|
- HatchPattern::Gong
|
|
|
- } else if value.bidirectional_pattern() != 0 {
|
|
|
- if value.continuous_pattern() != 0 {
|
|
|
- HatchPattern::Continuous
|
|
|
- } else {
|
|
|
- HatchPattern::Bidirectional
|
|
|
- }
|
|
|
- } else {
|
|
|
- HatchPattern::Directional
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#[cfg_attr(feature = "default-debug", derive(Debug))]
|
|
|
-#[derive(BinRead, BinWrite, Clone, Diff, PartialEq)]
|
|
|
-#[diff(attr(
|
|
|
- #[derive(Debug, PartialEq)]
|
|
|
-))]
|
|
|
-// #[brw(magic(46u32))] // Number of fields in this struct
|
|
|
-#[brw(magic(47u32))] // Number of fields in this struct
|
|
|
-pub struct LegacyHatchSetting {
|
|
|
- pub mark_contour: U32,
|
|
|
- pub hatch_0_enable: U32,
|
|
|
- pub hatch_0_pen: U32,
|
|
|
- pub hatch_0_flags: FieldOf<HatchFlag>,
|
|
|
- pub hatch_0_edge_offset: F64,
|
|
|
- pub hatch_0_line_spacing: F64,
|
|
|
- pub hatch_0_start_offset: F64,
|
|
|
- pub hatch_0_end_offset: F64,
|
|
|
- pub hatch_0_angle: F64,
|
|
|
- pub hatch_1_enable: U32,
|
|
|
- pub hatch_1_pen: U32,
|
|
|
- pub hatch_1_flags: FieldOf<HatchFlag>,
|
|
|
- pub hatch_1_edge_offset: F64,
|
|
|
- pub hatch_1_line_spacing: F64,
|
|
|
- pub hatch_1_start_offset: F64,
|
|
|
- pub hatch_1_end_offset: F64,
|
|
|
- pub hatch_1_angle: F64,
|
|
|
- pub any_hatch_enabled: U32,
|
|
|
- pub hatch_0_rotate_angle: F64,
|
|
|
- pub hatch_1_rotate_angle: F64,
|
|
|
- pub hatch_2_enable: U32,
|
|
|
- pub hatch_2_pen: U32,
|
|
|
- pub hatch_2_flags: FieldOf<HatchFlag>,
|
|
|
- pub hatch_2_edge_offset: F64,
|
|
|
- pub hatch_2_line_spacing: F64,
|
|
|
- pub hatch_2_start_offset: F64,
|
|
|
- pub hatch_2_end_offset: F64,
|
|
|
- pub hatch_2_angle: F64,
|
|
|
- pub hatch_2_rotate_angle: F64,
|
|
|
- pub hatch_0_line_reduction: F64,
|
|
|
- pub hatch_1_line_reduction: F64,
|
|
|
- pub hatch_2_line_reduction: F64,
|
|
|
- pub hatch_0_loop_count: U32,
|
|
|
- pub hatch_1_loop_count: U32,
|
|
|
- pub hatch_2_loop_count: U32,
|
|
|
- pub hatch_0_loop_distance: F64,
|
|
|
- pub hatch_1_loop_distance: F64,
|
|
|
- pub hatch_2_loop_distance: F64,
|
|
|
- pub _unknown_1: [Field; 3],
|
|
|
- pub contour_priority: U32,
|
|
|
- pub hatch_0_count: U32,
|
|
|
- pub hatch_1_count: U32,
|
|
|
- pub hatch_2_count: U32,
|
|
|
-}
|
|
|
-
|
|
|
-// Custom Debug implementation to only print known fields
|
|
|
-#[cfg(not(feature = "default-debug"))]
|
|
|
-impl Debug for LegacyHatchSetting {
|
|
|
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
- f.debug_struct("LegacyHatchSetting")
|
|
|
- .field("mark_contour", &self.mark_contour)
|
|
|
- .field("hatch_0_enable", &self.hatch_0_enable)
|
|
|
- .field("hatch_0_pen", &self.hatch_0_pen)
|
|
|
- .field("hatch_0_flags", &self.hatch_0_flags)
|
|
|
- .field("hatch_0_edge_offset", &self.hatch_0_edge_offset)
|
|
|
- .field("hatch_0_line_spacing", &self.hatch_0_line_spacing)
|
|
|
- .field("hatch_0_start_offset", &self.hatch_0_start_offset)
|
|
|
- .field("hatch_0_end_offset", &self.hatch_0_end_offset)
|
|
|
- .field("hatch_0_angle", &self.hatch_0_angle)
|
|
|
- .field("hatch_1_enable", &self.hatch_1_enable)
|
|
|
- .field("hatch_1_pen", &self.hatch_1_pen)
|
|
|
- .field("hatch_1_flags", &self.hatch_1_flags)
|
|
|
- .field("hatch_1_edge_offset", &self.hatch_1_edge_offset)
|
|
|
- .field("hatch_1_line_spacing", &self.hatch_1_line_spacing)
|
|
|
- .field("hatch_1_start_offset", &self.hatch_1_start_offset)
|
|
|
- .field("hatch_1_end_offset", &self.hatch_1_end_offset)
|
|
|
- .field("hatch_1_angle", &self.hatch_1_angle)
|
|
|
- .field("any_hatch_enabled", &self.any_hatch_enabled)
|
|
|
- .field("hatch_0_auto_rotate_angle", &self.hatch_0_rotate_angle)
|
|
|
- .field("hatch_1_auto_rotate_angle", &self.hatch_1_rotate_angle)
|
|
|
- .field("hatch_2_enable", &self.hatch_2_enable)
|
|
|
- .field("hatch_2_pen", &self.hatch_2_pen)
|
|
|
- .field("hatch_2_flags", &self.hatch_2_flags)
|
|
|
- .field("hatch_2_edge_offset", &self.hatch_2_edge_offset)
|
|
|
- .field("hatch_2_line_spacing", &self.hatch_2_line_spacing)
|
|
|
- .field("hatch_2_start_offset", &self.hatch_2_start_offset)
|
|
|
- .field("hatch_2_end_offset", &self.hatch_2_end_offset)
|
|
|
- .field("hatch_2_angle", &self.hatch_2_angle)
|
|
|
- .field("hatch_2_auto_rotate_angle", &self.hatch_2_rotate_angle)
|
|
|
- .field("hatch_0_line_reduction", &self.hatch_0_line_reduction)
|
|
|
- .field("hatch_1_line_reduction", &self.hatch_1_line_reduction)
|
|
|
- .field("hatch_2_line_reduction", &self.hatch_2_line_reduction)
|
|
|
- .field("hatch_0_loop_count", &self.hatch_0_loop_count)
|
|
|
- .field("hatch_1_loop_count", &self.hatch_1_loop_count)
|
|
|
- .field("hatch_2_loop_count", &self.hatch_2_loop_count)
|
|
|
- .field("hatch_0_loop_distance", &self.hatch_0_loop_distance)
|
|
|
- .field("hatch_1_loop_distance", &self.hatch_1_loop_distance)
|
|
|
- .field("hatch_2_loop_distance", &self.hatch_2_loop_distance)
|
|
|
- .field("contour_priority", &self.contour_priority)
|
|
|
- .field("hatch_0_count", &self.hatch_0_count)
|
|
|
- .field("hatch_1_count", &self.hatch_1_count)
|
|
|
- .field("hatch_2_count", &self.hatch_2_count)
|
|
|
- .finish()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#[cfg_attr(feature = "default-debug", derive(Debug))]
|
|
|
-#[derive(BinRead, BinWrite, Clone, Diff, PartialEq)]
|
|
|
-#[diff(attr(
|
|
|
- #[derive(Debug, PartialEq)]
|
|
|
-))]
|
|
|
-#[brw(magic(15u32))] // Number of fields in this struct
|
|
|
-pub struct HatchSetting {
|
|
|
- pub count: U32,
|
|
|
- pub enabled: U32,
|
|
|
- pub pen: U32,
|
|
|
- pub flags: FieldOf<HatchFlag>,
|
|
|
- pub edge_offset: F64,
|
|
|
- pub line_spacing: F64,
|
|
|
- pub start_offset: F64,
|
|
|
- pub end_offset: F64,
|
|
|
- pub angle: F64,
|
|
|
- pub rotate_angle: F64,
|
|
|
- pub line_reduction: F64,
|
|
|
- pub loop_distance: F64,
|
|
|
- pub loop_count: U32,
|
|
|
- pub _unknown_1: [Field; 2],
|
|
|
-}
|
|
|
-
|
|
|
-// Custom Debug implementation to only print known fields
|
|
|
-#[cfg(not(feature = "default-debug"))]
|
|
|
-impl Debug for HatchSetting {
|
|
|
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
- f.debug_struct("HatchSettings")
|
|
|
- .field("count", &self.count)
|
|
|
- .field("enabled", &self.enabled)
|
|
|
- .field("pen", &self.pen)
|
|
|
- .field("flags", &self.flags)
|
|
|
- .field("edge_offset", &self.edge_offset)
|
|
|
- .field("line_spacing", &self.line_spacing)
|
|
|
- .field("start_offset", &self.start_offset)
|
|
|
- .field("end_offset", &self.end_offset)
|
|
|
- .field("angle", &self.angle)
|
|
|
- .field("auto_rotate_angle", &self.rotate_angle)
|
|
|
- .field("line_reduction", &self.line_reduction)
|
|
|
- .field("loop_distance", &self.loop_distance)
|
|
|
- .field("loop_count", &self.loop_count)
|
|
|
- .finish()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl Default for HatchSetting {
|
|
|
- fn default() -> Self {
|
|
|
- Self {
|
|
|
- count: 1.into(),
|
|
|
- enabled: false.into(),
|
|
|
- pen: 0.into(),
|
|
|
- flags: HatchFlag::new().into(),
|
|
|
- edge_offset: 0.0.into(),
|
|
|
- line_spacing: 1.0.into(),
|
|
|
- start_offset: 0.0.into(),
|
|
|
- end_offset: 0.0.into(),
|
|
|
- angle: 0.0.into(),
|
|
|
- rotate_angle: 10.0.into(),
|
|
|
- line_reduction: 0.0.into(),
|
|
|
- loop_distance: 0.5.into(),
|
|
|
- loop_count: 0.into(),
|
|
|
- _unknown_1: [vec![0, 0, 0, 0, 0, 0, 0, 0].into(), vec![0, 0, 0, 0].into()].into(),
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl From<Vec<HatchSetting>> for LegacyHatchSetting {
|
|
|
- fn from(value: Vec<HatchSetting>) -> Self {
|
|
|
- LegacyHatchSetting {
|
|
|
- mark_contour: false.into(),
|
|
|
- hatch_0_enable: value.get(0).map(|x| x.enabled).unwrap_or_default(),
|
|
|
- hatch_0_pen: value.get(0).map(|x| x.pen).unwrap_or_default(),
|
|
|
- hatch_0_flags: value.get(0).map(|x| x.flags).unwrap_or_default(),
|
|
|
- hatch_0_edge_offset: value.get(0).map(|x| x.edge_offset).unwrap_or_default(),
|
|
|
- hatch_0_line_spacing: value.get(0).map(|x| x.line_spacing).unwrap_or_default(),
|
|
|
- hatch_0_start_offset: value.get(0).map(|x| x.start_offset).unwrap_or_default(),
|
|
|
- hatch_0_end_offset: value.get(0).map(|x| x.end_offset).unwrap_or_default(),
|
|
|
- hatch_0_angle: value.get(0).map(|x| x.angle).unwrap_or_default(),
|
|
|
- hatch_1_enable: value.get(1).map(|x| x.enabled).unwrap_or_default(),
|
|
|
- hatch_1_pen: value.get(1).map(|x| x.pen).unwrap_or_default(),
|
|
|
- hatch_1_flags: value.get(1).map(|x| x.flags).unwrap_or_default(),
|
|
|
- hatch_1_edge_offset: value.get(1).map(|x| x.edge_offset).unwrap_or_default(),
|
|
|
- hatch_1_line_spacing: value.get(1).map(|x| x.line_spacing).unwrap_or_default(),
|
|
|
- hatch_1_start_offset: value.get(1).map(|x| x.start_offset).unwrap_or_default(),
|
|
|
- hatch_1_end_offset: value.get(1).map(|x| x.end_offset).unwrap_or_default(),
|
|
|
- hatch_1_angle: value.get(1).map(|x| x.angle).unwrap_or_default(),
|
|
|
- any_hatch_enabled: value.iter().any(|x| x.enabled.into()).into(),
|
|
|
- hatch_0_rotate_angle: value.get(0).map(|x| x.rotate_angle).unwrap_or_default(),
|
|
|
- hatch_1_rotate_angle: value.get(1).map(|x| x.rotate_angle).unwrap_or_default(),
|
|
|
- hatch_2_enable: value.get(2).map(|x| x.enabled).unwrap_or_default(),
|
|
|
- hatch_2_pen: value.get(2).map(|x| x.pen).unwrap_or_default(),
|
|
|
- hatch_2_flags: value.get(2).map(|x| x.flags).unwrap_or_default(),
|
|
|
- hatch_2_edge_offset: value.get(2).map(|x| x.edge_offset).unwrap_or_default(),
|
|
|
- hatch_2_line_spacing: value.get(2).map(|x| x.line_spacing).unwrap_or_default(),
|
|
|
- hatch_2_start_offset: value.get(2).map(|x| x.start_offset).unwrap_or_default(),
|
|
|
- hatch_2_end_offset: value.get(2).map(|x| x.end_offset).unwrap_or_default(),
|
|
|
- hatch_2_angle: value.get(2).map(|x| x.angle).unwrap_or_default(),
|
|
|
- hatch_2_rotate_angle: value.get(2).map(|x| x.rotate_angle).unwrap_or_default(),
|
|
|
- hatch_0_line_reduction: value.get(0).map(|x| x.line_reduction).unwrap_or_default(),
|
|
|
- hatch_1_line_reduction: value.get(1).map(|x| x.line_reduction).unwrap_or_default(),
|
|
|
- hatch_2_line_reduction: value.get(2).map(|x| x.line_reduction).unwrap_or_default(),
|
|
|
- hatch_0_loop_count: value.get(0).map(|x| x.loop_count).unwrap_or_default(),
|
|
|
- hatch_1_loop_count: value.get(1).map(|x| x.loop_count).unwrap_or_default(),
|
|
|
- hatch_2_loop_count: value.get(2).map(|x| x.loop_count).unwrap_or_default(),
|
|
|
- hatch_0_loop_distance: value.get(0).map(|x| x.loop_distance).unwrap_or_default(),
|
|
|
- hatch_1_loop_distance: value.get(1).map(|x| x.loop_distance).unwrap_or_default(),
|
|
|
- hatch_2_loop_distance: value.get(2).map(|x| x.loop_distance).unwrap_or_default(),
|
|
|
- _unknown_1: [
|
|
|
- vec![0, 0, 0, 0, 0, 0, 0, 0].into(),
|
|
|
- vec![0, 0, 0, 0, 0, 0, 0, 0].into(),
|
|
|
- vec![0, 0, 0, 0, 0, 0, 0, 0].into(),
|
|
|
- ]
|
|
|
- .into(),
|
|
|
- contour_priority: false.into(),
|
|
|
- hatch_0_count: value.get(0).map(|x| x.count).unwrap_or_default(),
|
|
|
- hatch_1_count: value.get(1).map(|x| x.count).unwrap_or_default(),
|
|
|
- hatch_2_count: value.get(2).map(|x| x.count).unwrap_or_default(),
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(BinRead, BinWrite, Clone, Debug, Diff, PartialEq)]
|
|
|
-#[diff(attr(
|
|
|
- #[derive(Debug, PartialEq)]
|
|
|
-))]
|
|
|
-pub struct HatchLine {
|
|
|
- pub lines: ArrayOf<Lines>,
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(BinRead, BinWrite, Clone, Debug, Diff, PartialEq)]
|
|
|
-#[diff(attr(
|
|
|
- #[derive(Debug, PartialEq)]
|
|
|
-))]
|
|
|
-#[brw(magic(16_u32))] // ObjectType::HatchLine
|
|
|
-pub struct HatchLines {
|
|
|
- pub core: ObjectCore, // HatchType::HatchLine
|
|
|
- pub hatch_line: ArrayOf<HatchLine>,
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(BinRead, BinWrite, Clone, Debug, Diff, PartialEq)]
|
|
|
-#[diff(attr(
|
|
|
- #[derive(Debug, PartialEq)]
|
|
|
-))]
|
|
|
-pub struct Hatches {
|
|
|
- pub core: ObjectCore, // HatchType::HatchLine
|
|
|
- pub hatch_lines: ArrayOf<HatchLines>,
|
|
|
-}
|
|
|
-
|
|
|
-impl Hatches {
|
|
|
- pub fn set_pen(&mut self, pen: u32) {
|
|
|
- // Ignore self.core.pen
|
|
|
- self.hatch_lines.iter_mut().for_each(|x| {
|
|
|
- // Ignore HatchLines.core.pen
|
|
|
- x.hatch_line.iter_mut().for_each(|x| {
|
|
|
- x.lines.iter_mut().for_each(|x| {
|
|
|
- x.core.pen = pen.into();
|
|
|
- })
|
|
|
- })
|
|
|
- });
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#[binrw]
|
|
|
-#[derive(Clone, Debug, Diff, PartialEq)]
|
|
|
-#[diff(attr(
|
|
|
- #[derive(Debug, PartialEq)]
|
|
|
-))]
|
|
|
-pub struct Hatch {
|
|
|
- pub core: ObjectCore,
|
|
|
- pub outline: ArrayOf<Object>,
|
|
|
- pub legacy_setting: LegacyHatchSetting,
|
|
|
-
|
|
|
- #[br(temp)]
|
|
|
- #[bw(try_calc(u32::try_from(hatch_settings.len()).unwrap().try_into()))]
|
|
|
- pub num_settings: U32,
|
|
|
-
|
|
|
- pub _unknown_1: Field,
|
|
|
-
|
|
|
- #[br(count = num_settings.value)]
|
|
|
- pub hatch_settings: Vec<HatchSetting>,
|
|
|
-
|
|
|
- #[brw(if(legacy_setting.any_hatch_enabled.value == 1))]
|
|
|
- pub hatches: Option<Hatches>,
|
|
|
-}
|
|
|
-
|
|
|
-impl Display for Hatch {
|
|
|
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
- write!(f, "{}", self.core)?;
|
|
|
- for object in self.outline.iter() {
|
|
|
- write!(f, "\nOutline: {}", object)?;
|
|
|
- }
|
|
|
- write!(
|
|
|
- f,
|
|
|
- "\nMark Contour: {}, Contour Priority: {}",
|
|
|
- *self.legacy_setting.mark_contour != 0,
|
|
|
- *self.legacy_setting.contour_priority != 0
|
|
|
- )?;
|
|
|
- for (index, setting) in self.hatch_settings.iter().enumerate() {
|
|
|
- if setting.enabled.into() {
|
|
|
- write!(
|
|
|
- f,
|
|
|
- "\nHatch #{}: All Calc: {}, Follow Edge Once: {}, Cross Hatch: {}, Pattern: {}, Angle: {:.2}, Pen: {}, Count: {}, Line Space: {:.2}, Avg Distribte Line: {}",
|
|
|
- index,
|
|
|
- setting.flags.all_calc() != 0,
|
|
|
- setting.flags.follow_edge_once() != 0,
|
|
|
- setting.flags.cross_hatch() != 0,
|
|
|
- HatchPattern::from(*setting.flags),
|
|
|
- *setting.angle,
|
|
|
- *setting.pen,
|
|
|
- *setting.count,
|
|
|
- *setting.line_spacing,
|
|
|
- setting.flags.average_distribute_line() != 0,
|
|
|
- )?;
|
|
|
- write!(
|
|
|
- f,
|
|
|
- "\n Edge Offset: {:.2}, Start Offset: {:.2}, End Offset: {:.2}, Line Reduction: {:.2}, Loop Count: {}, Loop Distance: {:.2}, Auto Rotate: {}, Auto Rotate Angle: {:.2}",
|
|
|
- *setting.edge_offset,
|
|
|
- *setting.start_offset,
|
|
|
- *setting.end_offset,
|
|
|
- *setting.line_reduction,
|
|
|
- *setting.loop_count,
|
|
|
- *setting.loop_distance,
|
|
|
- setting.flags.auto_rotate_hatch_angle() != 0,
|
|
|
- *setting.rotate_angle,
|
|
|
- )?;
|
|
|
- }
|
|
|
- }
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl Translate for Hatch {
|
|
|
- fn move_absolute(&mut self, origin: Option<Coordinate>, z: Option<f64>) {
|
|
|
- self.outline
|
|
|
- .iter_mut()
|
|
|
- .for_each(|x| x.move_absolute(origin, z));
|
|
|
- origin.map(|origin| {
|
|
|
- let delta: Coordinate = origin - *self.core.origin;
|
|
|
- self.hatches.iter_mut().for_each(|x| {
|
|
|
- // Ignore Hatches.core.origin
|
|
|
- x.hatch_lines.iter_mut().for_each(|x| {
|
|
|
- // Ignore HatchLines.core.origin
|
|
|
- x.hatch_line.iter_mut().for_each(|x| {
|
|
|
- x.lines
|
|
|
- .iter_mut()
|
|
|
- .for_each(|x| x.move_relative(Some(delta), None));
|
|
|
- })
|
|
|
- })
|
|
|
- });
|
|
|
- });
|
|
|
- self.core.move_absolute(origin, z);
|
|
|
- }
|
|
|
-
|
|
|
- fn move_relative(&mut self, delta: Option<Coordinate>, z: Option<f64>) {
|
|
|
- self.outline
|
|
|
- .iter_mut()
|
|
|
- .for_each(|x| x.move_relative(delta, z));
|
|
|
- delta.map(|delta| {
|
|
|
- self.hatches.iter_mut().for_each(|x| {
|
|
|
- // Ignore Hatches.core.origin
|
|
|
- x.hatch_lines.iter_mut().for_each(|x| {
|
|
|
- // Ignore HatchLines.core.origin
|
|
|
- x.hatch_line.iter_mut().for_each(|x| {
|
|
|
- x.lines
|
|
|
- .iter_mut()
|
|
|
- .for_each(|x| x.move_relative(Some(delta), None));
|
|
|
- })
|
|
|
- })
|
|
|
- });
|
|
|
- });
|
|
|
- self.core.move_relative(delta, z);
|
|
|
- }
|
|
|
-}
|
|
|
+use std::fmt::{Debug, Display};
|
|
|
+
|
|
|
+use crate::{
|
|
|
+ array_of::ArrayOf,
|
|
|
+ field_of::FieldOf,
|
|
|
+ types::{Field, Point, F64, U32},
|
|
|
+};
|
|
|
+use binrw::{binrw, BinRead, BinWrite};
|
|
|
+use diff::Diff;
|
|
|
+use modular_bitfield::{
|
|
|
+ bitfield,
|
|
|
+ specifiers::{B1, B18},
|
|
|
+};
|
|
|
+use serde::{Deserialize, Serialize};
|
|
|
+
|
|
|
+use super::{line::Lines, Object, ObjectCore, Translate};
|
|
|
+
|
|
|
+#[bitfield(bits = 32)]
|
|
|
+#[derive(BinRead, BinWrite, Copy, Clone, Debug, Default, Diff, PartialEq)]
|
|
|
+#[diff(attr(
|
|
|
+ #[derive(Debug, PartialEq)]
|
|
|
+))]
|
|
|
+#[br(map = Self::from_bytes)]
|
|
|
+#[bw(map = |&x| Self::into_bytes(x))]
|
|
|
+pub struct HatchFlag {
|
|
|
+ pub all_calc: B1,
|
|
|
+ pub follow_edge_once: B1,
|
|
|
+ pub continuous_pattern: B1, // Hatch type 3 when combined with bidirectional_pattern
|
|
|
+ pub bidirectional_pattern: B1, // Hatch type 1
|
|
|
+ pub ring_pattern: B1, // Hatch type 2
|
|
|
+ #[skip]
|
|
|
+ __: B1,
|
|
|
+ pub auto_rotate_hatch_angle: B1,
|
|
|
+ pub average_distribute_line: B1,
|
|
|
+ #[skip]
|
|
|
+ __: B1,
|
|
|
+ pub gong_pattern: B1, // Hatch type 4 when combined with bidirectional_pattern
|
|
|
+ pub cross_hatch: B1,
|
|
|
+ pub background_pattern: B1, // Hatch type 5, must set all_calc as well
|
|
|
+ pub fill_pattern: B1, // Hatch type 6 when combined with continuous_pattern and bidirectional_pattern
|
|
|
+ pub zigzag_pattern: B1, // Hatch type 7
|
|
|
+ #[skip]
|
|
|
+ __: B18,
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Copy, Clone, Debug, Serialize, Deserialize, strum::Display)]
|
|
|
+pub enum HatchPattern {
|
|
|
+ Directional,
|
|
|
+ Bidirectional,
|
|
|
+ Ring,
|
|
|
+ Continuous,
|
|
|
+ Gong,
|
|
|
+ Background,
|
|
|
+ Fill,
|
|
|
+ Zigzag,
|
|
|
+}
|
|
|
+
|
|
|
+impl From<HatchPattern> for HatchFlag {
|
|
|
+ fn from(value: HatchPattern) -> Self {
|
|
|
+ let mut ret = Self::new();
|
|
|
+ match value {
|
|
|
+ HatchPattern::Directional => (),
|
|
|
+ HatchPattern::Bidirectional => ret.set_bidirectional_pattern(1),
|
|
|
+ HatchPattern::Ring => ret.set_ring_pattern(1),
|
|
|
+ HatchPattern::Continuous => {
|
|
|
+ ret.set_bidirectional_pattern(1);
|
|
|
+ ret.set_continuous_pattern(1);
|
|
|
+ }
|
|
|
+ HatchPattern::Gong => {
|
|
|
+ ret.set_bidirectional_pattern(1);
|
|
|
+ ret.set_gong_pattern(1);
|
|
|
+ }
|
|
|
+ HatchPattern::Background => {
|
|
|
+ ret.set_background_pattern(1);
|
|
|
+ ret.set_all_calc(1);
|
|
|
+ }
|
|
|
+ HatchPattern::Fill => ret.set_fill_pattern(1),
|
|
|
+ HatchPattern::Zigzag => ret.set_zigzag_pattern(1),
|
|
|
+ }
|
|
|
+ ret
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl From<HatchFlag> for HatchPattern {
|
|
|
+ fn from(value: HatchFlag) -> Self {
|
|
|
+ if value.ring_pattern() != 0 {
|
|
|
+ HatchPattern::Ring
|
|
|
+ } else if value.background_pattern() != 0 {
|
|
|
+ HatchPattern::Background
|
|
|
+ } else if value.fill_pattern() != 0 {
|
|
|
+ HatchPattern::Fill
|
|
|
+ } else if value.zigzag_pattern() != 0 {
|
|
|
+ HatchPattern::Zigzag
|
|
|
+ } else if value.gong_pattern() != 0 {
|
|
|
+ HatchPattern::Gong
|
|
|
+ } else if value.bidirectional_pattern() != 0 {
|
|
|
+ if value.continuous_pattern() != 0 {
|
|
|
+ HatchPattern::Continuous
|
|
|
+ } else {
|
|
|
+ HatchPattern::Bidirectional
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ HatchPattern::Directional
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[cfg_attr(feature = "default-debug", derive(Debug))]
|
|
|
+#[derive(BinRead, BinWrite, Clone, Diff, PartialEq)]
|
|
|
+#[diff(attr(
|
|
|
+ #[derive(Debug, PartialEq)]
|
|
|
+))]
|
|
|
+// #[brw(magic(46u32))] // Number of fields in this struct
|
|
|
+#[brw(magic(47u32))] // Number of fields in this struct
|
|
|
+pub struct LegacyHatchSetting {
|
|
|
+ pub mark_contour: U32,
|
|
|
+ pub hatch_0_enable: U32,
|
|
|
+ pub hatch_0_pen: U32,
|
|
|
+ pub hatch_0_flags: FieldOf<HatchFlag>,
|
|
|
+ pub hatch_0_edge_offset: F64,
|
|
|
+ pub hatch_0_line_spacing: F64,
|
|
|
+ pub hatch_0_start_offset: F64,
|
|
|
+ pub hatch_0_end_offset: F64,
|
|
|
+ pub hatch_0_angle: F64,
|
|
|
+ pub hatch_1_enable: U32,
|
|
|
+ pub hatch_1_pen: U32,
|
|
|
+ pub hatch_1_flags: FieldOf<HatchFlag>,
|
|
|
+ pub hatch_1_edge_offset: F64,
|
|
|
+ pub hatch_1_line_spacing: F64,
|
|
|
+ pub hatch_1_start_offset: F64,
|
|
|
+ pub hatch_1_end_offset: F64,
|
|
|
+ pub hatch_1_angle: F64,
|
|
|
+ pub any_hatch_enabled: U32,
|
|
|
+ pub hatch_0_rotate_angle: F64,
|
|
|
+ pub hatch_1_rotate_angle: F64,
|
|
|
+ pub hatch_2_enable: U32,
|
|
|
+ pub hatch_2_pen: U32,
|
|
|
+ pub hatch_2_flags: FieldOf<HatchFlag>,
|
|
|
+ pub hatch_2_edge_offset: F64,
|
|
|
+ pub hatch_2_line_spacing: F64,
|
|
|
+ pub hatch_2_start_offset: F64,
|
|
|
+ pub hatch_2_end_offset: F64,
|
|
|
+ pub hatch_2_angle: F64,
|
|
|
+ pub hatch_2_rotate_angle: F64,
|
|
|
+ pub hatch_0_line_reduction: F64,
|
|
|
+ pub hatch_1_line_reduction: F64,
|
|
|
+ pub hatch_2_line_reduction: F64,
|
|
|
+ pub hatch_0_loop_count: U32,
|
|
|
+ pub hatch_1_loop_count: U32,
|
|
|
+ pub hatch_2_loop_count: U32,
|
|
|
+ pub hatch_0_loop_distance: F64,
|
|
|
+ pub hatch_1_loop_distance: F64,
|
|
|
+ pub hatch_2_loop_distance: F64,
|
|
|
+ pub _unknown_1: [Field; 3],
|
|
|
+ pub contour_priority: U32,
|
|
|
+ pub hatch_0_count: U32,
|
|
|
+ pub hatch_1_count: U32,
|
|
|
+ pub hatch_2_count: U32,
|
|
|
+}
|
|
|
+
|
|
|
+// Custom Debug implementation to only print known fields
|
|
|
+#[cfg(not(feature = "default-debug"))]
|
|
|
+impl Debug for LegacyHatchSetting {
|
|
|
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
+ f.debug_struct("LegacyHatchSetting")
|
|
|
+ .field("mark_contour", &self.mark_contour)
|
|
|
+ .field("hatch_0_enable", &self.hatch_0_enable)
|
|
|
+ .field("hatch_0_pen", &self.hatch_0_pen)
|
|
|
+ .field("hatch_0_flags", &self.hatch_0_flags)
|
|
|
+ .field("hatch_0_edge_offset", &self.hatch_0_edge_offset)
|
|
|
+ .field("hatch_0_line_spacing", &self.hatch_0_line_spacing)
|
|
|
+ .field("hatch_0_start_offset", &self.hatch_0_start_offset)
|
|
|
+ .field("hatch_0_end_offset", &self.hatch_0_end_offset)
|
|
|
+ .field("hatch_0_angle", &self.hatch_0_angle)
|
|
|
+ .field("hatch_1_enable", &self.hatch_1_enable)
|
|
|
+ .field("hatch_1_pen", &self.hatch_1_pen)
|
|
|
+ .field("hatch_1_flags", &self.hatch_1_flags)
|
|
|
+ .field("hatch_1_edge_offset", &self.hatch_1_edge_offset)
|
|
|
+ .field("hatch_1_line_spacing", &self.hatch_1_line_spacing)
|
|
|
+ .field("hatch_1_start_offset", &self.hatch_1_start_offset)
|
|
|
+ .field("hatch_1_end_offset", &self.hatch_1_end_offset)
|
|
|
+ .field("hatch_1_angle", &self.hatch_1_angle)
|
|
|
+ .field("any_hatch_enabled", &self.any_hatch_enabled)
|
|
|
+ .field("hatch_0_auto_rotate_angle", &self.hatch_0_rotate_angle)
|
|
|
+ .field("hatch_1_auto_rotate_angle", &self.hatch_1_rotate_angle)
|
|
|
+ .field("hatch_2_enable", &self.hatch_2_enable)
|
|
|
+ .field("hatch_2_pen", &self.hatch_2_pen)
|
|
|
+ .field("hatch_2_flags", &self.hatch_2_flags)
|
|
|
+ .field("hatch_2_edge_offset", &self.hatch_2_edge_offset)
|
|
|
+ .field("hatch_2_line_spacing", &self.hatch_2_line_spacing)
|
|
|
+ .field("hatch_2_start_offset", &self.hatch_2_start_offset)
|
|
|
+ .field("hatch_2_end_offset", &self.hatch_2_end_offset)
|
|
|
+ .field("hatch_2_angle", &self.hatch_2_angle)
|
|
|
+ .field("hatch_2_auto_rotate_angle", &self.hatch_2_rotate_angle)
|
|
|
+ .field("hatch_0_line_reduction", &self.hatch_0_line_reduction)
|
|
|
+ .field("hatch_1_line_reduction", &self.hatch_1_line_reduction)
|
|
|
+ .field("hatch_2_line_reduction", &self.hatch_2_line_reduction)
|
|
|
+ .field("hatch_0_loop_count", &self.hatch_0_loop_count)
|
|
|
+ .field("hatch_1_loop_count", &self.hatch_1_loop_count)
|
|
|
+ .field("hatch_2_loop_count", &self.hatch_2_loop_count)
|
|
|
+ .field("hatch_0_loop_distance", &self.hatch_0_loop_distance)
|
|
|
+ .field("hatch_1_loop_distance", &self.hatch_1_loop_distance)
|
|
|
+ .field("hatch_2_loop_distance", &self.hatch_2_loop_distance)
|
|
|
+ .field("contour_priority", &self.contour_priority)
|
|
|
+ .field("hatch_0_count", &self.hatch_0_count)
|
|
|
+ .field("hatch_1_count", &self.hatch_1_count)
|
|
|
+ .field("hatch_2_count", &self.hatch_2_count)
|
|
|
+ .finish()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[cfg_attr(feature = "default-debug", derive(Debug))]
|
|
|
+#[derive(BinRead, BinWrite, Clone, Diff, PartialEq)]
|
|
|
+#[diff(attr(
|
|
|
+ #[derive(Debug, PartialEq)]
|
|
|
+))]
|
|
|
+#[brw(magic(15u32))] // Number of fields in this struct
|
|
|
+pub struct HatchSetting {
|
|
|
+ pub count: U32,
|
|
|
+ pub enabled: U32,
|
|
|
+ pub pen: U32,
|
|
|
+ pub flags: FieldOf<HatchFlag>,
|
|
|
+ pub edge_offset: F64,
|
|
|
+ pub line_spacing: F64,
|
|
|
+ pub start_offset: F64,
|
|
|
+ pub end_offset: F64,
|
|
|
+ pub angle: F64,
|
|
|
+ pub rotate_angle: F64,
|
|
|
+ pub line_reduction: F64,
|
|
|
+ pub loop_distance: F64,
|
|
|
+ pub loop_count: U32,
|
|
|
+ pub _unknown_1: [Field; 2],
|
|
|
+}
|
|
|
+
|
|
|
+// Custom Debug implementation to only print known fields
|
|
|
+#[cfg(not(feature = "default-debug"))]
|
|
|
+impl Debug for HatchSetting {
|
|
|
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
+ f.debug_struct("HatchSettings")
|
|
|
+ .field("count", &self.count)
|
|
|
+ .field("enabled", &self.enabled)
|
|
|
+ .field("pen", &self.pen)
|
|
|
+ .field("flags", &self.flags)
|
|
|
+ .field("edge_offset", &self.edge_offset)
|
|
|
+ .field("line_spacing", &self.line_spacing)
|
|
|
+ .field("start_offset", &self.start_offset)
|
|
|
+ .field("end_offset", &self.end_offset)
|
|
|
+ .field("angle", &self.angle)
|
|
|
+ .field("auto_rotate_angle", &self.rotate_angle)
|
|
|
+ .field("line_reduction", &self.line_reduction)
|
|
|
+ .field("loop_distance", &self.loop_distance)
|
|
|
+ .field("loop_count", &self.loop_count)
|
|
|
+ .finish()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Default for HatchSetting {
|
|
|
+ fn default() -> Self {
|
|
|
+ Self {
|
|
|
+ count: 1.into(),
|
|
|
+ enabled: false.into(),
|
|
|
+ pen: 0.into(),
|
|
|
+ flags: HatchFlag::new().into(),
|
|
|
+ edge_offset: 0.0.into(),
|
|
|
+ line_spacing: 1.0.into(),
|
|
|
+ start_offset: 0.0.into(),
|
|
|
+ end_offset: 0.0.into(),
|
|
|
+ angle: 0.0.into(),
|
|
|
+ rotate_angle: 10.0.into(),
|
|
|
+ line_reduction: 0.0.into(),
|
|
|
+ loop_distance: 0.5.into(),
|
|
|
+ loop_count: 0.into(),
|
|
|
+ _unknown_1: [vec![0, 0, 0, 0, 0, 0, 0, 0].into(), vec![0, 0, 0, 0].into()].into(),
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl From<Vec<HatchSetting>> for LegacyHatchSetting {
|
|
|
+ fn from(value: Vec<HatchSetting>) -> Self {
|
|
|
+ LegacyHatchSetting {
|
|
|
+ mark_contour: false.into(),
|
|
|
+ hatch_0_enable: value.get(0).map(|x| x.enabled).unwrap_or_default(),
|
|
|
+ hatch_0_pen: value.get(0).map(|x| x.pen).unwrap_or_default(),
|
|
|
+ hatch_0_flags: value.get(0).map(|x| x.flags).unwrap_or_default(),
|
|
|
+ hatch_0_edge_offset: value.get(0).map(|x| x.edge_offset).unwrap_or_default(),
|
|
|
+ hatch_0_line_spacing: value.get(0).map(|x| x.line_spacing).unwrap_or_default(),
|
|
|
+ hatch_0_start_offset: value.get(0).map(|x| x.start_offset).unwrap_or_default(),
|
|
|
+ hatch_0_end_offset: value.get(0).map(|x| x.end_offset).unwrap_or_default(),
|
|
|
+ hatch_0_angle: value.get(0).map(|x| x.angle).unwrap_or_default(),
|
|
|
+ hatch_1_enable: value.get(1).map(|x| x.enabled).unwrap_or_default(),
|
|
|
+ hatch_1_pen: value.get(1).map(|x| x.pen).unwrap_or_default(),
|
|
|
+ hatch_1_flags: value.get(1).map(|x| x.flags).unwrap_or_default(),
|
|
|
+ hatch_1_edge_offset: value.get(1).map(|x| x.edge_offset).unwrap_or_default(),
|
|
|
+ hatch_1_line_spacing: value.get(1).map(|x| x.line_spacing).unwrap_or_default(),
|
|
|
+ hatch_1_start_offset: value.get(1).map(|x| x.start_offset).unwrap_or_default(),
|
|
|
+ hatch_1_end_offset: value.get(1).map(|x| x.end_offset).unwrap_or_default(),
|
|
|
+ hatch_1_angle: value.get(1).map(|x| x.angle).unwrap_or_default(),
|
|
|
+ any_hatch_enabled: value.iter().any(|x| x.enabled.into()).into(),
|
|
|
+ hatch_0_rotate_angle: value.get(0).map(|x| x.rotate_angle).unwrap_or_default(),
|
|
|
+ hatch_1_rotate_angle: value.get(1).map(|x| x.rotate_angle).unwrap_or_default(),
|
|
|
+ hatch_2_enable: value.get(2).map(|x| x.enabled).unwrap_or_default(),
|
|
|
+ hatch_2_pen: value.get(2).map(|x| x.pen).unwrap_or_default(),
|
|
|
+ hatch_2_flags: value.get(2).map(|x| x.flags).unwrap_or_default(),
|
|
|
+ hatch_2_edge_offset: value.get(2).map(|x| x.edge_offset).unwrap_or_default(),
|
|
|
+ hatch_2_line_spacing: value.get(2).map(|x| x.line_spacing).unwrap_or_default(),
|
|
|
+ hatch_2_start_offset: value.get(2).map(|x| x.start_offset).unwrap_or_default(),
|
|
|
+ hatch_2_end_offset: value.get(2).map(|x| x.end_offset).unwrap_or_default(),
|
|
|
+ hatch_2_angle: value.get(2).map(|x| x.angle).unwrap_or_default(),
|
|
|
+ hatch_2_rotate_angle: value.get(2).map(|x| x.rotate_angle).unwrap_or_default(),
|
|
|
+ hatch_0_line_reduction: value.get(0).map(|x| x.line_reduction).unwrap_or_default(),
|
|
|
+ hatch_1_line_reduction: value.get(1).map(|x| x.line_reduction).unwrap_or_default(),
|
|
|
+ hatch_2_line_reduction: value.get(2).map(|x| x.line_reduction).unwrap_or_default(),
|
|
|
+ hatch_0_loop_count: value.get(0).map(|x| x.loop_count).unwrap_or_default(),
|
|
|
+ hatch_1_loop_count: value.get(1).map(|x| x.loop_count).unwrap_or_default(),
|
|
|
+ hatch_2_loop_count: value.get(2).map(|x| x.loop_count).unwrap_or_default(),
|
|
|
+ hatch_0_loop_distance: value.get(0).map(|x| x.loop_distance).unwrap_or_default(),
|
|
|
+ hatch_1_loop_distance: value.get(1).map(|x| x.loop_distance).unwrap_or_default(),
|
|
|
+ hatch_2_loop_distance: value.get(2).map(|x| x.loop_distance).unwrap_or_default(),
|
|
|
+ _unknown_1: [
|
|
|
+ vec![0, 0, 0, 0, 0, 0, 0, 0].into(),
|
|
|
+ vec![0, 0, 0, 0, 0, 0, 0, 0].into(),
|
|
|
+ vec![0, 0, 0, 0, 0, 0, 0, 0].into(),
|
|
|
+ ]
|
|
|
+ .into(),
|
|
|
+ contour_priority: false.into(),
|
|
|
+ hatch_0_count: value.get(0).map(|x| x.count).unwrap_or_default(),
|
|
|
+ hatch_1_count: value.get(1).map(|x| x.count).unwrap_or_default(),
|
|
|
+ hatch_2_count: value.get(2).map(|x| x.count).unwrap_or_default(),
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(BinRead, BinWrite, Clone, Debug, Diff, PartialEq)]
|
|
|
+#[diff(attr(
|
|
|
+ #[derive(Debug, PartialEq)]
|
|
|
+))]
|
|
|
+pub struct HatchLine {
|
|
|
+ pub lines: ArrayOf<Lines>,
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(BinRead, BinWrite, Clone, Debug, Diff, PartialEq)]
|
|
|
+#[diff(attr(
|
|
|
+ #[derive(Debug, PartialEq)]
|
|
|
+))]
|
|
|
+#[brw(magic(16_u32))] // ObjectType::HatchLine
|
|
|
+pub struct HatchLines {
|
|
|
+ pub core: ObjectCore, // HatchType::HatchLine
|
|
|
+ pub hatch_line: ArrayOf<HatchLine>,
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(BinRead, BinWrite, Clone, Debug, Diff, PartialEq)]
|
|
|
+#[diff(attr(
|
|
|
+ #[derive(Debug, PartialEq)]
|
|
|
+))]
|
|
|
+pub struct Hatches {
|
|
|
+ pub core: ObjectCore, // HatchType::HatchLine
|
|
|
+ pub hatch_lines: ArrayOf<HatchLines>,
|
|
|
+}
|
|
|
+
|
|
|
+impl Hatches {
|
|
|
+ pub fn set_pen(&mut self, pen: u32) {
|
|
|
+ // Ignore self.core.pen
|
|
|
+ self.hatch_lines.iter_mut().for_each(|x| {
|
|
|
+ // Ignore HatchLines.core.pen
|
|
|
+ x.hatch_line.iter_mut().for_each(|x| {
|
|
|
+ x.lines.iter_mut().for_each(|x| {
|
|
|
+ x.core.pen = pen.into();
|
|
|
+ })
|
|
|
+ })
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[binrw]
|
|
|
+#[derive(Clone, Debug, Diff, PartialEq)]
|
|
|
+#[diff(attr(
|
|
|
+ #[derive(Debug, PartialEq)]
|
|
|
+))]
|
|
|
+pub struct Hatch {
|
|
|
+ pub core: ObjectCore,
|
|
|
+ pub outline: ArrayOf<Object>,
|
|
|
+ pub legacy_setting: LegacyHatchSetting,
|
|
|
+
|
|
|
+ #[br(temp)]
|
|
|
+ #[bw(try_calc(u32::try_from(hatch_settings.len()).unwrap().try_into()))]
|
|
|
+ pub num_settings: U32,
|
|
|
+
|
|
|
+ pub _unknown_1: Field,
|
|
|
+
|
|
|
+ #[br(count = num_settings.value)]
|
|
|
+ pub hatch_settings: Vec<HatchSetting>,
|
|
|
+
|
|
|
+ #[brw(if(legacy_setting.any_hatch_enabled.value == 1))]
|
|
|
+ pub hatches: Option<Hatches>,
|
|
|
+}
|
|
|
+
|
|
|
+impl Display for Hatch {
|
|
|
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
+ write!(f, "{}", self.core)?;
|
|
|
+ for object in self.outline.iter() {
|
|
|
+ write!(f, "\nOutline: {}", object)?;
|
|
|
+ }
|
|
|
+ write!(
|
|
|
+ f,
|
|
|
+ "\nMark Contour: {}, Contour Priority: {}",
|
|
|
+ *self.legacy_setting.mark_contour != 0,
|
|
|
+ *self.legacy_setting.contour_priority != 0
|
|
|
+ )?;
|
|
|
+ for (index, setting) in self.hatch_settings.iter().enumerate() {
|
|
|
+ if setting.enabled.into() {
|
|
|
+ write!(
|
|
|
+ f,
|
|
|
+ "\nHatch #{}: All Calc: {}, Follow Edge Once: {}, Cross Hatch: {}, Pattern: {}, Angle: {:.2}, Pen: {}, Count: {}, Line Space: {:.2}, Avg Distribte Line: {}",
|
|
|
+ index,
|
|
|
+ setting.flags.all_calc() != 0,
|
|
|
+ setting.flags.follow_edge_once() != 0,
|
|
|
+ setting.flags.cross_hatch() != 0,
|
|
|
+ HatchPattern::from(*setting.flags),
|
|
|
+ *setting.angle,
|
|
|
+ *setting.pen,
|
|
|
+ *setting.count,
|
|
|
+ *setting.line_spacing,
|
|
|
+ setting.flags.average_distribute_line() != 0,
|
|
|
+ )?;
|
|
|
+ write!(
|
|
|
+ f,
|
|
|
+ "\n Edge Offset: {:.2}, Start Offset: {:.2}, End Offset: {:.2}, Line Reduction: {:.2}, Loop Count: {}, Loop Distance: {:.2}, Auto Rotate: {}, Auto Rotate Angle: {:.2}",
|
|
|
+ *setting.edge_offset,
|
|
|
+ *setting.start_offset,
|
|
|
+ *setting.end_offset,
|
|
|
+ *setting.line_reduction,
|
|
|
+ *setting.loop_count,
|
|
|
+ *setting.loop_distance,
|
|
|
+ setting.flags.auto_rotate_hatch_angle() != 0,
|
|
|
+ *setting.rotate_angle,
|
|
|
+ )?;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Ok(())
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Translate for Hatch {
|
|
|
+ fn move_absolute(&mut self, origin: Option<Point>, z: Option<f64>) {
|
|
|
+ self.outline
|
|
|
+ .iter_mut()
|
|
|
+ .for_each(|x| x.move_absolute(origin, z));
|
|
|
+ origin.map(|origin| {
|
|
|
+ let delta: Point = origin - *self.core.origin;
|
|
|
+ self.hatches.iter_mut().for_each(|x| {
|
|
|
+ // Ignore Hatches.core.origin
|
|
|
+ x.hatch_lines.iter_mut().for_each(|x| {
|
|
|
+ // Ignore HatchLines.core.origin
|
|
|
+ x.hatch_line.iter_mut().for_each(|x| {
|
|
|
+ x.lines
|
|
|
+ .iter_mut()
|
|
|
+ .for_each(|x| x.move_relative(Some(delta), None));
|
|
|
+ })
|
|
|
+ })
|
|
|
+ });
|
|
|
+ });
|
|
|
+ self.core.move_absolute(origin, z);
|
|
|
+ }
|
|
|
+
|
|
|
+ fn move_relative(&mut self, delta: Option<Point>, z: Option<f64>) {
|
|
|
+ self.outline
|
|
|
+ .iter_mut()
|
|
|
+ .for_each(|x| x.move_relative(delta, z));
|
|
|
+ delta.map(|delta| {
|
|
|
+ self.hatches.iter_mut().for_each(|x| {
|
|
|
+ // Ignore Hatches.core.origin
|
|
|
+ x.hatch_lines.iter_mut().for_each(|x| {
|
|
|
+ // Ignore HatchLines.core.origin
|
|
|
+ x.hatch_line.iter_mut().for_each(|x| {
|
|
|
+ x.lines
|
|
|
+ .iter_mut()
|
|
|
+ .for_each(|x| x.move_relative(Some(delta), None));
|
|
|
+ })
|
|
|
+ })
|
|
|
+ });
|
|
|
+ });
|
|
|
+ self.core.move_relative(delta, z);
|
|
|
+ }
|
|
|
+}
|