Skip to content

Commit

Permalink
Add Reflect and FromReflect for AssetPath (#8531)
Browse files Browse the repository at this point in the history
# Objective

- Add Reflect and FromReflect for AssetPath
- Fixes #8458

## Solution

- Straightforward derive of `Reflect` and `FromReflect` for `AssetPath`
- Implement `Reflect` and `FromReflect` for `Cow<'static, Path>` as to
satisfy the 'static lifetime requierments of bevy_reflect.
Implementation is a direct copy of that for `Cow<'static, str>` so maybe
it begs the question that was already asked in #7429 - maybe it would be
benefitial to write a general implementation for `Reflect` for
`Cow<'static, T>`.
  • Loading branch information
minchopaskal authored May 8, 2023
1 parent 57fdb83 commit fe57b9f
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 6 deletions.
6 changes: 4 additions & 2 deletions crates/bevy_asset/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,10 @@ impl Plugin for AssetPlugin {
app.insert_resource(asset_server);
}

app.register_type::<HandleId>()
.add_systems(PreUpdate, asset_server::free_unused_assets_system);
app.register_type::<HandleId>();
app.register_type::<AssetPath>();

app.add_systems(PreUpdate, asset_server::free_unused_assets_system);
app.init_schedule(LoadAssets);
app.init_schedule(AssetEvents);

Expand Down
7 changes: 5 additions & 2 deletions crates/bevy_asset/src/path.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use bevy_reflect::{
FromReflect, Reflect, ReflectDeserialize, ReflectFromReflect, ReflectSerialize,
};
use bevy_utils::AHasher;
use serde::{Deserialize, Serialize};
use std::{
Expand All @@ -8,7 +10,8 @@ use std::{
};

/// Represents a path to an asset in the file system.
#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize)]
#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, Reflect, FromReflect)]
#[reflect(Debug, PartialEq, Hash, Serialize, Deserialize, FromReflect)]
pub struct AssetPath<'a> {
path: Cow<'a, Path>,
label: Option<Cow<'a, str>>,
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use std::borrow::Cow;
use std::ffi::OsString;
use std::marker::PhantomData;
use std::ops::Range;
use std::path::PathBuf;
use std::path::{Path, PathBuf};

#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(target_arch = "wasm32"))]
Expand Down Expand Up @@ -59,6 +59,7 @@ fn register_rust_types(app: &mut App) {
.register_type::<Option<bool>>()
.register_type::<Option<f64>>()
.register_type::<Cow<'static, str>>()
.register_type::<Cow<'static, Path>>()
.register_type::<Duration>()
.register_type::<Instant>();
}
Expand Down
111 changes: 110 additions & 1 deletion crates/bevy_reflect/src/impls/std.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::std_traits::ReflectDefault;
use crate::{self as bevy_reflect, ReflectFromPtr, ReflectOwned};
use crate::{self as bevy_reflect, ReflectFromPtr, ReflectFromReflect, ReflectOwned};
use crate::{
map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, DynamicMap, Enum,
EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, MapInfo, MapIter,
Expand All @@ -12,6 +12,7 @@ use crate::utility::{reflect_hasher, GenericTypeInfoCell, NonGenericTypeInfoCell
use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_value};
use bevy_utils::HashSet;
use bevy_utils::{Duration, Instant};
use std::fmt;
use std::{
any::Any,
borrow::Cow,
Expand Down Expand Up @@ -1169,6 +1170,114 @@ impl FromReflect for &'static Path {
}
}

impl Reflect for Cow<'static, Path> {
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}

fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
Some(<Self as Typed>::type_info())
}

fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}

fn as_any(&self) -> &dyn Any {
self
}

fn as_any_mut(&mut self) -> &mut dyn Any {
self
}

fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
self
}

fn as_reflect(&self) -> &dyn Reflect {
self
}

fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}

fn apply(&mut self, value: &dyn Reflect) {
let value = value.as_any();
if let Some(value) = value.downcast_ref::<Self>() {
*self = value.clone();
} else {
panic!("Value is not a {}.", std::any::type_name::<Self>());
}
}

fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
*self = value.take()?;
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 clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone())
}

fn reflect_hash(&self) -> Option<u64> {
let mut hasher = reflect_hasher();
Hash::hash(&std::any::Any::type_id(self), &mut hasher);
Hash::hash(self, &mut hasher);
Some(hasher.finish())
}

fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
let value = value.as_any();
if let Some(value) = value.downcast_ref::<Self>() {
Some(std::cmp::PartialEq::eq(self, value))
} else {
Some(false)
}
}

fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fmt::Debug::fmt(&self, f)
}
}

impl Typed for Cow<'static, Path> {
fn type_info() -> &'static TypeInfo {
static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::<Self>()))
}
}

impl FromReflect for Cow<'static, Path> {
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
Some(reflect.as_any().downcast_ref::<Self>()?.clone())
}
}

impl GetTypeRegistration for Cow<'static, Path> {
fn get_type_registration() -> TypeRegistration {
let mut registration = TypeRegistration::of::<Self>();
registration.insert::<ReflectDeserialize>(FromType::<Self>::from_type());
registration.insert::<ReflectFromPtr>(FromType::<Self>::from_type());
registration.insert::<ReflectSerialize>(FromType::<Self>::from_type());
registration.insert::<ReflectFromReflect>(FromType::<Self>::from_type());
registration
}
}

#[cfg(test)]
mod tests {
use crate as bevy_reflect;
Expand Down

0 comments on commit fe57b9f

Please sign in to comment.