mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
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
3 changed files with 70 additions and 55 deletions
|
@ -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 a new issue