mirror of
https://github.com/bevyengine/bevy
synced 2024-12-18 17:13:10 +00:00
93fc2d12cf
# Objective The type `AssetLoadError` has `PartialEq` and `Eq` impls, which is problematic due to the fact that the `AssetLoaderError` and `AddAsyncError` variants lie in their impls: they will return `true` for any `Box<dyn Error>` with the same `TypeId`, even if the actual value is different. This can lead to subtle bugs if a user relies on the equality comparison to ensure that two values are equal. The same is true for `DependencyLoadState`, `RecursiveDependencyLoadState`. More generally, it is an anti-pattern for large error types involving dynamic dispatch, such as `AssetLoadError`, to have equality comparisons. Directly comparing two errors for equality is usually not desired -- if some logic needs to branch based on the value of an error, it is usually more correct to check for specific variants and inspect their fields. As far as I can tell, the only reason these errors have equality comparisons is because the `LoadState` enum wraps `AssetLoadError` for its `Failed` variant. This equality comparison is only used to check for `== LoadState::Loaded`, which we can easily replace with an `is_loaded` method. ## Solution Remove the `{Partial}Eq` impls from `LoadState`, which also allows us to remove it from the error types. ## Migration Guide The types `bevy_asset::AssetLoadError` and `bevy_asset::LoadState` no longer support equality comparisons. If you need to check for an asset's load state, consider checking for a specific variant using `LoadState::is_loaded` or the `matches!` macro. Similarly, consider using the `matches!` macro to check for specific variants of the `AssetLoadError` type if you need to inspect the value of an asset load error in your code. `DependencyLoadState` and `RecursiveDependencyLoadState` are not released yet, so no migration needed, --------- Co-authored-by: Joseph <21144246+JoJoJet@users.noreply.github.com>
97 lines
2.7 KiB
Rust
97 lines
2.7 KiB
Rust
//! This example illustrates how to create a texture for use with a `texture_2d_array<f32>` shader
|
|
//! uniform variable.
|
|
|
|
use bevy::{
|
|
prelude::*,
|
|
reflect::TypePath,
|
|
render::render_resource::{AsBindGroup, ShaderRef},
|
|
};
|
|
|
|
/// This example uses a shader source file from the assets subdirectory
|
|
const SHADER_ASSET_PATH: &str = "shaders/array_texture.wgsl";
|
|
|
|
fn main() {
|
|
App::new()
|
|
.add_plugins((
|
|
DefaultPlugins,
|
|
MaterialPlugin::<ArrayTextureMaterial>::default(),
|
|
))
|
|
.add_systems(Startup, setup)
|
|
.add_systems(Update, create_array_texture)
|
|
.run();
|
|
}
|
|
|
|
#[derive(Resource)]
|
|
struct LoadingTexture {
|
|
is_loaded: bool,
|
|
handle: Handle<Image>,
|
|
}
|
|
|
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|
// Start loading the texture.
|
|
commands.insert_resource(LoadingTexture {
|
|
is_loaded: false,
|
|
handle: asset_server.load("textures/array_texture.png"),
|
|
});
|
|
|
|
// light
|
|
commands.spawn((
|
|
DirectionalLight::default(),
|
|
Transform::from_xyz(3.0, 2.0, 1.0).looking_at(Vec3::ZERO, Vec3::Y),
|
|
));
|
|
|
|
// camera
|
|
commands.spawn((
|
|
Camera3d::default(),
|
|
Transform::from_xyz(5.0, 5.0, 5.0).looking_at(Vec3::new(1.5, 0.0, 0.0), Vec3::Y),
|
|
));
|
|
}
|
|
|
|
fn create_array_texture(
|
|
mut commands: Commands,
|
|
asset_server: Res<AssetServer>,
|
|
mut loading_texture: ResMut<LoadingTexture>,
|
|
mut images: ResMut<Assets<Image>>,
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
mut materials: ResMut<Assets<ArrayTextureMaterial>>,
|
|
) {
|
|
if loading_texture.is_loaded
|
|
|| !asset_server
|
|
.load_state(loading_texture.handle.id())
|
|
.is_loaded()
|
|
{
|
|
return;
|
|
}
|
|
loading_texture.is_loaded = true;
|
|
let image = images.get_mut(&loading_texture.handle).unwrap();
|
|
|
|
// Create a new array texture asset from the loaded texture.
|
|
let array_layers = 4;
|
|
image.reinterpret_stacked_2d_as_array(array_layers);
|
|
|
|
// Spawn some cubes using the array texture
|
|
let mesh_handle = meshes.add(Cuboid::default());
|
|
let material_handle = materials.add(ArrayTextureMaterial {
|
|
array_texture: loading_texture.handle.clone(),
|
|
});
|
|
for x in -5..=5 {
|
|
commands.spawn((
|
|
Mesh3d(mesh_handle.clone()),
|
|
MeshMaterial3d(material_handle.clone()),
|
|
Transform::from_xyz(x as f32 + 0.5, 0.0, 0.0),
|
|
));
|
|
}
|
|
}
|
|
|
|
#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
|
|
struct ArrayTextureMaterial {
|
|
#[texture(0, dimension = "2d_array")]
|
|
#[sampler(1)]
|
|
array_texture: Handle<Image>,
|
|
}
|
|
|
|
impl Material for ArrayTextureMaterial {
|
|
fn fragment_shader() -> ShaderRef {
|
|
SHADER_ASSET_PATH.into()
|
|
}
|
|
}
|