use super::resources::*;
use super::systems::*;
use crate::prelude::material::Material3dFlag;
use crate::prelude::mesh::Mesh3dFlag;
use crate::traits::*;
use bevy_core_pipeline::core_3d::{Camera3dDepthTextureUsage, ScreenSpaceTransmissionQuality};
use bevy_render::camera::{CameraMainTextureUsages, CameraRenderGraph};
use log::warn;
use moonshine_save::file_from_resource;
use moonshine_save::load::LoadPlugin;
use moonshine_save::load::load;
use moonshine_save::prelude::save_default_with;
use moonshine_save::save::SaveInput;
use moonshine_save::save::SavePlugin;
use std::any::type_name;
use std::ops::Range;
use std::{any::TypeId, marker::PhantomData};
use bevy_app::prelude::*;
use bevy_asset::prelude::*;
use bevy_ecs::prelude::*;
use bevy_math::prelude::*;
use bevy_pbr::prelude::*;
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
use bevy_render::prelude::*;
pub fn skip_serializing<SkippedType: 'static>(app: &mut App) {
type L = SerializeFilter;
let mut skip_list = app
.world_mut()
.get_resource_or_insert_with::<L>(|| L::default());
let skip_list_copy = skip_list.clone();
skip_list.0.components = skip_list_copy
.0
.components
.deny_by_id(TypeId::of::<SkippedType>());
}
pub struct SerializeComponentFor<T: ComponentWrapper> {
thing: PhantomData<fn() -> T>,
}
impl<T: ComponentWrapper> Default for SerializeComponentFor<T> {
fn default() -> Self {
Self {
thing: Default::default(),
}
}
}
impl<T: ComponentWrapper> Plugin for SerializeComponentFor<T> {
fn build(&self, app: &mut App) {
skip_serializing::<T::WrapperTarget>(app);
app.world_mut();
app.register_type::<T>().add_systems(
PreUpdate,
(serialize_for::<T>, deserialize_for::<T>).chain(),
);
}
}
#[derive(Default)]
pub struct SerializeAssetFor<T: AssetWrapper> {
thing: PhantomData<fn() -> T>,
}
impl<T: AssetWrapper> Plugin for SerializeAssetFor<T> {
fn build(&self, app: &mut App) {
skip_serializing::<T::WrapperTarget>(app);
app.add_systems(
PreUpdate,
(try_serialize_asset_for::<T>, deserialize_asset_for::<T>).chain(),
);
app.register_type::<T>()
.world_mut()
.register_component_hooks::<T>()
.on_add(|mut world, e, _id| {
let comp = {
match world.entity(e).get::<T>() {
Some(val) => val,
None => {
warn!("could not get {:#?} on: {:#}", type_name::<Self>(), e);
return;
}
}
};
let handle = {
match comp.asset_state() {
AssetState::Path(path) => {
let Some(asset_server) = world.get_resource::<AssetServer>() else {
warn!("could not get asset server?");
return;
};
asset_server.load(path)
}
AssetState::Pure(pure) => {
let Some(assets) = world.get_resource::<AssetServer>() else {
warn!(
"no mut Assets<T> found for {:#}",
type_name::<Assets<AssetType<T>>>()
);
return;
};
let asset = AssetType::<T>::from(pure);
assets.add(asset)
}
}
};
let componentized_asset = T::WrapperTarget::from(handle);
world.commands().entity(e).insert(componentized_asset);
});
}
}
pub struct SerializationBasePlugin;
impl Plugin for SerializationBasePlugin {
fn build(&self, app: &mut App) {
app.add_plugins(SerializeAssetFor::<Material3dFlag>::default())
.add_plugins(SerializeAssetFor::<Mesh3dFlag>::default());
}
}
pub struct SerializationPlugin;
impl Plugin for SerializationPlugin {
fn build(&self, app: &mut App) {
app.register_type::<[f32; 3]>()
.register_type::<AlphaMode>()
.register_type::<ParallaxMappingMethod>()
.register_type::<Camera3dDepthTextureUsage>()
.register_type::<InheritedVisibility>()
.register_type::<ScreenSpaceTransmissionQuality>()
.register_type::<[[f32; 3]; 3]>()
.register_type::<[Vec3; 3]>()
.register_type::<CameraRenderGraph>()
.register_type::<CameraMainTextureUsages>()
.register_type::<TypeRegistryOnSave>()
.register_type::<LoadRequest>()
.register_type::<SaveRequest>()
.register_type::<ComponentsOnSave>()
.register_type::<ShowSerializable>()
.register_type::<ShowUnserializable>()
.register_type::<Range<f32>>()
.register_type_data::<Range<f32>, ReflectSerialize>()
.register_type_data::<Range<f32>, ReflectDeserialize>()
.init_resource::<SerializeFilter>()
.insert_resource(ShowSerializable::default())
.insert_resource(ShowUnserializable::default())
.insert_resource(ComponentsOnSave::default())
.insert_resource(TypeRegistryOnSave::default())
.insert_resource(RefreshCounter::default());
app.add_plugins((SavePlugin, LoadPlugin))
.add_systems(
PreUpdate,
update_last_saved_typedata.run_if(resource_added::<SaveRequest>),
)
.add_systems(
PreUpdate,
update_last_saved_typedata.run_if(resource_added::<LoadRequest>),
)
.add_systems(
PreUpdate,
update_last_saved_typedata.run_if(resource_changed::<RefreshCounter>),
)
.add_systems(
PreUpdate,
save_default_with(save_filter).into(file_from_resource::<SaveRequest>()),
)
.init_resource::<WrapAssetSerializers>()
.init_resource::<WrapAssetDeserializers>()
.init_resource::<WrapCompSerializers>()
.init_resource::<WrapCompDeserializers>()
.add_systems(PreUpdate, load(file_from_resource::<LoadRequest>()));
}
}
fn save_filter(f: Res<SerializeFilter>) -> SaveInput {
f.0.clone()
}