mindustry logic execution, map- and schematic- parsing and rendering
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use super::{really_unsafe_index, unsafe_assert, Image, Overlay, OverlayAt};
use std::simd::SimdInt;
use std::simd::SimdPartialOrd;
use std::simd::{simd_swizzle, Simd};

#[inline]
pub unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) {
    const LAST4: Simd<u8, 16> = Simd::from_array([
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
    ]);

    let mut srci = 0;
    let mut dsti = 0;
    while dsti + 16 <= rgb.len() {
        let old: Simd<u8, 16> = Simd::from_slice(rgb.get_unchecked(dsti..dsti + 16));
        let new: Simd<u8, 16> = Simd::from_slice(rgba.get_unchecked(srci..srci + 16));

        let threshold = new.simd_ge(Simd::splat(128)).to_int().cast::<u8>();
        let mut mask = simd_swizzle!(
            threshold,
            [3, 3, 3, 7, 7, 7, 11, 11, 11, 15, 15, 15, 0, 0, 0, 0]
        );
        mask &= LAST4;

        let new_rgb = simd_swizzle!(new, [0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 0, 0, 0, 0]);
        let blended = (new_rgb & mask) | (old & !mask);
        blended.copy_to_slice(rgb.get_unchecked_mut(dsti..dsti + 16));

        srci += 16;
        dsti += 12;
    }

    while dsti + 3 <= rgb.len() {
        if *rgba.get_unchecked(srci + 3) >= 128 {
            std::ptr::copy_nonoverlapping(
                rgba.get_unchecked(srci..srci + 3).as_ptr(),
                rgb.get_unchecked_mut(dsti..dsti + 3).as_mut_ptr(),
                3,
            );
        }

        srci += 4;
        dsti += 3;
    }
}

impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 3> {
    unsafe fn overlay_at(&mut self, with: &Image<&[u8], 4>, x: u32, y: u32) -> &mut Self {
        unsafe_assert!(x + with.width() <= self.width());
        unsafe_assert!(y + with.height() <= self.height());
        for j in 0..with.height() {
            let i_x = j as usize * with.width() as usize * 4
                ..(j as usize + 1) * with.width() as usize * 4;
            let o_x = ((j as usize + y as usize) * self.width() as usize + x as usize) * 3
                ..((j as usize + y as usize) * self.width() as usize
                    + x as usize
                    + with.width() as usize)
                    * 3;
            blit(
                self.buffer.get_unchecked_mut(o_x),
                with.buffer.get_unchecked(i_x),
            )
        }
        self
    }
}

impl Overlay<Image<&[u8], 4>> for Image<&mut [u8], 3> {
    unsafe fn overlay(&mut self, with: &Image<&[u8], 4>) -> &mut Self {
        unsafe_assert!(self.width() == with.width());
        unsafe_assert!(self.height() == with.height());
        for (i, chunk) in with
            .buffer
            .chunks_exact(with.width() as usize * 4)
            .enumerate()
        {
            blit(
                self.buffer.get_unchecked_mut(
                    i * with.width() as usize * 3..(i + 1) * with.width() as usize * 3,
                ),
                chunk,
            );
        }
        self
    }
}

impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 4> {
    unsafe fn overlay_at(&mut self, with: &Image<&[u8], 4>, x: u32, y: u32) -> &mut Self {
        for j in 0..with.height() {
            for i in 0..with.width() {
                let with_index = really_unsafe_index(i, j, with.width()).unchecked_mul(4);
                let their_px = with
                    .buffer
                    .get_unchecked(with_index..with_index.unchecked_add(4));
                if *their_px.get_unchecked(3) >= 128 {
                    let our_index =
                        really_unsafe_index(i.unchecked_add(x), j.unchecked_add(y), self.width())
                            .unchecked_mul(4);
                    let our_px = self
                        .buffer
                        .get_unchecked_mut(our_index..our_index.unchecked_add(4));
                    std::ptr::copy_nonoverlapping(their_px.as_ptr(), our_px.as_mut_ptr(), 4);
                }
            }
        }

        self
    }
}