use std::collections::HashMap;
use bevy::prelude::*;
use crate::render::{NoesisRenderState, NoesisSet};
#[derive(Component, Clone, Default, Debug)]
pub struct NoesisVisibility {
pub set: HashMap<String, bool>,
}
impl NoesisVisibility {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn show(self, name: impl Into<String>) -> Self {
self.set(name, true)
}
#[must_use]
pub fn hide(self, name: impl Into<String>) -> Self {
self.set(name, false)
}
#[must_use]
pub fn set(mut self, name: impl Into<String>, visible: bool) -> Self {
self.set.insert(name.into(), visible);
self
}
pub fn reveal(&mut self, name: impl Into<String>) {
self.set.insert(name.into(), true);
}
pub fn collapse(&mut self, name: impl Into<String>) {
self.set.insert(name.into(), false);
}
pub fn write(&mut self, name: impl Into<String>, visible: bool) {
self.set.insert(name.into(), visible);
}
}
#[allow(clippy::needless_pass_by_value)]
pub(crate) fn sync_visibility_bridge(
views: Query<(Entity, Ref<NoesisVisibility>)>,
state: Option<NonSendMut<NoesisRenderState>>,
) {
let Some(mut state) = state else {
return;
};
for (entity, vis) in &views {
if vis.is_changed() || state.scene_rebuilt_this_frame(entity) {
state.apply_visibility_for(entity, &vis.set);
}
}
}
pub struct NoesisVisibilityPlugin;
impl Plugin for NoesisVisibilityPlugin {
fn build(&self, app: &mut App) {
app.add_systems(PostUpdate, sync_visibility_bridge.in_set(NoesisSet::Apply));
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn builder_collects_set() {
let v = NoesisVisibility::new()
.show("QuitConfirmOverlay")
.hide("LoadingSpinner")
.set("Hud", true);
assert_eq!(v.set.get("QuitConfirmOverlay"), Some(&true));
assert_eq!(v.set.get("LoadingSpinner"), Some(&false));
assert_eq!(v.set.get("Hud"), Some(&true));
}
}