use std::any::{Any, TypeId};
use bevy::{
prelude::*,
reflect::GetTypeRegistration,
render::{
extract_resource::ExtractResource,
render_asset::RenderAssets,
render_resource::{BindGroup, BindGroupLayout, CachedComputePipelineId},
renderer::RenderDevice,
texture::{FallbackImage, GpuImage},
},
};
pub use bevy_atmosphere_macros::Atmospheric;
pub trait Atmospheric: Send + Sync + Reflect + Any + 'static {
fn as_bind_group(
&self,
layout: &BindGroupLayout,
render_device: &RenderDevice,
images: &RenderAssets<GpuImage>,
fallback_image: &FallbackImage,
) -> BindGroup;
fn clone_dynamic(&self) -> Box<dyn Atmospheric>;
fn as_reflect(&self) -> &dyn Reflect;
fn as_reflect_mut(&mut self) -> &mut dyn Reflect;
}
impl Clone for Box<dyn Atmospheric> {
fn clone(&self) -> Self {
self.clone_dynamic()
}
}
#[derive(Clone)]
pub struct AtmosphereModelMetadata {
pub id: TypeId,
pub bind_group_layout: BindGroupLayout,
pub pipeline: CachedComputePipelineId,
}
pub trait RegisterAtmosphereModel: GetTypeRegistration {
fn register(app: &mut App);
fn bind_group_layout(render_device: &RenderDevice) -> BindGroupLayout;
}
pub trait AddAtmosphereModel {
fn add_atmosphere_model<T: RegisterAtmosphereModel>(&mut self) -> &mut App;
}
impl AddAtmosphereModel for App {
fn add_atmosphere_model<T: RegisterAtmosphereModel>(&mut self) -> &mut App {
T::register(self);
self
}
}
#[derive(Resource, ExtractResource, Clone)]
pub struct AtmosphereModel {
model: Box<dyn Atmospheric>,
}
impl From<&AtmosphereModel> for AtmosphereModel {
fn from(atmosphere: &AtmosphereModel) -> Self {
atmosphere.clone()
}
}
impl AtmosphereModel {
pub fn new(model: impl Atmospheric + 'static) -> Self {
Self {
model: Box::new(model),
}
}
#[inline]
pub fn model(&self) -> &dyn Atmospheric {
&*self.model
}
#[inline]
pub fn model_mut(&mut self) -> &mut dyn Atmospheric {
&mut *self.model
}
pub fn to_ref<T: Atmospheric>(&self) -> Option<&T> {
Atmospheric::as_reflect(&*self.model).downcast_ref()
}
pub fn to_mut<T: Atmospheric>(&mut self) -> Option<&mut T> {
Atmospheric::as_reflect_mut(&mut *self.model).downcast_mut()
}
}
cfg_if::cfg_if! {
if #[cfg(feature = "nishita")] {
impl Default for AtmosphereModel {
fn default() -> Self {
use crate::collection::nishita::Nishita;
Self::new(Nishita::default())
}
}
} else if #[cfg(feature = "gradient")] {
impl Default for AtmosphereModel {
fn default() -> Self {
use crate::collection::gradient::Gradient;
Self::new(Gradient::default())
}
}
} else {
impl Default for AtmosphereModel {
fn default() -> Self {
panic!("Enable at least one atmospheric model!");
}
}
}
}