use crate::mesh::Mesh;
use bevy_asset::{AsAssetId, AssetEvent, AssetId, Handle};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{
change_detection::DetectChangesMut, component::Component, message::MessageReader,
reflect::ReflectComponent, system::Query, template::FromTemplate,
};
use bevy_platform::{collections::HashSet, hash::FixedHasher};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_transform::components::Transform;
use core::any::TypeId;
use derive_more::derive::From;
#[derive(
Component, FromTemplate, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq, From,
)]
#[reflect(Component, Default, Clone, PartialEq)]
#[require(Transform)]
pub struct Mesh2d(pub Handle<Mesh>);
impl From<Mesh2d> for AssetId<Mesh> {
fn from(mesh: Mesh2d) -> Self {
mesh.id()
}
}
impl From<&Mesh2d> for AssetId<Mesh> {
fn from(mesh: &Mesh2d) -> Self {
mesh.id()
}
}
impl AsAssetId for Mesh2d {
type Asset = Mesh;
fn as_asset_id(&self) -> AssetId<Self::Asset> {
self.id()
}
}
#[derive(
Component, FromTemplate, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq, From,
)]
#[reflect(Component, Default, Clone, PartialEq)]
#[require(Transform)]
pub struct Mesh3d(pub Handle<Mesh>);
impl From<Mesh3d> for AssetId<Mesh> {
fn from(mesh: Mesh3d) -> Self {
mesh.id()
}
}
impl From<&Mesh3d> for AssetId<Mesh> {
fn from(mesh: &Mesh3d) -> Self {
mesh.id()
}
}
impl AsAssetId for Mesh3d {
type Asset = Mesh;
fn as_asset_id(&self) -> AssetId<Self::Asset> {
self.id()
}
}
pub fn mark_2d_meshes_as_changed_if_their_assets_changed(
mut meshes_2d: Query<&mut Mesh2d>,
mut mesh_asset_events: MessageReader<AssetEvent<Mesh>>,
) {
let mut changed_meshes: HashSet<AssetId<Mesh>, FixedHasher> = HashSet::default();
for mesh_asset_event in mesh_asset_events.read() {
if let AssetEvent::Modified { id } = mesh_asset_event {
changed_meshes.insert(*id);
}
}
if changed_meshes.is_empty() {
return;
}
for mut mesh_2d in &mut meshes_2d {
if changed_meshes.contains(&mesh_2d.0.id()) {
mesh_2d.set_changed();
}
}
}
pub fn mark_3d_meshes_as_changed_if_their_assets_changed(
mut meshes_3d: Query<&mut Mesh3d>,
mut mesh_asset_events: MessageReader<AssetEvent<Mesh>>,
) {
let mut changed_meshes: HashSet<AssetId<Mesh>, FixedHasher> = HashSet::default();
for mesh_asset_event in mesh_asset_events.read() {
if let AssetEvent::Modified { id } = mesh_asset_event {
changed_meshes.insert(*id);
}
}
if changed_meshes.is_empty() {
return;
}
meshes_3d.par_iter_mut().for_each(|mut mesh_3d| {
if changed_meshes.contains(&mesh_3d.0.id()) {
mesh_3d.set_changed();
}
});
}
#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq)]
#[reflect(Component, Default, Clone, PartialEq)]
pub struct MeshTag {
#[deref]
pub value: u32,
#[cfg(debug_assertions)]
type_id: Option<TypeId>,
}
impl MeshTag {
pub const fn new(value: u32) -> MeshTag {
MeshTag {
value,
#[cfg(debug_assertions)]
type_id: None,
}
}
pub fn with_type<T>(value: u32) -> MeshTag
where
T: 'static + Sized,
{
MeshTag::with_type_id(value, TypeId::of::<T>())
}
pub fn with_type_id(value: u32, _type_id: TypeId) -> MeshTag {
MeshTag {
value,
#[cfg(debug_assertions)]
type_id: Some(_type_id),
}
}
pub fn type_is<T>(&self) -> bool
where
T: 'static + Sized,
{
self.type_id_is(TypeId::of::<T>())
}
#[cfg(debug_assertions)]
pub fn type_id_is(&self, type_id: TypeId) -> bool {
self.type_id == Some(type_id)
}
#[cfg(not(debug_assertions))]
pub fn type_id_is(&self, _: TypeId) -> bool {
true
}
}