 b6a647cc01
			
		
	
	
		b6a647cc01
		
	
	
	
	
		
			
			Adds a `default()` shorthand for `Default::default()` ... because life is too short to constantly type `Default::default()`.
```rust
use bevy::prelude::*;
#[derive(Default)]
struct Foo {
  bar: usize,
  baz: usize,
}
// Normally you would do this:
let foo = Foo {
  bar: 10,
  ..Default::default()
};
// But now you can do this:
let foo = Foo {
  bar: 10,
  ..default()
};
```
The examples have been adapted to use `..default()`. I've left internal crates as-is for now because they don't pull in the bevy prelude, and the ergonomics of each case should be considered individually.
		
	
			
		
			
				
	
	
		
			165 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			165 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use bevy::{
 | |
|     ecs::system::{lifetimeless::SRes, SystemParamItem},
 | |
|     pbr::MaterialPipeline,
 | |
|     prelude::*,
 | |
|     reflect::TypeUuid,
 | |
|     render::{
 | |
|         render_asset::{PrepareAssetError, RenderAsset, RenderAssets},
 | |
|         render_resource::{
 | |
|             BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout,
 | |
|             BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType,
 | |
|             SamplerBindingType, ShaderStages, TextureSampleType, TextureViewDimension,
 | |
|         },
 | |
|         renderer::RenderDevice,
 | |
|     },
 | |
| };
 | |
| 
 | |
| fn main() {
 | |
|     App::new()
 | |
|         .add_plugins(DefaultPlugins)
 | |
|         .add_plugin(MaterialPlugin::<CustomMaterial>::default())
 | |
|         .add_startup_system(setup)
 | |
|         .add_system(rotate_camera)
 | |
|         .run();
 | |
| }
 | |
| 
 | |
| #[derive(Component)]
 | |
| struct MainCamera;
 | |
| 
 | |
| fn setup(
 | |
|     mut commands: Commands,
 | |
|     asset_server: Res<AssetServer>,
 | |
|     mut meshes: ResMut<Assets<Mesh>>,
 | |
|     mut custom_materials: ResMut<Assets<CustomMaterial>>,
 | |
|     mut standard_materials: ResMut<Assets<StandardMaterial>>,
 | |
| ) {
 | |
|     commands.spawn_bundle(PbrBundle {
 | |
|         mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
 | |
|         material: standard_materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
 | |
|         ..default()
 | |
|     });
 | |
|     commands.spawn_bundle(PointLightBundle {
 | |
|         transform: Transform::from_xyz(4.0, 8.0, 4.0),
 | |
|         ..default()
 | |
|     });
 | |
|     commands.spawn_bundle(PerspectiveCameraBundle {
 | |
|         transform: Transform::from_xyz(0.0, 2.5, 1.0).looking_at(Vec3::default(), Vec3::Y),
 | |
|         ..default()
 | |
|     });
 | |
| 
 | |
|     commands.spawn().insert_bundle(MaterialMeshBundle {
 | |
|         mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
 | |
|         transform: Transform::from_xyz(0.0, 0.5, 0.0),
 | |
|         material: custom_materials.add(CustomMaterial {
 | |
|             texture: asset_server.load(
 | |
|                 "models/FlightHelmet/FlightHelmet_Materials_LensesMat_OcclusionRoughMetal.png",
 | |
|             ),
 | |
|         }),
 | |
|         ..default()
 | |
|     });
 | |
| 
 | |
|     // camera
 | |
|     commands
 | |
|         .spawn_bundle(PerspectiveCameraBundle {
 | |
|             transform: Transform::from_xyz(4.0, 2.5, 4.0).looking_at(Vec3::ZERO, Vec3::Y),
 | |
|             ..default()
 | |
|         })
 | |
|         .insert(MainCamera);
 | |
| }
 | |
| 
 | |
| fn rotate_camera(mut camera: Query<&mut Transform, With<MainCamera>>, time: Res<Time>) {
 | |
|     let cam_transform = camera.single_mut().into_inner();
 | |
| 
 | |
|     cam_transform.rotate_around(
 | |
|         Vec3::ZERO,
 | |
|         Quat::from_axis_angle(Vec3::Y, 45f32.to_radians() * time.delta_seconds()),
 | |
|     );
 | |
|     cam_transform.look_at(Vec3::ZERO, Vec3::Y);
 | |
| }
 | |
