Skip to main content

maple_render_core/
mapping.rs

1use std::sync::OnceLock;
2
3use image::RgbaImage;
4
5#[derive(Clone)]
6pub struct Mapping {
7    pub light: RgbaImage,
8    pub dark: RgbaImage,
9    pub map1: RgbaImage,
10    pub map2: RgbaImage,
11    pub neutral: RgbaImage,
12    pub scale: i32,
13    pub light_name: String,
14    pub dark_name: String,
15    pub map1_name: String,
16    pub map2_name: String,
17    pub neutral_name: String,
18    /// Cached result of [`Self::has_nonzero_smoothing`]. `None` until first query.
19    pub(crate) smooth_cache: OnceLock<bool>,
20}
21
22impl Default for Mapping {
23    fn default() -> Self {
24        Mapping {
25            light: RgbaImage::new(1, 1),
26            dark: RgbaImage::new(1, 1),
27            map1: RgbaImage::new(1, 1),
28            map2: RgbaImage::new(1, 1),
29            neutral: RgbaImage::new(1, 1),
30            scale: 1,
31            light_name: String::new(),
32            dark_name: String::new(),
33            map1_name: String::new(),
34            map2_name: String::new(),
35            neutral_name: String::new(),
36            smooth_cache: OnceLock::new(),
37        }
38    }
39}
40
41impl Mapping {
42    pub fn new() -> Self {
43        Mapping::default()
44    }
45
46    pub fn width(&self) -> u32 {
47        self.light.width()
48    }
49
50    pub fn height(&self) -> u32 {
51        self.light.height()
52    }
53
54    /// Whether the `map2` ("sel") image's channel 2 (the edge-smoothing flag)
55    /// contains any nonzero pixel. When false (the common case for shipped
56    /// templates), [`crate::render::Render`]'s smoothing pass is a no-op and can
57    /// be skipped entirely, avoiding a full output-image clone + scan.
58    ///
59    /// The result is computed once and cached for the lifetime of this mapping.
60    pub fn has_nonzero_smoothing(&self) -> bool {
61        *self.smooth_cache.get_or_init(|| {
62            // RGBA: channel 2 is at byte offset +2 of each 4-byte pixel.
63            let raw = self.map2.as_raw();
64            raw.chunks_exact(4).any(|px| px[2] != 0)
65        })
66    }
67}