Browse Source

Added circular reference checking
Added RTTI field flags

Marko Pintera 13 years ago
parent
commit
f212513ba8

+ 1 - 0
CamelotRenderer/Include/CmShaderRTTI.h

@@ -3,6 +3,7 @@
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
 #include "CmRTTIType.h"
 #include "CmRTTIType.h"
 #include "CmShader.h"
 #include "CmShader.h"
+#include "CmMaterial.h"
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {

+ 2 - 2
CamelotUtility/Include/CmPrerequisitesUtil.h

@@ -70,6 +70,6 @@ THE SOFTWARE
 // Forward declarations
 // Forward declarations
 #include "CmFwdDeclUtil.h"
 #include "CmFwdDeclUtil.h"
 
 
-#include "CmString.h"
+#include "CmRTTIPrerequisites.h"
 
 
-#include "CmRTTIPrerequisites.h"
+#include "CmString.h"

+ 27 - 52
CamelotUtility/Include/CmRTTIField.h

@@ -17,53 +17,6 @@ namespace CamelotEngine
 	class RTTITypeBase;
 	class RTTITypeBase;
 	struct RTTIField;
 	struct RTTIField;
 
 
-	/**
-	 * @brief	Strings need to copy their data in a slightly more intricate way than just memcpy.
-	 */
-	template<> struct RTTIPlainType<String>
-	{	
-		enum { id = 20 }; enum { hasDynamicSize = 1 };
-
-		static void toMemory(String& data, char* memory)
-		{ 
-			UINT32 size = getDynamicSize(data);
-
-			memcpy(memory, &size, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size -= sizeof(UINT32);
-			memcpy(memory, data.data(), size); 
-		}
-
-		static void fromMemory(String& data, char* memory)
-		{ 
-			UINT32 size;
-			memcpy(&size, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			size -= sizeof(UINT32);
-			char* buffer = new char[size + 1]; // TODO - Use a better allocator
-			memcpy(buffer, memory, size); 
-			buffer[size] = '\0';
-			data = String(buffer);
-
-			delete[] buffer; 
-		}
-
-		static UINT32 getDynamicSize(String& data)	
-		{ 
-			UINT64 dataSize = data.size() * sizeof(String::value_type) + sizeof(UINT32);
-
-#if CM_DEBUG_MODE
-			if(dataSize > std::numeric_limits<UINT32>::max())
-			{
-				CM_EXCEPT(InternalErrorException, "Data overflow! Size doesn't fit into 32 bits.");
-			}
-#endif
-
-			return (UINT32)dataSize;
-		}	
-	}; 
-
 	/**
 	/**
 	 * @brief	Types of fields we can serialize:
 	 * @brief	Types of fields we can serialize:
 	 * 			
 	 * 			
@@ -73,9 +26,9 @@ namespace CamelotEngine
 	 *				 Managed data blocks have their buffers deleted after they go out of scope. This is useful if you need to return some
 	 *				 Managed data blocks have their buffers deleted after they go out of scope. This is useful if you need to return some
 	 *				 temporary data. On the other hand if the data in the block belongs to your class, and isn't temporary, keep the data unmanaged.
 	 *				 temporary data. On the other hand if the data in the block belongs to your class, and isn't temporary, keep the data unmanaged.
 	 *				 
 	 *				 
-	 * - Complex - Field that is of IReflectable type. Cannot be a pointer to IReflectable and must be actual value type. 
+	 * - Reflectable - Field that is of IReflectable type. Cannot be a pointer to IReflectable and must be actual value type. 
 	 * 
 	 * 
-	 * - ComplexPtr - A pointer to IReflectable.
+	 * - ReflectablePtr - A pointer to IReflectable.
 	 */
 	 */
 	enum SerializableFieldType
 	enum SerializableFieldType
 	{
 	{
@@ -85,6 +38,24 @@ namespace CamelotEngine
 		SerializableFT_ReflectablePtr
 		SerializableFT_ReflectablePtr
 	};
 	};
 
 
+	/**
+	 * @brief	Various flags you can assign to RTTI fields.
+	 */
+	enum RTTIFieldFlag
+	{
+		// This flag is only used on field types of ReflectablePtr type, and it is used
+		// to solve circular references. Circular references cause an issue when deserializing, 
+		// as the algorithm doesn't know which object to deserialize first. By making one of 
+		// the references weak, you tell the algorithm that it doesn't have to guarantee 
+		// the object will be fully deserialized before being assigned to the field.
+		//
+		// In short: If you make a reference weak, when "set" method of that field is called,
+		// it is not guaranteed the value provided is fully initialized, so you should not access any of its
+		// data until deserialization is fully complete. You only need to use this flag if the RTTI system
+		// complains that is has found a circular reference.
+		RTTI_Flag_WeakRef = 0x01
+	};
+
 	/**
 	/**
 	 * @brief	Structure that keeps meta-data concerning a single class field. 
 	 * @brief	Structure that keeps meta-data concerning a single class field. 
 	 */
 	 */
@@ -100,12 +71,15 @@ namespace CamelotEngine
 		UINT16 mUniqueId;
 		UINT16 mUniqueId;
 		bool mIsVectorType;
 		bool mIsVectorType;
 		SerializableFieldType mType;
 		SerializableFieldType mType;
+		UINT64 mFlags;
 
 
 		bool isPlainType() { return mType == SerializableFT_Plain; }
 		bool isPlainType() { return mType == SerializableFT_Plain; }
 		bool isDataBlockType() { return mType == SerializableFT_DataBlock; }
 		bool isDataBlockType() { return mType == SerializableFT_DataBlock; }
-		bool isComplexType() { return mType == SerializableFT_Reflectable; }
-		bool isComplexPtrType() { return mType == SerializableFT_ReflectablePtr; }
+		bool isReflectableType() { return mType == SerializableFT_Reflectable; }
+		bool isReflectablePtrType() { return mType == SerializableFT_ReflectablePtr; }
 		
 		
+		UINT64 getFlags() const { return mFlags; }
+
 		virtual UINT32 getArraySize(void* object) = 0;
 		virtual UINT32 getArraySize(void* object) = 0;
 		virtual void setArraySize(void* object, UINT32 size) = 0;
 		virtual void setArraySize(void* object, UINT32 size) = 0;
 
 
@@ -148,7 +122,7 @@ namespace CamelotEngine
 
 
 	protected:
 	protected:
 		void initAll(boost::any valueGetter, boost::any valueSetter, boost::any arraySizeGetter, boost::any arraySizeSetter,
 		void initAll(boost::any valueGetter, boost::any valueSetter, boost::any arraySizeGetter, boost::any arraySizeSetter,
-			std::string mName, UINT16 mUniqueId, bool mIsVectorType, SerializableFieldType type)
+			std::string mName, UINT16 mUniqueId, bool mIsVectorType, SerializableFieldType type, UINT64 flags)
 		{
 		{
 			this->valueGetter = valueGetter;
 			this->valueGetter = valueGetter;
 			this->valueSetter = valueSetter;
 			this->valueSetter = valueSetter;
@@ -158,6 +132,7 @@ namespace CamelotEngine
 			this->mUniqueId = mUniqueId;
 			this->mUniqueId = mUniqueId;
 			this->mIsVectorType = mIsVectorType;
 			this->mIsVectorType = mIsVectorType;
 			this->mType = type;
 			this->mType = type;
+			this->mFlags = flags;
 		}
 		}
 	};
 	};
 }
 }

