Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manual "Reflect Value" AssetPath impl to fix dynamic linking #9752

Merged
merged 5 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 138 additions & 5 deletions crates/bevy_asset/src/path.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use bevy_reflect::{
std_traits::ReflectDefault, utility::NonGenericTypeInfoCell, FromReflect, FromType,
GetTypeRegistration, Reflect, ReflectDeserialize, ReflectFromPtr, ReflectFromReflect,
ReflectMut, ReflectOwned, ReflectRef, ReflectSerialize, TypeInfo, TypePath, TypeRegistration,
Typed, ValueInfo,
};
use bevy_utils::CowArc;
use serde::{de::Visitor, ser::SerializeTupleStruct, Deserialize, Serialize};
use std::{
fmt::{Debug, Display},
hash::Hash,
hash::{Hash, Hasher},
ops::Deref,
path::{Path, PathBuf},
};
Expand All @@ -19,7 +24,7 @@ use std::{
///
/// ```no_run
/// # use bevy_asset::{Asset, AssetServer, Handle};
/// # use bevy_reflect::TypePath;
/// # use TypePath;
/// #
/// # #[derive(Asset, TypePath, Default)]
/// # struct Mesh;
Expand All @@ -40,8 +45,8 @@ use std::{
/// This means that the common case of `asset_server.load("my_scene.scn")` when it creates and
/// clones internal owned [`AssetPaths`](AssetPath).
/// This also means that you should use [`AssetPath::new`] in cases where `&str` is the explicit type.
#[derive(Eq, PartialEq, Hash, Clone, Reflect)]
#[reflect(Debug, PartialEq, Hash, Serialize, Deserialize)]
#[derive(Eq, PartialEq, Hash, Clone, Default)]
// #[reflect(Debug, PartialEq, Hash, Serialize, Deserialize)]
pub struct AssetPath<'a> {
cart marked this conversation as resolved.
Show resolved Hide resolved
path: CowArc<'a, Path>,
label: Option<CowArc<'a, str>>,
Expand Down Expand Up @@ -270,3 +275,131 @@ impl<'de> Visitor<'de> for AssetPathVisitor {
Ok(AssetPath::from(v))
}
}

#[allow(unused_mut)]
impl GetTypeRegistration for AssetPath<'static> {
cart marked this conversation as resolved.
Show resolved Hide resolved
fn get_type_registration() -> TypeRegistration {
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
let mut registration = TypeRegistration::of::<Self>();
registration.insert::<ReflectFromPtr>(FromType::<Self>::from_type());
registration.insert::<ReflectFromReflect>(FromType::<Self>::from_type());
registration.insert::<ReflectSerialize>(FromType::<Self>::from_type());
registration.insert::<ReflectDeserialize>(FromType::<Self>::from_type());
registration.insert::<ReflectDefault>(FromType::<Self>::from_type());
registration
}
}

impl TypePath for AssetPath<'static> {
fn type_path() -> &'static str {
"AssetPath<'static>"
}
cart marked this conversation as resolved.
Show resolved Hide resolved
fn short_type_path() -> &'static str {
"AssetPath<'static>"
}
fn type_ident() -> Option<&'static str> {
Some("AssetPath<'static>")
}
fn crate_name() -> Option<&'static str> {
Option::None
}
fn module_path() -> Option<&'static str> {
Option::None
}
}
impl Typed for AssetPath<'static> {
fn type_info() -> &'static TypeInfo {
static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
CELL.get_or_set(|| {
let info = ValueInfo::new::<Self>();
TypeInfo::Value(info)
})
}
}
impl Reflect for AssetPath<'static> {
#[inline]
fn type_name(&self) -> &str {
::core::any::type_name::<Self>()
}
#[inline]
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
Some(<Self as Typed>::type_info())
}
#[inline]
fn into_any(self: Box<Self>) -> Box<dyn ::core::any::Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn ::core::any::Any {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any {
self
}
#[inline]
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn Reflect {
self
}
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}
#[inline]
fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Reflect) {
let value = Reflect::as_any(value);
if let Some(value) = value.downcast_ref::<Self>() {
*self = value.clone();
} else {
panic!("Value is not {}.", std::any::type_name::<Self>());
}
}
#[inline]
fn set(
&mut self,
value: Box<dyn bevy_reflect::Reflect>,
) -> Result<(), Box<dyn bevy_reflect::Reflect>> {
*self = <dyn bevy_reflect::Reflect>::take(value)?;
Ok(())
}
fn reflect_ref(&self) -> ReflectRef {
ReflectRef::Value(self)
}
fn reflect_mut(&mut self) -> ReflectMut {
ReflectMut::Value(self)
}
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Value(self)
}
fn reflect_hash(&self) -> Option<u64> {
let mut hasher = bevy_reflect::utility::reflect_hasher();
Hash::hash(&::core::any::Any::type_id(self), &mut hasher);
Hash::hash(self, &mut hasher);
Some(Hasher::finish(&hasher))
}
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
let value = <dyn Reflect>::as_any(value);
if let Some(value) = <dyn ::core::any::Any>::downcast_ref::<Self>(value) {
Some(::core::cmp::PartialEq::eq(self, value))
} else {
Some(false)
}
}
fn debug(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
::core::fmt::Debug::fmt(self, f)
}
}
impl FromReflect for AssetPath<'static> {
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
Some(Clone::clone(<dyn ::core::any::Any>::downcast_ref::<
AssetPath<'static>,
>(<dyn Reflect>::as_any(reflect))?))
}
}
12 changes: 12 additions & 0 deletions crates/bevy_utils/src/cow_arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,18 @@ impl<'a, T: PartialOrd + ?Sized> PartialOrd for CowArc<'a, T> {
}
}

impl Default for CowArc<'static, str> {
fn default() -> Self {
CowArc::Static(Default::default())
}
}

impl Default for CowArc<'static, Path> {
fn default() -> Self {
CowArc::Static(Path::new(""))
}
}

impl<'a, T: Ord + ?Sized> Ord for CowArc<'a, T> {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
Expand Down
Loading