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

[Merged by Bors] - bevy_scene: Replace root list with struct #6354

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
84 changes: 43 additions & 41 deletions assets/scenes/load_scene_example.scn.ron
Original file line number Diff line number Diff line change
@@ -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,
),
},
],
),
]
},
],
),
]
)
133 changes: 116 additions & 17 deletions crates/bevy_scene/src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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,
Expand Down Expand Up @@ -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,
}
Expand All @@ -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<A>(self, mut map: A) -> std::result::Result<Self::Value, A::Error>
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<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
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<DynamicEntity>;

fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(SceneEntitySeqVisitor {
type_registry: self.type_registry,
})
}
}
Expand Down Expand Up @@ -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,
}
Expand Down