Remove the Component
trait implementation from Handle
(#15796)
# Objective - Closes #15716 - Closes #15718 ## Solution - Replace `Handle<MeshletMesh>` with a new `MeshletMesh3d` component - As expected there were some random things that needed fixing: - A couple tests were storing handles just to prevent them from being dropped I believe, which seems to have been unnecessary in some. - The `SpriteBundle` still had a `Handle<Image>` field. I've removed this. - Tests in `bevy_sprite` incorrectly added a `Handle<Image>` field outside of the `Sprite` component. - A few examples were still inserting `Handle`s, switched those to their corresponding wrappers. - 2 examples that were still querying for `Handle<Image>` were changed to query `Sprite` ## Testing - I've verified that the changed example work now ## Migration Guide `Handle` can no longer be used as a `Component`. All existing Bevy types using this pattern have been wrapped in their own semantically meaningful type. You should do the same for any custom `Handle` components your project needs. The `Handle<MeshletMesh>` component is now `MeshletMesh3d`. The `WithMeshletMesh` type alias has been removed. Use `With<MeshletMesh3d>` instead.
This commit is contained in:
parent
a6be9b4ccd
commit
3da0ef048e
@ -58,7 +58,7 @@ pub(crate) fn trigger_animation_event(
|
|||||||
/// let mut player = AnimationPlayer::default();
|
/// let mut player = AnimationPlayer::default();
|
||||||
/// player.play(animation_index).repeat();
|
/// player.play(animation_index).repeat();
|
||||||
///
|
///
|
||||||
/// commands.spawn((graphs.add(graph), player));
|
/// commands.spawn((AnimationGraphHandle(graphs.add(graph)), player));
|
||||||
/// }
|
/// }
|
||||||
/// #
|
/// #
|
||||||
/// # bevy_ecs::system::assert_is_system(setup_animation);
|
/// # bevy_ecs::system::assert_is_system(setup_animation);
|
||||||
|
@ -3,7 +3,6 @@ use crate::{
|
|||||||
UntypedAssetId,
|
UntypedAssetId,
|
||||||
};
|
};
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use bevy_ecs::prelude::*;
|
|
||||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath};
|
use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath};
|
||||||
use core::{
|
use core::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
@ -122,8 +121,8 @@ impl core::fmt::Debug for StrongHandle {
|
|||||||
/// of the [`Handle`] are dropped.
|
/// of the [`Handle`] are dropped.
|
||||||
///
|
///
|
||||||
/// [`Handle::Strong`] also provides access to useful [`Asset`] metadata, such as the [`AssetPath`] (if it exists).
|
/// [`Handle::Strong`] also provides access to useful [`Asset`] metadata, such as the [`AssetPath`] (if it exists).
|
||||||
#[derive(Component, Reflect)]
|
#[derive(Reflect)]
|
||||||
#[reflect(Default, Component, Debug, Hash, PartialEq)]
|
#[reflect(Default, Debug, Hash, PartialEq)]
|
||||||
pub enum Handle<A: Asset> {
|
pub enum Handle<A: Asset> {
|
||||||
/// A "strong" reference to a live (or loading) [`Asset`]. If a [`Handle`] is [`Handle::Strong`], the [`Asset`] will be kept
|
/// A "strong" reference to a live (or loading) [`Asset`]. If a [`Handle`] is [`Handle::Strong`], the [`Asset`] will be kept
|
||||||
/// alive until the [`Handle`] is dropped. Strong handles also provide access to additional asset metadata.
|
/// alive until the [`Handle`] is dropped. Strong handles also provide access to additional asset metadata.
|
||||||
|
@ -900,7 +900,6 @@ mod tests {
|
|||||||
let asset_server = app.world().resource::<AssetServer>().clone();
|
let asset_server = app.world().resource::<AssetServer>().clone();
|
||||||
let handle: Handle<CoolText> = asset_server.load(a_path);
|
let handle: Handle<CoolText> = asset_server.load(a_path);
|
||||||
let a_id = handle.id();
|
let a_id = handle.id();
|
||||||
let entity = app.world_mut().spawn(handle).id();
|
|
||||||
app.update();
|
app.update();
|
||||||
{
|
{
|
||||||
let a_text = get::<CoolText>(app.world(), a_id);
|
let a_text = get::<CoolText>(app.world(), a_id);
|
||||||
@ -1090,7 +1089,8 @@ mod tests {
|
|||||||
a.text = "Changed".to_string();
|
a.text = "Changed".to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.world_mut().despawn(entity);
|
drop(handle);
|
||||||
|
|
||||||
app.update();
|
app.update();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.world().resource::<Assets<CoolText>>().len(),
|
app.world().resource::<Assets<CoolText>>().len(),
|
||||||
@ -1225,7 +1225,6 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.world_mut().spawn(handle);
|
|
||||||
gate_opener.open(a_path);
|
gate_opener.open(a_path);
|
||||||
gate_opener.open(b_path);
|
gate_opener.open(b_path);
|
||||||
gate_opener.open(c_path);
|
gate_opener.open(c_path);
|
||||||
@ -1345,7 +1344,6 @@ mod tests {
|
|||||||
let asset_server = app.world().resource::<AssetServer>().clone();
|
let asset_server = app.world().resource::<AssetServer>().clone();
|
||||||
let handle: Handle<CoolText> = asset_server.load(a_path);
|
let handle: Handle<CoolText> = asset_server.load(a_path);
|
||||||
let a_id = handle.id();
|
let a_id = handle.id();
|
||||||
app.world_mut().spawn(handle);
|
|
||||||
|
|
||||||
gate_opener.open(a_path);
|
gate_opener.open(a_path);
|
||||||
run_app_until(&mut app, |world| {
|
run_app_until(&mut app, |world| {
|
||||||
@ -1746,8 +1744,6 @@ mod tests {
|
|||||||
let a_handle: Handle<CoolText> = asset_server.load(a_path);
|
let a_handle: Handle<CoolText> = asset_server.load(a_path);
|
||||||
let a_id = a_handle.id();
|
let a_id = a_handle.id();
|
||||||
|
|
||||||
app.world_mut().spawn(a_handle);
|
|
||||||
|
|
||||||
run_app_until(&mut app, |world| {
|
run_app_until(&mut app, |world| {
|
||||||
let tracker = world.resource::<ErrorTracker>();
|
let tracker = world.resource::<ErrorTracker>();
|
||||||
match tracker.finished_asset {
|
match tracker.finished_asset {
|
||||||
|
@ -2229,7 +2229,7 @@ mod test {
|
|||||||
AssetApp, AssetPlugin, AssetServer, Assets, Handle, LoadState,
|
AssetApp, AssetPlugin, AssetServer, Assets, Handle, LoadState,
|
||||||
};
|
};
|
||||||
use bevy_core::TaskPoolPlugin;
|
use bevy_core::TaskPoolPlugin;
|
||||||
use bevy_ecs::world::World;
|
use bevy_ecs::{system::Resource, world::World};
|
||||||
use bevy_log::LogPlugin;
|
use bevy_log::LogPlugin;
|
||||||
use bevy_render::mesh::{skinning::SkinnedMeshInverseBindposes, MeshPlugin};
|
use bevy_render::mesh::{skinning::SkinnedMeshInverseBindposes, MeshPlugin};
|
||||||
use bevy_scene::ScenePlugin;
|
use bevy_scene::ScenePlugin;
|
||||||
@ -2270,6 +2270,10 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_gltf_into_app(gltf_path: &str, gltf: &str) -> App {
|
fn load_gltf_into_app(gltf_path: &str, gltf: &str) -> App {
|
||||||
|
#[expect(unused)]
|
||||||
|
#[derive(Resource)]
|
||||||
|
struct GltfHandle(Handle<Gltf>);
|
||||||
|
|
||||||
let dir = Dir::default();
|
let dir = Dir::default();
|
||||||
dir.insert_asset_text(Path::new(gltf_path), gltf);
|
dir.insert_asset_text(Path::new(gltf_path), gltf);
|
||||||
let mut app = test_app(dir);
|
let mut app = test_app(dir);
|
||||||
@ -2277,7 +2281,7 @@ mod test {
|
|||||||
let asset_server = app.world().resource::<AssetServer>().clone();
|
let asset_server = app.world().resource::<AssetServer>().clone();
|
||||||
let handle: Handle<Gltf> = asset_server.load(gltf_path.to_string());
|
let handle: Handle<Gltf> = asset_server.load(gltf_path.to_string());
|
||||||
let handle_id = handle.id();
|
let handle_id = handle.id();
|
||||||
app.world_mut().spawn(handle.clone());
|
app.insert_resource(GltfHandle(handle));
|
||||||
app.update();
|
app.update();
|
||||||
run_app_until(&mut app, |_world| {
|
run_app_until(&mut app, |_world| {
|
||||||
let load_state = asset_server.get_load_state(handle_id).unwrap();
|
let load_state = asset_server.get_load_state(handle_id).unwrap();
|
||||||
@ -2509,7 +2513,6 @@ mod test {
|
|||||||
let asset_server = app.world().resource::<AssetServer>().clone();
|
let asset_server = app.world().resource::<AssetServer>().clone();
|
||||||
let handle: Handle<Gltf> = asset_server.load(gltf_path);
|
let handle: Handle<Gltf> = asset_server.load(gltf_path);
|
||||||
let handle_id = handle.id();
|
let handle_id = handle.id();
|
||||||
app.world_mut().spawn(handle.clone());
|
|
||||||
app.update();
|
app.update();
|
||||||
run_app_until(&mut app, |_world| {
|
run_app_until(&mut app, |_world| {
|
||||||
let load_state = asset_server.get_load_state(handle_id).unwrap();
|
let load_state = asset_server.get_load_state(handle_id).unwrap();
|
||||||
@ -2552,7 +2555,6 @@ mod test {
|
|||||||
let asset_server = app.world().resource::<AssetServer>().clone();
|
let asset_server = app.world().resource::<AssetServer>().clone();
|
||||||
let handle: Handle<Gltf> = asset_server.load(gltf_path);
|
let handle: Handle<Gltf> = asset_server.load(gltf_path);
|
||||||
let handle_id = handle.id();
|
let handle_id = handle.id();
|
||||||
app.world_mut().spawn(handle.clone());
|
|
||||||
app.update();
|
app.update();
|
||||||
run_app_until(&mut app, |_world| {
|
run_app_until(&mut app, |_world| {
|
||||||
let load_state = asset_server.get_load_state(handle_id).unwrap();
|
let load_state = asset_server.get_load_state(handle_id).unwrap();
|
||||||
|
@ -36,7 +36,7 @@ pub const MESHLET_MESH_ASSET_VERSION: u64 = 1;
|
|||||||
/// * Materials must use the [`crate::Material::meshlet_mesh_fragment_shader`] method (and similar variants for prepass/deferred shaders)
|
/// * Materials must use the [`crate::Material::meshlet_mesh_fragment_shader`] method (and similar variants for prepass/deferred shaders)
|
||||||
/// which requires certain shader patterns that differ from the regular material shaders.
|
/// which requires certain shader patterns that differ from the regular material shaders.
|
||||||
///
|
///
|
||||||
/// See also [`super::MaterialMeshletMeshBundle`] and [`super::MeshletPlugin`].
|
/// See also [`super::MeshletMesh3d`] and [`super::MeshletPlugin`].
|
||||||
#[derive(Asset, TypePath, Clone)]
|
#[derive(Asset, TypePath, Clone)]
|
||||||
pub struct MeshletMesh {
|
pub struct MeshletMesh {
|
||||||
/// Quantized and bitstream-packed vertex positions for meshlet vertices.
|
/// Quantized and bitstream-packed vertex positions for meshlet vertices.
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use super::{meshlet_mesh_manager::MeshletMeshManager, MeshletMesh};
|
use super::{meshlet_mesh_manager::MeshletMeshManager, MeshletMesh, MeshletMesh3d};
|
||||||
use crate::{
|
use crate::{
|
||||||
Material, MeshFlags, MeshTransforms, MeshUniform, NotShadowCaster, NotShadowReceiver,
|
Material, MeshFlags, MeshTransforms, MeshUniform, NotShadowCaster, NotShadowReceiver,
|
||||||
PreviousGlobalTransform, RenderMaterialInstances,
|
PreviousGlobalTransform, RenderMaterialInstances,
|
||||||
};
|
};
|
||||||
use bevy_asset::{AssetEvent, AssetServer, Assets, Handle, UntypedAssetId};
|
use bevy_asset::{AssetEvent, AssetServer, Assets, UntypedAssetId};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
entity::{Entities, Entity, EntityHashMap},
|
entity::{Entities, Entity, EntityHashMap},
|
||||||
event::EventReader,
|
event::EventReader,
|
||||||
@ -168,7 +168,7 @@ pub fn extract_meshlet_mesh_entities(
|
|||||||
SystemState<(
|
SystemState<(
|
||||||
Query<(
|
Query<(
|
||||||
Entity,
|
Entity,
|
||||||
&Handle<MeshletMesh>,
|
&MeshletMesh3d,
|
||||||
&GlobalTransform,
|
&GlobalTransform,
|
||||||
Option<&PreviousGlobalTransform>,
|
Option<&PreviousGlobalTransform>,
|
||||||
Option<&RenderLayers>,
|
Option<&RenderLayers>,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#![expect(deprecated)]
|
||||||
//! Render high-poly 3d meshes using an efficient GPU-driven method. See [`MeshletPlugin`] and [`MeshletMesh`] for details.
|
//! Render high-poly 3d meshes using an efficient GPU-driven method. See [`MeshletPlugin`] and [`MeshletMesh`] for details.
|
||||||
|
|
||||||
mod asset;
|
mod asset;
|
||||||
@ -57,19 +58,23 @@ use self::{
|
|||||||
};
|
};
|
||||||
use crate::{graph::NodePbr, Material, MeshMaterial3d};
|
use crate::{graph::NodePbr, Material, MeshMaterial3d};
|
||||||
use bevy_app::{App, Plugin, PostUpdate};
|
use bevy_app::{App, Plugin, PostUpdate};
|
||||||
use bevy_asset::{load_internal_asset, AssetApp, Handle};
|
use bevy_asset::{load_internal_asset, AssetApp, AssetId, Handle};
|
||||||
use bevy_core_pipeline::{
|
use bevy_core_pipeline::{
|
||||||
core_3d::graph::{Core3d, Node3d},
|
core_3d::graph::{Core3d, Node3d},
|
||||||
prepass::{DeferredPrepass, MotionVectorPrepass, NormalPrepass},
|
prepass::{DeferredPrepass, MotionVectorPrepass, NormalPrepass},
|
||||||
};
|
};
|
||||||
|
use bevy_derive::{Deref, DerefMut};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
bundle::Bundle,
|
bundle::Bundle,
|
||||||
|
component::Component,
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
prelude::With,
|
prelude::With,
|
||||||
query::Has,
|
query::Has,
|
||||||
|
reflect::ReflectComponent,
|
||||||
schedule::IntoSystemConfigs,
|
schedule::IntoSystemConfigs,
|
||||||
system::{Commands, Query},
|
system::{Commands, Query},
|
||||||
};
|
};
|
||||||
|
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
render_graph::{RenderGraphApp, ViewNodeRunner},
|
render_graph::{RenderGraphApp, ViewNodeRunner},
|
||||||
render_resource::Shader,
|
render_resource::Shader,
|
||||||
@ -83,6 +88,7 @@ use bevy_render::{
|
|||||||
};
|
};
|
||||||
use bevy_transform::components::{GlobalTransform, Transform};
|
use bevy_transform::components::{GlobalTransform, Transform};
|
||||||
use bevy_utils::tracing::error;
|
use bevy_utils::tracing::error;
|
||||||
|
use derive_more::From;
|
||||||
|
|
||||||
const MESHLET_BINDINGS_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(1325134235233421);
|
const MESHLET_BINDINGS_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(1325134235233421);
|
||||||
const MESHLET_MESH_MATERIAL_SHADER_HANDLE: Handle<Shader> =
|
const MESHLET_MESH_MATERIAL_SHADER_HANDLE: Handle<Shader> =
|
||||||
@ -206,7 +212,7 @@ impl Plugin for MeshletPlugin {
|
|||||||
.register_asset_loader(MeshletMeshLoader)
|
.register_asset_loader(MeshletMeshLoader)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
check_visibility::<WithMeshletMesh>.in_set(VisibilitySystems::CheckVisibility),
|
check_visibility::<With<MeshletMesh3d>>.in_set(VisibilitySystems::CheckVisibility),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,10 +290,31 @@ impl Plugin for MeshletPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq, From)]
|
||||||
|
#[reflect(Component, Default)]
|
||||||
|
#[require(Transform, Visibility)]
|
||||||
|
pub struct MeshletMesh3d(pub Handle<MeshletMesh>);
|
||||||
|
|
||||||
|
impl From<MeshletMesh3d> for AssetId<MeshletMesh> {
|
||||||
|
fn from(mesh: MeshletMesh3d) -> Self {
|
||||||
|
mesh.id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&MeshletMesh3d> for AssetId<MeshletMesh> {
|
||||||
|
fn from(mesh: &MeshletMesh3d) -> Self {
|
||||||
|
mesh.id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A component bundle for entities with a [`MeshletMesh`] and a [`Material`].
|
/// A component bundle for entities with a [`MeshletMesh`] and a [`Material`].
|
||||||
#[derive(Bundle, Clone)]
|
#[derive(Bundle, Clone)]
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.15.0",
|
||||||
|
note = "Use the `MeshletMesh3d` and `MeshMaterial3d` components instead. Inserting them will now also insert the other components required by them automatically."
|
||||||
|
)]
|
||||||
pub struct MaterialMeshletMeshBundle<M: Material> {
|
pub struct MaterialMeshletMeshBundle<M: Material> {
|
||||||
pub meshlet_mesh: Handle<MeshletMesh>,
|
pub meshlet_mesh: MeshletMesh3d,
|
||||||
pub material: MeshMaterial3d<M>,
|
pub material: MeshMaterial3d<M>,
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
pub global_transform: GlobalTransform,
|
pub global_transform: GlobalTransform,
|
||||||
@ -313,10 +340,6 @@ impl<M: Material> Default for MaterialMeshletMeshBundle<M> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A convenient alias for `With<Handle<MeshletMesh>>`, for use with
|
|
||||||
/// [`bevy_render::view::VisibleEntities`].
|
|
||||||
pub type WithMeshletMesh = With<Handle<MeshletMesh>>;
|
|
||||||
|
|
||||||
fn configure_meshlet_views(
|
fn configure_meshlet_views(
|
||||||
mut views_3d: Query<(
|
mut views_3d: Query<(
|
||||||
Entity,
|
Entity,
|
||||||
|
@ -35,7 +35,7 @@ use bevy_utils::tracing::error;
|
|||||||
#[cfg(feature = "meshlet")]
|
#[cfg(feature = "meshlet")]
|
||||||
use crate::meshlet::{
|
use crate::meshlet::{
|
||||||
prepare_material_meshlet_meshes_prepass, queue_material_meshlet_meshes, InstanceManager,
|
prepare_material_meshlet_meshes_prepass, queue_material_meshlet_meshes, InstanceManager,
|
||||||
MeshletMesh,
|
MeshletMesh3d,
|
||||||
};
|
};
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ pub struct PreviousGlobalTransform(pub Affine3A);
|
|||||||
#[cfg(not(feature = "meshlet"))]
|
#[cfg(not(feature = "meshlet"))]
|
||||||
type PreviousMeshFilter = With<Mesh3d>;
|
type PreviousMeshFilter = With<Mesh3d>;
|
||||||
#[cfg(feature = "meshlet")]
|
#[cfg(feature = "meshlet")]
|
||||||
type PreviousMeshFilter = Or<(With<Mesh3d>, With<Handle<MeshletMesh>>)>;
|
type PreviousMeshFilter = Or<(With<Mesh3d>, With<MeshletMesh3d>)>;
|
||||||
|
|
||||||
pub fn update_mesh_previous_global_transforms(
|
pub fn update_mesh_previous_global_transforms(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
#![expect(deprecated)]
|
#![expect(deprecated)]
|
||||||
use crate::Sprite;
|
use crate::Sprite;
|
||||||
use bevy_asset::Handle;
|
|
||||||
use bevy_ecs::bundle::Bundle;
|
use bevy_ecs::bundle::Bundle;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
sync_world::SyncToRenderWorld,
|
sync_world::SyncToRenderWorld,
|
||||||
texture::Image,
|
|
||||||
view::{InheritedVisibility, ViewVisibility, Visibility},
|
view::{InheritedVisibility, ViewVisibility, Visibility},
|
||||||
};
|
};
|
||||||
use bevy_transform::components::{GlobalTransform, Transform};
|
use bevy_transform::components::{GlobalTransform, Transform};
|
||||||
@ -28,8 +26,6 @@ pub struct SpriteBundle {
|
|||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
/// The absolute transform of the sprite. This should generally not be written to directly.
|
/// The absolute transform of the sprite. This should generally not be written to directly.
|
||||||
pub global_transform: GlobalTransform,
|
pub global_transform: GlobalTransform,
|
||||||
/// A reference-counted handle to the image asset to be drawn.
|
|
||||||
pub texture: Handle<Image>,
|
|
||||||
/// User indication of whether an entity is visible
|
/// User indication of whether an entity is visible
|
||||||
pub visibility: Visibility,
|
pub visibility: Visibility,
|
||||||
/// Inherited visibility of an entity.
|
/// Inherited visibility of an entity.
|
||||||
|
@ -299,13 +299,11 @@ mod test {
|
|||||||
// Add entities
|
// Add entities
|
||||||
let entity = app
|
let entity = app
|
||||||
.world_mut()
|
.world_mut()
|
||||||
.spawn((
|
.spawn(Sprite {
|
||||||
Sprite {
|
custom_size: Some(Vec2::ZERO),
|
||||||
custom_size: Some(Vec2::ZERO),
|
image: image_handle,
|
||||||
..default()
|
..default()
|
||||||
},
|
})
|
||||||
image_handle,
|
|
||||||
))
|
|
||||||
.id();
|
.id();
|
||||||
|
|
||||||
// Create initial AABB
|
// Create initial AABB
|
||||||
@ -364,14 +362,12 @@ mod test {
|
|||||||
// Add entities
|
// Add entities
|
||||||
let entity = app
|
let entity = app
|
||||||
.world_mut()
|
.world_mut()
|
||||||
.spawn((
|
.spawn(Sprite {
|
||||||
Sprite {
|
rect: Some(Rect::new(0., 0., 0.5, 1.)),
|
||||||
rect: Some(Rect::new(0., 0., 0.5, 1.)),
|
anchor: Anchor::TopRight,
|
||||||
anchor: Anchor::TopRight,
|
image: image_handle,
|
||||||
..default()
|
..default()
|
||||||
},
|
})
|
||||||
image_handle,
|
|
||||||
))
|
|
||||||
.id();
|
.id();
|
||||||
|
|
||||||
// Create AABB
|
// Create AABB
|
||||||
|
@ -98,7 +98,7 @@ fn spawn_car_paint_sphere(
|
|||||||
commands
|
commands
|
||||||
.spawn((
|
.spawn((
|
||||||
Mesh3d(sphere.clone()),
|
Mesh3d(sphere.clone()),
|
||||||
materials.add(StandardMaterial {
|
MeshMaterial3d(materials.add(StandardMaterial {
|
||||||
clearcoat: 1.0,
|
clearcoat: 1.0,
|
||||||
clearcoat_perceptual_roughness: 0.1,
|
clearcoat_perceptual_roughness: 0.1,
|
||||||
normal_map_texture: Some(asset_server.load_with_settings(
|
normal_map_texture: Some(asset_server.load_with_settings(
|
||||||
@ -109,7 +109,7 @@ fn spawn_car_paint_sphere(
|
|||||||
perceptual_roughness: 0.5,
|
perceptual_roughness: 0.5,
|
||||||
base_color: BLUE.into(),
|
base_color: BLUE.into(),
|
||||||
..default()
|
..default()
|
||||||
}),
|
})),
|
||||||
Transform::from_xyz(-1.0, 1.0, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)),
|
Transform::from_xyz(-1.0, 1.0, 0.0).with_scale(Vec3::splat(SPHERE_SCALE)),
|
||||||
))
|
))
|
||||||
.insert(ExampleSphere);
|
.insert(ExampleSphere);
|
||||||
|
@ -7,7 +7,7 @@ mod camera_controller;
|
|||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
pbr::{
|
pbr::{
|
||||||
experimental::meshlet::{MaterialMeshletMeshBundle, MeshletPlugin},
|
experimental::meshlet::{MeshletMesh3d, MeshletPlugin},
|
||||||
CascadeShadowConfigBuilder, DirectionalLightShadowMap,
|
CascadeShadowConfigBuilder, DirectionalLightShadowMap,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
@ -84,9 +84,9 @@ fn setup(
|
|||||||
let debug_material = debug_materials.add(MeshletDebugMaterial::default());
|
let debug_material = debug_materials.add(MeshletDebugMaterial::default());
|
||||||
|
|
||||||
for x in -2..=2 {
|
for x in -2..=2 {
|
||||||
commands.spawn(MaterialMeshletMeshBundle {
|
commands.spawn((
|
||||||
meshlet_mesh: meshlet_mesh_handle.clone(),
|
MeshletMesh3d(meshlet_mesh_handle.clone()),
|
||||||
material: MeshMaterial3d(standard_materials.add(StandardMaterial {
|
MeshMaterial3d(standard_materials.add(StandardMaterial {
|
||||||
base_color: match x {
|
base_color: match x {
|
||||||
-2 => Srgba::hex("#dc2626").unwrap().into(),
|
-2 => Srgba::hex("#dc2626").unwrap().into(),
|
||||||
-1 => Srgba::hex("#ea580c").unwrap().into(),
|
-1 => Srgba::hex("#ea580c").unwrap().into(),
|
||||||
@ -98,22 +98,20 @@ fn setup(
|
|||||||
perceptual_roughness: (x + 2) as f32 / 4.0,
|
perceptual_roughness: (x + 2) as f32 / 4.0,
|
||||||
..default()
|
..default()
|
||||||
})),
|
})),
|
||||||
transform: Transform::default()
|
Transform::default()
|
||||||
.with_scale(Vec3::splat(0.2))
|
.with_scale(Vec3::splat(0.2))
|
||||||
.with_translation(Vec3::new(x as f32 / 2.0, 0.0, -0.3)),
|
.with_translation(Vec3::new(x as f32 / 2.0, 0.0, -0.3)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
for x in -2..=2 {
|
for x in -2..=2 {
|
||||||
commands.spawn(MaterialMeshletMeshBundle {
|
commands.spawn((
|
||||||
meshlet_mesh: meshlet_mesh_handle.clone(),
|
MeshletMesh3d(meshlet_mesh_handle.clone()),
|
||||||
material: debug_material.clone().into(),
|
MeshMaterial3d(debug_material.clone()),
|
||||||
transform: Transform::default()
|
Transform::default()
|
||||||
.with_scale(Vec3::splat(0.2))
|
.with_scale(Vec3::splat(0.2))
|
||||||
.with_rotation(Quat::from_rotation_y(PI))
|
.with_rotation(Quat::from_rotation_y(PI))
|
||||||
.with_translation(Vec3::new(x as f32 / 2.0, 0.0, 0.3)),
|
.with_translation(Vec3::new(x as f32 / 2.0, 0.0, 0.3)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
|
@ -43,7 +43,7 @@ fn setup(
|
|||||||
Transform::from_translation(vec3(-6., 2., 0.)),
|
Transform::from_translation(vec3(-6., 2., 0.)),
|
||||||
animation_target_name,
|
animation_target_name,
|
||||||
animation_player,
|
animation_player,
|
||||||
animation_graph,
|
AnimationGraphHandle(animation_graph),
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
|
|
||||||
|
@ -105,22 +105,20 @@ fn spawn_text(mut commands: Commands) {
|
|||||||
},
|
},
|
||||||
))
|
))
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
|
parent.spawn(Text::new("Space: swap the right sprite's image handle"));
|
||||||
parent.spawn(Text::new(
|
parent.spawn(Text::new(
|
||||||
"Space: swap image texture paths by mutating a Handle<Image>",
|
"Return: modify the image Asset of the left sprite, affecting all uses of it",
|
||||||
));
|
|
||||||
parent.spawn(Text::new(
|
|
||||||
"Return: mutate the image Asset itself, changing all copies of it",
|
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alter_handle(
|
fn alter_handle(
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut right_bird: Query<(&mut Bird, &mut Handle<Image>), Without<Left>>,
|
mut right_bird: Query<(&mut Bird, &mut Sprite), Without<Left>>,
|
||||||
) {
|
) {
|
||||||
// Image handles, like other parts of the ECS, can be queried as mutable and modified at
|
// Image handles, like other parts of the ECS, can be queried as mutable and modified at
|
||||||
// runtime. We only spawned one bird without the `Left` marker component.
|
// runtime. We only spawned one bird without the `Left` marker component.
|
||||||
let Ok((mut bird, mut handle)) = right_bird.get_single_mut() else {
|
let Ok((mut bird, mut sprite)) = right_bird.get_single_mut() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -130,18 +128,18 @@ fn alter_handle(
|
|||||||
// Modify the handle associated with the Bird on the right side. Note that we will only
|
// Modify the handle associated with the Bird on the right side. Note that we will only
|
||||||
// have to load the same path from storage media once: repeated attempts will re-use the
|
// have to load the same path from storage media once: repeated attempts will re-use the
|
||||||
// asset.
|
// asset.
|
||||||
*handle = asset_server.load(bird.get_texture_path());
|
sprite.image = asset_server.load(bird.get_texture_path());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alter_asset(mut images: ResMut<Assets<Image>>, left_bird: Query<&Handle<Image>, With<Left>>) {
|
fn alter_asset(mut images: ResMut<Assets<Image>>, left_bird: Query<&Sprite, With<Left>>) {
|
||||||
// It's convenient to retrieve the asset handle stored with the bird on the left. However,
|
// It's convenient to retrieve the asset handle stored with the bird on the left. However,
|
||||||
// we could just as easily have retained this in a resource or a dedicated component.
|
// we could just as easily have retained this in a resource or a dedicated component.
|
||||||
let Ok(handle) = left_bird.get_single() else {
|
let Ok(sprite) = left_bird.get_single() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Obtain a mutable reference to the Image asset.
|
// Obtain a mutable reference to the Image asset.
|
||||||
let Some(image) = images.get_mut(handle) else {
|
let Some(image) = images.get_mut(&sprite.image) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,12 +84,12 @@ fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Switch texture to display every frame to show the one that was written to most recently.
|
// Switch texture to display every frame to show the one that was written to most recently.
|
||||||
fn switch_textures(images: Res<GameOfLifeImages>, mut displayed: Query<&mut Handle<Image>>) {
|
fn switch_textures(images: Res<GameOfLifeImages>, mut displayed: Query<&mut Sprite>) {
|
||||||
let mut displayed = displayed.single_mut();
|
let mut sprite = displayed.single_mut();
|
||||||
if *displayed == images.texture_a {
|
if sprite.image == images.texture_a {
|
||||||
*displayed = images.texture_b.clone_weak();
|
sprite.image = images.texture_b.clone_weak();
|
||||||
} else {
|
} else {
|
||||||
*displayed = images.texture_a.clone_weak();
|
sprite.image = images.texture_a.clone_weak();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ fn main() {
|
|||||||
|
|
||||||
fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
|
fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
meshes.add(Cuboid::new(0.5, 0.5, 0.5)),
|
Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
|
||||||
SpatialBundle::INHERITED_IDENTITY,
|
SpatialBundle::INHERITED_IDENTITY,
|
||||||
InstanceMaterialData(
|
InstanceMaterialData(
|
||||||
(1..=10)
|
(1..=10)
|
||||||
|
@ -79,7 +79,7 @@ fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
|
|||||||
// with our specialized pipeline
|
// with our specialized pipeline
|
||||||
CustomRenderedEntity,
|
CustomRenderedEntity,
|
||||||
// We need to add the mesh handle to the entity
|
// We need to add the mesh handle to the entity
|
||||||
meshes.add(mesh.clone()),
|
Mesh3d(meshes.add(mesh.clone())),
|
||||||
// This bundle's components are needed for something to be rendered
|
// This bundle's components are needed for something to be rendered
|
||||||
SpatialBundle {
|
SpatialBundle {
|
||||||
transform: Transform::from_xyz(x, y, 0.0),
|
transform: Transform::from_xyz(x, y, 0.0),
|
||||||
|
Loading…
Reference in New Issue
Block a user