Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'src/data/renderer.rs')
-rw-r--r--src/data/renderer.rs296
1 files changed, 0 insertions, 296 deletions
diff --git a/src/data/renderer.rs b/src/data/renderer.rs
deleted file mode 100644
index 4bbcbe7..0000000
--- a/src/data/renderer.rs
+++ /dev/null
@@ -1,296 +0,0 @@
-//! schematic drawing
-pub(crate) use super::autotile::*;
-use super::schematic::Schematic;
-use super::GridPos;
-use crate::block::Rotation;
-pub(crate) use crate::utils::{Image, ImageHolder, ImageUtils, Overlay, Repeat};
-use crate::Map;
-include!(concat!(env!("OUT_DIR"), "/full.rs"));
-include!(concat!(env!("OUT_DIR"), "/quar.rs"));
-include!(concat!(env!("OUT_DIR"), "/eigh.rs"));
-
-#[derive(Debug, Copy, Clone)]
-#[repr(u8)]
-pub enum Scale {
- Full,
- // Half,
- Quarter,
- Eigth,
-}
-
-impl Scale {
- #[must_use]
- pub const fn px(self) -> u8 {
- match self {
- Self::Full => 32,
- Self::Quarter => 32 / 4,
- Self::Eigth => 32 / 8,
- }
- }
-}
-
-impl std::ops::Mul<u32> for Scale {
- type Output = u32;
- fn mul(self, rhs: u32) -> u32 {
- self.px() as u32 * rhs
- }
-}
-
-#[macro_export]
-macro_rules! load {
- ("empty", $scale:expr) => {
- ImageHolder::from(match $scale {
- $crate::data::renderer::Scale::Quarter => &$crate::data::renderer::quar::EMPTY,
- $crate::data::renderer::Scale::Eigth => &$crate::data::renderer::eigh::EMPTY,
- $crate::data::renderer::Scale::Full => &$crate::data::renderer::full::EMPTY,
- }.copy())
- };
- ($name:literal, $scale:expr) => { paste::paste! {
- ImageHolder::from(match $scale {
- $crate::data::renderer::Scale::Quarter => &$crate::data::renderer::quar::[<$name:snake:upper>],
- $crate::data::renderer::Scale::Eigth => &$crate::data::renderer::eigh::[<$name:snake:upper>],
- $crate::data::renderer::Scale::Full => &$crate::data::renderer::full::[<$name:snake:upper>],
- }.copy())
- } };
- ($name: literal) => { paste::paste! {
- [$crate::data::renderer::full::[<$name:snake:upper>].copy(), $crate::data::renderer::quar::[<$name:snake:upper>].copy(), $crate::data::renderer::eigh::[<$name:snake:upper>].copy()]
- } };
- (from $v:ident which is [$($k:literal $(|)?)+], $scale: ident) => {
- $crate::data::renderer::load!($scale -> match $v {
- $($k => $k,)+
- })
- };
- // turn load!(s -> match x { "v" => "y" }) into match x { "v" => load!("y", s) }
- ($scale:ident -> match $v:ident { $($k:pat => $nam:literal $(,)?)+ }) => {
- match $v {
- $($k => $crate::data::renderer::load!($nam, $scale),)+
- #[allow(unreachable_patterns)]
- n => unreachable!("{n:?}"),
- }
- };
- (concat $x:literal => $v:ident which is [$($k:literal $(|)?)+], $scale: ident) => { paste::paste! {
- match $v {
- $($k =>
- ImageHolder::from(match $scale {
- $crate::data::renderer::Scale::Quarter => &$crate::data::renderer::quar::[<$k:snake:upper _ $x:snake:upper>],
- $crate::data::renderer::Scale::Eigth => &$crate::data::renderer::eigh::[<$k:snake:upper _ $x:snake:upper>],
- $crate::data::renderer::Scale::Full => &$crate::data::renderer::full::[<$k:snake:upper _ $x:snake:upper>],
- }.copy()),
- )+
- #[allow(unreachable_patterns)]
- n => unreachable!("{n:?}"),
- }
- } };
-}
-pub(crate) use load;
-
-/// trait for renderable objects
-pub trait Renderable {
- /// create a picture
- #[must_use = "i did so much work for you"]
- fn render(&self) -> Image<Vec<u8>, 3>;
-}
-
-impl Renderable for Schematic<'_> {
- /// creates a picture of a schematic. Bridges and node connections are not drawn.
- /// ```
- /// use mindus::*;
- /// let mut s = Schematic::new(2, 3);
- /// s.put(0, 0, &block::distribution::DISTRIBUTOR);
- /// s.put(0, 2, &block::distribution::ROUTER);
- /// s.put(1, 2, &block::walls::COPPER_WALL);
- /// let output /*: Image */ = s.render();
- /// ```
- fn render(&self) -> Image<Vec<u8>, 3> {
- // fill background
- // SAFETY: metal-floor is 32x32, the output is a multiple of 32
- let mut bg = unsafe {
- load!("metal-floor", Scale::Full).borrow().repeated(
- ((self.width + 2) * 32) as u32,
- ((self.height + 2) * 32) as u32,
- )
- };
- let mut canvas = Image::alloc(
- ((self.width + 2) * 32) as u32,
- ((self.height + 2) * 32) as u32,
- );
- for (GridPos(x, y), tile) in self.block_iter() {
- let ctx = if tile.block.wants_context() {
- let pctx = PositionContext {
- position: GridPos(x, y),
- width: self.width,
- height: self.height,
- };
- Some(RenderingContext {
- cross: self.cross(&pctx),
- position: pctx,
- })
- } else {
- None
- };
- let x = x as u32 - ((tile.block.get_size() - 1) / 2) as u32;
- let y = self.height as u32 - y as u32 - ((tile.block.get_size() / 2) + 1) as u32;
- unsafe {
- canvas.as_mut().overlay_at(
- &tile
- .image(
- ctx.as_ref(),
- tile.get_rotation().unwrap_or(Rotation::Up),
- Scale::Full,
- )
- .borrow(),
- (x + 1) * 32,
- (y + 1) * 32,
- )
- };
- }
- canvas.as_mut().shadow();
- for x in 0..canvas.width() {
- for y in 0..canvas.height() {
- // canvas has a shadow
- let p2 = unsafe { canvas.pixel(x, y) };
- let p = unsafe { bg.pixel_mut(x, y) };
- crate::utils::image::blend(p.try_into().unwrap(), p2);
- }
- }
- bg.remove_channel()
- }
-}
-
-impl Renderable for Map<'_> {
- /// Draws a map
- fn render(&self) -> Image<Vec<u8>, 3> {
- let scale = if self.width + self.height < 2000 {
- Scale::Quarter
- } else {
- Scale::Eigth
- };
- // todo combine these (beware of floor drawing atop buildings) (planned solution:? ptr blocks)
- let mut floor: Image<_, 3> =
- Image::alloc(scale * self.width as u32, scale * self.height as u32);
- let mut top: Image<_, 4> =
- Image::alloc(scale * self.width as u32, scale * self.height as u32);
- rayon::join(
- || {
- for y in 0..self.height {
- for x in 0..self.width {
- // Map::new() allocates w*h items
- let j = x + self.width * y;
- let tile = unsafe { self.tiles.get_unchecked(j) };
- let y = self.height - y - 1;
- // draw the floor first.
- // println!("draw {tile:?} ({x}, {y})");
- unsafe {
- floor.as_mut().overlay_at(
- &tile.floor(scale).borrow(),
- scale * x as u32,
- scale * y as u32,
- )
- };
- if tile.has_ore() {
- unsafe {
- floor.as_mut().overlay_at(
- &tile.ore(scale).borrow(),
- scale * x as u32,
- scale * y as u32,
- )
- };
- }
- }
- }
- },
- || {
- for y in 0..self.height {
- for x in 0..self.width {
- // Map::new() allocates w*h items
- let j = x + self.width * y;
- let tile = unsafe { self.tiles.get_unchecked(j) };
- let y = self.height - y - 1;
- // println!("draw {tile:?} ({x}, {y})");
- if let Some(build) = tile.build() {
- let s = build.block.get_size();
- let x = x
- - (match s {
- 1 | 2 => 0,
- 3 | 4 => 1,
- 5 | 6 => 2,
- 7 | 8 => 3,
- 9 => 4,
- // SAFETY: no block too big
- _ => unsafe { std::hint::unreachable_unchecked() },
- }) as usize;
- let y = y
- - (match s {
- 1 => 0,
- 2 | 3 => 1,
- 4 | 5 => 2,
- 6 | 7 => 3,
- 8 | 9 => 4,
- // SAFETY: no block too big
- _ => unsafe { std::hint::unreachable_unchecked() },
- }) as usize;
- let ctx = if build.block.wants_context() {
- let pctx = PositionContext {
- position: GridPos(x, y),
- width: self.width,
- height: self.height,
- };
- let rctx = RenderingContext {
- cross: self.cross(j, &pctx),
- position: pctx,
- };
- Some(rctx)
- } else {
- None
- };
- unsafe {
- top.as_mut().overlay_at(
- &tile.build_image(ctx.as_ref(), scale).borrow(),
- scale * x as u32,
- scale * y as u32,
- )
- };
- }
- }
- }
- },
- );
- unsafe { floor.as_mut().overlay_at(&top.as_ref(), 0, 0) };
- floor
- }
-}
-
-#[test]
-fn all_blocks() {
- use crate::block::content::Type;
- use crate::content::Content;
- let reg = crate::block::build_registry();
- for t in 19..Type::WorldMessage as u16 {
- let t = Type::try_from(t).unwrap();
- if matches!(t, |Type::Empty| Type::SlagCentrifuge
- | Type::HeatReactor
- | Type::LegacyMechPad
- | Type::LegacyUnitFactory
- | Type::LegacyUnitFactoryAir
- | Type::LegacyUnitFactoryGround
- | Type::CommandCenter)
- {
- continue;
- }
- let name = dbg!(t.get_name());
- let t = reg.get(name).unwrap();
- let _ = t.image(
- None,
- Some(&RenderingContext {
- cross: [None; 4],
- position: PositionContext {
- position: GridPos(0, 0),
- width: 5,
- height: 5,
- },
- }),
- Rotation::Up,
- Scale::Quarter,
- );
- }
-}