| 
 | |
| #[derive(Debug, Clone, TypeUuid)]
 | |
| #[uuid = "b62bb455-a72c-4b56-87bb-81e0554e234f"]
 | |
| pub struct CustomMaterial {
 | |
|     texture: Handle<Image>,
 | |
| }
 | |
| 
 | |
| #[derive(Clone)]
 | |
| pub struct GpuCustomMaterial {
 | |
|     bind_group: BindGroup,
 | |
| }
 | |
| 
 | |
| impl RenderAsset for CustomMaterial {
 | |
|     type ExtractedAsset = CustomMaterial;
 | |
|     type PreparedAsset = GpuCustomMaterial;
 | |
|     type Param = (
 | |
|         SRes<RenderDevice>,
 | |
|         SRes<RenderAssets<Image>>,
 | |
|         SRes<MaterialPipeline<Self>>,
 | |
|     );
 | |
|     fn extract_asset(&self) -> Self::ExtractedAsset {
 | |
|         self.clone()
 | |
|     }
 | |
| 
 | |
|     fn prepare_asset(
 | |
|         extracted_asset: Self::ExtractedAsset,
 | |
|         (render_device, gpu_images, material_pipeline): &mut SystemParamItem<Self::Param>,
 | |
|     ) -> Result<Self::PreparedAsset, PrepareAssetError<Self::ExtractedAsset>> {
 | |
|         let gpu_image = match gpu_images.get(&extracted_asset.texture) {
 | |
|             Some(gpu_image) => gpu_image,
 | |
|             // if the image isn't loaded yet, try next frame
 | |
|             None => return Err(PrepareAssetError::RetryNextUpdate(extracted_asset)),
 | |
|         };
 | |
| 
 | |
|         let bind_group = render_device.create_bind_group(&BindGroupDescriptor {
 | |
|             entries: &[
 | |
|                 BindGroupEntry {
 | |
|                     binding: 0,
 | |
|                     resource: BindingResource::TextureView(&gpu_image.texture_view),
 | |
|                 },
 | |
|                 BindGroupEntry {
 | |
|                     binding: 1,
 | |
|                     resource: BindingResource::Sampler(&gpu_image.sampler),
 | |
|                 },
 | |
|             ],
 | |
|             label: None,
 | |
|             layout: &material_pipeline.material_layout,
 | |
|         });
 | |
| 
 | |
|         Ok(GpuCustomMaterial { bind_group })
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Material for CustomMaterial {
 | |
|     fn fragment_shader(asset_server: &AssetServer) -> Option<Handle<Shader>> {
 | |
|         Some(asset_server.load("shaders/custom_material_screenspace_texture.wgsl"))
 | |
|     }
 | |
| 
 | |
|     fn bind_group(render_asset: &<Self as RenderAsset>::PreparedAsset) -> &BindGroup {
 | |
|         &render_asset.bind_group
 | |
|     }
 | |
| 
 | |
|     fn bind_group_layout(render_device: &RenderDevice) -> BindGroupLayout {
 | |
|         render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
 | |
|             entries: &[
 | |
|                 BindGroupLayoutEntry {
 | |
|                     binding: 0,
 | |
|                     visibility: ShaderStages::FRAGMENT,
 | |
|                     ty: BindingType::Texture {
 | |
|                         sample_type: TextureSampleType::Float { filterable: true },
 | |
|                         view_dimension: TextureViewDimension::D2,
 | |
|                         multisampled: false,
 | |
|                     },
 | |
|                     count: None,
 | |
|                 },
 | |
|                 BindGroupLayoutEntry {
 | |
|                     binding: 1,
 | |
|                     visibility: ShaderStages::FRAGMENT,
 | |
|                     ty: BindingType::Sampler(SamplerBindingType::Filtering),
 | |
|                     count: None,
 | |
|                 },
 | |
|             ],
 | |
|             label: None,
 | |
|         })
 | |
|     }
 | |
| }
 |