diff --git a/fyrox-resource/src/lib.rs b/fyrox-resource/src/lib.rs index 9f8340f73..eb7b153fe 100644 --- a/fyrox-resource/src/lib.rs +++ b/fyrox-resource/src/lib.rs @@ -39,6 +39,7 @@ use crate::{ }; use fxhash::FxHashSet; pub use fyrox_core as core; +use serde::{Deserialize, Serialize}; use std::{ any::Any, error::Error, @@ -197,7 +198,12 @@ where /// ## Default State /// /// Default state of the resource will be [`ResourceState::Ok`] with `T::default`. -#[derive(Reflect)] +#[derive(Reflect, Serialize, Deserialize)] +#[serde( + bound = "T: TypedResourceData", + from = "UntypedResource", + into = "UntypedResource" +)] pub struct Resource { untyped: UntypedResource, #[reflect(hidden)] @@ -448,10 +454,12 @@ where { #[inline] fn from(untyped: UntypedResource) -> Self { - assert_eq!( - untyped.type_uuid(), - Some(::type_uuid()) - ); + if let Some(type_uuid) = untyped.type_uuid() { + let expected = ::type_uuid(); + if type_uuid != expected { + panic!("Resource type mismatch. Expected: {expected}. Found: {type_uuid}"); + } + } Self { untyped, phantom: Default::default(), @@ -834,6 +842,24 @@ mod tests { } } + #[test] + fn test_serialize() { + let uuid = uuid!("6d1aadb5-42e1-485b-910b-fa4d81b61855"); + let typed = Resource::::from(uuid); + let untyped = UntypedResource::from(uuid); + let s = ron::ser::to_string(&typed).unwrap(); + assert_eq!(&ron::ser::to_string(&uuid).unwrap(), &s); + assert_eq!(&ron::ser::to_string(&untyped).unwrap(), &s); + let output_uuid = ron::de::from_str::(&s).unwrap(); + assert_eq!(output_uuid, uuid); + let untyped = ron::de::from_str::(&s).unwrap(); + assert_eq!(untyped.resource_uuid(), uuid); + assert_eq!(untyped.kind(), ResourceKind::External); + let output = ron::de::from_str::>(&s).unwrap(); + assert_eq!(output.resource_uuid(), uuid); + assert_eq!(output.kind(), ResourceKind::External); + } + #[test] fn test_registry_scan() { write_test_resources(TEST_FOLDER1, 0..2); diff --git a/fyrox-resource/src/untyped.rs b/fyrox-resource/src/untyped.rs index bdd245e0d..16326ca76 100644 --- a/fyrox-resource/src/untyped.rs +++ b/fyrox-resource/src/untyped.rs @@ -37,6 +37,7 @@ use fyrox_core::io::FileError; use fyrox_core::log::Log; use fyrox_core::parking_lot::MutexGuard; use fyrox_core::SafeLock; +use serde::{Deserialize, Serialize}; use std::fmt::Write; use std::{ error::Error, @@ -451,10 +452,24 @@ impl Visit for ResourceHeader { /// that the resource is in default state. This is a trade-off to prevent wrapping internals into /// `Option`, that in some cases could lead to convoluted code with lots of `unwrap`s and state /// assumptions. -#[derive(Default, Clone, Reflect, TypeUuidProvider)] +#[derive(Default, Clone, Reflect, TypeUuidProvider, Deserialize)] +#[serde(from = "Uuid")] #[type_uuid(id = "21613484-7145-4d1c-87d8-62fa767560ab")] pub struct UntypedResource(pub Arc>); +impl Serialize for UntypedResource { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let header = self.lock(); + if header.kind == ResourceKind::Embedded { + panic!("Embedded resources cannot be serialized."); + } + header.uuid.serialize(serializer) + } +} + impl Visit for UntypedResource { fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult { let result = self.visit_with_type_uuid(name, None, visitor);