+ 4 - 3
CamelotUtility/Include/CmRTTIManagedDataBlockField.h

@@ -24,11 +24,12 @@ namespace CamelotEngine
 		 * 						serializing data to disk and similar. It is primarily used for compatibility
 		 * 						serializing data to disk and similar. It is primarily used for compatibility
 		 * 						between different versions of serialized data.
 		 * 						between different versions of serialized data.
 		 * @param	getter  	The getter method for the field. Cannot be null. Must be a specific signature: SerializableDataBlock(ObjectType*)
 		 * @param	getter  	The getter method for the field. Cannot be null. Must be a specific signature: SerializableDataBlock(ObjectType*)
-		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, SerializableDataBlock)
+		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, SerializableDataBlock)	
+		 * @param	flags		Various flags you can use to specialize how systems handle this field
 		 */
 		 */
-		void initSingle(const std::string& name, UINT16 uniqueId, boost::any getter, boost::any setter)
+		void initSingle(const std::string& name, UINT16 uniqueId, boost::any getter, boost::any setter, UINT64 flags)
 		{
 		{
-			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_DataBlock);
+			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_DataBlock, flags);
 		}
 		}
 
 
 		virtual UINT32 getTypeSize()
 		virtual UINT32 getTypeSize()

+ 6 - 6
CamelotUtility/Include/CmRTTIPlainField.h

@@ -148,9 +148,9 @@ namespace CamelotEngine
 		 * 						between different versions of serialized data.
 		 * 						between different versions of serialized data.
 		 * @param	getter  	The getter method for the field. Cannot be null. Must be a specific signature: DataType(ObjectType*).
 		 * @param	getter  	The getter method for the field. Cannot be null. Must be a specific signature: DataType(ObjectType*).
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, DataType)
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, DataType)
-		 * 						
+		 * @param	flags		Various flags you can use to specialize how systems handle this field
 		 */
 		 */
-		void initSingle(const std::string& name, UINT16 uniqueId, boost::any getter, boost::any setter)
+		void initSingle(const std::string& name, UINT16 uniqueId, boost::any getter, boost::any setter, UINT64 flags)
 		{
 		{
 			int typeId = RTTIPlainType<DataType>::id; // Just making sure provided type has a type ID
 			int typeId = RTTIPlainType<DataType>::id; // Just making sure provided type has a type ID
 
 
@@ -158,7 +158,7 @@ namespace CamelotEngine
 				"Trying to create a plain RTTI field with size larger than 255. In order to use larger sizes for plain types please specialize " \
 				"Trying to create a plain RTTI field with size larger than 255. In order to use larger sizes for plain types please specialize " \
 				" RTTIPlainType, set hasDynamicSize to true.");
 				" RTTIPlainType, set hasDynamicSize to true.");
 
 
-			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_Plain);
+			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_Plain, flags);
 		}
 		}
 
 
 		/**
 		/**
@@ -174,10 +174,10 @@ namespace CamelotEngine
 		 * @param	getSize 	Getter method that returns the size of an array. Cannot be null. Must be a specific signature: UINT32(ObjectType*)
 		 * @param	getSize 	Getter method that returns the size of an array. Cannot be null. Must be a specific signature: UINT32(ObjectType*)
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, UINT32, DataType)
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, UINT32, DataType)
 		 * @param	setSize 	Setter method that allows you to resize an array. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
 		 * @param	setSize 	Setter method that allows you to resize an array. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
-		 * 						
+		 * @param	flags		Various flags you can use to specialize how systems handle this field
 		 */
 		 */
 		void initArray(const std::string& name, UINT16 uniqueId, boost::any getter, 
 		void initArray(const std::string& name, UINT16 uniqueId, boost::any getter, 
-			boost::any getSize, boost::any setter, boost::any setSize)
+			boost::any getSize, boost::any setter, boost::any setSize, UINT64 flags)
 		{
 		{
 			int typeId = RTTIPlainType<DataType>::id; // Just making sure provided type has a type ID
 			int typeId = RTTIPlainType<DataType>::id; // Just making sure provided type has a type ID
 
 
@@ -185,7 +185,7 @@ namespace CamelotEngine
 				"Trying to create a plain RTTI field with size larger than 255. In order to use larger sizes for plain types please specialize " \
 				"Trying to create a plain RTTI field with size larger than 255. In order to use larger sizes for plain types please specialize " \
 				" RTTIPlainType, set hasDynamicSize to true.");
 				" RTTIPlainType, set hasDynamicSize to true.");
 
 
-			initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_Plain);
+			initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_Plain, flags);
 		}
 		}
 
 
 		virtual UINT32 getTypeSize()
 		virtual UINT32 getTypeSize()

+ 6 - 4
CamelotUtility/Include/CmRTTIReflectableField.h

