feat: impl proper entity handles
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
use std::ops::Deref;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use super::bevy_channel::{BevyChannel, BevyChannelReader};
|
use super::bevy_channel::{BevyChannel, BevyChannelReader};
|
||||||
@@ -16,16 +19,28 @@ fn despawn(mut cmds: Commands, mut reader: ResMut<BevyChannelReader<Entity>>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
|
pub struct EntityHandle(Arc<EntityHandleInner>);
|
||||||
|
impl EntityHandle {
|
||||||
|
pub fn get(&self) -> Entity {
|
||||||
|
self.0.0
|
||||||
|
}
|
||||||
|
pub fn new(entity: Entity) -> Self {
|
||||||
|
Self(EntityHandleInner(entity).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Deref for EntityHandle {
|
||||||
|
type Target = Entity;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
static DESTROY: BevyChannel<Entity> = BevyChannel::new();
|
static DESTROY: BevyChannel<Entity> = BevyChannel::new();
|
||||||
#[derive(Deref, DerefMut, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct EntityHandle(pub Entity);
|
pub struct EntityHandleInner(Entity);
|
||||||
impl Drop for EntityHandle {
|
impl Drop for EntityHandleInner {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
DESTROY.send(self.0);
|
DESTROY.send(self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<Entity> for EntityHandle {
|
|
||||||
fn from(value: Entity) -> Self {
|
|
||||||
Self(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -73,10 +73,11 @@ fn update_sound_event(
|
|||||||
},
|
},
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
sound.spatial.set_entity(entity);
|
let entity = EntityHandle::new(entity);
|
||||||
sound.entity.set(entity.into()).unwrap();
|
sound.spatial.set_entity(entity.clone());
|
||||||
|
sound.entity.set(entity).unwrap();
|
||||||
}
|
}
|
||||||
if let Some(sink) = sound.entity.get().and_then(|e| sinks.get(e.0).ok()) {
|
if let Some(sink) = sound.entity.get().and_then(|e| sinks.get(e.get()).ok()) {
|
||||||
if sound.play.lock().take().is_some() {
|
if sound.play.lock().take().is_some() {
|
||||||
sink.play();
|
sink.play();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ fn build_line_mesh(
|
|||||||
extension: LineExtension {},
|
extension: LineExtension {},
|
||||||
})),
|
})),
|
||||||
));
|
));
|
||||||
_ = lines.entity.set(e.id().into());
|
_ = lines.entity.set(EntityHandle::new(e.id()));
|
||||||
e
|
e
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -107,7 +107,10 @@ fn load_models(
|
|||||||
Visibility::Hidden,
|
Visibility::Hidden,
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
model.bevy_scene_entity.set(entity.into()).unwrap();
|
model
|
||||||
|
.bevy_scene_entity
|
||||||
|
.set(EntityHandle::new(entity))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +147,7 @@ fn apply_materials(
|
|||||||
for (param_name, param) in model_part.pending_material_parameters.lock().drain() {
|
for (param_name, param) in model_part.pending_material_parameters.lock().drain() {
|
||||||
let mut new_mat = materials.get(&mesh_mat.0).unwrap().clone();
|
let mut new_mat = materials.get(&mesh_mat.0).unwrap().clone();
|
||||||
param.apply_to_material(
|
param.apply_to_material(
|
||||||
&model_part.space.node().unwrap().get_client().unwrap(),
|
&model_part.spatial.node().unwrap().get_client().unwrap(),
|
||||||
&mut new_mat,
|
&mut new_mat,
|
||||||
¶m_name,
|
¶m_name,
|
||||||
&asset_server,
|
&asset_server,
|
||||||
@@ -193,7 +196,7 @@ fn gen_model_parts(
|
|||||||
.unwrap_or_else(|| name.to_string());
|
.unwrap_or_else(|| name.to_string());
|
||||||
let parent_spatial = parent
|
let parent_spatial = parent
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|p| p.space.clone())
|
.map(|p| p.spatial.clone())
|
||||||
.unwrap_or_else(|| model.spatial.clone());
|
.unwrap_or_else(|| model.spatial.clone());
|
||||||
let client = model.spatial.node()?.get_client()?;
|
let client = model.spatial.node()?.get_client()?;
|
||||||
let (spatial, model_part) =
|
let (spatial, model_part) =
|
||||||
@@ -211,8 +214,7 @@ fn gen_model_parts(
|
|||||||
entity: OnceLock::new(),
|
entity: OnceLock::new(),
|
||||||
mesh_entity: OnceLock::new(),
|
mesh_entity: OnceLock::new(),
|
||||||
path,
|
path,
|
||||||
space: spatial.clone(),
|
spatial: spatial.clone(),
|
||||||
_model: Arc::downgrade(&model),
|
|
||||||
pending_material_parameters: Mutex::default(),
|
pending_material_parameters: Mutex::default(),
|
||||||
pending_material_replacement: Mutex::default(),
|
pending_material_replacement: Mutex::default(),
|
||||||
holdout: AtomicBool::new(false),
|
holdout: AtomicBool::new(false),
|
||||||
@@ -222,8 +224,8 @@ fn gen_model_parts(
|
|||||||
(spatial, model_part)
|
(spatial, model_part)
|
||||||
}
|
}
|
||||||
Some(part) => {
|
Some(part) => {
|
||||||
part.space.set_spatial_parent(&parent_spatial).unwrap();
|
part.spatial.set_spatial_parent(&parent_spatial).unwrap();
|
||||||
(part.space.clone(), part.clone())
|
(part.spatial.clone(), part.clone())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let aabb = Aabb::enclosing(
|
let aabb = Aabb::enclosing(
|
||||||
@@ -247,8 +249,8 @@ fn gen_model_parts(
|
|||||||
});
|
});
|
||||||
let _ = spatial.set_spatial_parent(&parent_spatial);
|
let _ = spatial.set_spatial_parent(&parent_spatial);
|
||||||
spatial.set_local_transform(transform.compute_matrix());
|
spatial.set_local_transform(transform.compute_matrix());
|
||||||
|
let entity_handle = EntityHandle::new(entity);
|
||||||
spatial.set_entity(entity);
|
spatial.set_entity(entity_handle.clone());
|
||||||
cmds.entity(entity)
|
cmds.entity(entity)
|
||||||
.insert(SpatialNode(Arc::downgrade(&spatial)));
|
.insert(SpatialNode(Arc::downgrade(&spatial)));
|
||||||
let mesh_entity = children_query
|
let mesh_entity = children_query
|
||||||
@@ -257,17 +259,18 @@ fn gen_model_parts(
|
|||||||
.flat_map(|v| v.iter())
|
.flat_map(|v| v.iter())
|
||||||
.find(|e| has_mesh.get(*e).unwrap_or(false))?;
|
.find(|e| has_mesh.get(*e).unwrap_or(false))?;
|
||||||
_ = model_part.bounds.set(aabb);
|
_ = model_part.bounds.set(aabb);
|
||||||
_ = model_part.entity.set(entity.into());
|
_ = model_part.entity.set(entity_handle);
|
||||||
_ = model_part.mesh_entity.set(mesh_entity.into());
|
_ = model_part.mesh_entity.set(EntityHandle::new(mesh_entity));
|
||||||
parts.push(model_part.clone());
|
parts.push(model_part.clone());
|
||||||
Some(model_part)
|
Some(model_part)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ = model.parts.set(parts);
|
_ = model.parts.set(parts);
|
||||||
|
model.pre_bound_parts.lock().clear();
|
||||||
model
|
model
|
||||||
.spatial
|
.spatial
|
||||||
.set_entity(model.bevy_scene_entity.get().unwrap().0);
|
.set_entity(model.bevy_scene_entity.get().unwrap().clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,8 +327,6 @@ impl HashedPbrMaterial {
|
|||||||
mat.emissive_texture.hash(state);
|
mat.emissive_texture.hash(state);
|
||||||
mat.metallic_roughness_texture.hash(state);
|
mat.metallic_roughness_texture.hash(state);
|
||||||
mat.occlusion_texture.hash(state);
|
mat.occlusion_texture.hash(state);
|
||||||
// should always be the same, TODO: make the spherical harmonics buffer a per mesh instance thing
|
|
||||||
// mat.spherical_harmonics.hash(state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn hash_color<H: Hasher>(color: Color, state: &mut H) {
|
fn hash_color<H: Hasher>(color: Color, state: &mut H) {
|
||||||
@@ -463,8 +464,7 @@ pub struct ModelPart {
|
|||||||
entity: OnceLock<EntityHandle>,
|
entity: OnceLock<EntityHandle>,
|
||||||
mesh_entity: OnceLock<EntityHandle>,
|
mesh_entity: OnceLock<EntityHandle>,
|
||||||
path: String,
|
path: String,
|
||||||
space: Arc<Spatial>,
|
spatial: Arc<Spatial>,
|
||||||
_model: Weak<Model>,
|
|
||||||
pending_material_parameters: Mutex<FxHashMap<String, MaterialParameter>>,
|
pending_material_parameters: Mutex<FxHashMap<String, MaterialParameter>>,
|
||||||
pending_material_replacement: Mutex<Option<Handle<BevyMaterial>>>,
|
pending_material_replacement: Mutex<Option<Handle<BevyMaterial>>>,
|
||||||
holdout: AtomicBool,
|
holdout: AtomicBool,
|
||||||
@@ -591,8 +591,7 @@ impl Model {
|
|||||||
entity: OnceLock::new(),
|
entity: OnceLock::new(),
|
||||||
mesh_entity: OnceLock::new(),
|
mesh_entity: OnceLock::new(),
|
||||||
path: part_path,
|
path: part_path,
|
||||||
space: spatial,
|
spatial,
|
||||||
_model: Arc::downgrade(self),
|
|
||||||
pending_material_parameters: Mutex::default(),
|
pending_material_parameters: Mutex::default(),
|
||||||
pending_material_replacement: Mutex::default(),
|
pending_material_replacement: Mutex::default(),
|
||||||
holdout: AtomicBool::new(false),
|
holdout: AtomicBool::new(false),
|
||||||
@@ -617,7 +616,7 @@ impl ModelAspect for Model {
|
|||||||
let model = node.get_aspect::<Model>()?;
|
let model = node.get_aspect::<Model>()?;
|
||||||
let part = model.get_model_part(part_path)?;
|
let part = model.get_model_part(part_path)?;
|
||||||
Alias::create_with_id(
|
Alias::create_with_id(
|
||||||
&part.space.node().unwrap(),
|
&part.spatial.node().unwrap(),
|
||||||
&calling_client,
|
&calling_client,
|
||||||
id,
|
id,
|
||||||
MODEL_PART_ASPECT_ALIAS_INFO.clone(),
|
MODEL_PART_ASPECT_ALIAS_INFO.clone(),
|
||||||
@@ -628,6 +627,11 @@ impl ModelAspect for Model {
|
|||||||
}
|
}
|
||||||
impl Drop for Model {
|
impl Drop for Model {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
for p in self.parts.get().unwrap().iter() {
|
||||||
|
if let Some(node) = p.spatial.node() {
|
||||||
|
node.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
MODEL_REGISTRY.remove(self);
|
MODEL_REGISTRY.remove(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,7 +152,8 @@ fn spawn_text(
|
|||||||
))
|
))
|
||||||
.add_children(&letters)
|
.add_children(&letters)
|
||||||
.id();
|
.id();
|
||||||
text.entity.lock().replace(EntityHandle(entity));
|
let entity = EntityHandle::new(entity);
|
||||||
|
text.entity.lock().replace(entity.clone());
|
||||||
text.spatial.set_entity(entity);
|
text.spatial.set_entity(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ fn spawn_spatial_nodes(mut cmds: Commands) {
|
|||||||
let entity = cmds
|
let entity = cmds
|
||||||
.spawn((SpatialNode(Arc::downgrade(&spatial)), Name::new("Spatial")))
|
.spawn((SpatialNode(Arc::downgrade(&spatial)), Name::new("Spatial")))
|
||||||
.id();
|
.id();
|
||||||
spatial.set_entity(entity);
|
spatial.set_entity(EntityHandle::new(entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,15 +160,15 @@ impl Spatial {
|
|||||||
spatial.mark_dirty();
|
spatial.mark_dirty();
|
||||||
spatial
|
spatial
|
||||||
}
|
}
|
||||||
pub fn set_entity(&self, entity: Entity) {
|
pub fn set_entity(&self, entity: EntityHandle) {
|
||||||
self.entity.write().replace(entity.into());
|
self.entity.write().replace(entity);
|
||||||
self.mark_dirty();
|
self.mark_dirty();
|
||||||
for child in self.children.get_valid_contents() {
|
for child in self.children.get_valid_contents() {
|
||||||
child.mark_dirty();
|
child.mark_dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get_entity(&self) -> Option<Entity> {
|
pub fn get_entity(&self) -> Option<Entity> {
|
||||||
self.entity.read().as_ref().map(|v| v.0)
|
self.entity.read().as_ref().map(|v| v.get())
|
||||||
}
|
}
|
||||||
pub fn add_to(
|
pub fn add_to(
|
||||||
node: &Arc<Node>,
|
node: &Arc<Node>,
|
||||||
@@ -222,7 +222,7 @@ impl Spatial {
|
|||||||
bounds
|
bounds
|
||||||
}
|
}
|
||||||
pub(super) fn mark_dirty(&self) {
|
pub(super) fn mark_dirty(&self) {
|
||||||
let Some(entity) = self.entity.read().as_ref().map(|v| v.0) else {
|
let Some(entity) = self.entity.read().as_ref().map(|v| v.get()) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let enabled = self
|
let enabled = self
|
||||||
@@ -232,7 +232,7 @@ impl Spatial {
|
|||||||
let transform = enabled.then(|| BevyTransform::from_matrix(self.local_transform()));
|
let transform = enabled.then(|| BevyTransform::from_matrix(self.local_transform()));
|
||||||
let parent = self
|
let parent = self
|
||||||
.get_parent()
|
.get_parent()
|
||||||
.and_then(|v| v.entity.read().as_ref().map(|v| v.0));
|
.and_then(|v| v.entity.read().as_ref().map(|v| v.get()));
|
||||||
UPDATED_SPATIALS_NODES
|
UPDATED_SPATIALS_NODES
|
||||||
.lock()
|
.lock()
|
||||||
.insert(entity, (transform, parent));
|
.insert(entity, (transform, parent));
|
||||||
|
|||||||
Reference in New Issue
Block a user