use ::serde;
use bevy::reflect::{serde::*, *};
use bevy::{asset::LoadContext, prelude::*};
pub trait MaterialProcessor: TypePath + Clone + Send + Sync + 'static {
type Child: MaterialProcessor;
fn child(&self) -> Option<&Self::Child>;
fn try_deserialize<'de, D: serde::Deserializer<'de>>(
&self,
ctx: &mut MaterialProcessorContext,
registration: &TypeRegistration,
registry: &TypeRegistry,
deserializer: D,
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error>;
fn try_deserialize_recursive<'de, D: serde::Deserializer<'de>>(
&self,
ctx: &mut MaterialProcessorContext,
registration: &TypeRegistration,
registry: &TypeRegistry,
deserializer: D,
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error> {
if let Some(child) = self.child() {
match child.try_deserialize_recursive(ctx, registration, registry, deserializer) {
Ok(Err(returned_deserializer)) => self.try_deserialize(ctx, registration, registry, returned_deserializer),
out => out,
}
} else {
Ok(Err(deserializer))
}
}
}
impl MaterialProcessor for () {
type Child = Self;
fn child(&self) -> Option<&Self::Child> {
None
}
fn try_deserialize<'de, D: serde::Deserializer<'de>>(
&self,
_ctx: &mut MaterialProcessorContext,
_registration: &TypeRegistration,
_registry: &TypeRegistry,
deserializer: D,
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error> {
Ok(Err(deserializer))
}
}
pub struct MaterialProcessorContext<'w, 'l> {
pub load_context: &'l mut LoadContext<'w>,
}
pub struct MaterialDeserializerProcessor<'w, 'l, P: MaterialProcessor> {
pub ctx: MaterialProcessorContext<'w, 'l>,
pub material_processor: &'l P,
}
impl<P: MaterialProcessor> ReflectDeserializerProcessor for MaterialDeserializerProcessor<'_, '_, P> {
fn try_deserialize<'de, D: serde::Deserializer<'de>>(
&mut self,
registration: &TypeRegistration,
registry: &TypeRegistry,
deserializer: D,
) -> Result<Result<Box<dyn PartialReflect>, D>, D::Error> {
self.material_processor
.try_deserialize_recursive(&mut self.ctx, registration, registry, deserializer)
}
}