Skip to content

Fix #11111 by making asset settings part of AssetPath #19187

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 32 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4e66032
Changed `MetaTransform` to be a `Box<dyn Settings>` that will optiona…
greeble-dev May 8, 2025
14a2a36
Trying a different tack - add the settings to `AssetPath`.
greeble-dev May 8, 2025
5779ba2
Updated examples.
greeble-dev May 8, 2025
eab30f4
Removed meta transform since it's no longer used.
greeble-dev May 8, 2025
a47b90f
Added type id to AssetPathSettingsId. Implemented Display for AssetPa…
greeble-dev May 9, 2025
f0f645c
Removed `load_with_settings` and variants. This is now done by `Asset…
greeble-dev May 9, 2025
11e6762
Fixed `ExrTextureLoadingSettings` missing clone.
greeble-dev May 9, 2025
feb7aba
Fixed remaining examples.
greeble-dev May 9, 2025
9bf90b4
Changed glTF importer to calculate the texture handles once and reuse…
greeble-dev May 9, 2025
2287bc3
Renamed `AssetPathSettings` to `ErasedSettings`.
greeble-dev May 9, 2025
765d951
Clarified comment.
greeble-dev May 9, 2025
529637e
Revert "Fixed remaining examples."
greeble-dev May 10, 2025
5d735dd
Revert "Removed `load_with_settings` and variants. This is now done b…
greeble-dev May 10, 2025
2e271c7
Revert "Updated examples."
greeble-dev May 10, 2025
d4c55fd
Temporarily disabled clippy warning.
greeble-dev May 10, 2025
01b4471
Changed `load_with_settings` and variants to take a closure instead o…
greeble-dev May 10, 2025
a086ff7
Removed settings from `NestedLoader`. This was no longer necessary si…
greeble-dev May 10, 2025
416432c
Added comment about `load_with_meta_transform` function name.
greeble-dev May 10, 2025
15432f2
Updated `asset_processing` example.
greeble-dev May 10, 2025
94e09a9
Changed `ErasedSettings` and `ErasedSettingsId` members to be private…
greeble-dev May 10, 2025
e2e9c30
Replaced `ron::ser::to_string` with a (hopefully?) more efficient `ro…
greeble-dev May 10, 2025
e8cc845
Updated comments.
greeble-dev May 10, 2025
760a32a
Moved HashWriter.
greeble-dev May 10, 2025
888779b
Moved `HashWriter` into its own module.
greeble-dev May 10, 2025
90218b2
Reverted doc example.
greeble-dev May 10, 2025
4d81753
Fixed the `alter_sprite` and `alter_mesh` examples. They needed to co…
greeble-dev May 12, 2025
810ad78
Added proper tests for HashWriter. Currently failing as I suspect it'…
greeble-dev May 12, 2025
65d5e28
Removed `HashWriter` and went back to serializing a string. Seems lik…
greeble-dev May 12, 2025
27b8d21
Updated comments.
greeble-dev May 12, 2025
85d7fea
Fixed typos.
greeble-dev May 12, 2025
e05641a
Fixed imports in `asset_processing` example.
greeble-dev May 12, 2025
b4c9426
Redid glTF changes. Now we keep around both the path and the handle -…
greeble-dev May 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions crates/bevy_asset/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,10 +387,7 @@ impl<A: Asset> Assets<A> {
pub fn add(&mut self, asset: impl Into<A>) -> Handle<A> {
let index = self.dense_storage.allocator.reserve();
self.insert_with_index(index, asset.into()).unwrap();
Handle::Strong(
self.handle_provider
.get_handle(index.into(), false, None, None),
)
Handle::Strong(self.handle_provider.get_handle(index.into(), false, None))
}

/// Upgrade an `AssetId` into a strong `Handle` that will prevent asset drop.
Expand All @@ -408,7 +405,7 @@ impl<A: Asset> Assets<A> {
AssetId::Uuid { uuid } => uuid.into(),
};
Some(Handle::Strong(
self.handle_provider.get_handle(index, false, None, None),
self.handle_provider.get_handle(index, false, None),
))
}

Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_asset/src/direct_access_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ pub trait DirectAssetAccessExt {
fn load_asset<'a, A: Asset>(&self, path: impl Into<AssetPath<'a>>) -> Handle<A>;

