Browse Source

Documentation
Fix for a null reference in inspector

Marko Pintera 10 years ago
parent
commit
4527457d2f

+ 6 - 0
MBansheeEditor/Inspector/InspectableObject.cs

@@ -29,6 +29,12 @@ namespace BansheeEditor
                 return true;
 
             object newPropertyValue = property.GetValue<object>();
+            if (propertyValue == null)
+                return newPropertyValue != null;
+            
+            if (newPropertyValue == null)
+                return propertyValue != null;
+            
             if (!propertyValue.Equals(newPropertyValue))
                 return true;
 

+ 142 - 17
SBansheeEngine/Include/BsManagedSerializableDictionary.h

@@ -7,19 +7,7 @@
 namespace BansheeEngine
 {
 	/**
-	 * @brief	TODO
-	 *
-	 * @note	This class can be in two states:
-	 *			 - Linked - When the object has a link to a managed object. This is the default 
-	 *                      state when a new instance of ManagedSerializableObject is created.
-	 *						Any operations during this state will operate directly on the linked
-	 *						managed object.
-	 *			 - Serialized - When the object has no link to the managed object but instead just
-	 *							contains cached object and field data that may be used for initializing
-	 *							a managed object. Any operations during this state will operate
-	 *							only on the cached internal data.
-	 *			You can transfer between these states by calling serialize(linked->serialized) &
-	 *	
+	 * @brief	Contains key and value data used for serializing a managed dictionary.
 	 */
 	struct BS_SCR_BE_EXPORT ManagedSerializableDictionaryKeyValue : public IReflectable
 	{
@@ -36,19 +24,42 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableDictionaryKeyValueRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Allows access to an underlying managed dictionary, or a cached version of that dictionary that
+	 *			can be serialized/deserialized.
+	 *
+	 * @note	This class can be in two states:
+	 *			 - Linked - When the object has a link to a managed object. This is the default 
+	 *                      state when a new instance of ManagedSerializableObject is created.
+	 *						Any operations during this state will operate directly on the linked
+	 *						managed object.
+	 *			 - Serialized - When the object has no link to the managed object but instead just
+	 *							contains cached object and field data that may be used for initializing
+	 *							a managed object. Any operations during this state will operate
+	 *							only on the cached internal data.
+	 *			You can transfer between these states by calling serialize(linked->serialized) &
+	 *			deserialize (serialized->linked).
+	 *	
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableDictionary : public IReflectable
 	{
 	private:
 		struct ConstructPrivately {};
 		
+		/**
+		 * @brief	Generates a hash value for field data.
+		 */
 		struct BS_SCR_BE_EXPORT Hash
 		{
 			inline size_t operator()(const ManagedSerializableFieldDataPtr& x) const;
 		};
 
+		/**
+		 * @brief	Compares two field data objects.
+		 */
 		struct BS_SCR_BE_EXPORT Equals
 		{
 			inline bool operator()(const ManagedSerializableFieldDataPtr& a, const ManagedSerializableFieldDataPtr& b) const;
@@ -57,14 +68,43 @@ namespace BansheeEngine
 	public:
 		typedef UnorderedMap<ManagedSerializableFieldDataPtr, ManagedSerializableFieldDataPtr> CachedEntriesMap;
 
+		/**
+		 * @brief	Helper class that enumerates over all entires in a managed dictionary. Operates on 
+		 *			managed object if the parent dictionary is in linked state, or on cached data otherwise.
+		 */
 		class Enumerator
 		{
 		public:
+			/**
+			 * @brief	Constructs a new enumerator for the provided managed object.
+			 *
+			 * @param	instance	Managed instance of type System.Collections.Generic.Dictionary.
+			 * @param	parent		Serializable parent of the managed instance.
+			 */
 			Enumerator(MonoObject* instance, const ManagedSerializableDictionary* parent);
 
+			/**
+			 * @brief	Returns the wrapped key data at the current enumerator position.
+			 *			Only valid to call this if enumerator is valid (i.e. last call to 
+			 *			::moveNext returned true).
+			 */
 			ManagedSerializableFieldDataPtr getKey() const;
+
+			/**
+			 * @brief	Returns the wrapped value data at the current enumerator position.
+			 *			Only valid to call this if enumerator is valid (i.e. last call to 
+			 *			::moveNext returned true).
+			 */
 			ManagedSerializableFieldDataPtr getValue() const;
 
+			/**
+			 * @brief	Moves the enumerator to the next position. Initially enumerator is
+			 *			at an invalid position and must be called at least once before accesing
+			 *			its data.
+			 *
+			 * @return	Returns if the enumerator is at valid position. When the enumerator returns
+			 *			false it means there are no more elements to enumerate.
+			 */
 			bool moveNext();
 
 		private:
@@ -80,23 +120,107 @@ namespace BansheeEngine
 		ManagedSerializableDictionary(const ConstructPrivately& dummy, const ManagedSerializableTypeInfoDictionaryPtr& typeInfo, MonoObject* managedInstance);
 		ManagedSerializableDictionary(const ConstructPrivately& dummy);
 
+		/**
+		 * @brief	Returns the internal managed instance of the dictionary. This will return null if
+		 *			the object is in serialized mode.
+		 */
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
+
+		/**
+		 * @brief	Returns the type information for the internal dictionary.
+		 */
 		ManagedSerializableTypeInfoDictionaryPtr getTypeInfo() const { return mDictionaryTypeInfo; }
 
+		/**
+		 * @brief	Returns the dictionary value at the specified key. If the key doesn't exist
+		 *			the default value for the type is returned. Operates on managed object if in 
+		 *			linked state, or on cached data otherwise.
+		 *
+		 * @param	key		Wrapper around the key data at which to retrieve the value.
+		 *
+		 * @return	A wrapper around the value in the dictionary at the specified key.
+		 */
 		ManagedSerializableFieldDataPtr getFieldData(const ManagedSerializableFieldDataPtr& key);
+
+		/**
+		 * @brief	Sets the dictionary value at the specified key. Operates on managed object if in 
+		 *			linked state, or on cached data otherwise.
+		 *
+		 * @param	key		Wrapper around the key data at which to set the value.
+		 * @param	val		Wrapper around the value to set at the specified key.
+		 */
 		void setFieldData(const ManagedSerializableFieldDataPtr& key, const ManagedSerializableFieldDataPtr& val);
+
+		/**
+		 * @brief	Deletes the key/value pair at the specified key. If the key doesn't exist
+		 *			this operation does nothing. Operates on managed object if in linked state, 
+		 *			or on cached data otherwise.
+		 *
+		 * @param	key		Wrapper around the key data at which to delete the value.
+		 */
 		void removeFieldData(const ManagedSerializableFieldDataPtr& key);
+
+		/**
+		 * @brief	Checks if the dictionary contains the specified key. Operates on managed object 
+		 *			if in linked state, or on cached data otherwise.
+		 *
+		 * @param	key		Wrapper around the key data which to check.
+		 */
 		bool contains(const ManagedSerializableFieldDataPtr& key) const;
+
+		/**
+		 * @brief	Returns an enumerator object that allows you to iterate over
+		 *			all key/value pairs in the dictionary.
+		 */
 		Enumerator getEnumerator() const;
 
+		/**
+		 * @brief	Serializes the internal managed object into a set of cached data that can be saved
+		 *			in memory/disk and can be deserialized later. Does nothing if object is already is 
+		 *			serialized mode. When in serialized mode the reference to the managed instance will be lost.
+		 */
 		void serialize();
+
+		/**
+		 * @brief	Deserializes a set of cached data into a managed object. This action may fail in case the cached
+		 *			data contains a type that no longer exists. You may check if it completely successfully if ::getManagedInstance
+		 *			returns non-null after.
+		 *
+		 *			This action transfers the object into linked mode. All further operations will operate directly on the managed instance
+		 *			and the cached data will be cleared. If you call this method on an already linked object the old object will be
+		 *			replaced and initialized with empty data (since cached data does not exist).
+		 */
 		void deserialize();
 
+		/**
+		 * @brief	Creates a managed serializable dictionary that references an existing managed dictionary. Created object will be in linked mode.
+		 *
+		 * @param	managedInstance		Constructed managed instance of the dictionary to link with. Its type must correspond with the provided type info.
+		 * @param	typeInfo			Type information for the dictionary and its key/value pair.
+		 */
 		static ManagedSerializableDictionaryPtr createFromExisting(MonoObject* managedInstance, const ManagedSerializableTypeInfoDictionaryPtr& typeInfo);
+
+		/**
+		 * @brief	Creates a managed serializable dictionary that creates and references a brand new managed dictionary instance.
+		 *
+		 * @param	typeInfo	Type of the dictionary to create.
+		 */
 		static ManagedSerializableDictionaryPtr createNew(const ManagedSerializableTypeInfoDictionaryPtr& typeInfo);
+
+		/**
+		 * @brief	Creates a managed dictionary instance.
+		 *
+		 * @param	typeInfo	Type of the dictionary to create.
+		 */
 		static MonoObject* createManagedInstance(const ManagedSerializableTypeInfoDictionaryPtr& typeInfo);
 
 	protected:
+		/**
+		 * @brief	Retrieves needed Mono types and methods. Should be called
+		 *			before performing any operations with the managed object.
+		 */
+		void initMonoObjects(MonoClass* dictionaryClass);
+
 		MonoObject* mManagedInstance;
 
 		MonoMethod* mAddMethod;
@@ -112,17 +236,18 @@ namespace BansheeEngine
 		ManagedSerializableTypeInfoDictionaryPtr mDictionaryTypeInfo;
 		CachedEntriesMap mCachedEntries;
 
-		void initMonoObjects(MonoClass* dictionaryClass);
-
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
 		
+		/**
+		 * @brief	Creates an empty and uninitialized object used for serialization purposes.
+		 */
 		static ManagedSerializableDictionaryPtr createEmpty();
 
 	public:
 		friend class ManagedSerializableDictionaryRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 }

+ 132 - 22
SBansheeEngine/Include/BsManagedSerializableDiff.h

@@ -5,9 +5,25 @@
 
 namespace BansheeEngine
 {
+	/**
+	 * @brief	Handles creation and applying of managed diffs. A diff contains differences
+	 *			between two objects of identical types. If the initial state of an object
+	 *			is known the recorded differences can be saved and applied to the original
+	 *			state to restore the modified object.
+	 *
+	 *			Differences are recorded per primitive field in an object. 
+	 *			Complex objects are recursed. Special handling is implemented
+	 *			to properly generate diffs for arrays, lists and dictionaries.
+	 *
+	 *			All primitive types supported by managed serialization are supported.
+	 *			(see ScriptPrimitiveType)
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableDiff : public IReflectable
 	{
 	public:
+		/**
+		 * @brief	A base class for all modifications recorded in a diff.
+		 */
 		struct BS_SCR_BE_EXPORT Modification : public IReflectable
 		{
 			virtual ~Modification();
@@ -18,18 +34,22 @@ namespace BansheeEngine
 		public:
 			friend class ModificationRTTI;
 			static RTTITypeBase* getRTTIStatic();
-			virtual RTTITypeBase* getRTTI() const;
+			virtual RTTITypeBase* getRTTI() const override;
 		};
 
+		/**
+		 * @brief	Contains a modification of a specific field in an object along
+		 *			with information about the field and its parent object.
+		 */
 		struct BS_SCR_BE_EXPORT ModifiedField : public IReflectable
 		{
 			ModifiedField() { }
 			ModifiedField(const ManagedSerializableTypeInfoPtr& parentType,
 				const ManagedSerializableFieldInfoPtr& fieldType, const SPtr<Modification>& modification);
 
-			ManagedSerializableTypeInfoPtr parentType;
-			ManagedSerializableFieldInfoPtr fieldType;
-			SPtr<Modification> modification;
+			ManagedSerializableTypeInfoPtr parentType; /**< Type of the parent object the field belongs to. */
+			ManagedSerializableFieldInfoPtr fieldType; /**< Data type of the field. */
+			SPtr<Modification> modification; /**< Recorded modification(s) on the field. */
 
 			/************************************************************************/
 			/* 								RTTI		                     		*/
@@ -37,16 +57,19 @@ namespace BansheeEngine
 		public:
 			friend class ModifiedFieldRTTI;
 			static RTTITypeBase* getRTTIStatic();
-			virtual RTTITypeBase* getRTTI() const;
+			virtual RTTITypeBase* getRTTI() const override;
 		};
 
+		/**
+		 * @brief	Represents a single modified array or list entry.
+		 */
 		struct BS_SCR_BE_EXPORT ModifiedArrayEntry : public IReflectable
 		{
 			ModifiedArrayEntry() { }
 			ModifiedArrayEntry(UINT32 idx, const SPtr<Modification>& modification);
 
-			UINT32 idx;
-			SPtr<Modification> modification;
+			UINT32 idx; /**< Index of the array/list entry that is modified. */
+			SPtr<Modification> modification; /**< Recorded modification(s) on the entry. */
 
 			/************************************************************************/
 			/* 								RTTI		                     		*/
@@ -54,16 +77,19 @@ namespace BansheeEngine
 		public:
 			friend class ModifiedArrayEntryRTTI;
 			static RTTITypeBase* getRTTIStatic();
-			virtual RTTITypeBase* getRTTI() const;
+			virtual RTTITypeBase* getRTTI() const override;
 		};
 
+		/**
+		 * @brief	Represents a single modified dictionary entry.
+		 */
 		struct BS_SCR_BE_EXPORT ModifiedDictionaryEntry : public IReflectable
 		{
 			ModifiedDictionaryEntry() { }
 			ModifiedDictionaryEntry(const ManagedSerializableFieldDataPtr& key, const SPtr<Modification>& modification);
 
-			ManagedSerializableFieldDataPtr key;
-			SPtr<Modification> modification;
+			ManagedSerializableFieldDataPtr key; /**< Serialized value of the key for the modified entry. */
+			SPtr<Modification> modification; /**< Recorded modification(s) on the dictionary entry value. */
 
 			/************************************************************************/
 			/* 								RTTI		                     		*/
@@ -71,14 +97,18 @@ namespace BansheeEngine
 		public:
 			friend class ModifiedArrayEntryRTTI;
 			static RTTITypeBase* getRTTIStatic();
-			virtual RTTITypeBase* getRTTI() const;
+			virtual RTTITypeBase* getRTTI() const override;
 		};
 
+		/**
+		 * @brief	Contains data about all modifications in a single complex object.
+		 *			(aside from arrays, list, dictionaries which are handled specially).
+		 */
 		struct BS_SCR_BE_EXPORT ModifiedObject : Modification
 		{
 			static SPtr<ModifiedObject> create();
 
-			Vector<ModifiedField> entries;
+			Vector<ModifiedField> entries; /**< A list of entries containing each modified field in the object. */
 
 			/************************************************************************/
 			/* 								RTTI		                     		*/
@@ -86,16 +116,19 @@ namespace BansheeEngine
 		public:
 			friend class ModifiedObjectRTTI;
 			static RTTITypeBase* getRTTIStatic();
-			virtual RTTITypeBase* getRTTI() const;
+			virtual RTTITypeBase* getRTTI() const override;
 		};
 
+		/**
+		 * @brief	Contains data about all modifications in an array or a list.
+		 */
 		struct BS_SCR_BE_EXPORT ModifiedArray : Modification
 		{
 			static SPtr<ModifiedArray> create();
 
-			Vector<ModifiedArrayEntry> entries;
-			Vector<UINT32> origSizes;
-			Vector<UINT32> newSizes;
+			Vector<ModifiedArrayEntry> entries; /**< A list of all modified array/list entries along with their indices. */
+			Vector<UINT32> origSizes; /**< Original size of the array/list (one size per dimension). */
+			Vector<UINT32> newSizes; /**< New size of the array/list (one size per dimension). */
 
 			/************************************************************************/
 			/* 								RTTI		                     		*/
@@ -103,15 +136,18 @@ namespace BansheeEngine
 		public:
 			friend class ModifiedArrayRTTI;
 			static RTTITypeBase* getRTTIStatic();
-			virtual RTTITypeBase* getRTTI() const;
+			virtual RTTITypeBase* getRTTI() const override;
 		};
 
+		/**
+		 * @brief	Contains data about all modifications in a dictionary.
+		 */
 		struct BS_SCR_BE_EXPORT ModifiedDictionary : Modification
 		{
 			static SPtr<ModifiedDictionary> create();
 
-			Vector<ModifiedDictionaryEntry> entries;
-			Vector<ManagedSerializableFieldDataPtr> removed;
+			Vector<ModifiedDictionaryEntry> entries; /**< A list of modified entries in the dictionary. */
+			Vector<ManagedSerializableFieldDataPtr> removed; /**< A list of keys for entries that were removed from the dictionary. */
 
 			/************************************************************************/
 			/* 								RTTI		                     		*/
@@ -119,9 +155,13 @@ namespace BansheeEngine
 		public:
 			friend class ModifiedDictionaryRTTI;
 			static RTTITypeBase* getRTTIStatic();
-			virtual RTTITypeBase* getRTTI() const;
+			virtual RTTITypeBase* getRTTI() const override;
 		};
 
+		/**
+		 * @brief	Contains data about modification of a primitive field.
+		 *			(i.e. fields new value)
+		 */
 		struct BS_SCR_BE_EXPORT ModifiedEntry : Modification
 		{
 			ModifiedEntry() { }
@@ -137,24 +177,94 @@ namespace BansheeEngine
 		public:
 			friend class ModifiedEntryRTTI;
 			static RTTITypeBase* getRTTIStatic();
-			virtual RTTITypeBase* getRTTI() const;
+			virtual RTTITypeBase* getRTTI() const override;
 		};
 
 	public:
 		ManagedSerializableDiff();
 		~ManagedSerializableDiff();
 
+		/**
+		 * @brief	Generates a new managed diff object by comparing two objects of the same type. Callers must
+		 *			ensure both objects are not null and of identical types.
+		 *
+		 * @param	oldObj	Original object. This is the object you can apply the diff to to convert it to /p newObj.
+		 * @param	newObj	New modified object. Any values in this object that differ from the original object will be
+		 *					recorded in the diff.
+		 *
+		 * @return	Returns null if objects are identical.
+		 */
 		static ManagedSerializableDiffPtr create(const ManagedSerializableObjectPtr& oldObj, const ManagedSerializableObjectPtr& newObj);
+
+		/**
+		 * @brief	Applies the diff data stored in this object to the specified object, modifying all
+		 *			fields in the object to correspond to the stored diff data.
+		 */
 		void apply(const ManagedSerializableObjectPtr& obj);
 
 	private:
+		/**
+		 * @brief	Recursively generates a diff between all fields of the specified objects. Returns null if objects are identical.
+		 */
 		SPtr<ModifiedObject> generateDiff(const ManagedSerializableObjectPtr& oldObj, const ManagedSerializableObjectPtr& newObj);
+
+		/**
+		 * @brief	Generates a diff between two fields. Fields can be of any type and the system will generate the diff appropriately.
+		 *			Diff is generated recursively on all complex objects as well. Returns null if fields contain identical data.
+		 */
 		SPtr<Modification> generateDiff(const ManagedSerializableFieldDataPtr& oldData, const ManagedSerializableFieldDataPtr& newData,
 			UINT32 fieldTypeId);
+
+		/**
+		 * @brief	Applies an object modification to a managed object. Modifications are applied recursively.
+		 *
+		 * @param	mod Object modification to apply.
+		 * @param	obj	Object to apply the modification to.
+		 *
+		 * @return	New field data in the case modification needed the object to be re-created instead of just modified.
+		 */
 		ManagedSerializableFieldDataPtr applyDiff(const SPtr<ModifiedObject>& mod, const ManagedSerializableObjectPtr& obj);
+
+		/**
+		 * @brief	Applies an array modification to a managed array. Modifications are applied recursively.
+		 *
+		 * @param	mod Array modification to apply.
+		 * @param	obj	Array to apply the modification to.
+		 *
+		 * @return	New field data in the case modification needed the array to be re-created instead of just modified.
+		 */
 		ManagedSerializableFieldDataPtr applyDiff(const SPtr<ModifiedArray>& mod, const ManagedSerializableArrayPtr& obj);
+
+		/**
+		 * @brief	Applies an list modification to a managed list. Modifications are applied recursively.
+		 *
+		 * @param	mod List modification to apply.
+		 * @param	obj	List to apply the modification to.
+		 *
+		 * @return	New field data in the case modification needed the list to be re-created instead of just modified.
+		 */
 		ManagedSerializableFieldDataPtr applyDiff(const SPtr<ModifiedArray>& mod, const ManagedSerializableListPtr& obj);
+
+		/**
+		 * @brief	Applies an dictionary modification to a managed dictionary. Modifications are applied recursively.
+		 *
+		 * @param	mod Dictionary modification to apply.
+		 * @param	obj	Dictionary to apply the modification to.
+		 *
+		 * @return	New field data in the case modification needed the dictionary to be re-created instead of just modified.
+		 */
 		ManagedSerializableFieldDataPtr applyDiff(const SPtr<ModifiedDictionary>& mod, const ManagedSerializableDictionaryPtr& obj);
+
+		/**
+		 * @brief	Applies a modification to a single field. Field type is determined and the modification is applied
+		 *			to the specific field type as needed. Modifications are applied recursively.
+		 *
+		 * @param	mod			Modification to apply.
+		 * @param	fieldType	Type of the field we're applying the modification to.
+		 * @param	origData	Original data of the field.
+		 *
+		 * @return	New field data in the case modification needed the field data to be re-created instead of just modified.
+		 */
 		ManagedSerializableFieldDataPtr applyDiff(const SPtr<Modification>& mod, const ManagedSerializableTypeInfoPtr& fieldType,
 			const ManagedSerializableFieldDataPtr& origData);
 
@@ -166,6 +276,6 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableDiffRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 }

+ 543 - 61
SBansheeEngine/Include/BsManagedSerializableField.h

@@ -6,11 +6,27 @@
 
 namespace BansheeEngine
 {
+	/**
+	 * @brief	Contains data that can be used for identifying a field in an object
+	 *			when cross referenced with the object type.
+	 *
+	 * @note	Essentially a light-weight identifier for the field so that we
+	 *			don't need to store entire field type for each field when serializing.
+	 *			Instead field types are stored separately and we just use this object
+	 *			for lookup.
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldKey : public IReflectable
 	{
 	public:
 		ManagedSerializableFieldKey();
 		ManagedSerializableFieldKey(UINT16 typeId, UINT16 fieldId);
+
+		/**
+		 * @brief	Creates a new field key.
+		 *
+		 * @param	typeId	Unique ID of the parent type the field belongs to. See ManagedSerializableTypeInfoObject.
+		 * @param	fieldId	Unique ID of the field within its parent class. See ManagedSerializableObjectInfo.
+		 */
 		static ManagedSerializableFieldKeyPtr create(UINT16 typeId, UINT16 fieldId);
 
 		UINT16 mTypeId;
@@ -23,21 +39,77 @@ namespace BansheeEngine
 	public:
 		friend class ScriptSerializableFieldDataKeyRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains value of a single field in a managed object. This
+	 *			class can contain any data type and should be overridden for specific types.
+	 *
+	 *			Stored values can be serialized and stored for later use, and deserialized
+	 *			back to managed objects when needed. You must call ::serialize before
+	 *			performing RTTI serialization. After field data has been serialized
+	 *			you should not call any methods on it before calling ::deserialize.
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldData : public IReflectable
 	{
 	public:
 		virtual ~ManagedSerializableFieldData() { }
 
+		/**
+		 * @brief	Creates a new data wrapper for some field data.
+		 *
+		 * @param	typeInfo	Type of the data we're storing.
+		 * @param	value		Managed boxed value to store in the field. Value will be copied 
+		 *						into the internal buffer and stored.
+		 */
 		static ManagedSerializableFieldDataPtr create(const ManagedSerializableTypeInfoPtr& typeInfo, MonoObject* value);
+
+		/**
+		 * @brief	Returns the internal value.
+		 *
+		 * @param	typeInfo	Type of the data we're looking to retrieve. This isn't required
+		 *						for actually retrieving the data but is used as an extra check
+		 *						to ensure the field contains the data type we're looking for.
+		 *
+		 * @return	Pointer to the internal serialized data. Caller must ensure the pointer
+		 *			is cast to the proper type.
+		 */
 		virtual void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) = 0;
+
+		/**
+		 * @brief	Boxes the internal value and returns it.
+		 *
+		 * @param	typeInfo	Type of the data we're looking to retrieve. This isn't required
+		 *						for actually retrieving the data but is used as an extra check
+		 *						to ensure the field contains the data type we're looking for.
+		 *
+		 * @return	Boxed representation of the internal value.
+		 */
 		virtual MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) = 0;
+
+		/**
+		 * @brief	Checks if the internal value stored in this object matches the value stored in another.
+		 *			Does shallow comparison for complex objects.
+		 */
 		virtual bool equals(const ManagedSerializableFieldDataPtr& other) = 0;
+
+		/**
+		 * @brief	Returns a hash value for the internally stored value.
+		 */
 		virtual size_t getHash() = 0;
 
+		/**
+		 * @brief	Serializes the internal value so that it may be stored and deserialized later.
+		 *
+		 * @note	This is generally only relevant for complex objects, as primitive types have their
+		 *			values copied and serialized automatically whenever field data is created.
+		 */
 		virtual void serialize() { }
+
+		/**
+		 * @brief	Deserializes the internal value so that the managed instance can be retrieved.
+		 */
 		virtual void deserialize() { }
 
 		/************************************************************************/
@@ -47,9 +119,12 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains type and value of a single field in an object.
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataEntry : public IReflectable
 	{
 	public:
@@ -65,19 +140,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataEntryRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains boolean field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataBool : public ManagedSerializableFieldData
 	{
 	public:
-		bool value = false;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		bool value = false;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -85,19 +180,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataBoolRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains wide character field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataChar : public ManagedSerializableFieldData
 	{
 	public:
-		wchar_t value = 0;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		wchar_t value = 0;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -105,19 +220,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataCharRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains signed 8-bit integer field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */	
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataI8 : public ManagedSerializableFieldData
 	{
 	public:
-		INT8 value = 0;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		INT8 value = 0;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -125,19 +260,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataI8RTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains unsigned 8-bit integer field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataU8 : public ManagedSerializableFieldData
 	{
 	public:
-		UINT8 value = 0;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		UINT8 value = 0;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -145,19 +300,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataU8RTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains signed 16-bit integer field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataI16 : public ManagedSerializableFieldData
 	{
 	public:
-		INT16 value = 0;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		INT16 value = 0;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -165,19 +340,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataI16RTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains unsigned 16-bit field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataU16 : public ManagedSerializableFieldData
 	{
 	public:
-		UINT16 value = 0;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		UINT16 value = 0;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -185,19 +380,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataU16RTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains signed 32-bit integer field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataI32 : public ManagedSerializableFieldData
 	{
 	public:
-		INT32 value = 0;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		INT32 value = 0;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -205,19 +420,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataI32RTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains unsigned 32-bit integer field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataU32 : public ManagedSerializableFieldData
 	{
 	public:
-		UINT32 value = 0;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		UINT32 value = 0;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -225,19 +460,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataU32RTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains signed 64-bit integer field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataI64 : public ManagedSerializableFieldData
 	{
 	public:
-		INT64 value = 0;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		INT64 value = 0;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -245,19 +500,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataI64RTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains unsigned 64-bit integer field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataU64 : public ManagedSerializableFieldData
 	{
 	public:
-		UINT64 value = 0;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		UINT64 value = 0;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -265,19 +540,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataU64RTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains single precision floating point field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataFloat : public ManagedSerializableFieldData
 	{
 	public:
-		float value = 0.0f;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		float value = 0.0f;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -285,20 +580,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataFloatRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
-
+	/**
+	 * @brief	Contains double precision floating point field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataDouble : public ManagedSerializableFieldData
 	{
 	public:
-		double value = 0.0;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		double value = 0.0;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -306,19 +620,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataDoubleRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains wide character string field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataString : public ManagedSerializableFieldData
 	{
 	public:
-		WString value;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		WString value;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -326,19 +660,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataStringRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains resource reference field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataResourceRef : public ManagedSerializableFieldData
 	{
 	public:
-		HResource value;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		HResource value;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -346,19 +700,39 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataResourceRefRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains game object reference field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataGameObjectRef : public ManagedSerializableFieldData
 	{
 	public:
-		HGameObject value;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		HGameObject value;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -366,22 +740,49 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataGameObjectRefRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains complex object field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataObject : public ManagedSerializableFieldData
 	{
 	public:
-		ManagedSerializableObjectPtr value;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		/**
+		 * @copydoc ManagedSerializableFieldData::serialize
+		 */
 		virtual void serialize() override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::deserialize
+		 */
 		virtual void deserialize() override;
 
+		ManagedSerializableObjectPtr value;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -389,22 +790,49 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataObjectRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains array field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataArray : public ManagedSerializableFieldData
 	{
 	public:
-		ManagedSerializableArrayPtr value;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		/**
+		 * @copydoc ManagedSerializableFieldData::serialize
+		 */
 		virtual void serialize() override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::deserialize
+		 */
 		virtual void deserialize() override;
 
+		ManagedSerializableArrayPtr value;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -412,22 +840,49 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataArrayRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains list field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataList : public ManagedSerializableFieldData
 	{
 	public:
-		ManagedSerializableListPtr value;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		/**
+		 * @copydoc ManagedSerializableFieldData::serialize
+		 */
 		virtual void serialize() override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::deserialize
+		 */
 		virtual void deserialize() override;
 
+		ManagedSerializableListPtr value;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -435,22 +890,49 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataListRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 
+	/**
+	 * @brief	Contains dictionary field data.
+	 *
+	 * @copydoc	ManagedSerializableFieldData
+	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableFieldDataDictionary : public ManagedSerializableFieldData
 	{
 	public:
-		ManagedSerializableDictionaryPtr value;
-
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValue
+		 */
 		void* getValue(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getValueBoxed
+		 */
 		MonoObject* getValueBoxed(const ManagedSerializableTypeInfoPtr& typeInfo) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::equals
+		 */
 		bool equals(const ManagedSerializableFieldDataPtr& other) override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::getHash
+		 */
 		size_t getHash() override;
 
+		/**
+		 * @copydoc ManagedSerializableFieldData::serialize
+		 */
 		virtual void serialize() override;
+
+		/**
+		 * @copydoc ManagedSerializableFieldData::deserialize
+		 */
 		virtual void deserialize() override;
 
+		ManagedSerializableDictionaryPtr value;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -458,6 +940,6 @@ namespace BansheeEngine
 	public:
 		friend class ManagedSerializableFieldDataDictionaryRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 }

+ 95 - 6
SBansheeEngine/Include/BsManagedSerializableList.h

@@ -7,7 +7,8 @@
 namespace BansheeEngine
 {
 	/**
-	 * @brief	TODO
+	 * @brief	Allows access to an underlying managed list, or a cached version of that list that
+	 *			can be serialized/deserialized.
 	 *
 	 * @note	This class can be in two states:
 	 *			 - Linked - When the object has a link to a managed object. This is the default 
@@ -19,6 +20,7 @@ namespace BansheeEngine
 	 *							a managed object. Any operations during this state will operate
 	 *							only on the cached internal data.
 	 *			You can transfer between these states by calling serialize(linked->serialized) &
+	 *			deserialize (serialized->linked).
 	 *	
 	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableList : public IReflectable
@@ -30,22 +32,110 @@ namespace BansheeEngine
 		ManagedSerializableList(const ConstructPrivately& dummy, const ManagedSerializableTypeInfoListPtr& typeInfo, MonoObject* managedInstance);
 		ManagedSerializableList(const ConstructPrivately& dummy);
 
+		/**
+		 * @brief	Returns the internal managed instance of the list. This will return null if
+		 *			the object is in serialized mode.
+		 */
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
+
+		/**
+		 * @brief	Returns the type information for the internal list.
+		 */
 		ManagedSerializableTypeInfoListPtr getTypeInfo() const { return mListTypeInfo; }
 
+		/**
+		 * @brief	Changes the size of the list. Operates on managed object if in linked state, 
+		 *			or on cached data otherwise.
+		 */
 		void resize(UINT32 newSize);
+
+		/**
+		 * @brief	Sets a new element value at the specified list index. Operates on 
+		 *			managed object if in linked state, or on cached data otherwise.
+		 *
+		 * @param	arrayIdx	Index at which to set the value.
+		 * @param	val			Wrapper around the value to store in the list. Must be of the
+		 *						list element type.
+		 */
 		void setFieldData(UINT32 arrayIdx, const ManagedSerializableFieldDataPtr& val);
+
+		/**
+		 * @brief	Returns the element value at the specified list index. Operates on 
+		 *			managed object if in linked state, or on cached data otherwise.
+		 *
+		 * @param	arrayIdx	Index at which to retrieve the value.
+		 *
+		 * @return	A wrapper around the element value in the list.
+		 */
 		ManagedSerializableFieldDataPtr getFieldData(UINT32 arrayIdx);
+
+		/**
+		 * @brief	Returns the size of the list. Operates on managed object 
+		 *			if in linked state, or on cached data otherwise.
+		 */
 		UINT32 getLength() const { return mNumElements; }
 
+		/**
+		 * @brief	Serializes the internal managed object into a set of cached data that can be saved
+		 *			in memory/disk and can be deserialized later. Does nothing if object is already is 
+		 *			serialized mode. When in serialized mode the reference to the managed instance will be lost.
+		 */
 		void serialize();
+
+		/**
+		 * @brief	Deserializes a set of cached data into a managed object. This action may fail in case the cached
+		 *			data contains a type that no longer exists. You may check if it completely successfully if ::getManagedInstance
+		 *			returns non-null after.
+		 *
+		 *			This action transfers the object into linked mode. All further operations will operate directly on the managed instance
+		 *			and the cached data will be cleared. If you call this method on an already linked object the old object will be
+		 *			replaced and initialized with empty data (since cached data does not exist).
+		 */
 		void deserialize();
 
+		/**
+		 * @brief	Creates a managed serializable list that references an existing managed list. Created object will be in linked mode.
+		 *
+		 * @param	managedInstance		Constructed managed instance of the list to link with. Its type must correspond with the provided type info.
+		 * @param	typeInfo			Type information for the list and its elements.
+		 */
 		static ManagedSerializableListPtr createFromExisting(MonoObject* managedInstance, const ManagedSerializableTypeInfoListPtr& typeInfo);
+
+		/**
+		 * @brief	Creates a managed serializable list that creates and references a brand new managed list instance.
+		 *
+		 * @param	typeInfo	Type of the list to create.
+		 * @param	size		Initial size of the list.
+		 */
 		static ManagedSerializableListPtr createNew(const ManagedSerializableTypeInfoListPtr& typeInfo, UINT32 size);
+
+		/**
+		 * @brief	Creates a managed list instance.
+		 *
+		 * @param	typeInfo	Type of the list to create.
+		 * @param	size		Initial size of the list.
+		 */
 		static MonoObject* createManagedInstance(const ManagedSerializableTypeInfoListPtr& typeInfo, UINT32 size);
 
 	protected:
+		/**
+		 * @brief	Retrieves needed Mono types and methods. Should be called
+		 *			before performing any operations with the managed object.
+		 */
+		void initMonoObjects(MonoClass* listClass);
+
+		/**
+		 * @brief	Returns the size of the list. Operates on the 
+		 *			internal managed object.
+		 */
+		UINT32 getLengthInternal() const;
+
+		/**
+		 * @brief	Appends data to the end of the list. Operates on
+		 *			the internal managed object.
+		 */
+		void addFieldDataInternal(const ManagedSerializableFieldDataPtr& val);
+
 		MonoObject* mManagedInstance;
 
 		MonoMethod* mAddMethod;
@@ -59,19 +149,18 @@ namespace BansheeEngine
 		Vector<ManagedSerializableFieldDataPtr> mCachedEntries;
 		UINT32 mNumElements;
 
-		void initMonoObjects(MonoClass* listClass);
-		UINT32 getLengthInternal() const;
-		void addFieldDataInternal(const ManagedSerializableFieldDataPtr& val);
-
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
 		
+		/**
+		 * @brief	Creates an empty and uninitialized object used for serialization purposes.
+		 */
 		static ManagedSerializableListPtr createEmpty();
 
 	public:
 		friend class ManagedSerializableListRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 }

+ 72 - 3
SBansheeEngine/Include/BsManagedSerializableObject.h

@@ -8,7 +8,8 @@
 namespace BansheeEngine
 {
 	/**
-	 * @brief	TODO
+	 * @brief	Allows access to an underlying managed object, or a cached version of that object that
+	 *			can be serialized/deserialized.
 	 *
 	 * @note	This class can be in two states:
 	 *			 - Linked - When the object has a link to a managed object. This is the default 
@@ -20,18 +21,25 @@ namespace BansheeEngine
 	 *							a managed object. Any operations during this state will operate
 	 *							only on the cached internal data.
 	 *			You can transfer between these states by calling serialize(linked->serialized) &
-	 *			deserialize(serialized->linked).
+	 *			deserialize (serialized->linked).
+	 *	
 	 */
 	class BS_SCR_BE_EXPORT ManagedSerializableObject : public IReflectable
 	{
 	private:
 		struct ConstructPrivately {};
 
+		/**
+		 * @brief	Generates a hash value for field key data identifying a single field in the object.
+		 */
 		struct BS_SCR_BE_EXPORT Hash
 		{
 			inline size_t operator()(const ManagedSerializableFieldKey& x) const;
 		};
 
+		/**
+		 * @brief	Compares two field key objects.
+		 */
 		struct BS_SCR_BE_EXPORT Equals
 		{
 			inline bool operator()(const ManagedSerializableFieldKey& a, const ManagedSerializableFieldKey& b) const;
@@ -41,17 +49,75 @@ namespace BansheeEngine
 		ManagedSerializableObject(const ConstructPrivately& dummy, ManagedSerializableObjectInfoPtr objInfo, MonoObject* managedInstance);
 		ManagedSerializableObject(const ConstructPrivately& dummy);
 
+		/**
+		 * @brief	Returns the internal managed instance of the object. This will return null if
+		 *			the object is in serialized mode.
+		 */
 		MonoObject* getManagedInstance() const { return mManagedInstance; }
+
+		/**
+		 * @brief	Returns the type information for the internal object.
+		 */
 		ManagedSerializableObjectInfoPtr getObjectInfo() const { return mObjInfo; }
 
+		/**
+		 * @brief	Sets a new value of the specified field. Operates on 
+		 *			managed object if in linked state, or on cached data otherwise.
+		 *
+		 * @param	fieldInfo	Object describing the field to which to set the value. This field
+		 *						must belong to the type this object is initialized with.
+		 * @param	val			Wrapper around the value to store in the field.
+		 */
 		void setFieldData(const ManagedSerializableFieldInfoPtr& fieldInfo, const ManagedSerializableFieldDataPtr& val);
+
+		/**
+		 * @brief	Returns the value of the specified field. Operates on managed object 
+		 *			if in linked state, or on cached data otherwise.
+		 *
+		 * @param	fieldInfo	Object describing the field to which to set the value. This field
+		 *						must belong to the type this object is initialized with.
+		 *
+		 * @return	A wrapper around the value of the field.
+		 */
 		ManagedSerializableFieldDataPtr getFieldData(const ManagedSerializableFieldInfoPtr& fieldInfo) const;
 
+		/**
+		 * @brief	Serializes the internal managed object into a set of cached data that can be saved
+		 *			in memory/disk and can be deserialized later. Does nothing if object is already is 
+		 *			serialized mode. When in serialized mode the reference to the managed instance will be lost.
+		 */
 		void serialize();
+
+		/**
+		 * @brief	Deserializes a set of cached data into a managed object. This action may fail in case the cached
+		 *			data contains a type that no longer exists. You may check if it completely successfully if ::getManagedInstance
+		 *			returns non-null after.
+		 *
+		 *			This action transfers the object into linked mode. All further operations will operate directly on the managed instance
+		 *			and the cached data will be cleared. If you call this method on an already linked object the old object will be
+		 *			replaced and initialized with empty data (since cached data does not exist).
+		 */
 		void deserialize();
 
+		/**
+		 * @brief	Creates a managed serializable object that references an existing managed object. Created object will be in linked mode.
+		 *
+		 * @param	managedInstance		Constructed managed instance of the object to link with.
+		 */
 		static ManagedSerializableObjectPtr createFromExisting(MonoObject* managedInstance);
+
+		/**
+		 * @brief	Creates a managed serializable object that creates and references a brand new managed object instance.
+		 *
+		 * @param	type	Type of the object to create.
+		 */
 		static ManagedSerializableObjectPtr createNew(const ManagedSerializableTypeInfoObjectPtr& type);
+
+		/**
+		 * @brief	Creates a managed object instance.
+		 *
+		 * @param	type	Type of the object to create.
+		 */
 		static MonoObject* createManagedInstance(const ManagedSerializableTypeInfoObjectPtr& type);
 	protected:
 		MonoObject* mManagedInstance;
@@ -63,11 +129,14 @@ namespace BansheeEngine
 		/* 								RTTI		                     		*/
 		/************************************************************************/
 		
+		/**
+		 * @brief	Creates an empty and uninitialized object used for serialization purposes.
+		 */
 		static ManagedSerializableObjectPtr createEmpty();
 
 	public:
 		friend class ManagedSerializableObjectRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const;
+		virtual RTTITypeBase* getRTTI() const override;
 	};
 }

+ 4 - 5
TODO.txt

@@ -57,13 +57,12 @@ Code quality improvements:
 ----------------------------------------------------------------------
 Polish stage 1
 
-StringTable TODO:
-  - Issue in ScriptStringTable - I should allow it to be created from C# and in that case I need to call Internal_CreateInstance,
-    but it seems I'm using the default constructor for something else so I can't call it there (or can I?)
-  - Need to actually save & load the string tables from somewhere (probably don't need this for now)
+Fix inspector crashes:
+ - Try expanding/collapsing foldouts
+ - Had one with invalid index in Layout.InsertElement called from InspectableObject.Update
+ - And another 
 
 Test inspector selection, selecting a resource and adding/removing component updates
-Crash when showing the inspector (invalid index in Layout.InsertElement called from InspectableObject.Update)
 Handle seems to lag behind the selected mesh
 ProjectLibrary seems to import some files on every start-up
 Crash on shutdown in mono_gchandle_free