@@ -32,10 +32,11 @@ namespace CamelotEngine
 		 * 						between different versions of serialized data.
 		 * 						between different versions of serialized data.
 		 * @param	getter  	The getter method for the field. Cannot be null. Must be a specific signature: DataType&(ObjectType*)
 		 * @param	getter  	The getter method for the field. Cannot be null. Must be a specific signature: DataType&(ObjectType*)
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, DataType)
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, DataType)
+		 * @param	flags		Various flags you can use to specialize how systems handle this field
 		 */
 		 */
-		void initSingle(const std::string& name, UINT16 uniqueId, boost::any getter, boost::any setter)
+		void initSingle(const std::string& name, UINT16 uniqueId, boost::any getter, boost::any setter, UINT64 flags)
 		{
 		{
-			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_Reflectable);
+			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_Reflectable, flags);
 		}
 		}
 
 
 		/**
 		/**
@@ -50,11 +51,12 @@ namespace CamelotEngine
 		 * @param	getSize 	Getter method that returns the size of an array. Cannot be null. Must be a specific signature: UINT32(ObjectType*)
 		 * @param	getSize 	Getter method that returns the size of an array. Cannot be null. Must be a specific signature: UINT32(ObjectType*)
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, UINT32, DataType)
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, UINT32, DataType)
 		 * @param	setSize 	Setter method that allows you to resize an array. Can be null. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
 		 * @param	setSize 	Setter method that allows you to resize an array. Can be null. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
+		 * @param	flags		Various flags you can use to specialize how systems handle this field
 		 */
 		 */
 		void initArray(const std::string& name, UINT16 uniqueId, boost::any getter, 
 		void initArray(const std::string& name, UINT16 uniqueId, boost::any getter, 
-			boost::any getSize, boost::any setter, boost::any setSize)
+			boost::any getSize, boost::any setter, boost::any setSize, UINT64 flags)
 		{
 		{
-			initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_Reflectable);
+			initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_Reflectable, flags);
 		}
 		}
 
 
 		virtual UINT32 getTypeSize()
 		virtual UINT32 getTypeSize()

+ 18 - 4
CamelotUtility/Include/CmRTTIReflectablePtrField.h

@@ -15,6 +15,8 @@ namespace CamelotEngine
 		virtual void setArrayValue(void* object, UINT32 index, std::shared_ptr<IReflectable> value) = 0;
 		virtual void setArrayValue(void* object, UINT32 index, std::shared_ptr<IReflectable> value) = 0;
 
 
 		virtual std::shared_ptr<IReflectable> newObject() = 0;
 		virtual std::shared_ptr<IReflectable> newObject() = 0;
+		virtual UINT32 getRTTIId() = 0;
+		virtual const String& getRTTIName() = 0;
 
 
 		virtual bool hasDynamicSize() { return true; }
 		virtual bool hasDynamicSize() { return true; }
 	};
 	};
@@ -32,10 +34,11 @@ namespace CamelotEngine
 		 * 						between different versions of serialized data.
 		 * 						between different versions of serialized data.
 		 * @param	getter  	The getter method for the field. Cannot be null. Must be a specific signature: DataType*(ObjectType*)
 		 * @param	getter  	The getter method for the field. Cannot be null. Must be a specific signature: DataType*(ObjectType*)
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, DataType*)
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, DataType*)
+		 * @param	flags		Various flags you can use to specialize how systems handle this field
 		 */
 		 */
-		void initSingle(const std::string& name, UINT16 uniqueId, boost::any getter, boost::any setter)
+		void initSingle(const std::string& name, UINT16 uniqueId, boost::any getter, boost::any setter, UINT64 flags)
 		{
 		{
-			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_ReflectablePtr);
+			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_ReflectablePtr, flags);
 		}
 		}
 
 
 		/**
 		/**
@@ -50,11 +53,12 @@ namespace CamelotEngine
 		 * @param	getSize 	Getter method that returns the size of an array. Cannot be null. Must be a specific signature: UINT32(ObjectType*)
 		 * @param	getSize 	Getter method that returns the size of an array. Cannot be null. Must be a specific signature: UINT32(ObjectType*)
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, UINT32, DataType*)
 		 * @param	setter  	The setter method for the field. Can be null. Must be a specific signature: void(ObjectType*, UINT32, DataType*)
 		 * @param	setSize 	Setter method that allows you to resize an array. Can be null. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
 		 * @param	setSize 	Setter method that allows you to resize an array. Can be null. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
+		 * @param	flags		Various flags you can use to specialize how systems handle this field
 		 */
 		 */
 		void initArray(const std::string& name, UINT16 uniqueId, boost::any getter, 
 		void initArray(const std::string& name, UINT16 uniqueId, boost::any getter, 
-			boost::any getSize, boost::any setter, boost::any setSize)
+			boost::any getSize, boost::any setter, boost::any setSize, UINT64 flags)
 		{
 		{
-			initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_ReflectablePtr);
+			initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_ReflectablePtr, flags);
 		}
 		}
 
 
 		virtual UINT32 getTypeSize()
 		virtual UINT32 getTypeSize()
@@ -144,5 +148,15 @@ namespace CamelotEngine
 		{
 		{
 			return std::shared_ptr<IReflectable>(DataType::getRTTIStatic()->newRTTIObject());
 			return std::shared_ptr<IReflectable>(DataType::getRTTIStatic()->newRTTIObject());
 		}
 		}
+
+		virtual UINT32 getRTTIId()
+		{
+			return DataType::getRTTIStatic()->getRTTIId();
+		}
+
+		virtual const String& getRTTIName()
+		{
+			return DataType::getRTTIStatic()->getRTTIName();
+		}
 	};
 	};
 }
 }

+ 88 - 45
CamelotUtility/Include/CmRTTIType.h

@@ -252,6 +252,40 @@ namespace CamelotEngine
 		 */
 		 */
 		void addNewField(RTTIField* field);
 		void addNewField(RTTIField* field);
 
 
