SerializableProperty.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Runtime.CompilerServices;
  6. using System.Text;
  7. namespace BansheeEngine
  8. {
  9. public sealed class SerializableProperty : ScriptObject
  10. {
  11. public enum FieldType
  12. {
  13. Int,
  14. Float,
  15. Bool,
  16. String,
  17. Color,
  18. Vector2,
  19. Vector3,
  20. Vector4,
  21. GameObjectRef,
  22. ResourceRef,
  23. Object,
  24. Array,
  25. List,
  26. Dictionary
  27. }
  28. internal delegate object Getter();
  29. internal delegate void Setter(object value);
  30. private FieldType type;
  31. private Type internalType;
  32. private Getter getter;
  33. private Setter setter;
  34. // Constructed from native code
  35. private SerializableProperty()
  36. { }
  37. internal void Construct(FieldType type, Type internalType, Getter getter, Setter setter)
  38. {
  39. this.type = type;
  40. this.internalType = internalType;
  41. this.getter = getter;
  42. this.setter = setter;
  43. }
  44. public FieldType Type
  45. {
  46. get { return type; }
  47. }
  48. public Type InternalType
  49. {
  50. get { return internalType; }
  51. }
  52. public bool IsValueType
  53. {
  54. get { return internalType.IsValueType; }
  55. }
  56. public T GetValue<T>()
  57. {
  58. if (!typeof(T).IsAssignableFrom(internalType))
  59. throw new Exception("Attempted to retrieve a serializable value using an invalid type. Provided type: " + typeof(T) + ". Needed type: " + internalType);
  60. return (T)getter();
  61. }
  62. public T GetValueCopy<T>()
  63. {
  64. if (!typeof(T).IsAssignableFrom(internalType))
  65. throw new Exception("Attempted to retrieve a serializable value using an invalid type. Provided type: " + typeof(T) + ". Needed type: " + internalType);
  66. return (T)Internal_CloneManagedInstance(mCachedPtr, getter());
  67. }
  68. public void SetValue<T>(T value)
  69. {
  70. if (!typeof(T).IsAssignableFrom(internalType))
  71. throw new Exception("Attempted to set a serializable value using an invalid type. Provided type: " + typeof(T) + ". Needed type: " + internalType);
  72. setter(value);
  73. }
  74. public SerializableObject GetObject()
  75. {
  76. if (type != FieldType.Object)
  77. throw new Exception("Attempting to retrieve object information from a field that doesn't contain an object.");
  78. return Internal_CreateObject(mCachedPtr, GetValue<object>());
  79. }
  80. public SerializableArray GetArray()
  81. {
  82. if (type != FieldType.Array)
  83. throw new Exception("Attempting to retrieve array information from a field that doesn't contain an array.");
  84. return Internal_CreateArray(mCachedPtr, GetValue<Array>());
  85. }
  86. public SerializableList GetList()
  87. {
  88. if (type != FieldType.List)
  89. throw new Exception("Attempting to retrieve array information from a field that doesn't contain a list.");
  90. return Internal_CreateList(mCachedPtr, GetValue<IList>());
  91. }
  92. public SerializableDictionary GetDictionary()
  93. {
  94. if (type != FieldType.Dictionary)
  95. throw new Exception("Attempting to retrieve array information from a field that doesn't contain a dictionary.");
  96. return Internal_CreateDictionary(mCachedPtr, GetValue<IDictionary>());
  97. }
  98. public T CreateObjectInstance<T>()
  99. {
  100. if (type != FieldType.Object)
  101. throw new Exception("Attempting to retrieve object information from a field that doesn't contain an object.");
  102. return (T)Internal_CreateManagedObjectInstance(mCachedPtr);
  103. }
  104. public Array CreateArrayInstance(int[] lengths)
  105. {
  106. if (type != FieldType.Array)
  107. throw new Exception("Attempting to retrieve array information from a field that doesn't contain an array.");
  108. return Internal_CreateManagedArrayInstance(mCachedPtr, lengths);
  109. }
  110. public IList CreateListInstance(int length)
  111. {
  112. if (type != FieldType.List)
  113. throw new Exception("Attempting to retrieve array information from a field that doesn't contain a list.");
  114. return Internal_CreateManagedListInstance(mCachedPtr, length);
  115. }
  116. public IDictionary CreateDictionaryInstance()
  117. {
  118. if (type != FieldType.Dictionary)
  119. throw new Exception("Attempting to retrieve array information from a field that doesn't contain a dictionary.");
  120. return Internal_CreateManagedDictionaryInstance(mCachedPtr);
  121. }
  122. [MethodImpl(MethodImplOptions.InternalCall)]
  123. private static extern SerializableObject Internal_CreateObject(IntPtr nativeInstance, object instance);
  124. [MethodImpl(MethodImplOptions.InternalCall)]
  125. private static extern SerializableArray Internal_CreateArray(IntPtr nativeInstance, Array instance);
  126. [MethodImpl(MethodImplOptions.InternalCall)]
  127. private static extern SerializableList Internal_CreateList(IntPtr nativeInstance, IList instance);
  128. [MethodImpl(MethodImplOptions.InternalCall)]
  129. private static extern SerializableDictionary Internal_CreateDictionary(IntPtr nativeInstance, IDictionary instance);
  130. [MethodImpl(MethodImplOptions.InternalCall)]
  131. private static extern object Internal_CreateManagedObjectInstance(IntPtr nativeInstance);
  132. [MethodImpl(MethodImplOptions.InternalCall)]
  133. private static extern Array Internal_CreateManagedArrayInstance(IntPtr nativeInstance, int[] lengths);
  134. [MethodImpl(MethodImplOptions.InternalCall)]
  135. private static extern IList Internal_CreateManagedListInstance(IntPtr nativeInstance, int length);
  136. [MethodImpl(MethodImplOptions.InternalCall)]
  137. private static extern IDictionary Internal_CreateManagedDictionaryInstance(IntPtr nativeInstance);
  138. [MethodImpl(MethodImplOptions.InternalCall)]
  139. private static extern object Internal_CloneManagedInstance(IntPtr nativeInstance, object original);
  140. public static FieldType DetermineFieldType(Type internalType)
  141. {
  142. if (!internalType.IsArray)
  143. {
  144. if (internalType == typeof (Byte))
  145. return FieldType.Int;
  146. else if (internalType == typeof (SByte))
  147. return FieldType.Int;
  148. else if (internalType == typeof (Int16))
  149. return FieldType.Int;
  150. else if (internalType == typeof (UInt16))
  151. return FieldType.Int;
  152. else if (internalType == typeof (Int32))
  153. return FieldType.Int;
  154. else if (internalType == typeof (UInt32))
  155. return FieldType.Int;
  156. else if (internalType == typeof (Int64))
  157. return FieldType.Int;
  158. else if (internalType == typeof (UInt64))
  159. return FieldType.Int;
  160. else if (internalType == typeof (bool))
  161. return FieldType.Bool;
  162. else if (internalType == typeof (float))
  163. return FieldType.Float;
  164. else if (internalType == typeof (double))
  165. return FieldType.Float;
  166. else if (internalType == typeof (string))
  167. return FieldType.String;
  168. else if (internalType == typeof (Vector2))
  169. return FieldType.Vector2;
  170. else if (internalType == typeof (Vector3))
  171. return FieldType.Vector3;
  172. else if (internalType == typeof (Vector4))
  173. return FieldType.Vector4;
  174. else if (internalType == typeof (Color))
  175. return FieldType.Color;
  176. else if (internalType.IsSubclassOf(typeof (GameObject)))
  177. return FieldType.GameObjectRef;
  178. else if (internalType.IsSubclassOf(typeof (Resource)))
  179. return FieldType.ResourceRef;
  180. else if (internalType.IsGenericType)
  181. {
  182. Type genericType = internalType.GetGenericTypeDefinition();
  183. if (genericType == typeof (List<>))
  184. {
  185. return FieldType.List;
  186. }
  187. else if (genericType == typeof (Dictionary<,>))
  188. {
  189. return FieldType.Dictionary;
  190. }
  191. // Shouldn't happen because native code should only supply us with supported types
  192. throw new Exception("Cannot determine field type. Found an unsupported generic type.");
  193. }
  194. // Otherwise the type must be an object, unless some error occurred
  195. return FieldType.Object;
  196. }
  197. return FieldType.Array;
  198. }
  199. }
  200. }