fix(Spatial/Transforms): fix transform propagation by making bevy entities for all spatials
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
@@ -57,27 +57,24 @@ fn update_sound_event(
|
|||||||
for sound in SOUND_REGISTRY.get_valid_contents() {
|
for sound in SOUND_REGISTRY.get_valid_contents() {
|
||||||
if sound.entity.get().is_none() {
|
if sound.entity.get().is_none() {
|
||||||
let handle = asset_server.load(sound.pending_audio_path.as_path());
|
let handle = asset_server.load(sound.pending_audio_path.as_path());
|
||||||
sound
|
let entity = cmds
|
||||||
.entity
|
.spawn((
|
||||||
.set(
|
Name::new("Audio Node"),
|
||||||
cmds.spawn((
|
SpatialNode(Arc::downgrade(&sound.spatial)),
|
||||||
Name::new("Audio Node"),
|
AudioPlayer::new(handle),
|
||||||
SpatialNode(Arc::downgrade(&sound.spatial)),
|
PlaybackSettings {
|
||||||
AudioPlayer::new(handle),
|
mode: PlaybackMode::Once,
|
||||||
PlaybackSettings {
|
volume: Volume::Linear(sound.volume),
|
||||||
mode: PlaybackMode::Once,
|
speed: 1.0,
|
||||||
volume: Volume::Linear(sound.volume),
|
paused: true,
|
||||||
speed: 1.0,
|
muted: false,
|
||||||
paused: true,
|
spatial: true,
|
||||||
muted: false,
|
spatial_scale: None,
|
||||||
spatial: true,
|
},
|
||||||
spatial_scale: None,
|
))
|
||||||
},
|
.id();
|
||||||
))
|
sound.spatial.set_entity(entity);
|
||||||
.id()
|
sound.entity.set(entity.into()).unwrap();
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
.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.0).ok()) {
|
||||||
if sound.play.lock().take().is_some() {
|
if sound.play.lock().take().is_some() {
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ fn build_line_mesh(
|
|||||||
extension: LineExtension { unused: 0 },
|
extension: LineExtension { unused: 0 },
|
||||||
})),
|
})),
|
||||||
));
|
));
|
||||||
|
lines.spatial.set_entity(e.id());
|
||||||
_ = lines.entity.set(e.id().into());
|
_ = lines.entity.set(e.id().into());
|
||||||
e
|
e
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,6 +243,7 @@ fn gen_model_parts(
|
|||||||
});
|
});
|
||||||
spatial.set_local_transform(transform.compute_matrix());
|
spatial.set_local_transform(transform.compute_matrix());
|
||||||
|
|
||||||
|
spatial.set_entity(entity);
|
||||||
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
|
||||||
@@ -570,7 +571,6 @@ impl Model {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// TODO: this could be a denail of service vector
|
|
||||||
let client = self.spatial.node().unwrap().get_client().unwrap();
|
let client = self.spatial.node().unwrap().get_client().unwrap();
|
||||||
let part_node = client.scenegraph.add_node(Node::generate(&client, false));
|
let part_node = client.scenegraph.add_node(Node::generate(&client, false));
|
||||||
let spatial = Spatial::add_to(
|
let spatial = Spatial::add_to(
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ fn spawn_text(
|
|||||||
.add_children(&letters)
|
.add_children(&letters)
|
||||||
.id();
|
.id();
|
||||||
text.entity.lock().replace(EntityHandle(entity));
|
text.entity.lock().replace(EntityHandle(entity));
|
||||||
|
text.spatial.set_entity(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use super::fields::{Field, FieldTrait};
|
|||||||
use super::{Aspect, AspectIdentifier};
|
use super::{Aspect, AspectIdentifier};
|
||||||
use crate::bail;
|
use crate::bail;
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
|
use crate::core::entity_handle::EntityHandle;
|
||||||
use crate::core::error::Result;
|
use crate::core::error::Result;
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
use crate::nodes::{Node, OWNED_ASPECT_ALIAS_INFO};
|
use crate::nodes::{Node, OWNED_ASPECT_ALIAS_INFO};
|
||||||
@@ -27,11 +28,52 @@ impl Plugin for SpatialNodePlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
update_spatial_nodes.before(TransformSystem::TransformPropagate),
|
(
|
||||||
|
spawn_spatial_nodes,
|
||||||
|
update_spatial_node_parenting,
|
||||||
|
update_spatial_nodes,
|
||||||
|
)
|
||||||
|
.chain()
|
||||||
|
.before(TransformSystem::TransformPropagate),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn spawn_spatial_nodes(mut cmds: Commands) {
|
||||||
|
for spatial in SPATIAL_REGISTRY
|
||||||
|
.get_valid_contents()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|v| v.entity.lock().is_none())
|
||||||
|
{
|
||||||
|
let entity = cmds
|
||||||
|
.spawn((SpatialNode(Arc::downgrade(&spatial)), Name::new("Spatial")))
|
||||||
|
.id();
|
||||||
|
_ = spatial.set_entity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_spatial_node_parenting(
|
||||||
|
query: Query<(Entity, Option<&ChildOf>, &SpatialNode)>,
|
||||||
|
mut cmds: Commands,
|
||||||
|
) {
|
||||||
|
for (entity, parent, spatial) in &query {
|
||||||
|
let Some(spatial) = spatial.0.upgrade() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let parent_entity = spatial
|
||||||
|
.get_parent()
|
||||||
|
.and_then(|v| v.entity.lock().as_ref().map(|v| v.0));
|
||||||
|
// no changes needed, early exit
|
||||||
|
if parent.map(|v| v.0) == parent_entity {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
match parent_entity {
|
||||||
|
Some(e) => cmds.entity(entity).insert(ChildOf(e)),
|
||||||
|
None => cmds.entity(entity).remove::<ChildOf>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn update_spatial_nodes(
|
fn update_spatial_nodes(
|
||||||
mut query: Query<(
|
mut query: Query<(
|
||||||
&mut BevyTransform,
|
&mut BevyTransform,
|
||||||
@@ -69,22 +111,25 @@ fn update_spatial_nodes(
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
match child_of {
|
*transform = BevyTransform::from_matrix(spatial.local_transform());
|
||||||
Some(child_of) => {
|
// match child_of {
|
||||||
let Ok(parent) = parent_query.get(child_of.0) else {
|
// Some(child_of) => {
|
||||||
warn!("SpatialNode bevy Parent doesn't have global transform");
|
// let Ok(parent) = parent_query.get(child_of.0) else {
|
||||||
return;
|
// warn!("SpatialNode bevy Parent doesn't have global transform");
|
||||||
};
|
// return;
|
||||||
*transform =
|
// };
|
||||||
BevyTransform::from_matrix(parent.compute_matrix().inverse() * mat4);
|
// *transform =
|
||||||
}
|
// BevyTransform::from_matrix(parent.compute_matrix().inverse() * mat4);
|
||||||
None => {
|
// }
|
||||||
*transform = BevyTransform::from_matrix(mat4);
|
// None => {
|
||||||
}
|
// *transform = BevyTransform::from_matrix(mat4);
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SPATIAL_REGISTRY: Registry<Spatial> = Registry::new();
|
||||||
|
|
||||||
#[derive(Clone, Component, Debug)]
|
#[derive(Clone, Component, Debug)]
|
||||||
#[require(BevyTransform, Visibility)]
|
#[require(BevyTransform, Visibility)]
|
||||||
pub struct SpatialNode(pub Weak<Spatial>);
|
pub struct SpatialNode(pub Weak<Spatial>);
|
||||||
@@ -123,6 +168,7 @@ static ZONEABLE_REGISTRY: Registry<Spatial> = Registry::new();
|
|||||||
|
|
||||||
pub struct Spatial {
|
pub struct Spatial {
|
||||||
pub node: Weak<Node>,
|
pub node: Weak<Node>,
|
||||||
|
entity: Mutex<Option<EntityHandle>>,
|
||||||
parent: Mutex<Option<Arc<Spatial>>>,
|
parent: Mutex<Option<Arc<Spatial>>>,
|
||||||
old_parent: Mutex<Option<Arc<Spatial>>>,
|
old_parent: Mutex<Option<Arc<Spatial>>>,
|
||||||
transform: Mutex<Mat4>,
|
transform: Mutex<Mat4>,
|
||||||
@@ -133,8 +179,9 @@ pub struct Spatial {
|
|||||||
|
|
||||||
impl Spatial {
|
impl Spatial {
|
||||||
pub fn new(node: Weak<Node>, parent: Option<Arc<Spatial>>, transform: Mat4) -> Arc<Self> {
|
pub fn new(node: Weak<Node>, parent: Option<Arc<Spatial>>, transform: Mat4) -> Arc<Self> {
|
||||||
Arc::new(Spatial {
|
SPATIAL_REGISTRY.add(Spatial {
|
||||||
node,
|
node,
|
||||||
|
entity: Mutex::new(None),
|
||||||
parent: Mutex::new(parent),
|
parent: Mutex::new(parent),
|
||||||
old_parent: Mutex::new(None),
|
old_parent: Mutex::new(None),
|
||||||
transform: Mutex::new(transform),
|
transform: Mutex::new(transform),
|
||||||
@@ -143,6 +190,9 @@ impl Spatial {
|
|||||||
bounding_box_calc: OnceLock::default(),
|
bounding_box_calc: OnceLock::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
pub fn set_entity(&self, entity: Entity) {
|
||||||
|
self.entity.lock().replace(entity.into());
|
||||||
|
}
|
||||||
pub fn add_to(
|
pub fn add_to(
|
||||||
node: &Arc<Node>,
|
node: &Arc<Node>,
|
||||||
parent: Option<Arc<Spatial>>,
|
parent: Option<Arc<Spatial>>,
|
||||||
@@ -396,6 +446,7 @@ impl Drop for Spatial {
|
|||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
zone::release(self);
|
zone::release(self);
|
||||||
ZONEABLE_REGISTRY.remove(self);
|
ZONEABLE_REGISTRY.remove(self);
|
||||||
|
SPATIAL_REGISTRY.remove(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user