Depreciate LoadAndSave Asset Processor (#15090)
				
					
				
			# Objective - Fixes #15060 ## Solution - Added `IdentityAssetTransformer<A>` which is an `AssetTransformer` which infallibly returns the input `Asset` unmodified. - Replaced `LoadAndSave` and `LoadAndSaveSettings` with type definitions linking back to `LoadTransformAndSave` and `LoadTransformAndSaveSettings` respectively. - Marked `LoadAndSave` and `LoadAndSaveSettings` as depreciated with a migration guide included, hinting to the user to use the underlying type instead. ## Testing - Ran CI locally --- ## Migration Guide - Replace `LoadAndSave<L, S>` with `LoadTransformAndSave<L, IdentityAssetTransformer<<L as AssetLoader>::Asset>, S>` - Replace `LoadAndSaveSettings<L, S>` with `LoadTransformAndSaveSettings<L, (), S>`
This commit is contained in:
		
							parent
							
								
									ce32b5ca06
								
							
						
					
					
						commit
						dac4a5bbb4
					
				@ -1,4 +1,5 @@
 | 
			
		||||
use crate::io::SliceReader;
 | 
			
		||||
use crate::transformer::IdentityAssetTransformer;
 | 
			
		||||
use crate::{
 | 
			
		||||
    io::{
 | 
			
		||||
        AssetReaderError, AssetWriterError, MissingAssetWriterError,
 | 
			
		||||
@ -47,6 +48,11 @@ pub trait Process: Send + Sync + Sized + 'static {
 | 
			
		||||
/// an [`AssetSaver`] that allows you save any `S` asset. However you can
 | 
			
		||||
/// also implement [`Process`] directly if [`LoadTransformAndSave`] feels limiting or unnecessary.
 | 
			
		||||
///
 | 
			
		||||
/// If your [`Process`] does not need to transform the [`Asset`], you can use [`IdentityAssetTransformer`] as `T`.
 | 
			
		||||
/// This will directly return the input [`Asset`], allowing your [`Process`] to directly load and then save an [`Asset`].
 | 
			
		||||
/// However, this pattern should only be used for cases such as file format conversion.
 | 
			
		||||
/// Otherwise, consider refactoring your [`AssetLoader`] and [`AssetSaver`] to isolate the transformation step into an explicit [`AssetTransformer`].
 | 
			
		||||
///
 | 
			
		||||
/// This uses [`LoadTransformAndSaveSettings`] to configure the processor.
 | 
			
		||||
///
 | 
			
		||||
/// [`Asset`]: crate::Asset
 | 
			
		||||
@ -60,6 +66,18 @@ pub struct LoadTransformAndSave<
 | 
			
		||||
    marker: PhantomData<fn() -> L>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<L: AssetLoader, S: AssetSaver<Asset = L::Asset>> From<S>
 | 
			
		||||
    for LoadTransformAndSave<L, IdentityAssetTransformer<L::Asset>, S>
 | 
			
		||||
{
 | 
			
		||||
    fn from(value: S) -> Self {
 | 
			
		||||
        LoadTransformAndSave {
 | 
			
		||||
            transformer: IdentityAssetTransformer::new(),
 | 
			
		||||
            saver: value,
 | 
			
		||||
            marker: PhantomData,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Settings for the [`LoadTransformAndSave`] [`Process::Settings`] implementation.
 | 
			
		||||
///
 | 
			
		||||
/// `LoaderSettings` corresponds to [`AssetLoader::Settings`], `TransformerSettings` corresponds to [`AssetTransformer::Settings`],
 | 
			
		||||
@ -98,30 +116,16 @@ impl<
 | 
			
		||||
/// This uses [`LoadAndSaveSettings`] to configure the processor.
 | 
			
		||||
///
 | 
			
		||||
/// [`Asset`]: crate::Asset
 | 
			
		||||
pub struct LoadAndSave<L: AssetLoader, S: AssetSaver<Asset = L::Asset>> {
 | 
			
		||||
    saver: S,
 | 
			
		||||
    marker: PhantomData<fn() -> L>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<L: AssetLoader, S: AssetSaver<Asset = L::Asset>> From<S> for LoadAndSave<L, S> {
 | 
			
		||||
    fn from(value: S) -> Self {
 | 
			
		||||
        LoadAndSave {
 | 
			
		||||
            saver: value,
 | 
			
		||||
            marker: PhantomData,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#[deprecated = "Use `LoadTransformAndSave<L, IdentityAssetTransformer<<L as AssetLoader>::Asset>, S>` instead"]
 | 
			
		||||
pub type LoadAndSave<L, S> =
 | 
			
		||||
    LoadTransformAndSave<L, IdentityAssetTransformer<<L as AssetLoader>::Asset>, S>;
 | 
			
		||||
 | 
			
		||||
/// Settings for the [`LoadAndSave`] [`Process::Settings`] implementation.
 | 
			
		||||
///
 | 
			
		||||
/// `LoaderSettings` corresponds to [`AssetLoader::Settings`] and `SaverSettings` corresponds to [`AssetSaver::Settings`].
 | 
			
		||||
#[derive(Serialize, Deserialize, Default)]
 | 
			
		||||
pub struct LoadAndSaveSettings<LoaderSettings, SaverSettings> {
 | 
			
		||||
    /// The [`AssetLoader::Settings`] for [`LoadAndSave`].
 | 
			
		||||
    pub loader_settings: LoaderSettings,
 | 
			
		||||
    /// The [`AssetSaver::Settings`] for [`LoadAndSave`].
 | 
			
		||||
    pub saver_settings: SaverSettings,
 | 
			
		||||
}
 | 
			
		||||
#[deprecated = "Use `LoadTransformAndSaveSettings<LoaderSettings, (), SaverSettings>` instead"]
 | 
			
		||||
pub type LoadAndSaveSettings<LoaderSettings, SaverSettings> =
 | 
			
		||||
    LoadTransformAndSaveSettings<LoaderSettings, (), SaverSettings>;
 | 
			
		||||
 | 
			
		||||
/// An error that is encountered during [`Process::process`].
 | 
			
		||||
#[derive(Error, Debug)]
 | 
			
		||||
@ -213,36 +217,6 @@ where
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<Loader: AssetLoader, Saver: AssetSaver<Asset = Loader::Asset>> Process
 | 
			
		||||
    for LoadAndSave<Loader, Saver>
 | 
			
		||||
{
 | 
			
		||||
    type Settings = LoadAndSaveSettings<Loader::Settings, Saver::Settings>;
 | 
			
		||||
    type OutputLoader = Saver::OutputLoader;
 | 
			
		||||
 | 
			
		||||
    async fn process<'a>(
 | 
			
		||||
        &'a self,
 | 
			
		||||
        context: &'a mut ProcessContext<'_>,
 | 
			
		||||
        meta: AssetMeta<(), Self>,
 | 
			
		||||
        writer: &'a mut Writer,
 | 
			
		||||
    ) -> Result<<Self::OutputLoader as AssetLoader>::Settings, ProcessError> {
 | 
			
		||||
        let AssetAction::Process { settings, .. } = meta.asset else {
 | 
			
		||||
            return Err(ProcessError::WrongMetaType);
 | 
			
		||||
        };
 | 
			
		||||
        let loader_meta = AssetMeta::<Loader, ()>::new(AssetAction::Load {
 | 
			
		||||
            loader: std::any::type_name::<Loader>().to_string(),
 | 
			
		||||
            settings: settings.loader_settings,
 | 
			
		||||
        });
 | 
			
		||||
        let loaded_asset = context.load_source_asset(loader_meta).await?;
 | 
			
		||||
        let saved_asset = SavedAsset::<Loader::Asset>::from_loaded(&loaded_asset).unwrap();
 | 
			
		||||
        let output_settings = self
 | 
			
		||||
            .saver
 | 
			
		||||
            .save(writer, saved_asset, &settings.saver_settings)
 | 
			
		||||
            .await
 | 
			
		||||
            .map_err(|error| ProcessError::AssetSaveError(error.into()))?;
 | 
			
		||||
        Ok(output_settings)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// A type-erased variant of [`Process`] that enables interacting with processor implementations without knowing
 | 
			
		||||
/// their type.
 | 
			
		||||
pub trait ErasedProcessor: Send + Sync {
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,9 @@ use bevy_utils::{ConditionalSendFuture, HashMap};
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use std::{
 | 
			
		||||
    borrow::Borrow,
 | 
			
		||||
    convert::Infallible,
 | 
			
		||||
    hash::Hash,
 | 
			
		||||
    marker::PhantomData,
 | 
			
		||||
    ops::{Deref, DerefMut},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -241,3 +243,37 @@ impl<'a, A: Asset> TransformedSubAsset<'a, A> {
 | 
			
		||||
        self.labeled_assets.keys().map(|s| &**s)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// An identity [`AssetTransformer`] which infallibly returns the input [`Asset`] on transformation.]
 | 
			
		||||
pub struct IdentityAssetTransformer<A: Asset> {
 | 
			
		||||
    _phantom: PhantomData<fn(A) -> A>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<A: Asset> IdentityAssetTransformer<A> {
 | 
			
		||||
    pub const fn new() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            _phantom: PhantomData,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<A: Asset> Default for IdentityAssetTransformer<A> {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self::new()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<A: Asset> AssetTransformer for IdentityAssetTransformer<A> {
 | 
			
		||||
    type AssetInput = A;
 | 
			
		||||
    type AssetOutput = A;
 | 
			
		||||
    type Settings = ();
 | 
			
		||||
    type Error = Infallible;
 | 
			
		||||
 | 
			
		||||
    async fn transform<'a>(
 | 
			
		||||
        &'a self,
 | 
			
		||||
        asset: TransformedAsset<Self::AssetInput>,
 | 
			
		||||
        _settings: &'a Self::Settings,
 | 
			
		||||
    ) -> Result<TransformedAsset<Self::AssetOutput>, Self::Error> {
 | 
			
		||||
        Ok(asset)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -107,11 +107,16 @@ impl Plugin for ImagePlugin {
 | 
			
		||||
            .world()
 | 
			
		||||
            .get_resource::<bevy_asset::processor::AssetProcessor>()
 | 
			
		||||
        {
 | 
			
		||||
            processor.register_processor::<bevy_asset::processor::LoadAndSave<ImageLoader, CompressedImageSaver>>(
 | 
			
		||||
                CompressedImageSaver.into(),
 | 
			
		||||
            );
 | 
			
		||||
            processor
 | 
			
		||||
                .set_default_processor::<bevy_asset::processor::LoadAndSave<ImageLoader, CompressedImageSaver>>("png");
 | 
			
		||||
            processor.register_processor::<bevy_asset::processor::LoadTransformAndSave<
 | 
			
		||||
                ImageLoader,
 | 
			
		||||
                bevy_asset::transformer::IdentityAssetTransformer<Image>,
 | 
			
		||||
                CompressedImageSaver,
 | 
			
		||||
            >>(CompressedImageSaver.into());
 | 
			
		||||
            processor.set_default_processor::<bevy_asset::processor::LoadTransformAndSave<
 | 
			
		||||
                ImageLoader,
 | 
			
		||||
                bevy_asset::transformer::IdentityAssetTransformer<Image>,
 | 
			
		||||
                CompressedImageSaver,
 | 
			
		||||
            >>("png");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user