diff --git a/assets/scenes/load_scene_example.scn.ron b/assets/scenes/load_scene_example.scn.ron index 015b41774f3c0..696f0c79274f1 100644 --- a/assets/scenes/load_scene_example.scn.ron +++ b/assets/scenes/load_scene_example.scn.ron @@ -1,44 +1,46 @@ -[ - ( - entity: 0, - components: [ - { - "bevy_transform::components::transform::Transform": ( - translation: ( - x: 0.0, - y: 0.0, - z: 0.0 +( + entities: [ + ( + entity: 0, + components: [ + { + "bevy_transform::components::transform::Transform": ( + translation: ( + x: 0.0, + y: 0.0, + z: 0.0 + ), + rotation: (0.0, 0.0, 0.0, 1.0), + scale: ( + x: 1.0, + y: 1.0, + z: 1.0 + ), ), - rotation: (0.0, 0.0, 0.0, 1.0), - scale: ( + }, + { + "scene::ComponentB": ( + value: "hello", + ), + }, + { + "scene::ComponentA": ( x: 1.0, - y: 1.0, - z: 1.0 + y: 2.0, + ), + }, + ], + ), + ( + entity: 1, + components: [ + { + "scene::ComponentA": ( + x: 3.0, + y: 4.0, ), - ), - }, - { - "scene::ComponentB": ( - value: "hello", - ), - }, - { - "scene::ComponentA": ( - x: 1.0, - y: 2.0, - ), - }, - ], - ), - ( - entity: 1, - components: [ - { - "scene::ComponentA": ( - x: 3.0, - y: 4.0, - ), - }, - ], - ), -] + }, + ], + ), + ] +) diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index 8a3e5383af170..7515785692a8c 100644 --- a/crates/bevy_scene/src/serde.rs +++ b/crates/bevy_scene/src/serde.rs @@ -7,8 +7,16 @@ use bevy_reflect::{ use serde::{ de::{DeserializeSeed, Error, MapAccess, SeqAccess, Visitor}, ser::{SerializeSeq, SerializeStruct}, - Deserialize, Serialize, + Deserialize, Deserializer, Serialize, Serializer, }; +use std::fmt::Formatter; + +pub const SCENE_STRUCT: &str = "Scene"; +pub const SCENE_ENTITIES: &str = "entities"; + +pub const ENTITY_STRUCT: &str = "Entity"; +pub const ENTITY_FIELD_ENTITY: &str = "entity"; +pub const ENTITY_FIELD_COMPONENTS: &str = "components"; pub struct SceneSerializer<'a> { pub scene: &'a DynamicScene, @@ -26,8 +34,30 @@ impl<'a> Serialize for SceneSerializer<'a> { where S: serde::Serializer, { - let mut state = serializer.serialize_seq(Some(self.scene.entities.len()))?; - for entity in &self.scene.entities { + let mut state = serializer.serialize_struct(SCENE_STRUCT, 1)?; + state.serialize_field( + SCENE_ENTITIES, + &EntitiesSerializer { + entities: &self.scene.entities, + registry: self.registry, + }, + )?; + state.end() + } +} + +pub struct EntitiesSerializer<'a> { + pub entities: &'a [DynamicEntity], + pub registry: &'a TypeRegistryArc, +} + +impl<'a> Serialize for EntitiesSerializer<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut state = serializer.serialize_seq(Some(self.entities.len()))?; + for entity in self.entities { state.serialize_element(&EntitySerializer { entity, registry: self.registry, @@ -81,6 +111,19 @@ impl<'a> Serialize for ComponentsSerializer<'a> { } } +#[derive(Deserialize)] +#[serde(field_identifier, rename_all = "lowercase")] +enum SceneField { + Entities, +} + +#[derive(Deserialize)] +#[serde(field_identifier, rename_all = "lowercase")] +enum EntityField { + Entity, + Components, +} + pub struct SceneDeserializer<'a> { pub type_registry: &'a TypeRegistry, } @@ -92,10 +135,77 @@ impl<'a, 'de> DeserializeSeed<'de> for SceneDeserializer<'a> { where D: serde::Deserializer<'de>, { - Ok(DynamicScene { - entities: deserializer.deserialize_seq(SceneEntitySeqVisitor { + deserializer.deserialize_struct( + SCENE_STRUCT, + &[SCENE_ENTITIES], + SceneVisitor { + type_registry: self.type_registry, + }, + ) + } +} + +struct SceneVisitor<'a> { + pub type_registry: &'a TypeRegistry, +} + +impl<'a, 'de> Visitor<'de> for SceneVisitor<'a> { + type Value = DynamicScene; + + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { + formatter.write_str("scene struct") + } + + fn visit_map(self, mut map: A) -> std::result::Result + where + A: MapAccess<'de>, + { + let mut entities = None; + while let Some(key) = map.next_key()? { + match key { + SceneField::Entities => { + if entities.is_some() { + return Err(Error::duplicate_field(SCENE_ENTITIES)); + } + entities = Some(map.next_value_seed(SceneEntitySeqDeserializer { + type_registry: self.type_registry, + })?); + } + } + } + + let entities = entities.ok_or_else(|| Error::missing_field(SCENE_ENTITIES))?; + + Ok(DynamicScene { entities }) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let entities = seq + .next_element_seed(SceneEntitySeqDeserializer { type_registry: self.type_registry, - })?, + })? + .ok_or_else(|| Error::missing_field(SCENE_ENTITIES))?; + + Ok(DynamicScene { entities }) + } +} + +pub struct SceneEntitySeqDeserializer<'a> { + pub type_registry: &'a TypeRegistry, +} + +impl<'a, 'de> DeserializeSeed<'de> for SceneEntitySeqDeserializer<'a> { + type Value = Vec; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_seq(SceneEntitySeqVisitor { + type_registry: self.type_registry, }) } } @@ -147,17 +257,6 @@ impl<'a, 'de> DeserializeSeed<'de> for SceneEntityDeserializer<'a> { } } -#[derive(Deserialize)] -#[serde(field_identifier, rename_all = "lowercase")] -enum EntityField { - Entity, - Components, -} - -pub const ENTITY_STRUCT: &str = "Entity"; -pub const ENTITY_FIELD_ENTITY: &str = "entity"; -pub const ENTITY_FIELD_COMPONENTS: &str = "components"; - struct SceneEntityVisitor<'a> { pub registry: &'a TypeRegistry, }