#![doc = include_str!("../README.md")]
#![forbid(unsafe_code)]
mod canvas;
mod digest;
mod settings;
mod uv;
pub use canvas::{UV_SPAN_M, WetCanvas};
pub use settings::WetSettings;
pub use bloodstain;
pub use bloodstain::stain::StainShape;
use bevy::app::{App, Plugin, Update};
use bevy::asset::Assets;
use bevy::ecs::entity::Entity;
use bevy::ecs::schedule::{IntoScheduleConfigs, SystemSet};
use bevy::ecs::system::{Query, Res, ResMut};
use bevy::image::Image;
#[derive(SystemSet, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct WetmapSystems;
pub struct WetmapPlugin;
impl Plugin for WetmapPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<WetSettings>()
.add_systems(Update, upload_dirty_canvases.in_set(WetmapSystems));
}
}
fn upload_dirty_canvases(
settings: Option<Res<WetSettings>>,
images: Option<ResMut<Assets<Image>>>,
mut canvases: Query<(Entity, &mut WetCanvas)>,
) {
let (Some(settings), Some(mut images)) = (settings, images) else {
return;
};
let budget = settings.max_canvas_updates_per_tick as usize;
if budget == 0 {
return;
}
let mut order: Vec<(u32, Entity)> = canvases
.iter()
.filter_map(|(entity, canvas)| canvas.dirty_since().map(|since| (since, entity)))
.collect();
if order.is_empty() {
return;
}
order.sort_unstable();
for &(_, entity) in order.iter().take(budget) {
if let Ok((_, mut canvas)) = canvases.get_mut(entity) {
canvas.flush(&mut images);
}
}
}