+		/**
+		 * @brief	Checks if the templated DataType has any references back to us, that aren't weak.
+		 * 			
+		 * @note	This method assumes this class holds a non-weak reference to DataType.
+		 * 			DataType must derive from IReflectable and implement getRTTIStatic method.
+		 */
+		template<class DataType>
+		void checkForCircularReferences()
+		{
+			RTTITypeBase* type = DataType::getRTTIStatic();
+
+			for(UINT32 i = 0; i < type->getNumFields(); i++)
+			{
+				RTTIField* field = type->getField(i);
+
+				if(!field->isReflectablePtrType())
+					continue;
+
+				RTTIReflectablePtrFieldBase* reflectablePtrField = static_cast<RTTIReflectablePtrFieldBase*>(field);
+
+				if(reflectablePtrField->getRTTIId() == getRTTIId() && ((reflectablePtrField->getFlags() & RTTI_Flag_WeakRef) == 0))
+				{
+					throwCircularRefException(getRTTIName(), reflectablePtrField->getRTTIName());
+				}
+			}
+		}
+
+		/**
+		 * @brief	Throws an exception warning the user that a circular reference was found. 
+		 *
+		 * @note Only a separate function so I don't need to include CmException header.
+		 */
+		void throwCircularRefException(const String& myType, const String& otherType) const;
+
 	private:
 	private:
 		std::vector<RTTIField*> mFields;
 		std::vector<RTTIField*> mFields;
 	};
 	};
@@ -362,69 +396,72 @@ namespace CamelotEngine
 		/* 			FIELDS OPERATING DIRECTLY ON SERIALIZABLE OBJECT            */
 		/* 			FIELDS OPERATING DIRECTLY ON SERIALIZABLE OBJECT            */
 		/************************************************************************/
 		/************************************************************************/
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
-		void addPlainField(const std::string& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(), void (ObjectType::*setter)(DataType&) = nullptr)
+		void addPlainField(const std::string& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(), 
+			void (ObjectType::*setter)(DataType&) = nullptr, UINT64 flags = 0)
 		{
 		{
 			addPlainField<ObjectType, DataType>(name, uniqueId, 
 			addPlainField<ObjectType, DataType>(name, uniqueId, 
 				boost::function<DataType&(ObjectType*)>(getter), 
 				boost::function<DataType&(ObjectType*)>(getter), 
-				boost::function<void(ObjectType*, DataType&)>(setter));
+				boost::function<void(ObjectType*, DataType&)>(setter), flags);
 		}
 		}
 
 
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
-		void addReflectableField(const std::string& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(), void (ObjectType::*setter)(DataType&) = nullptr)
+		void addReflectableField(const std::string& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(), 
+			void (ObjectType::*setter)(DataType&) = nullptr, UINT64 flags = 0)
 		{
 		{
 			addReflectableField<ObjectType, DataType>(name, uniqueId, 
 			addReflectableField<ObjectType, DataType>(name, uniqueId, 
 				boost::function<DataType&(ObjectType*)>(getter), 
 				boost::function<DataType&(ObjectType*)>(getter), 
-				boost::function<void(ObjectType*, DataType&)>(setter));
+				boost::function<void(ObjectType*, DataType&)>(setter), flags);
 		}
 		}
 
 
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
-		void addReflectablePtrField(const std::string& name, UINT32 uniqueId, std::shared_ptr<DataType> (ObjectType::*getter)(), void (ObjectType::*setter)(std::shared_ptr<DataType>) = nullptr)
+		void addReflectablePtrField(const std::string& name, UINT32 uniqueId, std::shared_ptr<DataType> (ObjectType::*getter)(), 
+			void (ObjectType::*setter)(std::shared_ptr<DataType>) = nullptr, UINT64 flags = 0)
 		{
 		{
 			addReflectablePtrField<ObjectType, DataType>(name, uniqueId, 
 			addReflectablePtrField<ObjectType, DataType>(name, uniqueId, 
 				boost::function<std::shared_ptr<DataType>(ObjectType*)>(getter), 
 				boost::function<std::shared_ptr<DataType>(ObjectType*)>(getter), 
-				boost::function<void(ObjectType*, std::shared_ptr<DataType>)>(setter));
+				boost::function<void(ObjectType*, std::shared_ptr<DataType>)>(setter), flags);
 		}
 		}
 
 
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
 		void addPlainArrayField(const std::string& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
 		void addPlainArrayField(const std::string& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
-			void (ObjectType::*setter)(UINT32, DataType&) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr)
+			void (ObjectType::*setter)(UINT32, DataType&) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
 		{
 		{
 			addPlainArrayField<ObjectType, DataType>(name, uniqueId, 
 			addPlainArrayField<ObjectType, DataType>(name, uniqueId, 
 				boost::function<DataType&(ObjectType*, UINT32)>(getter), 
 				boost::function<DataType&(ObjectType*, UINT32)>(getter), 
 				boost::function<UINT32(ObjectType*)>(getSize), 
 				boost::function<UINT32(ObjectType*)>(getSize), 
 				boost::function<void(ObjectType*, UINT32, DataType&)>(setter), 
 				boost::function<void(ObjectType*, UINT32, DataType&)>(setter), 
-				boost::function<void(ObjectType*, UINT32)>(setSize));
+				boost::function<void(ObjectType*, UINT32)>(setSize), flags);
 		}	
 		}	
 
 
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
 		void addReflectableArrayField(const std::string& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
 		void addReflectableArrayField(const std::string& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
-			void (ObjectType::*setter)(UINT32, DataType&) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr)
+			void (ObjectType::*setter)(UINT32, DataType&) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
 		{
 		{
 			addReflectableArrayField<ObjectType, DataType>(name, uniqueId, 
 			addReflectableArrayField<ObjectType, DataType>(name, uniqueId, 
 				boost::function<DataType&(ObjectType*, UINT32)>(getter), 
 				boost::function<DataType&(ObjectType*, UINT32)>(getter), 
 				boost::function<UINT32(ObjectType*)>(getSize), 
 				boost::function<UINT32(ObjectType*)>(getSize), 
 				boost::function<void(ObjectType*, UINT32, DataType&)>(setter), 
 				boost::function<void(ObjectType*, UINT32, DataType&)>(setter), 
-				boost::function<void(ObjectType*, UINT32)>(setSize));
+				boost::function<void(ObjectType*, UINT32)>(setSize), flags);
 		}
 		}
 
 
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
 		void addReflectablePtrArrayField(const std::string& name, UINT32 uniqueId, std::shared_ptr<DataType> (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
 		void addReflectablePtrArrayField(const std::string& name, UINT32 uniqueId, std::shared_ptr<DataType> (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
-			void (ObjectType::*setter)(UINT32, std::shared_ptr<DataType>) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr)
+			void (ObjectType::*setter)(UINT32, std::shared_ptr<DataType>) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
 		{
 		{
 			addReflectablePtrArrayField<ObjectType, DataType>(name, uniqueId, 
 			addReflectablePtrArrayField<ObjectType, DataType>(name, uniqueId, 
 				boost::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>(getter), 
 				boost::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>(getter), 
 				boost::function<UINT32(ObjectType*)>(getSize), 
 				boost::function<UINT32(ObjectType*)>(getSize), 
 				boost::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>(setter), 
 				boost::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>(setter), 
-				boost::function<void(ObjectType*, UINT32)>(setSize));
+				boost::function<void(ObjectType*, UINT32)>(setSize), flags);
 		}
 		}
 
 
 		template<class ObjectType>
 		template<class ObjectType>
 		void addDataBlockField(const std::string& name, UINT32 uniqueId, ManagedDataBlock (ObjectType::*getter)(), 
 		void addDataBlockField(const std::string& name, UINT32 uniqueId, ManagedDataBlock (ObjectType::*getter)(), 
-			void (ObjectType::*setter)(ManagedDataBlock) = nullptr)
+			void (ObjectType::*setter)(ManagedDataBlock) = nullptr, UINT64 flags = 0)
 		{
 		{
 			addDataBlockField<ObjectType>(name, uniqueId, 
 			addDataBlockField<ObjectType>(name, uniqueId, 
 				boost::function<ManagedDataBlock(ObjectType*)>(getter),  
 				boost::function<ManagedDataBlock(ObjectType*)>(getter),  
-				boost::function<void(ObjectType*, ManagedDataBlock)>(setter));
+				boost::function<void(ObjectType*, ManagedDataBlock)>(setter), flags);
 		}	
 		}	
 
 
 	protected:
 	protected:
@@ -437,7 +474,7 @@ namespace CamelotEngine
 		template<class InterfaceType, class ObjectType, class DataType>
 		template<class InterfaceType, class ObjectType, class DataType>
 		void addPlainField(const std::string& name, UINT32 uniqueId, 
 		void addPlainField(const std::string& name, UINT32 uniqueId, 
 			DataType& (InterfaceType::*getter)(ObjectType*), 
 			DataType& (InterfaceType::*getter)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, DataType&) = nullptr)
+			void (InterfaceType::*setter)(ObjectType*, DataType&), UINT64 flags = 0)
 		{
 		{
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::RTTIType<Type, BaseType, MyRTTIType>, InterfaceType>::value), 
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::RTTIType<Type, BaseType, MyRTTIType>, InterfaceType>::value), 
 				"Class with the get/set methods must derive from CamelotEngine::RTTIType.");
 				"Class with the get/set methods must derive from CamelotEngine::RTTIType.");
@@ -447,35 +484,35 @@ namespace CamelotEngine
 
 
 			addPlainField<ObjectType, DataType>(name, uniqueId, 
 			addPlainField<ObjectType, DataType>(name, uniqueId, 
 				boost::function<DataType&(ObjectType*)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1)), 
 				boost::function<DataType&(ObjectType*)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1)), 
