1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
use crate::{ render_graph::{Node, ResourceSlots}, renderer::{BufferInfo, BufferUsage, RenderContext}, texture::{Texture, TextureDescriptor, TEXTURE_ASSET_INDEX}, }; use bevy_app::{Events, ManualEventReader}; use bevy_asset::{AssetEvent, Assets}; use bevy_ecs::world::World; use bevy_utils::HashSet; #[derive(Default)] pub struct TextureCopyNode { pub texture_event_reader: ManualEventReader<AssetEvent<Texture>>, } impl Node for TextureCopyNode { fn update( &mut self, world: &World, render_context: &mut dyn RenderContext, _input: &ResourceSlots, _output: &mut ResourceSlots, ) { let texture_events = world.get_resource::<Events<AssetEvent<Texture>>>().unwrap(); let textures = world.get_resource::<Assets<Texture>>().unwrap(); let mut copied_textures = HashSet::default(); for event in self.texture_event_reader.iter(&texture_events) { match event { AssetEvent::Created { handle } | AssetEvent::Modified { handle } => { if let Some(texture) = textures.get(handle) { if copied_textures.contains(&handle.id) { continue; } let texture_descriptor: TextureDescriptor = texture.into(); let width = texture.size.width as usize; let aligned_width = render_context.resources().get_aligned_texture_size(width); let format_size = texture.format.pixel_size(); let mut aligned_data = vec![ 0; format_size * aligned_width * texture.size.height as usize * texture.size.depth as usize ]; texture .data .chunks_exact(format_size * width) .enumerate() .for_each(|(index, row)| { let offset = index * aligned_width * format_size; aligned_data[offset..(offset + width * format_size)] .copy_from_slice(row); }); let texture_buffer = render_context.resources().create_buffer_with_data( BufferInfo { buffer_usage: BufferUsage::COPY_SRC, ..Default::default() }, &aligned_data, ); let texture_resource = render_context .resources() .get_asset_resource(handle, TEXTURE_ASSET_INDEX) .unwrap(); render_context.copy_buffer_to_texture( texture_buffer, 0, (format_size * aligned_width) as u32, texture_resource.get_texture().unwrap(), [0, 0, 0], 0, texture_descriptor.size, ); render_context.resources().remove_buffer(texture_buffer); copied_textures.insert(&handle.id); } } AssetEvent::Removed { .. } => {} } } } }