|  | @@ -7,6 +7,8 @@ use std::{
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  use binrw::{BinRead, BinWrite, BinWriterExt};
 | 
	
		
			
				|  |  |  use diff::Diff;
 | 
	
		
			
				|  |  | +use itertools::Itertools;
 | 
	
		
			
				|  |  | +use log::debug;
 | 
	
		
			
				|  |  |  use modular_bitfield::{
 | 
	
		
			
				|  |  |      bitfield,
 | 
	
		
			
				|  |  |      specifiers::{B1, B14},
 | 
	
	
		
			
				|  | @@ -305,10 +307,113 @@ impl ObjectModifier {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pub fn skew(&self) -> Coordinate {
 | 
	
		
			
				|  |  |          Coordinate {
 | 
	
		
			
				|  |  | -            x: self.modifiers.x_skew,
 | 
	
		
			
				|  |  | -            y: self.modifiers.y_skew,
 | 
	
		
			
				|  |  | +            x: self.modifiers.y_skew.asin(), // Radians from X axis
 | 
	
		
			
				|  |  | +            y: self.modifiers.x_skew.asin(), // Radians from Y axis
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /// Returns origin, width, and height of bounding box given two rectangular corners
 | 
	
		
			
				|  |  | +    pub fn corrected(&self, pt1: Coordinate, pt2: Coordinate) -> (Coordinate, f64, f64) {
 | 
	
		
			
				|  |  | +        debug!(
 | 
	
		
			
				|  |  | +            "Skew degree from X axis: {:.2}",
 | 
	
		
			
				|  |  | +            self.modifiers.x_skew.asin().to_degrees()
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        debug!(
 | 
	
		
			
				|  |  | +            "Skew degree from Y axis: {:.2}",
 | 
	
		
			
				|  |  | +            self.modifiers.y_skew.asin().to_degrees()
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // // Calculated unskewed width and height
 | 
	
		
			
				|  |  | +        // let Coordinate {
 | 
	
		
			
				|  |  | +        //     x: width,
 | 
	
		
			
				|  |  | +        //     y: height,
 | 
	
		
			
				|  |  | +        // } = (pt1.max(pt2) - pt1.min(pt2)) * self.scale();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // debug!("Drawn point 1: {}", pt1);
 | 
	
		
			
				|  |  | +        // debug!("Drawn point 2: {}", pt2);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Calculate all 4 points of drawn rectangle
 | 
	
		
			
				|  |  | +        let points: Vec<Coordinate> = vec![
 | 
	
		
			
				|  |  | +            Coordinate {
 | 
	
		
			
				|  |  | +                x: pt1.min(pt2).x,
 | 
	
		
			
				|  |  | +                y: pt1.min(pt2).y,
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            Coordinate {
 | 
	
		
			
				|  |  | +                x: pt1.min(pt2).x,
 | 
	
		
			
				|  |  | +                y: pt1.max(pt2).y,
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            Coordinate {
 | 
	
		
			
				|  |  | +                x: pt1.max(pt2).x,
 | 
	
		
			
				|  |  | +                y: pt1.max(pt2).y,
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            Coordinate {
 | 
	
		
			
				|  |  | +                x: pt1.max(pt2).x,
 | 
	
		
			
				|  |  | +                y: pt1.min(pt2).y,
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +        ];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        debug!(
 | 
	
		
			
				|  |  | +            "Drawn points: {}",
 | 
	
		
			
				|  |  | +            points
 | 
	
		
			
				|  |  | +                .iter()
 | 
	
		
			
				|  |  | +                .map(|x| format!("{x}"))
 | 
	
		
			
				|  |  | +                .collect_vec()
 | 
	
		
			
				|  |  | +                .join(", ")
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // trace!("X skew asin tan: {:.3}", self.modifiers.x_skew.asin().tan());
 | 
	
		
			
				|  |  | +        // trace!("Y skew asin tan: {:.3}", self.modifiers.y_skew.asin().tan());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // let skew = |pt: Coordinate| -> Coordinate {
 | 
	
		
			
				|  |  | +        //     Coordinate {
 | 
	
		
			
				|  |  | +        //         x: pt.x + pt.y * self.modifiers.x_skew.asin().tan(),
 | 
	
		
			
				|  |  | +        //         y: pt.y + pt.x * self.modifiers.y_skew.asin().tan(),
 | 
	
		
			
				|  |  | +        //     }
 | 
	
		
			
				|  |  | +        // };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let skewed_points: Vec<Coordinate> = points
 | 
	
		
			
				|  |  | +            .iter()
 | 
	
		
			
				|  |  | +            .map(|pt| Coordinate {
 | 
	
		
			
				|  |  | +                x: pt.x + pt.y * self.modifiers.x_skew.asin().tan(),
 | 
	
		
			
				|  |  | +                y: pt.y + pt.x * self.modifiers.y_skew.asin().tan(),
 | 
	
		
			
				|  |  | +            })
 | 
	
		
			
				|  |  | +            .collect_vec();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        debug!(
 | 
	
		
			
				|  |  | +            "Skewed points: {}",
 | 
	
		
			
				|  |  | +            skewed_points
 | 
	
		
			
				|  |  | +                .iter()
 | 
	
		
			
				|  |  | +                .map(|x| format!("{x}"))
 | 
	
		
			
				|  |  | +                .collect_vec()
 | 
	
		
			
				|  |  | +                .join(", ")
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let min_x: f64 = skewed_points.iter().fold(f64::MAX, |acc, pt| acc.min(pt.x));
 | 
	
		
			
				|  |  | +        let max_x: f64 = skewed_points.iter().fold(f64::MIN, |acc, pt| acc.max(pt.x));
 | 
	
		
			
				|  |  | +        let min_y: f64 = skewed_points.iter().fold(f64::MAX, |acc, pt| acc.min(pt.y));
 | 
	
		
			
				|  |  | +        let max_y: f64 = skewed_points.iter().fold(f64::MIN, |acc, pt| acc.max(pt.y));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let bounding_box_pts: (Coordinate, Coordinate) = (
 | 
	
		
			
				|  |  | +            Coordinate { x: min_x, y: min_y },
 | 
	
		
			
				|  |  | +            Coordinate { x: max_x, y: max_y },
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        debug!(
 | 
	
		
			
				|  |  | +            "Bounding box (scaled): {}, {}",
 | 
	
		
			
				|  |  | +            bounding_box_pts.0, bounding_box_pts.1
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let origin: Coordinate = self.correction()
 | 
	
		
			
				|  |  | +            + self.scale() * (bounding_box_pts.0 + bounding_box_pts.1)
 | 
	
		
			
				|  |  | +                / Coordinate::from((2.0, 2.0));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let Coordinate {
 | 
	
		
			
				|  |  | +            x: width,
 | 
	
		
			
				|  |  | +            y: height,
 | 
	
		
			
				|  |  | +        } = (bounding_box_pts.1 - bounding_box_pts.0) * self.scale();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        (origin, width, height)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  impl Default for ObjectModifier {
 | 
	
	
		
			
				|  | @@ -326,12 +431,10 @@ impl Default for ObjectModifier {
 | 
	
		
			
				|  |  |  ))]
 | 
	
		
			
				|  |  |  pub struct ScaleValues {
 | 
	
		
			
				|  |  |      pub x_scale: f64, // X scaled ratio on drawn object
 | 
	
		
			
				|  |  | -    // #[br(assert(_unknown_1 == 0.0))]
 | 
	
		
			
				|  |  | -    pub x_skew: f64,
 | 
	
		
			
				|  |  | +    pub y_skew: f64,
 | 
	
		
			
				|  |  |      #[br(assert(_unknown_2 == 0.0))]
 | 
	
		
			
				|  |  |      _unknown_2: f64,
 | 
	
		
			
				|  |  | -    // #[br(assert(_unknown_3 == 0.0))]
 | 
	
		
			
				|  |  | -    pub y_skew: f64,
 | 
	
		
			
				|  |  | +    pub x_skew: f64,
 | 
	
		
			
				|  |  |      pub y_scale: f64, // Y scaled ratio on drawn object
 | 
	
		
			
				|  |  |      #[br(assert(_unknown_4 == 0.0))]
 | 
	
		
			
				|  |  |      _unknown_4: f64,
 | 
	
	
		
			
				|  | @@ -344,9 +447,9 @@ impl Default for ScaleValues {
 | 
	
		
			
				|  |  |      fn default() -> Self {
 | 
	
		
			
				|  |  |          Self {
 | 
	
		
			
				|  |  |              x_scale: 1.0.into(),
 | 
	
		
			
				|  |  | -            x_skew: 0.0.into(),
 | 
	
		
			
				|  |  | -            _unknown_2: 0.0.into(),
 | 
	
		
			
				|  |  |              y_skew: 0.0.into(),
 | 
	
		
			
				|  |  | +            _unknown_2: 0.0.into(),
 | 
	
		
			
				|  |  | +            x_skew: 0.0.into(),
 | 
	
		
			
				|  |  |              y_scale: 1.0.into(),
 | 
	
		
			
				|  |  |              _unknown_4: 0.0.into(),
 | 
	
		
			
				|  |  |              correction: (0.0, 0.0).into(),
 |