/// Load an asset with settings, similarly to [`AssetServer::load_with_settings`].
fn load_asset_with_settings<'a, A: Asset, S: Settings>(
fn load_asset_with_settings<'a, A: Asset, S: Settings + serde::Serialize + Default>(
&self,
path: impl Into<AssetPath<'a>>,
settings: impl Fn(&mut S) + Send + Sync + 'static,
settings: impl FnOnce(&mut S) + Send + Sync + 'static,
) -> Handle<A>;
}
impl DirectAssetAccessExt for World {
Expand All @@ -40,10 +40,10 @@ impl DirectAssetAccessExt for World {
///
/// # Panics
/// If `self` doesn't have an [`AssetServer`] resource initialized yet.
fn load_asset_with_settings<'a, A: Asset, S: Settings>(
fn load_asset_with_settings<'a, A: Asset, S: Settings + serde::Serialize + Default>(
&self,
path: impl Into<AssetPath<'a>>,
settings: impl Fn(&mut S) + Send + Sync + 'static,
settings: impl FnOnce(&mut S) + Send + Sync + 'static,
) -> Handle<A> {
self.resource::<AssetServer>()
.load_with_settings(path, settings)
Expand Down
31 changes: 3 additions & 28 deletions crates/bevy_asset/src/handle.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::{
meta::MetaTransform, Asset, AssetId, AssetIndexAllocator, AssetPath, InternalAssetId,
UntypedAssetId,
};
use crate::{Asset, AssetId, AssetIndexAllocator, AssetPath, InternalAssetId, UntypedAssetId};
use alloc::sync::Arc;
use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath};
use core::{
Expand Down Expand Up @@ -44,20 +41,18 @@ impl AssetHandleProvider {
/// [`UntypedHandle`] will match the [`Asset`] [`TypeId`] assigned to this [`AssetHandleProvider`].
pub fn reserve_handle(&self) -> UntypedHandle {
let index = self.allocator.reserve();
UntypedHandle::Strong(self.get_handle(InternalAssetId::Index(index), false, None, None))
UntypedHandle::Strong(self.get_handle(InternalAssetId::Index(index), false, None))
}

pub(crate) fn get_handle(
&self,
id: InternalAssetId,
asset_server_managed: bool,
path: Option<AssetPath<'static>>,
meta_transform: Option<MetaTransform>,
) -> Arc<StrongHandle> {
Arc::new(StrongHandle {
id: id.untyped(self.type_id),
drop_sender: self.drop_sender.clone(),
meta_transform,
path,
asset_server_managed,
})
Expand All @@ -67,15 +62,9 @@ impl AssetHandleProvider {
&self,
asset_server_managed: bool,
path: Option<AssetPath<'static>>,
meta_transform: Option<MetaTransform>,
) -> Arc<StrongHandle> {
let index = self.allocator.reserve();
self.get_handle(
InternalAssetId::Index(index),
asset_server_managed,
path,
meta_transform,
)
self.get_handle(InternalAssetId::Index(index), asset_server_managed, path)
}
}

Expand All @@ -86,10 +75,6 @@ pub struct StrongHandle {
pub(crate) id: UntypedAssetId,
pub(crate) asset_server_managed: bool,
pub(crate) path: Option<AssetPath<'static>>,
/// Modifies asset meta. This is stored on the handle because it is:
/// 1. configuration tied to the lifetime of a specific asset load
/// 2. configuration that must be repeatable when the asset is hot-reloaded
pub(crate) meta_transform: Option<MetaTransform>,
pub(crate) drop_sender: Sender<DropEvent>,
}

Expand Down Expand Up @@ -381,16 +366,6 @@ impl UntypedHandle {
pub fn try_typed<A: Asset>(self) -> Result<Handle<A>, UntypedAssetConversionError> {
Handle::try_from(self)
}

/// The "meta transform" for the strong handle. This will only be [`Some`] if the handle is strong and there is a meta transform
/// associated with it.
#[inline]
pub fn meta_transform(&self) -> Option<&MetaTransform> {
match self {
UntypedHandle::Strong(handle) => handle.meta_transform.as_ref(),
UntypedHandle::Weak(_) => None,
}
}
}

impl PartialEq for UntypedHandle {
Expand Down
8 changes: 3 additions & 5 deletions crates/bevy_asset/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub trait AssetLoader: Send + Sync + 'static {
/// The top level [`Asset`] loaded by this [`AssetLoader`].
type Asset: Asset;
/// The settings type used by this [`AssetLoader`].
type Settings: Settings + Default + Serialize + for<'a> Deserialize<'a>;
type Settings: Settings + Default + Serialize + for<'a> Deserialize<'a> + Clone;
/// The type of [error](`std::error::Error`) which could be encountered by this loader.
type Error: Into<Box<dyn core::error::Error + Send + Sync + 'static>>;
/// Asynchronously loads [`AssetLoader::Asset`] (and any other labeled assets) from the bytes provided by [`Reader`].
Expand Down Expand Up @@ -432,9 +432,7 @@ impl<'a> LoadContext<'a> {
let label = label.into();
let loaded_asset: ErasedLoadedAsset = loaded_asset.into();
let labeled_path = self.asset_path.clone().with_label(label.clone());
let handle = self
.asset_server
.get_or_create_path_handle(labeled_path, None);
let handle = self.asset_server.get_or_create_path_handle(labeled_path);
self.labeled_assets.insert(
label,
LabeledAsset {
Expand Down Expand Up @@ -518,7 +516,7 @@ impl<'a> LoadContext<'a> {
label: impl Into<CowArc<'b, str>>,
) -> Handle<A> {
let path = self.asset_path.clone().with_label(label);
let handle = self.asset_server.get_or_create_path_handle::<A>(path, None);
let handle = self.asset_server.get_or_create_path_handle::<A>(path);
self.dependencies.insert(handle.id().untyped());
handle
}
Expand Down
72 changes: 12 additions & 60 deletions crates/bevy_asset/src/loader_builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
//! [`LoadContext::loader`].

use crate::{
io::Reader,
meta::{meta_transform_settings, AssetMetaDyn, MetaTransform, Settings},
Asset, AssetLoadError, AssetPath, ErasedAssetLoader, ErasedLoadedAsset, Handle, LoadContext,
LoadDirectError, LoadedAsset, LoadedUntypedAsset, UntypedHandle,
io::Reader, Asset, AssetLoadError, AssetPath, ErasedAssetLoader, ErasedLoadedAsset, Handle,
LoadContext, LoadDirectError, LoadedAsset, LoadedUntypedAsset, UntypedHandle,
};
use alloc::{borrow::ToOwned, boxed::Box, sync::Arc};
use core::any::TypeId;
Expand Down Expand Up @@ -117,7 +115,6 @@ impl ReaderRef<'_> {
/// [`LoadTransformAndSave`]: crate::processor::LoadTransformAndSave
pub struct NestedLoader<'ctx, 'builder, T, M> {
load_context: &'builder mut LoadContext<'ctx>,
meta_transform: Option<MetaTransform>,
typing: T,
mode: M,
}
Expand Down Expand Up @@ -168,41 +165,13 @@ impl<'ctx, 'builder> NestedLoader<'ctx, 'builder, StaticTyped, Deferred> {
pub(crate) fn new(load_context: &'builder mut LoadContext<'ctx>) -> Self {
NestedLoader {
load_context,
meta_transform: None,
typing: StaticTyped(()),
mode: Deferred(()),
}
}
}

impl<'ctx, 'builder, T: sealed::Typing, M: sealed::Mode> NestedLoader<'ctx, 'builder, T, M> {
fn with_transform(
mut self,
transform: impl Fn(&mut dyn AssetMetaDyn) + Send + Sync + 'static,
) -> Self {
if let Some(prev_transform) = self.meta_transform {
self.meta_transform = Some(Box::new(move |meta| {
prev_transform(meta);
transform(meta);
}));
} else {
self.meta_transform = Some(Box::new(transform));
}
self
}

/// Configure the settings used to load the asset.
///
/// If the settings type `S` does not match the settings expected by `A`'s asset loader, an error will be printed to the log
/// and the asset load will fail.
#[must_use]
pub fn with_settings<S: Settings>(
self,
settings: impl Fn(&mut S) + Send + Sync + 'static,
) -> Self {
self.with_transform(move |meta| meta_transform_settings(meta, &settings))
}

// convert between `T`s

/// When [`load`]ing, you must pass in the asset type as a type parameter
Expand All @@ -218,7 +187,6 @@ impl<'ctx, 'builder, T: sealed::Typing, M: sealed::Mode> NestedLoader<'ctx, 'bui
pub fn with_static_type(self) -> NestedLoader<'ctx, 'builder, StaticTyped, M> {
NestedLoader {
load_context: self.load_context,
meta_transform: self.meta_transform,
typing: StaticTyped(()),
mode: self.mode,
}
Expand All @@ -235,7 +203,6 @@ impl<'ctx, 'builder, T: sealed::Typing, M: sealed::Mode> NestedLoader<'ctx, 'bui
) -> NestedLoader<'ctx, 'builder, DynamicTyped, M> {
NestedLoader {
load_context: self.load_context,
meta_transform: self.meta_transform,
typing: DynamicTyped { asset_type_id },
mode: self.mode,
}
Expand All @@ -249,7 +216,6 @@ impl<'ctx, 'builder, T: sealed::Typing, M: sealed::Mode> NestedLoader<'ctx, 'bui
pub fn with_unknown_type(self) -> NestedLoader<'ctx, 'builder, UnknownTyped, M> {
NestedLoader {
load_context: self.load_context,
meta_transform: self.meta_transform,
typing: UnknownTyped(()),
mode: self.mode,
}
Expand All @@ -264,7 +230,6 @@ impl<'ctx, 'builder, T: sealed::Typing, M: sealed::Mode> NestedLoader<'ctx, 'bui
pub fn deferred(self) -> NestedLoader<'ctx, 'builder, T, Deferred> {
NestedLoader {
load_context: self.load_context,
meta_transform: self.meta_transform,
typing: self.typing,
mode: Deferred(()),
}
Expand All @@ -281,7 +246,6 @@ impl<'ctx, 'builder, T: sealed::Typing, M: sealed::Mode> NestedLoader<'ctx, 'bui
pub fn immediate<'c>(self) -> NestedLoader<'ctx, 'builder, T, Immediate<'builder, 'c>> {
NestedLoader {
load_context: self.load_context,
meta_transform: self.meta_transform,
typing: self.typing,
mode: Immediate { reader: None },
}
Expand All @@ -305,16 +269,13 @@ impl NestedLoader<'_, '_, StaticTyped, Deferred> {
pub fn load<'c, A: Asset>(self, path: impl Into<AssetPath<'c>>) -> Handle<A> {
let path = path.into().to_owned();
let handle = if self.load_context.should_load_dependencies {
self.load_context.asset_server.load_with_meta_transform(
path,
self.meta_transform,
(),
true,
)
self.load_context
.asset_server
.load_with_meta_transform(path, (), true)
} else {
self.load_context
.asset_server
.get_or_create_path_handle(path, None)
.get_or_create_path_handle(path)
};
self.load_context.dependencies.insert(handle.id().untyped());
handle
Expand All @@ -334,20 +295,11 @@ impl NestedLoader<'_, '_, DynamicTyped, Deferred> {
let handle = if self.load_context.should_load_dependencies {
self.load_context
.asset_server
.load_erased_with_meta_transform(
path,
self.typing.asset_type_id,
self.meta_transform,
(),
)
.load_erased_with_meta_transform(path, self.typing.asset_type_id, ())
} else {
self.load_context
.asset_server
.get_or_create_path_handle_erased(
path,
self.typing.asset_type_id,
self.meta_transform,
)
.get_or_create_path_handle_erased(path, self.typing.asset_type_id)
};
self.load_context.dependencies.insert(handle.id());
handle
Expand All @@ -364,11 +316,11 @@ impl NestedLoader<'_, '_, UnknownTyped, Deferred> {
let handle = if self.load_context.should_load_dependencies {
self.load_context
.asset_server
.load_unknown_type_with_meta_transform(path, self.meta_transform)
.load_unknown_type_with_meta_transform(path)
} else {
self.load_context
.asset_server
.get_or_create_path_handle(path, self.meta_transform)
.get_or_create_path_handle(path)
};
self.load_context.dependencies.insert(handle.id().untyped());
handle
Expand Down Expand Up @@ -428,8 +380,8 @@ impl<'builder, 'reader, T> NestedLoader<'_, '_, T, Immediate<'builder, 'reader>>
(meta, loader, ReaderRef::Boxed(reader))
};

if let Some(meta_transform) = self.meta_transform {
meta_transform(&mut *meta);
if let Some(settings) = path.settings() {
meta.apply_settings(settings.value());
}

let asset = self
Expand Down
Loading