Skip to content

Commit

Permalink
with_render_layers
Browse files Browse the repository at this point in the history
  • Loading branch information
Seldom-SE committed Jun 21, 2024
1 parent e112632 commit 12df124
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 60 deletions.
28 changes: 21 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -54,15 +55,10 @@ use text::text_plugin;
pub struct PxPlugin<L: PxLayer> {
screen_size: ScreenSize,
palette_path: PathBuf,
layers: RenderLayers,
_l: PhantomData<L>,
}

impl<L: PxLayer> Plugin for PxPlugin<L> {
fn build(&self, app: &mut App) {
app.fn_plugin(px_plugin::<L>(self.screen_size, self.palette_path.clone()));
}
}

impl<L: PxLayer> PxPlugin<L> {
/// 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
Expand All @@ -71,16 +67,34 @@ impl<L: PxLayer> PxPlugin<L> {
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<L: PxLayer> Plugin for PxPlugin<L> {
fn build(&self, app: &mut App) {
app.fn_plugin(px_plugin::<L>(
self.screen_size,
self.palette_path.clone(),
self.layers,
));
}
}

/// Function called by [`PxPlugin`]. You may instead call it directly or use `seldom_fn_plugin`,
/// which is another crate I maintain.
pub fn px_plugin<L: PxLayer>(
screen_size: ScreenSize,
palette_path: PathBuf,
layers: RenderLayers,
) -> impl FnOnce(&mut App) {
move |app| {
app.fn_plugin(animation_plugin)
Expand All @@ -91,7 +105,7 @@ pub fn px_plugin<L: PxLayer>(
.fn_plugin(map_plugin)
.fn_plugin(palette_plugin(palette_path))
.fn_plugin(position_plugin)
.fn_plugin(screen_plugin::<L>(screen_size))
.fn_plugin(screen_plugin::<L>(screen_size, layers))
.fn_plugin(sprite_plugin)
.fn_plugin(text_plugin);
#[cfg(feature = "particle")]
Expand Down
124 changes: 71 additions & 53 deletions src/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -28,7 +31,10 @@ use crate::{
const SCREEN_SHADER_HANDLE: Handle<Shader> =
Handle::weak_from_u128(0x48CE_4F2C_8B78_5954_08A8_461F_62E1_0E84);

pub(crate) fn screen_plugin<L: PxLayer>(size: ScreenSize) -> impl FnOnce(&mut App) {
pub(crate) fn screen_plugin<L: PxLayer>(
size: ScreenSize,
layers: RenderLayers,
) -> impl FnOnce(&mut App) {
move |app| {
app.world.resource_mut::<Assets<Shader>>().insert(
SCREEN_SHADER_HANDLE,
Expand All @@ -37,7 +43,7 @@ pub(crate) fn screen_plugin<L: PxLayer>(size: ScreenSize) -> impl FnOnce(&mut Ap
app.add_plugins(Material2dPlugin::<ScreenMaterial>::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,
(
Expand Down Expand Up @@ -161,59 +167,71 @@ fn insert_screen(
}

fn init_screen(
palette: PaletteParam,
mut screen_materials: ResMut<Assets<ScreenMaterial>>,
screens: Query<(), With<ScreenMarker>>,
screen: Res<Screen>,
mut meshes: ResMut<Assets<Mesh>>,
windows: Query<(Entity, &Window), With<PrimaryWindow>>,
mut window_resized: EventWriter<WindowResized>,
mut commands: Commands,
layers: RenderLayers,
) -> impl Fn(
PaletteParam,
ResMut<Assets<ScreenMaterial>>,
Query<(), With<ScreenMarker>>,
Res<Screen>,
ResMut<Assets<Mesh>>,
Query<(Entity, &Window), With<PrimaryWindow>>,
EventWriter<WindowResized>,
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(
Expand Down

0 comments on commit 12df124

Please sign in to comment.