Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
EntityComponentSerializer.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Reflection;
8 
9 using SiliconStudio.Core;
10 using SiliconStudio.Core.Reflection;
11 using SiliconStudio.Core.Serialization;
12 using SiliconStudio.Core.Serialization.Converters;
13 
14 namespace SiliconStudio.Paradox.EntityModel
15 {
16  public class EntityComponentSerializer<T> : DataSerializer<T> where T : EntityComponent, new()
17  {
18  public override void PreSerialize(ref T entityComponent, ArchiveMode mode, SerializationStream stream)
19  {
20  if (entityComponent == null)
21  entityComponent = new T();
22  }
23 
24  public override void Serialize(ref T entityComponent, ArchiveMode mode, SerializationStream stream)
25  {
26  if (mode == ArchiveMode.Serialize)
27  {
28  stream.Write(entityComponent.Entity);
29  stream.Write(EntityComponentData.GenerateEntityComponentData(entityComponent));
30  }
31  else if (mode == ArchiveMode.Deserialize)
32  {
33  var entity = stream.Read<Entity>();
34 
35  var data = stream.Read<EntityComponentData>();
36  EntityComponentData.RestoreEntityComponentData(entityComponent, data);
37  }
38  }
39  }
40 
41  [DataContract]
42  internal class EntityComponentData
43  {
44  // Used to store entity data while in merge/text mode
45  public static PropertyKey<EntityComponentData> Key = new PropertyKey<EntityComponentData>("Key", typeof(EntityComponentData));
46 
47  [DataMemberCustomSerializer]
48  public Entity Entity;
49  public List<EntityComponentProperty> Properties;
50  //public List<EntityComponentProperty> Properties;
51 
52  public static void RestoreEntityComponentData(EntityComponent entityComponent, EntityComponentData data)
53  {
54  foreach (var componentProperty in data.Properties)
55  {
56  switch (componentProperty.Type)
57  {
58  case EntityComponentPropertyType.Field:
59  {
60  var field = entityComponent.GetType().GetTypeInfo().GetDeclaredField(componentProperty.Name);
61  if (field == null) // Field disappeared? should we issue a warning?
62  continue;
63  var result = MergeObject(field.GetValue(entityComponent), componentProperty.Value);
64  field.SetValue(entityComponent, result);
65  }
66  break;
67  case EntityComponentPropertyType.Property:
68  {
69  var property = entityComponent.GetType().GetTypeInfo().GetDeclaredProperty(componentProperty.Name);
70  if (property == null) // Property disappeared? should we issue a warning?
71  continue;
72  var result = MergeObject(property.GetValue(entityComponent, null), componentProperty.Value);
73  if (property.CanWrite)
74  property.SetValue(entityComponent, result, null);
75  }
76  break;
77  default:
78  throw new NotImplementedException();
79  }
80  }
81  }
82 
83  public static EntityComponentData GenerateEntityComponentData(EntityComponent entityComponent)
84  {
85  var data = new EntityComponentData { Properties = new List<EntityComponentProperty>() };
86  foreach (var field in entityComponent.GetType().GetTypeInfo().DeclaredFields)
87  {
88  if (!field.GetCustomAttributes(typeof(DataMemberConvertAttribute), true).Any())
89  continue;
90 
91  data.Properties.Add(new EntityComponentProperty(EntityComponentPropertyType.Field, field.Name, field.GetValue(entityComponent)));
92  }
93 
94  foreach (var property in entityComponent.GetType().GetTypeInfo().DeclaredProperties)
95  {
96  if (!property.GetCustomAttributes(typeof(DataMemberConvertAttribute), true).Any())
97  continue;
98 
99  data.Properties.Add(new EntityComponentProperty(EntityComponentPropertyType.Property, property.Name, property.GetValue(entityComponent, null)));
100  }
101  return data;
102  }
103 
104  private static object MergeObject(object oldValue, object newValue)
105  {
106  if (oldValue is IList)
107  {
108  var oldList = (IList)oldValue;
109  oldList.Clear();
110  foreach (var item in (IEnumerable)newValue)
111  {
112  oldList.Add(item);
113  }
114  return oldList;
115  }
116  if (oldValue is IDictionary)
117  {
118  var oldDictionary = (IDictionary)oldValue;
119  oldDictionary.Clear();
120  foreach (DictionaryEntry item in (IDictionary)newValue)
121  {
122  oldDictionary.Add(item.Key, item.Value);
123  }
124  return oldDictionary;
125  }
126 
127  return newValue;
128  }
129  }
130 }
Game entity. It usually aggregates multiple EntityComponent
Definition: Entity.cs:28
override void PreSerialize(ref T entityComponent, ArchiveMode mode, SerializationStream stream)
Base class for implementation of SerializationStream.
Describes how to serialize and deserialize an object without knowing its type. Used as a common base ...
ArchiveMode
Enumerates the different mode of serialization (either serialization or deserialization).
Definition: ArchiveMode.cs:8
override void Serialize(ref T entityComponent, ArchiveMode mode, SerializationStream stream)
A class that represents a tag propety.
Definition: PropertyKey.cs:17