diff --git a/src/lib.rs b/src/lib.rs index cfa4439..d88d998 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ mod ui; use std::{marker::PhantomData, path::PathBuf}; use animation::animation_plugin; +use bevy::render::view::RenderLayers; use button::button_plugin; use camera::camera_plugin; use cursor::cursor_plugin; @@ -54,15 +55,10 @@ use text::text_plugin; pub struct PxPlugin { screen_size: ScreenSize, palette_path: PathBuf, + layers: RenderLayers, _l: PhantomData, } -impl Plugin for PxPlugin { - fn build(&self, app: &mut App) { - app.fn_plugin(px_plugin::(self.screen_size, self.palette_path.clone())); - } -} - impl PxPlugin { /// Create a [`PxPlugin`]. `screen_size` is the size of the screen in pixels. /// `palette_path` is the path from `assets/` to your game's palette. This palette will be used @@ -71,9 +67,26 @@ impl PxPlugin { Self { screen_size: screen_size.into(), palette_path: palette_path.into(), + layers: RenderLayers::default(), _l: default(), } } + + /// Sets the render layers that `seldom_pixel` will draw to + pub fn with_render_layers(mut self, layers: RenderLayers) -> Self { + self.layers = layers; + self + } +} + +impl Plugin for PxPlugin { + fn build(&self, app: &mut App) { + app.fn_plugin(px_plugin::( + self.screen_size, + self.palette_path.clone(), + self.layers, + )); + } } /// Function called by [`PxPlugin`]. You may instead call it directly or use `seldom_fn_plugin`, @@ -81,6 +94,7 @@ impl PxPlugin { pub fn px_plugin( screen_size: ScreenSize, palette_path: PathBuf, + layers: RenderLayers, ) -> impl FnOnce(&mut App) { move |app| { app.fn_plugin(animation_plugin) @@ -91,7 +105,7 @@ pub fn px_plugin( .fn_plugin(map_plugin) .fn_plugin(palette_plugin(palette_path)) .fn_plugin(position_plugin) - .fn_plugin(screen_plugin::(screen_size)) + .fn_plugin(screen_plugin::(screen_size, layers)) .fn_plugin(sprite_plugin) .fn_plugin(text_plugin); #[cfg(feature = "particle")] diff --git a/src/screen.rs b/src/screen.rs index e903e56..fb28b08 100644 --- a/src/screen.rs +++ b/src/screen.rs @@ -3,9 +3,12 @@ use std::collections::BTreeMap; use bevy::{ - render::render_resource::{ - AsBindGroup, Extent3d, ShaderRef, TextureDescriptor, TextureDimension, TextureFormat, - TextureUsages, + render::{ + render_resource::{ + AsBindGroup, Extent3d, ShaderRef, TextureDescriptor, TextureDimension, TextureFormat, + TextureUsages, + }, + view::RenderLayers, }, sprite::{Material2d, Material2dPlugin, MaterialMesh2dBundle}, window::{PrimaryWindow, WindowResized}, @@ -28,7 +31,10 @@ use crate::{ const SCREEN_SHADER_HANDLE: Handle = Handle::weak_from_u128(0x48CE_4F2C_8B78_5954_08A8_461F_62E1_0E84); -pub(crate) fn screen_plugin(size: ScreenSize) -> impl FnOnce(&mut App) { +pub(crate) fn screen_plugin( + size: ScreenSize, + layers: RenderLayers, +) -> impl FnOnce(&mut App) { move |app| { app.world.resource_mut::>().insert( SCREEN_SHADER_HANDLE, @@ -37,7 +43,7 @@ pub(crate) fn screen_plugin(size: ScreenSize) -> impl FnOnce(&mut Ap app.add_plugins(Material2dPlugin::::default()) .configure_sets(PostUpdate, PxSet::Draw) .add_systems(Startup, insert_screen(size)) - .add_systems(Update, init_screen) + .add_systems(Update, init_screen(layers)) .add_systems( PostUpdate, ( @@ -161,59 +167,71 @@ fn insert_screen( } fn init_screen( - palette: PaletteParam, - mut screen_materials: ResMut>, - screens: Query<(), With>, - screen: Res, - mut meshes: ResMut>, - windows: Query<(Entity, &Window), With>, - mut window_resized: EventWriter, - mut commands: Commands, + layers: RenderLayers, +) -> impl Fn( + PaletteParam, + ResMut>, + Query<(), With>, + Res, + ResMut>, + Query<(Entity, &Window), With>, + EventWriter, + Commands, ) { - if screens.iter().next().is_some() { - return; - } + move |palette, + mut screen_materials, + screens, + screen, + mut meshes, + windows, + mut window_resized, + mut commands| { + if screens.iter().next().is_some() { + return; + } - let Some(palette) = palette.get() else { - return; - }; + let Some(palette) = palette.get() else { + return; + }; - let mut screen_palette = [default(); 256]; + let mut screen_palette = [default(); 256]; - for (i, [r, g, b]) in palette.colors.iter().enumerate() { - let [r, g, b, _] = Color::rgb_u8(*r, *g, *b).as_linear_rgba_f32(); - screen_palette[i] = Vec3::new(r, g, b); - } + for (i, [r, g, b]) in palette.colors.iter().enumerate() { + let [r, g, b, _] = Color::rgb_u8(*r, *g, *b).as_linear_rgba_f32(); + screen_palette[i] = Vec3::new(r, g, b); + } - let (entity, window) = windows.single(); - let calculated_screen_scale = screen_scale( - screen.computed_size, - Vec2::new(window.width(), window.height()), - ) - .extend(1.); - - commands.spawn(( - MaterialMesh2dBundle { - mesh: meshes.add(Rectangle::default()).into(), - material: screen_materials.add(ScreenMaterial { - image: screen.image.clone(), - palette: screen_palette, - }), - transform: Transform::from_scale(calculated_screen_scale), - // Ensure transform matches global_transform to ensure correct rendering for WASM - global_transform: GlobalTransform::from_scale(calculated_screen_scale), - ..default() - }, - ScreenMarker, - Name::new("Screen"), - )); - - // I do not know why, but the screen does not display unless the window has been resized - window_resized.send(WindowResized { - window: entity, - width: window.width(), - height: window.height(), - }); + let (entity, window) = windows.single(); + let calculated_screen_scale = screen_scale( + screen.computed_size, + Vec2::new(window.width(), window.height()), + ) + .extend(1.); + + commands.spawn(( + ScreenMarker, + layers, + MaterialMesh2dBundle { + mesh: meshes.add(Rectangle::default()).into(), + material: screen_materials.add(ScreenMaterial { + image: screen.image.clone(), + palette: screen_palette, + }), + transform: Transform::from_scale(calculated_screen_scale), + // Ensure transform matches global_transform to ensure correct rendering for WASM + global_transform: GlobalTransform::from_scale(calculated_screen_scale), + ..default() + }, + Name::new("Screen"), + )); + + // I do not know why, but the screen does not display unless the window has been resized + window_resized.send(WindowResized { + window: entity, + width: window.width(), + height: window.height(), + }); + } } fn resize_screen(