use std::marker::PhantomData;
use bevy_app::{App, Plugin, FixedUpdate};
use bevy_asset::{Assets, Handle};
use bevy_audio::{AudioPlayer, AudioSource};
use bevy_ecs::{
query::Added,
system::{Query, ResMut},
};
use bevy_image::Image;
use bevy_mesh::{Mesh, Mesh3d};
use bevy_pbr::{MeshMaterial3d, StandardMaterial};
use tracing::debug;
use uuid::Uuid;
use crate::SyncMark;
pub(crate) struct HandleUUIDFixPlugin;
impl Plugin for HandleUUIDFixPlugin {
fn build(&self, app: &mut App) {
app.add_systems(FixedUpdate, replace_mesh_ids);
app.add_systems(FixedUpdate, replace_material_ids);
app.add_systems(FixedUpdate, replace_audio_ids);
}
}
fn replace_mesh_ids(
mut meshes: ResMut<Assets<Mesh>>,
mut q: Query<&mut Mesh3d, Added<SyncMark>>,
) {
for mut m in &mut q {
if !m.is_strong() {
continue;
}
let Some(asset) = meshes.remove(m.id()) else {
continue;
};
let id = Uuid::new_v4();
let _ = meshes.insert(id, asset);
m.0 = Handle::Uuid(id, PhantomData);
debug!("Reassigned mesh to uuid {:?}", id);
}
}
fn replace_material_ids(
mut images: ResMut<Assets<Image>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut q: Query<&mut MeshMaterial3d<StandardMaterial>, Added<SyncMark>>,
) {
for mut m in &mut q {
if !m.is_strong() {
continue;
}
let Some(mut asset) = materials.remove(m.id()) else {
continue;
};
let id = Uuid::new_v4();
replace_material_image_ids(&mut images, &mut asset);
let _ = materials.insert(id, asset);
m.0 = Handle::Uuid(id, PhantomData);
debug!("Reassigned material to uuid {:?}", id);
}
}
fn replace_material_image_ids(images: &mut Assets<Image>, material: &mut StandardMaterial) {
macro_rules! swap_image {
($image:expr) => {
if let Some(h) = $image.clone() {
$image = replace_image_id(images, h);
}
};
}
swap_image!(material.base_color_texture);
swap_image!(material.emissive_texture);
swap_image!(material.normal_map_texture);
swap_image!(material.occlusion_texture);
swap_image!(material.metallic_roughness_texture);
}
fn replace_image_id(images: &mut Assets<Image>, image: Handle<Image>) -> Option<Handle<Image>> {
if image.is_uuid() {
return Some(image);
}
let id = Uuid::new_v4();
let image = images.remove(image.id())?;
let _ = images.insert(id, image);
debug!("Reassigned image to uuid {:?}", id);
Some(Handle::Uuid(id, PhantomData))
}
fn replace_audio_ids(
mut audios: ResMut<Assets<AudioSource>>,
mut q: Query<&mut AudioPlayer, Added<SyncMark>>,
) {
for mut p in &mut q {
if !p.0.is_strong() {
continue;
}
let Some(asset) = audios.remove(p.0.id()) else {
continue;
};
let id = Uuid::new_v4();
let _ = audios.insert(id, asset);
p.0 = Handle::Uuid(id, PhantomData);
debug!("Reassigned audio to uuid {:?}", id);
}
}