-				boost::function<void(ObjectType*, DataType&)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2)));
+				boost::function<void(ObjectType*, DataType&)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
 		}
 		}
 
 
 		template<class InterfaceType, class ObjectType, class DataType>
 		template<class InterfaceType, class ObjectType, class DataType>
 		void addReflectableField(const std::string& name, UINT32 uniqueId, 
 		void addReflectableField(const std::string& name, UINT32 uniqueId, 
 			DataType& (InterfaceType::*getter)(ObjectType*), 
 			DataType& (InterfaceType::*getter)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, DataType&) = nullptr)
+			void (InterfaceType::*setter)(ObjectType*, DataType&), UINT64 flags = 0)
 		{
 		{
 			addReflectableField<ObjectType, DataType>(name, uniqueId, 
 			addReflectableField<ObjectType, DataType>(name, uniqueId, 
 				boost::function<DataType&(ObjectType*)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1)), 
 				boost::function<DataType&(ObjectType*)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1)), 
-				boost::function<void(ObjectType*, DataType&)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2)));
+				boost::function<void(ObjectType*, DataType&)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
 		}
 		}
 
 
 		template<class InterfaceType, class ObjectType, class DataType>
 		template<class InterfaceType, class ObjectType, class DataType>
 		void addReflectablePtrField(const std::string& name, UINT32 uniqueId, 
 		void addReflectablePtrField(const std::string& name, UINT32 uniqueId, 
 			std::shared_ptr<DataType> (InterfaceType::*getter)(ObjectType*), 
 			std::shared_ptr<DataType> (InterfaceType::*getter)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, std::shared_ptr<DataType>) = nullptr)
+			void (InterfaceType::*setter)(ObjectType*, std::shared_ptr<DataType>), UINT64 flags = 0)
 		{
 		{
 			addReflectablePtrField<ObjectType, DataType>(name, uniqueId, 
 			addReflectablePtrField<ObjectType, DataType>(name, uniqueId, 
 				boost::function<std::shared_ptr<DataType>(ObjectType*)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1)), 
 				boost::function<std::shared_ptr<DataType>(ObjectType*)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1)), 
-				boost::function<void(ObjectType*, std::shared_ptr<DataType>)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2)));
+				boost::function<void(ObjectType*, std::shared_ptr<DataType>)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
 		}
 		}
 
 
 		template<class InterfaceType, class ObjectType, class DataType>
 		template<class InterfaceType, class ObjectType, class DataType>
 		void addPlainArrayField(const std::string& name, UINT32 uniqueId, 
 		void addPlainArrayField(const std::string& name, UINT32 uniqueId, 
 			DataType& (InterfaceType::*getter)(ObjectType*, UINT32), 
 			DataType& (InterfaceType::*getter)(ObjectType*, UINT32), 
 			UINT32 (InterfaceType::*getSize)(ObjectType*), 
 			UINT32 (InterfaceType::*getSize)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, UINT32, DataType&) = nullptr, 
-			void(InterfaceType::*setSize)(ObjectType*, UINT32) = nullptr)
+			void (InterfaceType::*setter)(ObjectType*, UINT32, DataType&), 
+			void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
 		{
 		{
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::RTTIType<Type, BaseType, MyRTTIType>, InterfaceType>::value), 
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::RTTIType<Type, BaseType, MyRTTIType>, InterfaceType>::value), 
 				"Class with the get/set methods must derive from CamelotEngine::RTTIType.");
 				"Class with the get/set methods must derive from CamelotEngine::RTTIType.");
