use std::borrow::Cow;
use cgmath::{Decomposed, Transform, Vector2, Vector3};
use crate::camera::{eye_for_look_at, Camera, GraphicsOptions, Viewport};
use crate::math::{FreeCoordinate, Rgba};
use crate::raytracer::{PixelBuf, RaytraceInfo, RtBlockData, RtOptionsRef, SpaceRaytracer};
use crate::space::{Space, SpaceBlockData};
#[derive(Clone, Debug, Eq, PartialEq)]
#[allow(clippy::exhaustive_structs)]
pub struct CharacterRtData(pub Cow<'static, str>);
impl RtBlockData for CharacterRtData {
type Options = ();
fn from_block(_: RtOptionsRef<'_, Self::Options>, s: &SpaceBlockData) -> Self {
Self(
s.evaluated()
.attributes
.display_name
.chars()
.next()
.map(|c| Cow::Owned(c.to_string()))
.unwrap_or(Cow::Borrowed("#")),
)
}
fn error(_: RtOptionsRef<'_, Self::Options>) -> Self {
Self(Cow::Borrowed("X"))
}
fn sky(_: RtOptionsRef<'_, Self::Options>) -> Self {
Self(Cow::Borrowed(" "))
}
}
#[derive(Clone, Debug, Default, PartialEq)]
#[allow(clippy::derive_partial_eq_without_eq)]
pub struct CharacterBuf {
hit_text: Option<String>,
}
impl PixelBuf for CharacterBuf {
type BlockData = CharacterRtData;
#[inline]
fn opaque(&self) -> bool {
self.hit_text.is_some()
}
#[inline]
fn add(&mut self, _surface_color: Rgba, d: &Self::BlockData) {
if self.hit_text.is_none() {
self.hit_text = Some(String::from(d.0.clone()));
}
}
fn hit_nothing(&mut self) {
self.hit_text = Some(".".to_owned());
}
fn mean<const N: usize>(items: [Self; N]) -> Self {
Self {
hit_text: items.into_iter().flat_map(|cb| cb.hit_text).next(),
}
}
}
impl From<CharacterBuf> for String {
#[inline]
fn from(buf: CharacterBuf) -> String {
buf.hit_text.unwrap_or_else(|| ".".to_owned())
}
}
pub fn print_space(space: &Space, direction: impl Into<Vector3<FreeCoordinate>>) {
print_space_impl(space, direction, |s| {
print!("{s}");
});
}
fn print_space_impl<F: FnMut(&str)>(
space: &Space,
direction: impl Into<Vector3<FreeCoordinate>>,
mut write: F,
) -> RaytraceInfo {
let mut camera = Camera::new(
GraphicsOptions::default(),
Viewport {
nominal_size: Vector2::new(40., 40.),
framebuffer_size: Vector2::new(80, 40),
},
);
camera.set_view_transform(
Decomposed::look_at_rh(
eye_for_look_at(space.bounds(), direction.into()),
space.bounds().center(),
Vector3::new(0., 1., 0.),
)
.inverse_transform()
.unwrap(),
);
SpaceRaytracer::<CharacterRtData>::new(space, GraphicsOptions::default(), ())
.trace_scene_to_text::<CharacterBuf, _, _>(&camera, "\n", move |s| {
write(s);
let r: Result<(), ()> = Ok(());
r
})
.unwrap()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::block::{Block, Resolution::R4};
use crate::content::make_some_blocks;
use crate::universe::Universe;
#[test]
fn print_space_test() {
let mut space = Space::empty_positive(3, 1, 1);
let [b0, b1, b2] = make_some_blocks();
space.set((0, 0, 0), &b0).unwrap();
space.set((1, 0, 0), &b1).unwrap();
space.set((2, 0, 0), &b2).unwrap();
let mut output = String::new();
print_space_impl(&space, (1., 1., 1.), |s| output += s);
print!("{output}");
pretty_assertions::assert_eq!(
output,
"\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
...........................0000000000...........................................\n\
.......................0000000000000001111......................................\n\
........................000000001111111111111111................................\n\
........................00000011111111111111111112222...........................\n\
.........................0000011111111111111122222222222222.....................\n\
.........................000001111111111112222222222222222222222................\n\
...........................000011111111122222222222222222222222222..............\n\
.............................001111111112222222222222222222222222...............\n\
...............................111111111222222222222222222222222................\n\
..................................11111122222222222222222222222.................\n\
....................................11112222222222222222222222..................\n\
.......................................1222222222222222222222...................\n\
.........................................2222222222222222222....................\n\
............................................222222222222222.....................\n\
..............................................22222222222.......................\n\
................................................22222222........................\n\
...................................................2222.........................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
"
);
}
#[test]
fn partial_voxels() {
let resolution = R4;
let mut universe = Universe::new();
let mut block_space = Space::empty_positive(4, 2, 4);
block_space
.fill_uniform(block_space.bounds(), Block::from(Rgba::WHITE))
.unwrap();
let space_ref = universe.insert_anonymous(block_space);
let partial_block = Block::builder()
.voxels_ref(resolution, space_ref.clone())
.display_name("P")
.build();
let mut space = Space::empty_positive(2, 1, 1);
let [b0] = make_some_blocks();
space.set([0, 0, 0], &b0).unwrap();
space.set([1, 0, 0], &partial_block).unwrap();
let mut output = String::new();
print_space_impl(&space, (1., 1., 1.), |s| output += s);
print!("{output}");
pretty_assertions::assert_eq!(
output,
"\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
...............................000000...........................................\n\
......................0000000000000000000000....................................\n\
...................0000000000000000000000000000 .............................\n\
....................000000000000000000000000000 ......................\n\
....................000000000000000000000000000 ...............\n\
.....................0000000000000000000000000 ...........\n\
......................00000000000000000000000PP ...........\n\
......................00000000000000000000PPPPPPPPPP ............\n\
.......................000000000000000PPPPPPPPPPPPPPPPPP .............\n\
.......................000000000000PPPPPPPPPPPPPPPPPPPPPPPPPP ..............\n\
.........................0000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP...............\n\
............................0000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP................\n\
..............................00PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP.................\n\
................................0PPPPPPPPPPPPPPPPPPPPPPPPPPPPP..................\n\
..................................PPPPPPPPPPPPPPPPPPPPPPPPPPP...................\n\
....................................PPPPPPPPPPPPPPPPPPPPPPP.....................\n\
......................................PPPPPPPPPPPPPPPPPPPP......................\n\
........................................PPPPPPPPPPPPPPPPP.......................\n\
..........................................PPPPPPPPPPPPP.........................\n\
............................................PPPPPPPPPP..........................\n\
..............................................PPPPPP............................\n\
................................................PPP.............................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
................................................................................\n\
"
);
}
}