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::io::SliceReader;
|
||||||
|
use crate::transformer::IdentityAssetTransformer;
|
||||||
use crate::{
|
use crate::{
|
||||||
io::{
|
io::{
|
||||||
AssetReaderError, AssetWriterError, MissingAssetWriterError,
|
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
|
/// an [`AssetSaver`] that allows you save any `S` asset. However you can
|
||||||
/// also implement [`Process`] directly if [`LoadTransformAndSave`] feels limiting or unnecessary.
|
/// 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.
|
/// This uses [`LoadTransformAndSaveSettings`] to configure the processor.
|
||||||
///
|
///
|
||||||
/// [`Asset`]: crate::Asset
|
/// [`Asset`]: crate::Asset
|
||||||
@ -60,6 +66,18 @@ pub struct LoadTransformAndSave<
|
|||||||
marker: PhantomData<fn() -> L>,
|
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.
|
/// Settings for the [`LoadTransformAndSave`] [`Process::Settings`] implementation.
|
||||||
///
|
///
|
||||||
/// `LoaderSettings` corresponds to [`AssetLoader::Settings`], `TransformerSettings` corresponds to [`AssetTransformer::Settings`],
|
/// `LoaderSettings` corresponds to [`AssetLoader::Settings`], `TransformerSettings` corresponds to [`AssetTransformer::Settings`],
|
||||||
@ -98,30 +116,16 @@ impl<
|
|||||||
/// This uses [`LoadAndSaveSettings`] to configure the processor.
|
/// This uses [`LoadAndSaveSettings`] to configure the processor.
|
||||||
///
|
///
|
||||||
/// [`Asset`]: crate::Asset
|
/// [`Asset`]: crate::Asset
|
||||||
pub struct LoadAndSave<L: AssetLoader, S: AssetSaver<Asset = L::Asset>> {
|
#[deprecated = "Use `LoadTransformAndSave<L, IdentityAssetTransformer<<L as AssetLoader>::Asset>, S>` instead"]
|
||||||
saver: S,
|
pub type LoadAndSave<L, S> =
|
||||||
marker: PhantomData<fn() -> L>,
|
LoadTransformAndSave<L, IdentityAssetTransformer<<L as AssetLoader>::Asset>, S>;
|
||||||
}
|
|
||||||
|
|
||||||
impl<L: AssetLoader, S: AssetSaver<Asset = L::Asset>> From<S> for LoadAndSave<L, S> {
|
|
||||||
fn from(value: S) -> Self {
|
|
||||||
LoadAndSave {
|
|
||||||
saver: value,
|
|
||||||
marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Settings for the [`LoadAndSave`] [`Process::Settings`] implementation.
|
/// Settings for the [`LoadAndSave`] [`Process::Settings`] implementation.
|
||||||
///
|
///
|
||||||
/// `LoaderSettings` corresponds to [`AssetLoader::Settings`] and `SaverSettings` corresponds to [`AssetSaver::Settings`].
|
/// `LoaderSettings` corresponds to [`AssetLoader::Settings`] and `SaverSettings` corresponds to [`AssetSaver::Settings`].
|
||||||
#[derive(Serialize, Deserialize, Default)]
|
#[deprecated = "Use `LoadTransformAndSaveSettings<LoaderSettings, (), SaverSettings>` instead"]
|
||||||
pub struct LoadAndSaveSettings<LoaderSettings, SaverSettings> {
|
pub type LoadAndSaveSettings<LoaderSettings, SaverSettings> =
|
||||||
/// The [`AssetLoader::Settings`] for [`LoadAndSave`].
|
LoadTransformAndSaveSettings<LoaderSettings, (), SaverSettings>;
|
||||||
pub loader_settings: LoaderSettings,
|
|
||||||
/// The [`AssetSaver::Settings`] for [`LoadAndSave`].
|
|
||||||
pub saver_settings: SaverSettings,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An error that is encountered during [`Process::process`].
|
/// An error that is encountered during [`Process::process`].
|
||||||
#[derive(Error, Debug)]
|
#[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
|
/// A type-erased variant of [`Process`] that enables interacting with processor implementations without knowing
|
||||||
/// their type.
|
/// their type.
|
||||||
pub trait ErasedProcessor: Send + Sync {
|
pub trait ErasedProcessor: Send + Sync {
|
||||||
|
|||||||
@ -4,7 +4,9 @@ use bevy_utils::{ConditionalSendFuture, HashMap};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Borrow,
|
borrow::Borrow,
|
||||||
|
convert::Infallible,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
|
marker::PhantomData,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -241,3 +243,37 @@ impl<'a, A: Asset> TransformedSubAsset<'a, A> {
|
|||||||
self.labeled_assets.keys().map(|s| &**s)
|
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()
|
.world()
|
||||||
.get_resource::<bevy_asset::processor::AssetProcessor>()
|
.get_resource::<bevy_asset::processor::AssetProcessor>()
|
||||||
{
|
{
|
||||||
processor.register_processor::<bevy_asset::processor::LoadAndSave<ImageLoader, CompressedImageSaver>>(
|
processor.register_processor::<bevy_asset::processor::LoadTransformAndSave<
|
||||||
CompressedImageSaver.into(),
|
ImageLoader,
|
||||||
);
|
bevy_asset::transformer::IdentityAssetTransformer<Image>,
|
||||||
processor
|
CompressedImageSaver,
|
||||||
.set_default_processor::<bevy_asset::processor::LoadAndSave<ImageLoader, CompressedImageSaver>>("png");
|
>>(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) {
|
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user