@@ -487,115 +524,121 @@ namespace CamelotEngine
 				boost::function<DataType&(ObjectType*, UINT32)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
 				boost::function<DataType&(ObjectType*, UINT32)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
 				boost::function<UINT32(ObjectType*)>(boost::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
 				boost::function<UINT32(ObjectType*)>(boost::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
 				boost::function<void(ObjectType*, UINT32, DataType&)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
 				boost::function<void(ObjectType*, UINT32, DataType&)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
-				boost::function<void(ObjectType*, UINT32)>(boost::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)));
+				boost::function<void(ObjectType*, UINT32)>(boost::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
 		}	
 		}	
 
 
 		template<class InterfaceType, class ObjectType, class DataType>
 		template<class InterfaceType, class ObjectType, class DataType>
 		void addReflectableArrayField(const std::string& name, UINT32 uniqueId, 
 		void addReflectableArrayField(const std::string& name, UINT32 uniqueId, 
 			DataType& (InterfaceType::*getter)(ObjectType*, UINT32), 
 			DataType& (InterfaceType::*getter)(ObjectType*, UINT32), 
 			UINT32 (InterfaceType::*getSize)(ObjectType*), 
 			UINT32 (InterfaceType::*getSize)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, UINT32, DataType&) = nullptr, 
-			void(InterfaceType::*setSize)(ObjectType*, UINT32) = nullptr)
+			void (InterfaceType::*setter)(ObjectType*, UINT32, DataType&), 
+			void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
 		{
 		{
 			addReflectableArrayField<ObjectType, DataType>(name, uniqueId, 
 			addReflectableArrayField<ObjectType, DataType>(name, uniqueId, 
 				boost::function<DataType&(ObjectType*, UINT32)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
 				boost::function<DataType&(ObjectType*, UINT32)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
 				boost::function<UINT32(ObjectType*)>(boost::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
 				boost::function<UINT32(ObjectType*)>(boost::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
 				boost::function<void(ObjectType*, UINT32, DataType&)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
 				boost::function<void(ObjectType*, UINT32, DataType&)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
-				boost::function<void(ObjectType*, UINT32)>(boost::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)));
+				boost::function<void(ObjectType*, UINT32)>(boost::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
 		}
 		}
 
 
 		template<class InterfaceType, class ObjectType, class DataType>
 		template<class InterfaceType, class ObjectType, class DataType>
 		void addReflectablePtrArrayField(const std::string& name, UINT32 uniqueId, 
 		void addReflectablePtrArrayField(const std::string& name, UINT32 uniqueId, 
 			std::shared_ptr<DataType> (InterfaceType::*getter)(ObjectType*, UINT32), 
 			std::shared_ptr<DataType> (InterfaceType::*getter)(ObjectType*, UINT32), 
 			UINT32 (InterfaceType::*getSize)(ObjectType*), 
 			UINT32 (InterfaceType::*getSize)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, UINT32, std::shared_ptr<DataType>) = nullptr, 
-			void(InterfaceType::*setSize)(ObjectType*, UINT32) = nullptr)
+			void (InterfaceType::*setter)(ObjectType*, UINT32, std::shared_ptr<DataType>), 
+			void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
 		{
 		{
 			addReflectablePtrArrayField<ObjectType, DataType>(name, uniqueId, 
 			addReflectablePtrArrayField<ObjectType, DataType>(name, uniqueId, 
 				boost::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
 				boost::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
 				boost::function<UINT32(ObjectType*)>(boost::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
 				boost::function<UINT32(ObjectType*)>(boost::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
 				boost::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
 				boost::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
-				boost::function<void(ObjectType*, UINT32)>(boost::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)));
+				boost::function<void(ObjectType*, UINT32)>(boost::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
 		}
 		}
 
 
 		template<class InterfaceType, class ObjectType>
 		template<class InterfaceType, class ObjectType>
 		void addDataBlockField(const std::string& name, UINT32 uniqueId, ManagedDataBlock (InterfaceType::*getter)(ObjectType*), 
 		void addDataBlockField(const std::string& name, UINT32 uniqueId, ManagedDataBlock (InterfaceType::*getter)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, ManagedDataBlock) = nullptr)
+			void (InterfaceType::*setter)(ObjectType*, ManagedDataBlock), UINT64 flags = 0)
 		{
 		{
 			addDataBlockField<ObjectType>(name, uniqueId, 
 			addDataBlockField<ObjectType>(name, uniqueId, 
 				boost::function<ManagedDataBlock(ObjectType*)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1)),  
 				boost::function<ManagedDataBlock(ObjectType*)>(boost::bind(getter, static_cast<InterfaceType*>(this), _1)),  
-				boost::function<void(ObjectType*, ManagedDataBlock)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2)));
+				boost::function<void(ObjectType*, ManagedDataBlock)>(boost::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
 		}	
 		}	
 
 
 	private:
 	private:
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
-		void addPlainField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any setter = nullptr)
+		void addPlainField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any setter, UINT64 flags)
 		{
 		{
 			RTTIPlainField<DataType, ObjectType>* newField = new RTTIPlainField<DataType, ObjectType>();
 			RTTIPlainField<DataType, ObjectType>* newField = new RTTIPlainField<DataType, ObjectType>();
-			newField->initSingle(name, uniqueId, getter, setter);
+			newField->initSingle(name, uniqueId, getter, setter, flags);
 			addNewField(newField);
 			addNewField(newField);
 		}
 		}
 		
 		
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
-		void addReflectableField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any setter = nullptr)
+		void addReflectableField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any setter, UINT64 flags)
 		{
 		{
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::IReflectable, DataType>::value), 
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::IReflectable, DataType>::value), 
 				"Invalid data type for complex field. It needs to derive from CamelotEngine::IReflectable.");
 				"Invalid data type for complex field. It needs to derive from CamelotEngine::IReflectable.");
 
 
 			RTTIReflectableField<DataType, ObjectType>* newField = new RTTIReflectableField<DataType, ObjectType>();
 			RTTIReflectableField<DataType, ObjectType>* newField = new RTTIReflectableField<DataType, ObjectType>();
