use bevy::{prelude::*, render::render_resource::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages}}; use bevy_dither_post_process::components::DitherPostProcessSettings; use bevy_framebuffer_extract::{components::{ExtractFramebufferBundle, FramebufferExtractDestination}, render_assets::FramebufferExtractSource}; /// Marker component for terminal display #[derive(Component)] pub struct TerminalDisplay; /// Bundle for terminal display, contains a handle to an image to be used as a render target to /// render to the terminal #[derive(Bundle)] pub struct TerminalDisplayBundle { _terminal_display: TerminalDisplay, extract_framebuffer_bundle: ExtractFramebufferBundle, dither_post_process_settings: DitherPostProcessSettings, image_handle: Handle, } impl TerminalDisplayBundle { /// Create a new terminal display with the given dither level. A higher level exponentially /// increases the size of the bayer matrix used in the ordered dithering calculations. If in /// doubt, 3 is a good starting value to test with. pub fn new(dither_level: u32, asset_server: &AssetServer) -> Self { let terminal_size = crossterm::terminal::size().unwrap(); let size = Extent3d { width: (terminal_size.0 as u32) * 2, height: (terminal_size.1 as u32) * 4, depth_or_array_layers: 1, }; let mut image = Image { texture_descriptor: TextureDescriptor { label: None, size, dimension: TextureDimension::D2, format: TextureFormat::R8Unorm, mip_level_count: 1, sample_count: 1, usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_SRC | TextureUsages::RENDER_ATTACHMENT, view_formats: &[], }, ..default() }; image.resize(size); let image_handle = asset_server.add(image); let framebuffer_extract_source = asset_server.add(FramebufferExtractSource(image_handle.clone())); Self { _terminal_display: TerminalDisplay, extract_framebuffer_bundle: ExtractFramebufferBundle { source: framebuffer_extract_source, dest: FramebufferExtractDestination::default(), }, image_handle, dither_post_process_settings: DitherPostProcessSettings::new( dither_level, asset_server, ), } } /// Retrieves the handle to this display's target image. Anything written here will be /// displayed. pub fn image_handle(&self) -> Handle { self.image_handle.clone() } }