2020-05-03 01:35:18 +00:00
|
|
|
use std::{
|
|
|
|
fmt::Debug,
|
|
|
|
hash::{Hash, Hasher},
|
|
|
|
};
|
|
|
|
|
|
|
|
use std::{any::TypeId, marker::PhantomData};
|
2020-05-25 19:03:50 +00:00
|
|
|
use serde::{Serialize, Deserialize};
|
2020-05-03 01:35:18 +00:00
|
|
|
use uuid::Uuid;
|
2020-05-25 19:03:50 +00:00
|
|
|
use bevy_property::{Properties, Property, AsProperties};
|
2020-05-03 01:35:18 +00:00
|
|
|
|
2020-05-25 19:03:50 +00:00
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
2020-05-03 19:35:07 +00:00
|
|
|
pub struct HandleId(pub Uuid);
|
2020-05-06 01:44:32 +00:00
|
|
|
pub const DEFAULT_HANDLE_ID: HandleId =
|
|
|
|
HandleId(Uuid::from_u128(240940089166493627844978703213080810552));
|
2020-05-03 01:35:18 +00:00
|
|
|
|
|
|
|
impl HandleId {
|
|
|
|
pub fn new() -> HandleId {
|
|
|
|
HandleId(Uuid::new_v4())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-25 19:03:50 +00:00
|
|
|
impl Property for HandleId {
|
|
|
|
fn any(&self) -> &dyn std::any::Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
fn any_mut(&mut self) -> &mut dyn std::any::Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
fn clone_prop(&self) -> Box<dyn Property> {
|
|
|
|
Box::new(self.clone())
|
|
|
|
}
|
|
|
|
fn set(&mut self, value: &dyn Property) {
|
|
|
|
let value = value.any();
|
|
|
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
|
|
|
*self = *prop;
|
|
|
|
} else {
|
|
|
|
panic!("prop value is not {}", std::any::type_name::<Self>());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn apply(&mut self, value: &dyn Property) {
|
|
|
|
self.set(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AsProperties for HandleId {
|
|
|
|
fn as_properties(&self) -> Option<&dyn Properties> {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Properties)]
|
|
|
|
pub struct Handle<T> where T: 'static {
|
2020-05-03 01:35:18 +00:00
|
|
|
pub id: HandleId,
|
2020-05-25 19:03:50 +00:00
|
|
|
#[prop(ignore)]
|
2020-05-03 01:35:18 +00:00
|
|
|
marker: PhantomData<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Handle<T> {
|
2020-05-07 02:26:28 +00:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Handle {
|
|
|
|
id: HandleId::new(),
|
|
|
|
marker: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub const fn from_id(id: HandleId) -> Self {
|
2020-05-03 01:35:18 +00:00
|
|
|
Handle {
|
|
|
|
id,
|
|
|
|
marker: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-04 18:20:12 +00:00
|
|
|
pub const fn from_u128(value: u128) -> Self {
|
|
|
|
Handle {
|
|
|
|
id: HandleId(Uuid::from_u128(value)),
|
|
|
|
marker: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-03 19:35:07 +00:00
|
|
|
pub const fn from_bytes(bytes: [u8; 16]) -> Self {
|
|
|
|
Handle {
|
|
|
|
id: HandleId(Uuid::from_bytes(bytes)),
|
|
|
|
marker: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-03 01:35:18 +00:00
|
|
|
pub fn from_untyped(untyped_handle: HandleUntyped) -> Option<Handle<T>>
|
|
|
|
where
|
|
|
|
T: 'static,
|
|
|
|
{
|
|
|
|
if TypeId::of::<T>() == untyped_handle.type_id {
|
2020-05-07 02:26:28 +00:00
|
|
|
Some(Handle::from_id(untyped_handle.id))
|
2020-05-03 01:35:18 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-15 23:55:44 +00:00
|
|
|
impl<T> From<HandleId> for Handle<T> {
|
|
|
|
fn from(value: HandleId) -> Self {
|
|
|
|
Handle::from_id(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> From<u128> for Handle<T> {
|
|
|
|
fn from(value: u128) -> Self {
|
|
|
|
Handle::from_u128(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> From<[u8; 16]> for Handle<T> {
|
|
|
|
fn from(value: [u8; 16]) -> Self {
|
|
|
|
Handle::from_bytes(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> From<HandleUntyped> for Handle<T>
|
|
|
|
where
|
|
|
|
T: 'static,
|
|
|
|
{
|
|
|
|
fn from(handle: HandleUntyped) -> Self {
|
|
|
|
if TypeId::of::<T>() == handle.type_id {
|
|
|
|
Handle {
|
|
|
|
id: handle.id,
|
|
|
|
marker: PhantomData::default(),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
panic!("attempted to convert untyped handle to incorrect typed handle")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-03 01:35:18 +00:00
|
|
|
impl<T> Hash for Handle<T> {
|
|
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
|
|
self.id.hash(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> PartialEq for Handle<T> {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
self.id == other.id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Eq for Handle<T> {}
|
|
|
|
|
|
|
|
impl<T> Debug for Handle<T> {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
|
|
|
let name = std::any::type_name::<T>().split("::").last().unwrap();
|
|
|
|
write!(f, "Handle<{}>({:?})", name, self.id.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Default for Handle<T> {
|
|
|
|
fn default() -> Self {
|
|
|
|
Handle {
|
|
|
|
id: DEFAULT_HANDLE_ID,
|
|
|
|
marker: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Clone for Handle<T> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Handle {
|
|
|
|
id: self.id.clone(),
|
|
|
|
marker: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl<T> Copy for Handle<T> {}
|
|
|
|
|
2020-05-25 19:03:50 +00:00
|
|
|
// SAFE: T is phantom data and Handle::id is an integer
|
|
|
|
unsafe impl<T> Send for Handle<T> {}
|
|
|
|
unsafe impl<T> Sync for Handle<T> {}
|
|
|
|
|
2020-05-03 01:35:18 +00:00
|
|
|
#[derive(Hash, Copy, Clone, Eq, PartialEq, Debug)]
|
|
|
|
pub struct HandleUntyped {
|
|
|
|
pub id: HandleId,
|
|
|
|
pub type_id: TypeId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HandleUntyped {
|
|
|
|
pub fn is_handle<T: 'static>(untyped: &HandleUntyped) -> bool {
|
|
|
|
TypeId::of::<T>() == untyped.type_id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> From<Handle<T>> for HandleUntyped
|
|
|
|
where
|
|
|
|
T: 'static,
|
|
|
|
{
|
|
|
|
fn from(handle: Handle<T>) -> Self {
|
|
|
|
HandleUntyped {
|
|
|
|
id: handle.id,
|
|
|
|
type_id: TypeId::of::<T>(),
|
|
|
|
}
|
|
|
|
}
|
2020-05-16 07:27:30 +00:00
|
|
|
}
|