use crate::{
prelude::{ComponentsOnSave, TypeRegistryOnSave},
traits::*,
};
use std::any::{TypeId, type_name};
use bevy_asset::prelude::*;
use bevy_ecs::prelude::*;
use bevy_log::warn;
use bevy_reflect::TypeInfo;
use bevy_utils::HashMap;
use moonshine_save::save::Save;
pub fn serialize_for<Wrapper>(
thing_query: Query<
(Entity, &Wrapper::WrapperTarget),
Or<(
Added<Wrapper::WrapperTarget>,
Changed<Wrapper::WrapperTarget>,
)>,
>,
wrappers: Query<Entity, Changed<Wrapper>>,
mut commands: Commands,
) where
Wrapper: ComponentWrapper,
{
for (e, f) in thing_query.iter() {
if wrappers.contains(e) == false {
commands.entity(e).try_insert(Wrapper::from(&f));
}
}
}
pub fn try_serialize_asset_for<Wrapper>(
assets: ResMut<Assets<AssetType<Wrapper>>>,
things_query: Query<
(Entity, &Wrapper::WrapperTarget),
Or<(
Changed<Wrapper::WrapperTarget>,
Added<Wrapper::WrapperTarget>,
)>,
>,
changed_wrapper: Query<Entity, Changed<Wrapper>>,
mut commands: Commands,
) where
Wrapper: AssetWrapper,
{
for (e, thing_handle) in things_query.iter() {
if changed_wrapper.contains(e) == false {
let new_wrapper = if let Some(path) = thing_handle.path() {
Wrapper::from(path.to_string())
} else {
let Some(asset) = assets.get(&**thing_handle) else {
warn!(
"Attempted serialize non-file asset {:#} to {:#} while the asset was unloaded. Skipping attempt",
type_name::<AssetType<Wrapper>>(),
type_name::<Wrapper>()
);
return;
};
let pure = Wrapper::PureVariant::from(asset);
Wrapper::from(pure)
};
commands.entity(e).try_insert(new_wrapper);
}
}
}
pub fn deserialize_asset_for<Wrapper>(
mut assets: ResMut<Assets<AssetType<Wrapper>>>,
wrapper_thing_query: Query<(Entity, &Wrapper), Changed<Wrapper>>,
changed_wrapper_targets: Query<Entity, Changed<Wrapper::WrapperTarget>>,
mut commands: Commands,
asset_server: Res<AssetServer>,
) where
Wrapper: AssetWrapper,
{
for (e, wrapper_thing) in wrapper_thing_query.iter() {
log::trace!("converting wrapper thing {:#?}", e);
if changed_wrapper_targets.contains(e) == false {
let insert = match wrapper_thing.asset_state() {
AssetState::Path(wrapper_path) => {
let handle = asset_server.load(wrapper_path);
Wrapper::WrapperTarget::from(handle)
}
AssetState::Pure(wrapper) => {
let new_asset = AssetType::<Wrapper>::from(wrapper);
let handle = assets.add(new_asset);
Wrapper::WrapperTarget::from(handle)
}
};
commands.entity(e).try_insert(insert);
}
}
}
pub fn deserialize_for<Wrapper>(
wrapper_thing_query: Query<(Entity, &Wrapper), Or<(Added<Wrapper>, Changed<Wrapper>)>>,
mut commands: Commands,
) where
Wrapper: ComponentWrapper,
{
for (e, f) in wrapper_thing_query.iter() {
commands
.entity(e)
.try_insert(Wrapper::WrapperTarget::from(&f));
}
}
pub fn update_last_saved_typedata(world: &mut World) {
let mut enetities_to_save = world.query_filtered::<Entity, With<Save>>();
log::trace!("updating last saved type_data");
let type_registry = world.resource::<AppTypeRegistry>();
let mut saved_component_types = HashMap::new();
for e in enetities_to_save.iter(&world) {
for component in world.entity(e).archetype().components() {
let comp_info = world.components().get_info(component).unwrap();
saved_component_types.insert(comp_info.type_id().unwrap(), comp_info.name().to_owned());
}
}
let registered_types = type_registry
.read()
.iter()
.map(|id| {
let type_id = id.type_id();
return (type_id, TypeInfo::type_path(id.type_info()).to_owned());
})
.collect::<HashMap<TypeId, String>>();
type L = TypeRegistryOnSave;
world.insert_resource::<L>(L {
registry: registered_types,
});
type O = ComponentsOnSave;
world.insert_resource::<O>(O {
components: saved_component_types,
});
}