Path: blob/main/crates/bevy_asset/src/io/embedded/embedded_watcher.rs
6601 views
use crate::io::{1file::{get_asset_path, get_base_path, new_asset_event_debouncer, FilesystemEventHandler},2memory::Dir,3AssetSourceEvent, AssetWatcher,4};5use alloc::{boxed::Box, sync::Arc, vec::Vec};6use bevy_platform::collections::HashMap;7use core::time::Duration;8use notify_debouncer_full::{notify::RecommendedWatcher, Debouncer, RecommendedCache};9use parking_lot::RwLock;10use std::{11fs::File,12io::{BufReader, Read},13path::{Path, PathBuf},14};15use tracing::warn;1617/// A watcher for assets stored in the `embedded` asset source. Embedded assets are assets whose18/// bytes have been embedded into the Rust binary using the [`embedded_asset`](crate::embedded_asset) macro.19/// This watcher will watch for changes to the "source files", read the contents of changed files from the file system20/// and overwrite the initial static bytes of the file embedded in the binary with the new dynamically loaded bytes.21pub struct EmbeddedWatcher {22_watcher: Debouncer<RecommendedWatcher, RecommendedCache>,23}2425impl EmbeddedWatcher {26/// Creates a new `EmbeddedWatcher` that watches for changes to the embedded assets in the given `dir`.27pub fn new(28dir: Dir,29root_paths: Arc<RwLock<HashMap<Box<Path>, PathBuf>>>,30sender: crossbeam_channel::Sender<AssetSourceEvent>,31debounce_wait_time: Duration,32) -> Self {33let root = get_base_path();34let handler = EmbeddedEventHandler {35dir,36root: root.clone(),37sender,38root_paths,39last_event: None,40};41let watcher = new_asset_event_debouncer(root, debounce_wait_time, handler).unwrap();42Self { _watcher: watcher }43}44}4546impl AssetWatcher for EmbeddedWatcher {}4748/// A [`FilesystemEventHandler`] that uses [`EmbeddedAssetRegistry`](crate::io::embedded::EmbeddedAssetRegistry) to hot-reload49/// binary-embedded Rust source files. This will read the contents of changed files from the file system and overwrite50/// the initial static bytes from the file embedded in the binary.51pub(crate) struct EmbeddedEventHandler {52sender: crossbeam_channel::Sender<AssetSourceEvent>,53root_paths: Arc<RwLock<HashMap<Box<Path>, PathBuf>>>,54root: PathBuf,55dir: Dir,56last_event: Option<AssetSourceEvent>,57}5859impl FilesystemEventHandler for EmbeddedEventHandler {60fn begin(&mut self) {61self.last_event = None;62}6364fn get_path(&self, absolute_path: &Path) -> Option<(PathBuf, bool)> {65let (local_path, is_meta) = get_asset_path(&self.root, absolute_path);66let final_path = self.root_paths.read().get(local_path.as_path())?.clone();67if is_meta {68warn!("Meta file asset hot-reloading is not supported yet: {final_path:?}");69}70Some((final_path, false))71}7273fn handle(&mut self, absolute_paths: &[PathBuf], event: AssetSourceEvent) {74if self.last_event.as_ref() != Some(&event) {75if let AssetSourceEvent::ModifiedAsset(path) = &event76&& let Ok(file) = File::open(&absolute_paths[0])77{78let mut reader = BufReader::new(file);79let mut buffer = Vec::new();8081// Read file into vector.82if reader.read_to_end(&mut buffer).is_ok() {83self.dir.insert_asset(path, buffer);84}85}86self.last_event = Some(event.clone());87self.sender.send(event).unwrap();88}89}90}919293