-			newField->initSingle(name, uniqueId, getter, setter);
+			newField->initSingle(name, uniqueId, getter, setter, flags);
 			addNewField(newField);
 			addNewField(newField);
 		}
 		}
 
 
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
-		void addReflectablePtrField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any setter = nullptr)
+		void addReflectablePtrField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any setter, UINT64 flags)
 		{
 		{
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::IReflectable, DataType>::value), 
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::IReflectable, DataType>::value), 
 				"Invalid data type for complex field. It needs to derive from CamelotEngine::IReflectable.");
 				"Invalid data type for complex field. It needs to derive from CamelotEngine::IReflectable.");
 
 
+			if((flags & RTTI_Flag_WeakRef) == 0)
+				checkForCircularReferences<DataType>();
+
 			RTTIReflectablePtrField<DataType, ObjectType>* newField = new RTTIReflectablePtrField<DataType, ObjectType>();
 			RTTIReflectablePtrField<DataType, ObjectType>* newField = new RTTIReflectablePtrField<DataType, ObjectType>();
-			newField->initSingle(name, uniqueId, getter, setter);
+			newField->initSingle(name, uniqueId, getter, setter, flags);
 			addNewField(newField);
 			addNewField(newField);
 		}
 		}
 
 
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
 		void addPlainArrayField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any getSize, 
 		void addPlainArrayField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any getSize, 
-			boost::any setter = nullptr, boost::any setSize = nullptr)
+			boost::any setter, boost::any setSize, UINT64 flags)
 		{
 		{
 			RTTIPlainField<DataType, ObjectType>* newField = new RTTIPlainField<DataType, ObjectType>();
 			RTTIPlainField<DataType, ObjectType>* newField = new RTTIPlainField<DataType, ObjectType>();
-			newField->initArray(name, uniqueId, getter, getSize, setter, setSize);
+			newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
 			addNewField(newField);
 			addNewField(newField);
 		}	
 		}	
 
 
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
 		void addReflectableArrayField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any getSize, 
 		void addReflectableArrayField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any getSize, 
-			boost::any setter = nullptr, boost::any setSize = nullptr)
+			boost::any setter, boost::any setSize, UINT64 flags)
 		{
 		{
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::IReflectable, DataType>::value), 
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::IReflectable, DataType>::value), 
 				"Invalid data type for complex field. It needs to derive from CamelotEngine::IReflectable.");
 				"Invalid data type for complex field. It needs to derive from CamelotEngine::IReflectable.");
 
 
 			RTTIReflectableField<DataType, ObjectType>* newField = new RTTIReflectableField<DataType, ObjectType>();
 			RTTIReflectableField<DataType, ObjectType>* newField = new RTTIReflectableField<DataType, ObjectType>();
-			newField->initArray(name, uniqueId, getter, getSize, setter, setSize);
+			newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
 			addNewField(newField);
 			addNewField(newField);
 		}
 		}
 
 
 		template<class ObjectType, class DataType>
 		template<class ObjectType, class DataType>
 		void addReflectablePtrArrayField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any getSize, 
 		void addReflectablePtrArrayField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any getSize, 
-			boost::any setter = nullptr, boost::any setSize = nullptr)
+			boost::any setter, boost::any setSize, UINT64 flags)
 		{
 		{
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::IReflectable, DataType>::value), 
 			BOOST_STATIC_ASSERT_MSG((boost::is_base_of<CamelotEngine::IReflectable, DataType>::value), 
 				"Invalid data type for complex field. It needs to derive from CamelotEngine::IReflectable.");
 				"Invalid data type for complex field. It needs to derive from CamelotEngine::IReflectable.");
 
 
+			if((flags & RTTI_Flag_WeakRef) == 0)
+				checkForCircularReferences<DataType>();
+
 			RTTIReflectablePtrField<DataType, ObjectType>* newField = new RTTIReflectablePtrField<DataType, ObjectType>();
 			RTTIReflectablePtrField<DataType, ObjectType>* newField = new RTTIReflectablePtrField<DataType, ObjectType>();
-			newField->initArray(name, uniqueId, getter, getSize, setter, setSize);
+			newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
 			addNewField(newField);
 			addNewField(newField);
 		}
 		}
 
 
 		template<class ObjectType>
 		template<class ObjectType>
-		void addDataBlockField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any setter = nullptr)
+		void addDataBlockField(const std::string& name, UINT32 uniqueId, boost::any getter, boost::any setter, UINT64 flags)
 		{
 		{
 			RTTIManagedDataBlockField<ManagedDataBlock, ObjectType>* newField = new RTTIManagedDataBlockField<ManagedDataBlock, ObjectType>();
 			RTTIManagedDataBlockField<ManagedDataBlock, ObjectType>* newField = new RTTIManagedDataBlockField<ManagedDataBlock, ObjectType>();
-			newField->initSingle(name, uniqueId, getter,  setter);
+			newField->initSingle(name, uniqueId, getter,  setter, flags);
 			addNewField(newField);
 			addNewField(newField);
 		}	
 		}	
 	};
 	};

+ 49 - 0
CamelotUtility/Include/CmString.h

