feat: upgrade to numerical IDs
This commit is contained in:
@@ -9,7 +9,6 @@ use crate::create_interface;
|
||||
use color_eyre::eyre::{eyre, Result};
|
||||
use glam::{vec3a, Mat4, Quat, Vec3};
|
||||
use mint::Vector3;
|
||||
use nanoid::nanoid;
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use std::fmt::Debug;
|
||||
@@ -40,20 +39,18 @@ impl Transform {
|
||||
static ZONEABLE_REGISTRY: Registry<Spatial> = Registry::new();
|
||||
|
||||
pub struct Spatial {
|
||||
uid: String,
|
||||
pub(super) node: Weak<Node>,
|
||||
node: Weak<Node>,
|
||||
parent: Mutex<Option<Arc<Spatial>>>,
|
||||
old_parent: Mutex<Option<Arc<Spatial>>>,
|
||||
pub(super) transform: Mutex<Mat4>,
|
||||
transform: Mutex<Mat4>,
|
||||
zone: Mutex<Weak<Zone>>,
|
||||
children: Registry<Spatial>,
|
||||
pub(super) bounding_box_calc: OnceCell<fn(&Node) -> Bounds>,
|
||||
pub bounding_box_calc: OnceCell<fn(&Node) -> Bounds>,
|
||||
}
|
||||
|
||||
impl Spatial {
|
||||
pub fn new(node: Weak<Node>, parent: Option<Arc<Spatial>>, transform: Mat4) -> Arc<Self> {
|
||||
Arc::new(Spatial {
|
||||
uid: nanoid!(),
|
||||
node,
|
||||
parent: Mutex::new(parent),
|
||||
old_parent: Mutex::new(None),
|
||||
@@ -232,7 +229,7 @@ impl Spatial {
|
||||
self.zone
|
||||
.lock()
|
||||
.upgrade()
|
||||
.and_then(|zone| zone.field.upgrade())
|
||||
.map(|zone| zone.field.clone())
|
||||
.map(|field| field.distance(self, vec3a(0.0, 0.0, 0.0)))
|
||||
.unwrap_or(f32::MAX)
|
||||
}
|
||||
@@ -359,13 +356,12 @@ impl SpatialAspect for Spatial {
|
||||
}
|
||||
impl PartialEq for Spatial {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.uid == other.uid
|
||||
self.node.as_ptr() == other.node.as_ptr()
|
||||
}
|
||||
}
|
||||
impl Debug for Spatial {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Spatial")
|
||||
.field("uid", &self.uid)
|
||||
.field("parent", &self.parent)
|
||||
.field("old_parent", &self.old_parent)
|
||||
.field("transform", &self.transform)
|
||||
@@ -374,7 +370,7 @@ impl Debug for Spatial {
|
||||
}
|
||||
impl Drop for Spatial {
|
||||
fn drop(&mut self) {
|
||||
zone::release_drop(self);
|
||||
zone::release(self);
|
||||
ZONEABLE_REGISTRY.remove(self);
|
||||
}
|
||||
}
|
||||
@@ -397,26 +393,25 @@ pub fn parse_transform(transform: Transform, position: bool, rotation: bool, sca
|
||||
}
|
||||
|
||||
pub struct SpatialInterface;
|
||||
impl SpatialInterfaceAspect for SpatialInterface {
|
||||
impl InterfaceAspect for SpatialInterface {
|
||||
fn create_spatial(
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
name: String,
|
||||
id: u64,
|
||||
parent: Arc<Node>,
|
||||
transform: Transform,
|
||||
zoneable: bool,
|
||||
) -> Result<()> {
|
||||
let parent = parent.get_aspect::<Spatial>()?;
|
||||
let transform = parse_transform(transform, true, true, true);
|
||||
let node = Node::create_parent_name(&calling_client, "/spatial/spatial", &name, true)
|
||||
.add_to_scenegraph()?;
|
||||
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
|
||||
Spatial::add_to(&node, Some(parent.clone()), transform, zoneable);
|
||||
Ok(())
|
||||
}
|
||||
fn create_zone(
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
name: String,
|
||||
id: u64,
|
||||
parent: Arc<Node>,
|
||||
transform: Transform,
|
||||
field: Arc<Node>,
|
||||
@@ -425,12 +420,11 @@ impl SpatialInterfaceAspect for SpatialInterface {
|
||||
let transform = parse_transform(transform, true, true, false);
|
||||
let field = field.get_aspect::<Field>()?;
|
||||
|
||||
let node = Node::create_parent_name(&calling_client, "/spatial/zone", &name, true)
|
||||
.add_to_scenegraph()?;
|
||||
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
|
||||
let space = Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||
Zone::add_to(&node, space, &field);
|
||||
Zone::add_to(&node, space, field);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
create_interface!(SpatialInterface, SpatialInterfaceAspect, "/spatial");
|
||||
create_interface!(SpatialInterface);
|
||||
|
||||
@@ -1,166 +1,147 @@
|
||||
use super::{Spatial, ZoneAspect, ZONEABLE_REGISTRY};
|
||||
use super::{
|
||||
Spatial, ZoneAspect, SPATIAL_ASPECT_ALIAS_INFO, SPATIAL_REF_ASPECT_ALIAS_INFO,
|
||||
ZONEABLE_REGISTRY,
|
||||
};
|
||||
use crate::{
|
||||
core::{client::Client, registry::Registry},
|
||||
nodes::{
|
||||
alias::{Alias, AliasInfo},
|
||||
alias::{get_original, Alias, AliasList},
|
||||
fields::Field,
|
||||
Aspect, Node,
|
||||
},
|
||||
};
|
||||
use color_eyre::eyre::Result;
|
||||
use glam::vec3a;
|
||||
use parking_lot::Mutex;
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
pub fn capture(spatial: &Arc<Spatial>, zone: &Arc<Zone>) {
|
||||
let old_distance = spatial.zone_distance();
|
||||
let new_distance = zone
|
||||
.field
|
||||
.upgrade()
|
||||
.map(|field| field.distance(spatial, vec3a(0.0, 0.0, 0.0)))
|
||||
.unwrap_or(f32::MAX);
|
||||
let new_distance = zone.field.distance(spatial, vec3a(0.0, 0.0, 0.0));
|
||||
if new_distance.abs() < old_distance.abs() {
|
||||
release(spatial);
|
||||
*spatial.old_parent.lock() = spatial.get_parent();
|
||||
*spatial.zone.lock() = Arc::downgrade(zone);
|
||||
zone.captured.add_raw(spatial);
|
||||
let Some(node) = zone.spatial.node.upgrade() else {
|
||||
let Some(zone_node) = zone.spatial.node.upgrade() else {
|
||||
return;
|
||||
};
|
||||
let _ = super::zone_client::capture(&node, &spatial.uid);
|
||||
let Some(spatial_node) = spatial.node.upgrade() else {
|
||||
return;
|
||||
};
|
||||
let Ok(spatial_alias) = Alias::create(
|
||||
&spatial_node,
|
||||
&zone_node.get_client().unwrap(),
|
||||
SPATIAL_ASPECT_ALIAS_INFO.clone(),
|
||||
Some(&zone.captured),
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
let _ = super::zone_client::capture(&zone_node, &spatial_alias);
|
||||
}
|
||||
}
|
||||
pub fn release(spatial: &Arc<Spatial>) {
|
||||
pub fn release(spatial: &Spatial) {
|
||||
let Some(spatial_node) = spatial.node.upgrade() else {
|
||||
return;
|
||||
};
|
||||
let spatial = spatial_node.get_aspect::<Spatial>().unwrap();
|
||||
|
||||
let _ = spatial.set_spatial_parent_in_place(spatial.old_parent.lock().take().as_ref());
|
||||
let mut spatial_zone = spatial.zone.lock();
|
||||
|
||||
if let Some(spatial_zone) = spatial_zone.upgrade() {
|
||||
spatial_zone.captured.remove_aspect(spatial.as_ref());
|
||||
let Some(node) = spatial_zone.spatial.node.upgrade() else {
|
||||
return;
|
||||
};
|
||||
spatial_zone.captured.remove(spatial);
|
||||
let _ = super::zone_client::release(&node, &spatial.uid);
|
||||
let _ = super::zone_client::release(&node, spatial_node.id);
|
||||
}
|
||||
*spatial_zone = Weak::new();
|
||||
}
|
||||
pub(super) fn release_drop(spatial: &Spatial) {
|
||||
let spatial_zone = spatial.zone.lock();
|
||||
if let Some(spatial_zone) = spatial_zone.upgrade() {
|
||||
let Some(node) = spatial_zone.spatial.node.upgrade() else {
|
||||
return;
|
||||
};
|
||||
spatial_zone.captured.remove(spatial);
|
||||
let _ = super::zone_client::release(&node, &spatial.uid);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Zone {
|
||||
spatial: Arc<Spatial>,
|
||||
pub field: Weak<Field>,
|
||||
zoneables: Mutex<FxHashMap<String, Arc<Node>>>,
|
||||
captured: Registry<Spatial>,
|
||||
pub field: Arc<Field>,
|
||||
intersecting_spatials: Registry<Spatial>,
|
||||
intersecting: AliasList,
|
||||
captured: AliasList,
|
||||
}
|
||||
impl Zone {
|
||||
pub fn add_to(node: &Arc<Node>, spatial: Arc<Spatial>, field: &Arc<Field>) -> Arc<Zone> {
|
||||
pub fn add_to(node: &Arc<Node>, spatial: Arc<Spatial>, field: Arc<Field>) -> Arc<Zone> {
|
||||
let zone = Arc::new(Zone {
|
||||
spatial,
|
||||
field: Arc::downgrade(field),
|
||||
zoneables: Mutex::new(FxHashMap::default()),
|
||||
captured: Registry::new(),
|
||||
field,
|
||||
intersecting_spatials: Registry::default(),
|
||||
intersecting: AliasList::default(),
|
||||
captured: AliasList::default(),
|
||||
});
|
||||
<Zone as ZoneAspect>::add_node_members(node);
|
||||
node.add_aspect_raw(zone.clone());
|
||||
zone
|
||||
}
|
||||
pub fn update(&self) -> Result<()> {
|
||||
let node = self.spatial.node().unwrap();
|
||||
|
||||
let current_zoneables = Registry::new();
|
||||
for zoneable in ZONEABLE_REGISTRY.get_valid_contents() {
|
||||
let distance = self.field.distance(&zoneable, [0.0; 3].into());
|
||||
if distance > 0.0 {
|
||||
continue;
|
||||
}
|
||||
if let Some(zone) = zoneable.zone.lock().upgrade() {
|
||||
let zoneable_distance = zone.field.distance(&zoneable, [0.0; 3].into());
|
||||
if zoneable_distance < distance {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
current_zoneables.add_raw(&zoneable);
|
||||
}
|
||||
|
||||
let (added, removed) =
|
||||
Registry::get_changes(&self.intersecting_spatials, ¤t_zoneables);
|
||||
for added in added {
|
||||
let Some(added_node) = added.node() else {
|
||||
continue;
|
||||
};
|
||||
let Ok(alias) = Alias::create(
|
||||
&added_node,
|
||||
&self.spatial.node().unwrap().get_client().unwrap(),
|
||||
SPATIAL_REF_ASPECT_ALIAS_INFO.clone(),
|
||||
Some(&self.intersecting),
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
let _ = super::zone_client::enter(&node, &alias);
|
||||
}
|
||||
for removed in removed {
|
||||
let Some(removed_node) = removed.node() else {
|
||||
continue;
|
||||
};
|
||||
release(&removed);
|
||||
let _ = super::zone_client::leave(&node, removed_node.id);
|
||||
self.intersecting.remove_aspect(removed.as_ref());
|
||||
}
|
||||
self.intersecting_spatials.set(¤t_zoneables);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl Aspect for Zone {
|
||||
const NAME: &'static str = "Zone";
|
||||
}
|
||||
impl ZoneAspect for Zone {
|
||||
fn update(node: Arc<Node>, _calling_client: Arc<Client>) -> color_eyre::eyre::Result<()> {
|
||||
fn update(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
|
||||
let zone = node.get_aspect::<Zone>()?;
|
||||
let Some(field) = zone.field.upgrade() else {
|
||||
return Err(color_eyre::eyre::eyre!("Zone's field has been destroyed"));
|
||||
};
|
||||
let Some((zone_client, zone_node)) = zone
|
||||
.spatial
|
||||
.node
|
||||
.upgrade()
|
||||
.and_then(|n| n.get_client().zip(Some(n)))
|
||||
else {
|
||||
return Err(color_eyre::eyre::eyre!("No client on node?"));
|
||||
};
|
||||
let mut old_zoneables = zone.zoneables.lock();
|
||||
for (_uid, zoneable) in old_zoneables.iter() {
|
||||
zoneable.destroy();
|
||||
}
|
||||
let captured = zone.captured.get_valid_contents();
|
||||
let zoneables = ZONEABLE_REGISTRY
|
||||
.get_valid_contents()
|
||||
.into_iter()
|
||||
.filter(|zoneable| zoneable.node.upgrade().is_some())
|
||||
.filter(|zoneable| {
|
||||
if captured
|
||||
.iter()
|
||||
.any(|captured| Arc::ptr_eq(captured, zoneable))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
let spatial_zone_distance = zoneable.zone_distance();
|
||||
let self_zone_distance = field.distance(zoneable, vec3a(0.0, 0.0, 0.0));
|
||||
self_zone_distance < 0.0 && spatial_zone_distance > self_zone_distance
|
||||
})
|
||||
.filter_map(|zoneable| {
|
||||
let alias = Alias::create(
|
||||
&zone_client,
|
||||
zone_node.get_path(),
|
||||
&zoneable.uid,
|
||||
&zoneable.node.upgrade().unwrap(),
|
||||
AliasInfo {
|
||||
server_signals: vec![
|
||||
"set_transform",
|
||||
"set_spatial_parent",
|
||||
"set_spatial_parent_in_place",
|
||||
],
|
||||
server_methods: vec!["get_bounds", "get_transform"],
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.ok()?;
|
||||
Some((zoneable.uid.clone(), alias))
|
||||
})
|
||||
.collect::<FxHashMap<String, Arc<Node>>>();
|
||||
|
||||
for (uid, zoneable) in zoneables
|
||||
.iter()
|
||||
.filter(|(k, _)| !old_zoneables.contains_key(*k))
|
||||
{
|
||||
super::zone_client::enter(&node, uid, zoneable)?;
|
||||
}
|
||||
for left_uid in old_zoneables.keys().filter(|k| !zoneables.contains_key(*k)) {
|
||||
super::zone_client::leave(&node, &left_uid)?;
|
||||
}
|
||||
|
||||
*old_zoneables = zoneables;
|
||||
|
||||
let _ = zone.update();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn capture(
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
spatial: Arc<Node>,
|
||||
) -> color_eyre::eyre::Result<()> {
|
||||
fn capture(node: Arc<Node>, _calling_client: Arc<Client>, spatial: Arc<Node>) -> Result<()> {
|
||||
let zone = node.get_aspect::<Zone>()?;
|
||||
let spatial = spatial.get_aspect()?;
|
||||
capture(&spatial, &zone);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn release(
|
||||
_node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
spatial: Arc<Node>,
|
||||
) -> color_eyre::eyre::Result<()> {
|
||||
fn release(_node: Arc<Node>, _calling_client: Arc<Client>, spatial: Arc<Node>) -> Result<()> {
|
||||
let spatial = spatial.get_aspect()?;
|
||||
release(&spatial);
|
||||
Ok(())
|
||||
@@ -168,7 +149,13 @@ impl ZoneAspect for Zone {
|
||||
}
|
||||
impl Drop for Zone {
|
||||
fn drop(&mut self) {
|
||||
for captured in self.captured.get_valid_contents() {
|
||||
for captured in self
|
||||
.captured
|
||||
.get_aliases()
|
||||
.into_iter()
|
||||
.filter_map(get_original)
|
||||
.filter_map(|n| n.get_aspect::<Spatial>().ok())
|
||||
{
|
||||
release(&captured);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user