@@ -356,6 +356,55 @@ namespace CamelotEngine {
     CM_UTILITY_EXPORT bool isNumber(const String& val);
     CM_UTILITY_EXPORT bool isNumber(const String& val);
 	/** @} */
 	/** @} */
 
 
+	void CM_UTILITY_EXPORT __string_throwDataOverflowException();
+
+	/**
+	 * @brief	Strings need to copy their data in a slightly more intricate way than just memcpy.
+	 */
+	template<> struct RTTIPlainType<String>
+	{	
+		enum { id = 20 }; enum { hasDynamicSize = 1 };
+
+		static void toMemory(String& data, char* memory)
+		{ 
+			UINT32 size = getDynamicSize(data);
+
+			memcpy(memory, &size, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size -= sizeof(UINT32);
+			memcpy(memory, data.data(), size); 
+		}
+
+		static void fromMemory(String& data, char* memory)
+		{ 
+			UINT32 size;
+			memcpy(&size, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			size -= sizeof(UINT32);
+			char* buffer = new char[size + 1]; // TODO - Use a better allocator
+			memcpy(buffer, memory, size); 
+			buffer[size] = '\0';
+			data = String(buffer);
+
+			delete[] buffer; 
+		}
+
+		static UINT32 getDynamicSize(String& data)	
+		{ 
+			UINT64 dataSize = data.size() * sizeof(String::value_type) + sizeof(UINT32);
+
+#if CM_DEBUG_MODE
+			if(dataSize > std::numeric_limits<UINT32>::max())
+			{
+				__string_throwDataOverflowException();
+			}
+#endif
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
 } // namespace CamelotEngine
 } // namespace CamelotEngine
 
 
 #endif // _String_H__
 #endif // _String_H__

+ 6 - 6
CamelotUtility/Source/CmRTTIField.cpp

@@ -9,7 +9,7 @@ namespace CamelotEngine
 		{
 		{
 			CM_EXCEPT(InternalErrorException, 
 			CM_EXCEPT(InternalErrorException, 
 				"Invalid field type. Needed: Plain type. Got: " + toString(mIsVectorType) + ", " + 
 				"Invalid field type. Needed: Plain type. Got: " + toString(mIsVectorType) + ", " + 
-				toString(isPlainType()) + ", " + toString(isComplexType()) + ", " + toString(isDataBlockType()) + ", " + toString(isComplexPtrType()));
+				toString(isPlainType()) + ", " + toString(isReflectableType()) + ", " + toString(isDataBlockType()) + ", " + toString(isReflectablePtrType()));
 		}
 		}
 
 
 		checkIsArray(array);
 		checkIsArray(array);
@@ -21,17 +21,17 @@ namespace CamelotEngine
 		{
 		{
 			CM_EXCEPT(InternalErrorException, 
 			CM_EXCEPT(InternalErrorException, 
 				"Invalid field type. Needed: Data block. Got: " + toString(mIsVectorType) + ", " + 
 				"Invalid field type. Needed: Data block. Got: " + toString(mIsVectorType) + ", " + 
-				toString(isPlainType()) + ", " + toString(isComplexType()) + ", " + toString(isDataBlockType()) + ", " + toString(isComplexPtrType()));
+				toString(isPlainType()) + ", " + toString(isReflectableType()) + ", " + toString(isDataBlockType()) + ", " + toString(isReflectablePtrType()));
 		}
 		}
 	}
 	}
 
 
 	void RTTIField::checkIsComplex(bool array)
 	void RTTIField::checkIsComplex(bool array)
 	{
 	{
-		if(!isComplexType())
+		if(!isReflectableType())
 		{
 		{
 			CM_EXCEPT(InternalErrorException, 
 			CM_EXCEPT(InternalErrorException, 
 				"Invalid field type. Needed: Complex type. Got: " + toString(mIsVectorType) + ", " + 
 				"Invalid field type. Needed: Complex type. Got: " + toString(mIsVectorType) + ", " + 
-				toString(isPlainType()) + ", " + toString(isComplexType()) + ", " + toString(isDataBlockType()) + ", " + toString(isComplexPtrType()));
+				toString(isPlainType()) + ", " + toString(isReflectableType()) + ", " + toString(isDataBlockType()) + ", " + toString(isReflectablePtrType()));
 		}
 		}
 
 
 		checkIsArray(array);
 		checkIsArray(array);
@@ -39,11 +39,11 @@ namespace CamelotEngine
 
 
 	void RTTIField::checkIsComplexPtr(bool array)
 	void RTTIField::checkIsComplexPtr(bool array)
 	{
 	{
-		if(!isComplexPtrType())
+		if(!isReflectablePtrType())
 		{
 		{
 			CM_EXCEPT(InternalErrorException, 
 			CM_EXCEPT(InternalErrorException, 
 				"Invalid field type. Needed: Complex ptr type. Got: " + toString(mIsVectorType) + ", " + 
 				"Invalid field type. Needed: Complex ptr type. Got: " + toString(mIsVectorType) + ", " + 
-				toString(isPlainType()) + ", " + toString(isComplexType()) + ", " + toString(isDataBlockType()) + ", " + toString(isComplexPtrType()));
+				toString(isPlainType()) + ", " + toString(isReflectableType()) + ", " + toString(isDataBlockType()) + ", " + toString(isReflectablePtrType()));
 		}
 		}
 
 
 		checkIsArray(array);
 		checkIsArray(array);

+ 6 - 0
CamelotUtility/Source/CmRTTIType.cpp

@@ -65,4 +65,10 @@ namespace CamelotEngine
 
 
 		mFields.push_back(field);
 		mFields.push_back(field);
 	}
 	}
+
+	void RTTITypeBase::throwCircularRefException(const String& myType, const String& otherType) const
+	{
+		CM_EXCEPT(InternalErrorException, "Found circular reference on RTTI type: " + myType + " to type: " + otherType + "."
+			+ " Either remove one of the references or mark it as a weak reference when defining the RTTI field.");
+	}
 }
 }

+ 6 - 0
CamelotUtility/Source/CmString.cpp

@@ -35,6 +35,7 @@ THE SOFTWARE.
 #include "CmVector2.h"
 #include "CmVector2.h"
 #include "CmVector3.h"
 #include "CmVector3.h"
 #include "CmVector4.h"
 #include "CmVector4.h"
+#include "CmException.h"
 
 
 namespace CamelotEngine {
 namespace CamelotEngine {
 
 
@@ -684,4 +685,9 @@ namespace CamelotEngine {
 		str >> tst;
 		str >> tst;
 		return !str.fail() && str.eof();
 		return !str.fail() && str.eof();
 	}
 	}
+	//----------------------------------------------------------------------
+	void __string_throwDataOverflowException()
+	{
+		CM_EXCEPT(InternalErrorException, "Data overflow! Size doesn't fit into 32 bits.");
+	}
 }
 }