Forráskód Böngészése

More work on improving documentation for doxygen generation

BearishSun 9 éve
szülő
commit
a75b8cca77
39 módosított fájl, 7053 hozzáadás és 6816 törlés
  1. 1 19
      Doxyfile
  2. 130 117
      Source/BansheeUtility/Include/BsAsyncOp.h
  3. 124 121
      Source/BansheeUtility/Include/BsBinaryDiff.h
  4. 203 203
      Source/BansheeUtility/Include/BsBinarySerializer.h
  5. 285 284
      Source/BansheeUtility/Include/BsColor.h
  6. 86 83
      Source/BansheeUtility/Include/BsCrashHandler.h
  7. 4 2
      Source/BansheeUtility/Include/BsDebug.h
  8. 75 73
      Source/BansheeUtility/Include/BsDynLib.h
  9. 43 43
      Source/BansheeUtility/Include/BsDynLibManager.h
  10. 368 336
      Source/BansheeUtility/Include/BsEvent.h
  11. 189 189
      Source/BansheeUtility/Include/BsException.h
  12. 210 207
      Source/BansheeUtility/Include/BsFrameAlloc.h
  13. 126 120
      Source/BansheeUtility/Include/BsFwdDeclUtil.h
  14. 235 228
      Source/BansheeUtility/Include/BsGlobalFrameAlloc.h
  15. 94 94
      Source/BansheeUtility/Include/BsIReflectable.h
  16. 607 593
      Source/BansheeUtility/Include/BsMath.h
  17. 41 38
      Source/BansheeUtility/Include/BsMemAllocProfiler.h
  18. 29 12
      Source/BansheeUtility/Include/BsMemStack.h
  19. 414 404
      Source/BansheeUtility/Include/BsMemoryAllocator.h
  20. 65 66
      Source/BansheeUtility/Include/BsMessageHandlerFwd.h
  21. 35 20
      Source/BansheeUtility/Include/BsPath.h
  22. 234 187
      Source/BansheeUtility/Include/BsPrerequisitesUtil.h
  23. 194 189
      Source/BansheeUtility/Include/BsRTTIField.h
  24. 124 121
      Source/BansheeUtility/Include/BsRTTIManagedDataBlockField.h
  25. 293 288
      Source/BansheeUtility/Include/BsRTTIPlainField.h
  26. 616 616
      Source/BansheeUtility/Include/BsRTTIPrerequisites.h
  27. 6 3
      Source/BansheeUtility/Include/BsRTTIReflectableField.h
  28. 231 228
      Source/BansheeUtility/Include/BsRTTIReflectablePtrField.h
  29. 15 3
      Source/BansheeUtility/Include/BsRTTIType.h
  30. 77 76
      Source/BansheeUtility/Include/BsSphere.h
  31. 268 266
      Source/BansheeUtility/Include/BsStaticAlloc.h
  32. 905 895
      Source/BansheeUtility/Include/BsString.h
  33. 13 6
      Source/BansheeUtility/Include/BsStringFormat.h
  34. 9 7
      Source/BansheeUtility/Include/BsTestSuite.h
  35. 110 110
      Source/BansheeUtility/Include/BsTexAtlasGenerator.h
  36. 23 4
      Source/BansheeUtility/Include/BsThreadPool.h
  37. 401 401
      Source/BansheeUtility/Include/BsVector3.h
  38. 29 26
      Source/BansheeUtility/Include/Win32/BsWin32PlatformUtility.h
  39. 141 138
      Source/BansheeUtility/Include/Win32/BsWin32Window.h

+ 1 - 19
Doxyfile

@@ -775,25 +775,7 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = Documentation/Manuals/Native \
-                         Source/BansheeCore/Include \
-                         Source/BansheeD3D9RenderAPI/Include \
-                         Source/BansheeD3D11RenderAPI/Include \
-                         Source/BansheeEditor/Include \
-                         Source/BansheeEngine/Include \
-                         Source/BansheeFBXImporter/Include \
-                         Source/BansheeFontImporter/Include \
-                         Source/BansheeFreeImgImporter/Include \
-                         Source/BansheeGLRenderAPI/Include \
-                         Source/BansheeMono/Include \
-                         Source/BansheeOISInput/Include \
-                         Source/BansheePhysX/Include \
-                         Source/BansheeSL/Include \
-                         Source/BansheeUtility/Include \
-                         Source/RenderBeast/Include \
-                         Source/SBansheeEditor/Include \
-                         Source/SBansheeEngine/Include \
-                         Source/BansheeGLRenderAPI/Source/GLSL/include
+INPUT                  = Source/BansheeUtility/Include
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses

+ 130 - 117
Source/BansheeUtility/Include/BsAsyncOp.h

@@ -1,118 +1,131 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsException.h"
-#include "BsAny.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Threading
-	 *  @{
-	 */
-
-	/** Thread synchronization primitives used by AsyncOps and their callers. */
-	class BS_UTILITY_EXPORT AsyncOpSyncData
-	{
-	public:
-		BS_MUTEX(mMutex)
-		BS_THREAD_SYNCHRONISER(mCondition)
-	};
-
-	/**
-	 * Flag used for creating async operations signaling that we want to create an empty AsyncOp with no internal 
-	 * memory storage.
-	 */
-	struct BS_UTILITY_EXPORT AsyncOpEmpty {};
-
-	/**
-	 * Object you may use to check on the results of an asynchronous operation. Contains uninitialized data until 
-	 * hasCompleted() returns true. 
-	 * 			
-	 * @note	
-	 * You are allowed (and meant to) to copy this by value.
-	 * @note
-	 * You'll notice mIsCompleted isn't synchronized. This is because we're okay if mIsCompleted reports true a few cycles 
-	 * too late, which is not relevant for practical use. And in cases where you need to ensure operation has completed 
-	 * you will usually use some kind of synchronization primitive that includes a memory barrier anyway.
-	 */
-	class BS_UTILITY_EXPORT AsyncOp
-	{
-	private:
-		struct AsyncOpData
-		{
-			AsyncOpData()
-				:mIsCompleted(false)
-			{ }
-
-			Any mReturnValue;
-			volatile std::atomic<bool> mIsCompleted;
-		};
-
-	public:
-		AsyncOp()
-			:mData(bs_shared_ptr_new<AsyncOpData>())
-		{ }
-
-		AsyncOp(AsyncOpEmpty empty)
-		{ }
-
-		AsyncOp(const AsyncOpSyncDataPtr& syncData)
-			:mData(bs_shared_ptr_new<AsyncOpData>()), mSyncData(syncData)
-		{ }
-
-		AsyncOp(AsyncOpEmpty empty, const AsyncOpSyncDataPtr& syncData)
-			:mSyncData(syncData)
-		{ }
-
-		/** True if the async operation has completed. */
-		bool hasCompleted() const;
-
-		/**
-		 * Blocks the caller thread until the AsyncOp completes.
-		 *
-		 * @note
-		 * Do not call this on the thread that is completing the async op, as it will cause a deadlock. Make sure the 
-		 * command you are waiting for is actually queued for execution because a deadlock will occurr otherwise.
-		 */
-		void blockUntilComplete() const;
-
-		/** Retrieves the value returned by the async operation. Only valid if hasCompleted() returns true. */
-		template <typename T>
-		T getReturnValue() const 
-		{ 
-#if BS_DEBUG_MODE
-			if(!hasCompleted())
-				BS_EXCEPT(InternalErrorException, "Trying to get AsyncOp return value but the operation hasn't completed.");
-#endif
-			// Be careful if cast throws an exception. It doesn't support casting of polymorphic types. Provided and returned
-			// types must be EXACT. (You'll have to cast the data yourself when completing the operation)
-			return any_cast<T>(mData->mReturnValue);
-		}
-
-	public: // ***** INTERNAL ******
-		/** @cond INTERNAL */
-
-		/**
-		 * Mark the async operation as completed.
-		 *
-		 * @note	Internal method.
-		 */
-		void _completeOperation(Any returnValue);
-
-		/**
-		 * Mark the async operation as completed, without setting a return value.
-		 *
-		 * @note	Internal method.
-		 */
-		void _completeOperation();
-
-		/** @endcond */
-	private:
-		std::shared_ptr<AsyncOpData> mData;
-		AsyncOpSyncDataPtr mSyncData;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsException.h"
+#include "BsAny.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Threading-Internal
+	 *  @{
+	 */
+
+	/** Thread synchronization primitives used by AsyncOps and their callers. */
+	class BS_UTILITY_EXPORT AsyncOpSyncData
+	{
+	public:
+		BS_MUTEX(mMutex)
+		BS_THREAD_SYNCHRONISER(mCondition)
+	};
+
+	/**
+	 * Flag used for creating async operations signaling that we want to create an empty AsyncOp with no internal 
+	 * memory storage.
+	 */
+	struct BS_UTILITY_EXPORT AsyncOpEmpty {};
+
+	/** @} */
+	/** @} */
+
+	/** @addtogroup Threading
+	 *  @{
+	 */
+
+	/**
+	 * Object you may use to check on the results of an asynchronous operation. Contains uninitialized data until 
+	 * hasCompleted() returns true. 
+	 * 			
+	 * @note	
+	 * You are allowed (and meant to) to copy this by value.
+	 * @note
+	 * You'll notice mIsCompleted isn't synchronized. This is because we're okay if mIsCompleted reports true a few cycles 
+	 * too late, which is not relevant for practical use. And in cases where you need to ensure operation has completed 
+	 * you will usually use some kind of synchronization primitive that includes a memory barrier anyway.
+	 */
+	class BS_UTILITY_EXPORT AsyncOp
+	{
+	private:
+		struct AsyncOpData
+		{
+			AsyncOpData()
+				:mIsCompleted(false)
+			{ }
+
+			Any mReturnValue;
+			volatile std::atomic<bool> mIsCompleted;
+		};
+
+	public:
+		AsyncOp()
+			:mData(bs_shared_ptr_new<AsyncOpData>())
+		{ }
+
+		AsyncOp(AsyncOpEmpty empty)
+		{ }
+
+		AsyncOp(const AsyncOpSyncDataPtr& syncData)
+			:mData(bs_shared_ptr_new<AsyncOpData>()), mSyncData(syncData)
+		{ }
+
+		AsyncOp(AsyncOpEmpty empty, const AsyncOpSyncDataPtr& syncData)
+			:mSyncData(syncData)
+		{ }
+
+		/** True if the async operation has completed. */
+		bool hasCompleted() const;
+
+		/**
+		 * Blocks the caller thread until the AsyncOp completes.
+		 *
+		 * @note
+		 * Do not call this on the thread that is completing the async op, as it will cause a deadlock. Make sure the 
+		 * command you are waiting for is actually queued for execution because a deadlock will occurr otherwise.
+		 */
+		void blockUntilComplete() const;
+
+		/** Retrieves the value returned by the async operation. Only valid if hasCompleted() returns true. */
+		template <typename T>
+		T getReturnValue() const 
+		{ 
+#if BS_DEBUG_MODE
+			if(!hasCompleted())
+				BS_EXCEPT(InternalErrorException, "Trying to get AsyncOp return value but the operation hasn't completed.");
+#endif
+			// Be careful if cast throws an exception. It doesn't support casting of polymorphic types. Provided and returned
+			// types must be EXACT. (You'll have to cast the data yourself when completing the operation)
+			return any_cast<T>(mData->mReturnValue);
+		}
+
+	public: // ***** INTERNAL ******
+		/** @name Internal 
+		 *  @{
+		 */
+
+		/**
+		 * Mark the async operation as completed.
+		 *
+		 * @note	Internal method.
+		 */
+		void _completeOperation(Any returnValue);
+
+		/**
+		 * Mark the async operation as completed, without setting a return value.
+		 *
+		 * @note	Internal method.
+		 */
+		void _completeOperation();
+
+		/** @} */
+	private:
+		std::shared_ptr<AsyncOpData> mData;
+		AsyncOpSyncDataPtr mSyncData;
+	};
+
+	/** @} */
 }

+ 124 - 121
Source/BansheeUtility/Include/BsBinaryDiff.h

@@ -1,122 +1,125 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup Serialization
-	 *  @{
-	 */
-
-	/**
-	 * Represents an interface RTTI objects need to implement if they want to provide custom "diff" generation and applying.
-	 */
-	class BS_UTILITY_EXPORT IDiff
-	{
-	public:
-		virtual ~IDiff() { }
-
-		/**
-		 * Generates per-field differences between the provided original and new object. Any field or array entry that is 
-		 * different in the new object compared to the original will be output in the resulting object, with a full 
-		 * hierarchy of that field.
-		 *
-		 * Will return null if there is no difference.
-		 */
-		SPtr<SerializedObject> generateDiff(const SPtr<SerializedObject>& orgObj, const SPtr<SerializedObject>& newObj);
-
-		/**
-		 * Applies a previously generated per-field differences to the provided object. This will essentially transform the
-		 * original object the differences were generated for into the modified version.
-		 */
-		void applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff);
-
-	protected:
-		typedef UnorderedMap<SPtr<SerializedObject>, SPtr<SerializedObject>> ObjectMap;
-		typedef UnorderedMap<SPtr<SerializedObject>, SPtr<IReflectable>> DiffObjectMap;
-
-		/** Types of commands that are used when applying difference field values. */
-		enum DiffCommandType
-		{
-			Diff_Plain = 0x01,
-			Diff_Reflectable = 0x02,
-			Diff_ReflectablePtr = 0x03,
-			Diff_DataBlock = 0x04,
-			Diff_ArraySize = 0x05,
-			Diff_ObjectStart = 0x06,
-			Diff_ObjectEnd = 0x07,
-			Diff_ArrayFlag = 0x10
-		};
-		
-		/**
-		 * A command that is used for delaying writing to an object, it contains all necessary information for setting RTTI 
-		 * field values on an object.
-		 */
-		struct DiffCommand
-		{
-			RTTIField* field;
-			UINT32 type;
-			SPtr<IReflectable> object;
-			UINT8* value;
-			UINT32 size;
-
-			union
-			{
-				UINT32 arrayIdx;
-				UINT32 arraySize;
-			};
-		};
-
-		/**
-		 * Recursive version of generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&).
-		 *
-		 * @see		generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&)
-		 */
-		virtual SPtr<SerializedObject> generateDiff(const SPtr<SerializedObject>& orgObj, const SPtr<SerializedObject>& newObj, ObjectMap& objectMap) = 0;
-
-		/**
-		 * Generates a difference between data of a specific field type indiscriminately of the specific field type.
-		 *
-		 * @see		generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&)
-		 */
-		SPtr<SerializedInstance> generateDiff(RTTITypeBase* rtti, UINT32 fieldType, const SPtr<SerializedInstance>& orgData,
-			const SPtr<SerializedInstance>& newData, ObjectMap& objectMap);
-
-		/**
-		 * Recursive version of applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff). Outputs a 
-		 * set of commands that then must be executed in order to actually apply the difference to the provided object.
-		 *
-		 * @see		applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff)
-		 */
-		virtual void applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands) = 0;
-
-		/**
-		 * Applies diff according to the diff handler retrieved from the provided RTTI object.
-		 *
-		 * @see		applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff)
-		 */
-		void applyDiff(RTTITypeBase* rtti, const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands);
-	};
-
-	/**
-	 * Generates and applies "diffs". Diffs contain per-field differences between an original and new object. These 
-	 * differences can be saved and then applied to an original object to transform it to the new version.
-	 *
-	 * @note	Objects must be in intermediate serialized format generated by BinarySerializer.
-	 */
-	class BS_UTILITY_EXPORT BinaryDiff : public IDiff
-	{
-	private:
-		/** @copydoc	IDiff::generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&, ObjectMap&) */
-		SPtr<SerializedObject> generateDiff(const SPtr<SerializedObject>& orgObj, const SPtr<SerializedObject>& newObj, ObjectMap& objectMap) override;
-
-		/** @copydoc	IDiff::applyDiff(const SPtr<IReflectable>&, const SPtr<SerializedObject>&, DiffObjectMap&, Vector<DiffCommand>&) */
-		void applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands) override;
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Serialization-Internal
+	 *  @{
+	 */
+
+	/**
+	 * Represents an interface RTTI objects need to implement if they want to provide custom "diff" generation and applying.
+	 */
+	class BS_UTILITY_EXPORT IDiff
+	{
+	public:
+		virtual ~IDiff() { }
+
+		/**
+		 * Generates per-field differences between the provided original and new object. Any field or array entry that is 
+		 * different in the new object compared to the original will be output in the resulting object, with a full 
+		 * hierarchy of that field.
+		 *
+		 * Will return null if there is no difference.
+		 */
+		SPtr<SerializedObject> generateDiff(const SPtr<SerializedObject>& orgObj, const SPtr<SerializedObject>& newObj);
+
+		/**
+		 * Applies a previously generated per-field differences to the provided object. This will essentially transform the
+		 * original object the differences were generated for into the modified version.
+		 */
+		void applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff);
+
+	protected:
+		typedef UnorderedMap<SPtr<SerializedObject>, SPtr<SerializedObject>> ObjectMap;
+		typedef UnorderedMap<SPtr<SerializedObject>, SPtr<IReflectable>> DiffObjectMap;
+
+		/** Types of commands that are used when applying difference field values. */
+		enum DiffCommandType
+		{
+			Diff_Plain = 0x01,
+			Diff_Reflectable = 0x02,
+			Diff_ReflectablePtr = 0x03,
+			Diff_DataBlock = 0x04,
+			Diff_ArraySize = 0x05,
+			Diff_ObjectStart = 0x06,
+			Diff_ObjectEnd = 0x07,
+			Diff_ArrayFlag = 0x10
+		};
+		
+		/**
+		 * A command that is used for delaying writing to an object, it contains all necessary information for setting RTTI 
+		 * field values on an object.
+		 */
+		struct DiffCommand
+		{
+			RTTIField* field;
+			UINT32 type;
+			SPtr<IReflectable> object;
+			UINT8* value;
+			UINT32 size;
+
+			union
+			{
+				UINT32 arrayIdx;
+				UINT32 arraySize;
+			};
+		};
+
+		/**
+		 * Recursive version of generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&).
+		 *
+		 * @see		generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&)
+		 */
+		virtual SPtr<SerializedObject> generateDiff(const SPtr<SerializedObject>& orgObj, const SPtr<SerializedObject>& newObj, ObjectMap& objectMap) = 0;
+
+		/**
+		 * Generates a difference between data of a specific field type indiscriminately of the specific field type.
+		 *
+		 * @see		generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&)
+		 */
+		SPtr<SerializedInstance> generateDiff(RTTITypeBase* rtti, UINT32 fieldType, const SPtr<SerializedInstance>& orgData,
+			const SPtr<SerializedInstance>& newData, ObjectMap& objectMap);
+
+		/**
+		 * Recursive version of applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff). Outputs a 
+		 * set of commands that then must be executed in order to actually apply the difference to the provided object.
+		 *
+		 * @see		applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff)
+		 */
+		virtual void applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands) = 0;
+
+		/**
+		 * Applies diff according to the diff handler retrieved from the provided RTTI object.
+		 *
+		 * @see		applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff)
+		 */
+		void applyDiff(RTTITypeBase* rtti, const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands);
+	};
+
+	/**
+	 * Generates and applies "diffs". Diffs contain per-field differences between an original and new object. These 
+	 * differences can be saved and then applied to an original object to transform it to the new version.
+	 *
+	 * @note	Objects must be in intermediate serialized format generated by BinarySerializer.
+	 */
+	class BS_UTILITY_EXPORT BinaryDiff : public IDiff
+	{
+	private:
+		/** @copydoc	IDiff::generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&, ObjectMap&) */
+		SPtr<SerializedObject> generateDiff(const SPtr<SerializedObject>& orgObj, const SPtr<SerializedObject>& newObj, ObjectMap& objectMap) override;
+
+		/** @copydoc	IDiff::applyDiff(const SPtr<IReflectable>&, const SPtr<SerializedObject>&, DiffObjectMap&, Vector<DiffCommand>&) */
+		void applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands) override;
+	};
+
+	/** @} */
+	/** @} */
 }

+ 203 - 203
Source/BansheeUtility/Include/BsBinarySerializer.h

@@ -1,204 +1,204 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include <unordered_map>
-
-#include "BsPrerequisitesUtil.h"
-#include "BsSerializedObject.h"
-#include "BsRTTIField.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Serialization
-	 *  @{
-	 */
-
-	class IReflectable;
-	struct RTTIReflectableFieldBase;
-	struct RTTIReflectablePtrFieldBase;
-
-	// TODO - Low priority. I will probably want to extract a generalized Serializer class so we can re-use the code
-	// in text or other serializers
-	// TODO - Low priority. Encode does a chunk-based encode so that we don't need to know the buffer size in advance,
-	// and don't have to use a lot of memory for the buffer. Consider doing something similar for decode.
-	// TODO - Low priority. Add a simple encode method that doesn't require a callback, instead it calls the callback internally
-	// and creates the buffer internally.
-	/**
-	 * Encodes all the fields of the provided object into a binary format. Fields are encoded using their unique IDs. 
-	 * Encoded data will remain compatible for decoding even if you modify the encoded class, as long as you assign new 
-	 * unique field IDs to added/modified fields.
-	 * 			
-	 * Like for any serializable class, fields are defined in RTTIType that each IReflectable class must be able to return.
-	 *
-	 * Any data the object or its children are pointing to will also be serialized (unless the pointer isn't registered in 
-	 * RTTIType). Upon decoding the pointer addresses will be set to proper values.
-	 * 			
-	 * @note	
-	 * Child elements are guaranteed to be fully deserialized before their parents, except for fields marked with WeakRef flag.
-	 */
-	class BS_UTILITY_EXPORT BinarySerializer
-	{
-	public:
-		BinarySerializer();
-
-		/**
-		 * Encodes all serializable fields provided by @p object into a binary format. Data is written in chunks. Whenever a 
-		 * chunk is filled a callback is triggered that gives the user opportunity to expand or empty the buffer (for 
-		 * example write the chunk to disk)
-		 *
-		 * @param[in]	object					Object to encode into binary format.
-		 * @param[out]	buffer					Preallocated buffer where the data will be stored.
-		 * @param[in]	bufferLength			Length of the buffer, in bytes.
-		 * @param[out]	bytesWritten			Length of the data that was actually written to the buffer, in bytes.
-		 * @param[in]	flushBufferCallback 	This callback will get called whenever the buffer gets full (Be careful to 
-		 *										check the provided @p bytesRead variable, as buffer might not be full 
-		 *										completely). User must then either create a new buffer or empty the existing 
-		 *										one, and then return it by the callback. If the returned buffer address is 
-		 *										NULL, encoding is aborted.
-		 * @param[in]	shallow					Determines how to handle referenced objects. If true then references will 
-		 *										not be encoded and will be set to null. If false then references will be 
-		 *										encoded as well and restored upon decoding.
-		 */
-		void encode(IReflectable* object, UINT8* buffer, UINT32 bufferLength, UINT32* bytesWritten,
-			std::function<UINT8*(UINT8* buffer, UINT32 bytesWritten, UINT32& newBufferSize)> flushBufferCallback,
-			bool shallow = false);
-
-		/**
-		 * Decodes an object from binary data.
-		 *
-		 * @param[in]	data  		Binary data to decode.
-		 * @param[in]	dataLength	Length of the data in bytes.
-		 */
-		SPtr<IReflectable> decode(UINT8* data, UINT32 dataLength);
-
-		/**
-		 * Encodes an object into an intermediate representation.
-		 *
-		 * @param[in]	object		Object to encode.
-		 * @param[in]	shallow		Determines how to handle referenced objects. If true then references will not be encoded
-		 *							and will be set to null. If false then references will be encoded as well and restored
-		 *							upon decoding.
-		 */
-		SPtr<SerializedObject> _encodeIntermediate(IReflectable* object, bool shallow = false);
-
-		/**
-		 * Decodes an object in memory into an intermediate representation for easier parsing.
-		 *			
-		 * @param[in] 	data  		Binary data to decode.
-		 * @param[in]	dataLength	Length of the data in bytes.
-		 * @param[in]	copyData	Determines should the data be copied or just referenced. If referenced then the returned
-		 *							serialized object will be invalid as soon as the original data buffer is destroyed. 
-		 *							Referencing is faster than copying.
-		 *
-		 * @note	
-		 * Internal method.
-		 * @note
-		 * References to field data will point to the original buffer and will become invalid when it is destroyed.
-		 */
-		SPtr<SerializedObject> _decodeIntermediate(UINT8* data, UINT32 dataLength, bool copyData = false);
-
-		/**
-		 * Decodes an intermediate representation of a serialized object into the actual object.
-		 *			
-		 * @note	Internal method.
-		 */
-		SPtr<IReflectable> _decodeIntermediate(const SPtr<SerializedObject>& serializedObject);
-
-	private:
-		struct ObjectMetaData
-		{
-			UINT32 objectMeta;
-			UINT32 typeId;
-		};
-
-		struct ObjectToEncode
-		{
-			ObjectToEncode(UINT32 _objectId, std::shared_ptr<IReflectable> _object)
-				:objectId(_objectId), object(_object)
-			{ }
-
-			UINT32 objectId;
-			std::shared_ptr<IReflectable> object;
-		};
-
-		struct ObjectToDecode
-		{
-			ObjectToDecode(const SPtr<IReflectable>& _object, const SPtr<SerializedObject>& serializedObject)
-				:object(_object), serializedObject(serializedObject), isDecoded(false), decodeInProgress(false)
-			{ }
-
-			SPtr<IReflectable> object;
-			SPtr<SerializedObject> serializedObject;
-			bool isDecoded;
-			bool decodeInProgress; // Used for error reporting circular references
-		};
-
-		/** Encodes a single IReflectable object. */
-		UINT8* encodeInternal(IReflectable* object, UINT32 objectId, UINT8* buffer, UINT32& bufferLength, UINT32* bytesWritten,
-			std::function<UINT8*(UINT8* buffer, UINT32 bytesWritten, UINT32& newBufferSize)> flushBufferCallback, bool shallow);
-
-		/**	Decodes a single IReflectable object. */
-		void decodeInternal(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& serializableObject);
-
-		/**	Decodes an object in memory into an intermediate representation for easier parsing. */
-		bool decodeIntermediateInternal(UINT8* data, UINT32 dataLength, UINT32& bytesRead, SPtr<SerializedObject>& output, bool copyData);
-
-		/**	Helper method for encoding a complex object and copying its data to a buffer. */
-		UINT8* complexTypeToBuffer(IReflectable* object, UINT8* buffer, UINT32& bufferLength, UINT32* bytesWritten,
-			std::function<UINT8*(UINT8* buffer, UINT32 bytesWritten, UINT32& newBufferSize)> flushBufferCallback, bool shallow);
-
-		/**	Helper method for encoding a data block to a buffer. */
-		UINT8* dataBlockToBuffer(UINT8* data, UINT32 size, UINT8* buffer, UINT32& bufferLength, UINT32* bytesWritten,
-			std::function<UINT8*(UINT8* buffer, UINT32 bytesWritten, UINT32& newBufferSize)> flushBufferCallback);
-
-		/**	Finds an existing, or creates a unique unique identifier for the specified object. */
-		UINT32 findOrCreatePersistentId(IReflectable* object);
-
-		/**
-		 * Finds or creates an id for the provided object and returns it. And it adds the object to a list of objects that 
-		 * need to be encoded, if it's not already there.
-		 */
-		UINT32 registerObjectPtr(std::shared_ptr<IReflectable> object);
-
-		/** Encodes data required for representing a serialized field, into 4 bytes. */
-		static UINT32 encodeFieldMetaData(UINT16 id, UINT8 size, bool array, 
-			SerializableFieldType type, bool hasDynamicSize, bool terminator);
-
-		/** Decode meta field that was encoded using encodeFieldMetaData().*/
-		static void decodeFieldMetaData(UINT32 encodedData, UINT16& id, UINT8& size, bool& array, 
-			SerializableFieldType& type, bool& hasDynamicSize, bool& terminator);
-
-		/**
-		 * Encodes data required for representing an object identifier, into 8 bytes.
-		 *
-		 * @param[in]	objId	   	Unique ID of the object instance.
-		 * @param[in]	objTypeId  	Unique ID of the object type.
-		 * @param[in]	isBaseClass	true if this object is base class (i.e. just a part of a larger object).
-		 *
-		 * @note		Id can be a maximum of 30 bits, as two bits are reserved.
-		 */
-		static ObjectMetaData encodeObjectMetaData(UINT32 objId, UINT32 objTypeId, bool isBaseClass);
-
-		/** Decode meta field that was encoded using encodeObjectMetaData. */
-		static void decodeObjectMetaData(ObjectMetaData encodedData, UINT32& objId, UINT32& objTypeId, bool& isBaseClass);
-
-		/** Returns true if the provided encoded meta data represents object meta data. */
-		static bool isObjectMetaData(UINT32 encodedData);
-
-		UnorderedMap<void*, UINT32> mObjectAddrToId;
-		UINT32 mLastUsedObjectId;
-		Vector<ObjectToEncode> mObjectsToEncode;
-		UINT32 mTotalBytesWritten;
-
-		UnorderedMap<SPtr<SerializedObject>, ObjectToDecode> mObjectMap;
-		UnorderedMap<UINT32, SPtr<SerializedObject>> mInterimObjectMap;
-
-		static const int META_SIZE = 4; // Meta field size
-		static const int NUM_ELEM_FIELD_SIZE = 4; // Size of the field storing number of array elements
-		static const int COMPLEX_TYPE_FIELD_SIZE = 4; // Size of the field storing the size of a child complex type
-		static const int DATA_BLOCK_TYPE_FIELD_SIZE = 4;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include <unordered_map>
+
+#include "BsPrerequisitesUtil.h"
+#include "BsSerializedObject.h"
+#include "BsRTTIField.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Serialization
+	 *  @{
+	 */
+
+	class IReflectable;
+	struct RTTIReflectableFieldBase;
+	struct RTTIReflectablePtrFieldBase;
+
+	// TODO - Low priority. I will probably want to extract a generalized Serializer class so we can re-use the code
+	// in text or other serializers
+	// TODO - Low priority. Encode does a chunk-based encode so that we don't need to know the buffer size in advance,
+	// and don't have to use a lot of memory for the buffer. Consider doing something similar for decode.
+	// TODO - Low priority. Add a simple encode method that doesn't require a callback, instead it calls the callback internally
+	// and creates the buffer internally.
+	/**
+	 * Encodes all the fields of the provided object into a binary format. Fields are encoded using their unique IDs. 
+	 * Encoded data will remain compatible for decoding even if you modify the encoded class, as long as you assign new 
+	 * unique field IDs to added/modified fields.
+	 * 			
+	 * Like for any serializable class, fields are defined in RTTIType that each IReflectable class must be able to return.
+	 *
+	 * Any data the object or its children are pointing to will also be serialized (unless the pointer isn't registered in 
+	 * RTTIType). Upon decoding the pointer addresses will be set to proper values.
+	 * 			
+	 * @note	
+	 * Child elements are guaranteed to be fully deserialized before their parents, except for fields marked with WeakRef flag.
+	 */
+	class BS_UTILITY_EXPORT BinarySerializer
+	{
+	public:
+		BinarySerializer();
+
+		/**
+		 * Encodes all serializable fields provided by @p object into a binary format. Data is written in chunks. Whenever a 
+		 * chunk is filled a callback is triggered that gives the user opportunity to expand or empty the buffer (for 
+		 * example write the chunk to disk)
+		 *
+		 * @param[in]	object					Object to encode into binary format.
+		 * @param[out]	buffer					Preallocated buffer where the data will be stored.
+		 * @param[in]	bufferLength			Length of the buffer, in bytes.
+		 * @param[out]	bytesWritten			Length of the data that was actually written to the buffer, in bytes.
+		 * @param[in]	flushBufferCallback 	This callback will get called whenever the buffer gets full (Be careful to 
+		 *										check the provided @p bytesRead variable, as buffer might not be full 
+		 *										completely). User must then either create a new buffer or empty the existing 
+		 *										one, and then return it by the callback. If the returned buffer address is 
+		 *										NULL, encoding is aborted.
+		 * @param[in]	shallow					Determines how to handle referenced objects. If true then references will 
+		 *										not be encoded and will be set to null. If false then references will be 
+		 *										encoded as well and restored upon decoding.
+		 */
+		void encode(IReflectable* object, UINT8* buffer, UINT32 bufferLength, UINT32* bytesWritten,
+			std::function<UINT8*(UINT8* buffer, UINT32 bytesWritten, UINT32& newBufferSize)> flushBufferCallback,
+			bool shallow = false);
+
+		/**
+		 * Decodes an object from binary data.
+		 *
+		 * @param[in]	data  		Binary data to decode.
+		 * @param[in]	dataLength	Length of the data in bytes.
+		 */
+		SPtr<IReflectable> decode(UINT8* data, UINT32 dataLength);
+
+		/**
+		 * Encodes an object into an intermediate representation.
+		 *
+		 * @param[in]	object		Object to encode.
+		 * @param[in]	shallow		Determines how to handle referenced objects. If true then references will not be encoded
+		 *							and will be set to null. If false then references will be encoded as well and restored
+		 *							upon decoding.
+		 */
+		SPtr<SerializedObject> _encodeIntermediate(IReflectable* object, bool shallow = false);
+
+		/**
+		 * Decodes an object in memory into an intermediate representation for easier parsing.
+		 *			
+		 * @param[in] 	data  		Binary data to decode.
+		 * @param[in]	dataLength	Length of the data in bytes.
+		 * @param[in]	copyData	Determines should the data be copied or just referenced. If referenced then the returned
+		 *							serialized object will be invalid as soon as the original data buffer is destroyed. 
+		 *							Referencing is faster than copying.
+		 *
+		 * @note	
+		 * Internal method.
+		 * @note
+		 * References to field data will point to the original buffer and will become invalid when it is destroyed.
+		 */
+		SPtr<SerializedObject> _decodeIntermediate(UINT8* data, UINT32 dataLength, bool copyData = false);
+
+		/**
+		 * Decodes an intermediate representation of a serialized object into the actual object.
+		 *			
+		 * @note	Internal method.
+		 */
+		SPtr<IReflectable> _decodeIntermediate(const SPtr<SerializedObject>& serializedObject);
+
+	private:
+		struct ObjectMetaData
+		{
+			UINT32 objectMeta;
+			UINT32 typeId;
+		};
+
+		struct ObjectToEncode
+		{
+			ObjectToEncode(UINT32 _objectId, std::shared_ptr<IReflectable> _object)
+				:objectId(_objectId), object(_object)
+			{ }
+
+			UINT32 objectId;
+			std::shared_ptr<IReflectable> object;
+		};
+
+		struct ObjectToDecode
+		{
+			ObjectToDecode(const SPtr<IReflectable>& _object, const SPtr<SerializedObject>& serializedObject)
+				:object(_object), serializedObject(serializedObject), isDecoded(false), decodeInProgress(false)
+			{ }
+
+			SPtr<IReflectable> object;
+			SPtr<SerializedObject> serializedObject;
+			bool isDecoded;
+			bool decodeInProgress; // Used for error reporting circular references
+		};
+
+		/** Encodes a single IReflectable object. */
+		UINT8* encodeInternal(IReflectable* object, UINT32 objectId, UINT8* buffer, UINT32& bufferLength, UINT32* bytesWritten,
+			std::function<UINT8*(UINT8* buffer, UINT32 bytesWritten, UINT32& newBufferSize)> flushBufferCallback, bool shallow);
+
+		/**	Decodes a single IReflectable object. */
+		void decodeInternal(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& serializableObject);
+
+		/**	Decodes an object in memory into an intermediate representation for easier parsing. */
+		bool decodeIntermediateInternal(UINT8* data, UINT32 dataLength, UINT32& bytesRead, SPtr<SerializedObject>& output, bool copyData);
+
+		/**	Helper method for encoding a complex object and copying its data to a buffer. */
+		UINT8* complexTypeToBuffer(IReflectable* object, UINT8* buffer, UINT32& bufferLength, UINT32* bytesWritten,
+			std::function<UINT8*(UINT8* buffer, UINT32 bytesWritten, UINT32& newBufferSize)> flushBufferCallback, bool shallow);
+
+		/**	Helper method for encoding a data block to a buffer. */
+		UINT8* dataBlockToBuffer(UINT8* data, UINT32 size, UINT8* buffer, UINT32& bufferLength, UINT32* bytesWritten,
+			std::function<UINT8*(UINT8* buffer, UINT32 bytesWritten, UINT32& newBufferSize)> flushBufferCallback);
+
+		/**	Finds an existing, or creates a unique unique identifier for the specified object. */
+		UINT32 findOrCreatePersistentId(IReflectable* object);
+
+		/**
+		 * Finds or creates an id for the provided object and returns it. And it adds the object to a list of objects that 
+		 * need to be encoded, if it's not already there.
+		 */
+		UINT32 registerObjectPtr(std::shared_ptr<IReflectable> object);
+
+		/** Encodes data required for representing a serialized field, into 4 bytes. */
+		static UINT32 encodeFieldMetaData(UINT16 id, UINT8 size, bool array, 
+			SerializableFieldType type, bool hasDynamicSize, bool terminator);
+
+		/** Decode meta field that was encoded using encodeFieldMetaData().*/
+		static void decodeFieldMetaData(UINT32 encodedData, UINT16& id, UINT8& size, bool& array, 
+			SerializableFieldType& type, bool& hasDynamicSize, bool& terminator);
+
+		/**
+		 * Encodes data required for representing an object identifier, into 8 bytes.
+		 *
+		 * @param[in]	objId	   	Unique ID of the object instance.
+		 * @param[in]	objTypeId  	Unique ID of the object type.
+		 * @param[in]	isBaseClass	true if this object is base class (that is, just a part of a larger object).
+		 *
+		 * @note		Id can be a maximum of 30 bits, as two bits are reserved.
+		 */
+		static ObjectMetaData encodeObjectMetaData(UINT32 objId, UINT32 objTypeId, bool isBaseClass);
+
+		/** Decode meta field that was encoded using encodeObjectMetaData. */
+		static void decodeObjectMetaData(ObjectMetaData encodedData, UINT32& objId, UINT32& objTypeId, bool& isBaseClass);
+
+		/** Returns true if the provided encoded meta data represents object meta data. */
+		static bool isObjectMetaData(UINT32 encodedData);
+
+		UnorderedMap<void*, UINT32> mObjectAddrToId;
+		UINT32 mLastUsedObjectId;
+		Vector<ObjectToEncode> mObjectsToEncode;
+		UINT32 mTotalBytesWritten;
+
+		UnorderedMap<SPtr<SerializedObject>, ObjectToDecode> mObjectMap;
+		UnorderedMap<UINT32, SPtr<SerializedObject>> mInterimObjectMap;
+
+		static const int META_SIZE = 4; // Meta field size
+		static const int NUM_ELEM_FIELD_SIZE = 4; // Size of the field storing number of array elements
+		static const int COMPLEX_TYPE_FIELD_SIZE = 4; // Size of the field storing the size of a child complex type
+		static const int DATA_BLOCK_TYPE_FIELD_SIZE = 4;
+	};
+
+	/** @} */
 }

+ 285 - 284
Source/BansheeUtility/Include/BsColor.h

@@ -1,284 +1,285 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-/** @addtogroup Image
- *  @{
- */
-
-namespace BansheeEngine 
-{
-    typedef UINT32 RGBA;
-    typedef UINT32 ARGB;
-    typedef UINT32 ABGR;
-	typedef UINT32 BGRA;
-
-	/** 
-	 * Color represented as 4 components, each being a floating point value ranging from 0 to 1. Color components are 
-	 * red, green, blue and alpha.
-	 */
-    class BS_UTILITY_EXPORT Color
-    {
-    public:
-        static const Color ZERO;
-        static const Color Black;
-        static const Color White;
-        static const Color Red;
-        static const Color Green;
-        static const Color Blue;
-
-	    explicit Color(float red = 1.0f, float green = 1.0f,
-				    float blue = 1.0f, float alpha = 1.0f ) 
-					:r(red), g(green), b(blue), a(alpha)
-        { }
-
-	    bool operator==(const Color& rhs) const;
-	    bool operator!=(const Color& rhs) const;
-
-	    RGBA getAsRGBA(void) const;
-	    ARGB getAsARGB(void) const;
-		BGRA getAsBGRA(void) const;
-	    ABGR getAsABGR(void) const;
-
-        void setAsRGBA(const RGBA val);
-        void setAsARGB(const ARGB val);
-		void setAsBGRA(const BGRA val);
-        void setAsABGR(const ABGR val);
-
-		/** Clamps colour value to the range [0, 1]. */
-        void saturate()
-        {
-            if (r < 0)
-                r = 0;
-            else if (r > 1)
-                r = 1;
-
-            if (g < 0)
-                g = 0;
-            else if (g > 1)
-                g = 1;
-
-            if (b < 0)
-                b = 0;
-            else if (b > 1)
-                b = 1;
-
-            if (a < 0)
-                a = 0;
-            else if (a > 1)
-                a = 1;
-        }
-
-		/** Clamps colour value to the range [0, 1]. Returned saturated color as a copy. */
-        Color saturateCopy() const
-        {
-            Color ret = *this;
-            ret.saturate();
-            return ret;
-        }
-
-		float operator[] (const UINT32 i) const
-		{
-			assert(i < 4);
-
-			return *(&r+i);
-		}
-
-		float& operator[] (const UINT32 i)
-		{
-			assert(i < 4);
-
-			return *(&r+i);
-		}
-
-		/** Pointer accessor for direct copying. */
-		float* ptr()
-		{
-			return &r;
-		}
-
-		/** Pointer accessor for direct copying. */
-		const float* ptr() const
-		{
-			return &r;
-		}
-
-        Color operator+ (const Color& rhs) const
-        {
-            Color kSum;
-
-            kSum.r = r + rhs.r;
-            kSum.g = g + rhs.g;
-            kSum.b = b + rhs.b;
-            kSum.a = a + rhs.a;
-
-            return kSum;
-        }
-
-        Color operator- ( const Color& rhs) const
-        {
-            Color kDiff;
-
-            kDiff.r = r - rhs.r;
-            kDiff.g = g - rhs.g;
-            kDiff.b = b - rhs.b;
-            kDiff.a = a - rhs.a;
-
-            return kDiff;
-        }
-
-        Color operator* (const float rhs) const
-        {
-            Color kProd;
-
-            kProd.r = rhs*r;
-            kProd.g = rhs*g;
-            kProd.b = rhs*b;
-            kProd.a = rhs*a;
-
-            return kProd;
-        }
-
-        Color operator* (const Color& rhs) const
-        {
-            Color kProd;
-
-            kProd.r = rhs.r * r;
-            kProd.g = rhs.g * g;
-            kProd.b = rhs.b * b;
-            kProd.a = rhs.a * a;
-
-            return kProd;
-        }
-
-        Color operator/ (const Color& rhs) const
-        {
-            Color kProd;
-
-            kProd.r = rhs.r / r;
-            kProd.g = rhs.g / g;
-            kProd.b = rhs.b / b;
-            kProd.a = rhs.a / a;
-
-            return kProd;
-        }
-
-        Color operator/ (const float rhs) const
-        {
-            assert(rhs != 0.0f);
-
-            Color kDiv;
-
-            float fInv = 1.0f / rhs;
-            kDiv.r = r * fInv;
-            kDiv.g = g * fInv;
-            kDiv.b = b * fInv;
-            kDiv.a = a * fInv;
-
-            return kDiv;
-        }
-
-        friend Color operator* (const float lhs, const Color& rhs)
-        {
-            Color result;
-
-            result.r = lhs * rhs.r;
-            result.g = lhs * rhs.g;
-            result.b = lhs * rhs.b;
-            result.a = lhs * rhs.a;
-
-            return result;
-        }
-
-        Color& operator+= (const Color& rhs)
-        {
-            r += rhs.r;
-            g += rhs.g;
-            b += rhs.b;
-            a += rhs.a;
-
-            return *this;
-        }
-
-        Color& operator-= (const Color& rhs)
-        {
-            r -= rhs.r;
-            g -= rhs.g;
-            b -= rhs.b;
-            a -= rhs.a;
-
-            return *this;
-        }
-
-        Color& operator*= (const float rhs)
-        {
-            r *= rhs;
-            g *= rhs;
-            b *= rhs;
-            a *= rhs;
-
-            return *this;
-        }
-
-        Color& operator/= (const float rhs)
-        {
-            assert(rhs != 0.0f);
-
-            float fInv = 1.0f / rhs;
-
-            r *= rhs;
-            g *= rhs;
-            b *= rhs;
-            a *= rhs;
-
-            return *this;
-        }
-
-		/** 
-		 * Set a colour value from Hue, Saturation and Brightness.
-		 *
-		 * @param[in] hue			Hue value, scaled to the [0,1] range.
-		 * @param[in] saturation	Saturation level, [0,1].
-		 * @param[in] brightness	Brightness level, [0,1].
-		 */
-		void setHSB(float hue, float saturation, float brightness);
-
-		/** 
-		 * Convert the current color to Hue, Saturation and Brightness values. 
-		 * 
-		 * @param[in] hue			Output hue value, scaled to the [0,1] range.
-		 * @param[in] saturation	Output saturation level, [0,1].
-		 * @param[in] brightness	Output brightness level, [0,1].
-		 */
-		void getHSB(float* hue, float* saturation, float* brightness) const;
-
-		float r, g, b, a;
-    };
-
-	/** @cond SPECIALIZATIONS */
-	BS_ALLOW_MEMCPY_SERIALIZATION(Color);
-	/** @endcond */
-}
-
-/** @cond SPECIALIZATIONS */
-
-/** Hash value generator for Color. */
-template<> 
-struct std::hash<BansheeEngine::Color>
-{
-	size_t operator()(const BansheeEngine::Color& color) const
-	{
-		size_t hash = 0;
-		BansheeEngine::hash_combine(hash, color.r);
-		BansheeEngine::hash_combine(hash, color.g);
-		BansheeEngine::hash_combine(hash, color.b);
-		BansheeEngine::hash_combine(hash, color.a);
-
-		return hash;
-	}
-};
-
-/** @endcond */
-/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+namespace BansheeEngine 
+{
+	/** @addtogroup Image
+	 *  @{
+	 */
+
+    typedef UINT32 RGBA;
+    typedef UINT32 ARGB;
+    typedef UINT32 ABGR;
+	typedef UINT32 BGRA;
+
+	/** 
+	 * Color represented as 4 components, each being a floating point value ranging from 0 to 1. Color components are 
+	 * red, green, blue and alpha.
+	 */
+    class BS_UTILITY_EXPORT Color
+    {
+    public:
+        static const Color ZERO;
+        static const Color Black;
+        static const Color White;
+        static const Color Red;
+        static const Color Green;
+        static const Color Blue;
+
+	    explicit Color(float red = 1.0f, float green = 1.0f,
+				    float blue = 1.0f, float alpha = 1.0f ) 
+					:r(red), g(green), b(blue), a(alpha)
+        { }
+
+	    bool operator==(const Color& rhs) const;
+	    bool operator!=(const Color& rhs) const;
+
+	    RGBA getAsRGBA(void) const;
+	    ARGB getAsARGB(void) const;
+		BGRA getAsBGRA(void) const;
+	    ABGR getAsABGR(void) const;
+
+        void setAsRGBA(const RGBA val);
+        void setAsARGB(const ARGB val);
+		void setAsBGRA(const BGRA val);
+        void setAsABGR(const ABGR val);
+
+		/** Clamps colour value to the range [0, 1]. */
+        void saturate()
+        {
+            if (r < 0)
+                r = 0;
+            else if (r > 1)
+                r = 1;
+
+            if (g < 0)
+                g = 0;
+            else if (g > 1)
+                g = 1;
+
+            if (b < 0)
+                b = 0;
+            else if (b > 1)
+                b = 1;
+
+            if (a < 0)
+                a = 0;
+            else if (a > 1)
+                a = 1;
+        }
+
+		/** Clamps colour value to the range [0, 1]. Returned saturated color as a copy. */
+        Color saturateCopy() const
+        {
+            Color ret = *this;
+            ret.saturate();
+            return ret;
+        }
+
+		float operator[] (const UINT32 i) const
+		{
+			assert(i < 4);
+
+			return *(&r+i);
+		}
+
+		float& operator[] (const UINT32 i)
+		{
+			assert(i < 4);
+
+			return *(&r+i);
+		}
+
+		/** Pointer accessor for direct copying. */
+		float* ptr()
+		{
+			return &r;
+		}
+
+		/** Pointer accessor for direct copying. */
+		const float* ptr() const
+		{
+			return &r;
+		}
+
+        Color operator+ (const Color& rhs) const
+        {
+            Color kSum;
+
+            kSum.r = r + rhs.r;
+            kSum.g = g + rhs.g;
+            kSum.b = b + rhs.b;
+            kSum.a = a + rhs.a;
+
+            return kSum;
+        }
+
+        Color operator- ( const Color& rhs) const
+        {
+            Color kDiff;
+
+            kDiff.r = r - rhs.r;
+            kDiff.g = g - rhs.g;
+            kDiff.b = b - rhs.b;
+            kDiff.a = a - rhs.a;
+
+            return kDiff;
+        }
+
+        Color operator* (const float rhs) const
+        {
+            Color kProd;
+
+            kProd.r = rhs*r;
+            kProd.g = rhs*g;
+            kProd.b = rhs*b;
+            kProd.a = rhs*a;
+
+            return kProd;
+        }
+
+        Color operator* (const Color& rhs) const
+        {
+            Color kProd;
+
+            kProd.r = rhs.r * r;
+            kProd.g = rhs.g * g;
+            kProd.b = rhs.b * b;
+            kProd.a = rhs.a * a;
+
+            return kProd;
+        }
+
+        Color operator/ (const Color& rhs) const
+        {
+            Color kProd;
+
+            kProd.r = rhs.r / r;
+            kProd.g = rhs.g / g;
+            kProd.b = rhs.b / b;
+            kProd.a = rhs.a / a;
+
+            return kProd;
+        }
+
+        Color operator/ (const float rhs) const
+        {
+            assert(rhs != 0.0f);
+
+            Color kDiv;
+
+            float fInv = 1.0f / rhs;
+            kDiv.r = r * fInv;
+            kDiv.g = g * fInv;
+            kDiv.b = b * fInv;
+            kDiv.a = a * fInv;
+
+            return kDiv;
+        }
+
+        friend Color operator* (const float lhs, const Color& rhs)
+        {
+            Color result;
+
+            result.r = lhs * rhs.r;
+            result.g = lhs * rhs.g;
+            result.b = lhs * rhs.b;
+            result.a = lhs * rhs.a;
+
+            return result;
+        }
+
+        Color& operator+= (const Color& rhs)
+        {
+            r += rhs.r;
+            g += rhs.g;
+            b += rhs.b;
+            a += rhs.a;
+
+            return *this;
+        }
+
+        Color& operator-= (const Color& rhs)
+        {
+            r -= rhs.r;
+            g -= rhs.g;
+            b -= rhs.b;
+            a -= rhs.a;
+
+            return *this;
+        }
+
+        Color& operator*= (const float rhs)
+        {
+            r *= rhs;
+            g *= rhs;
+            b *= rhs;
+            a *= rhs;
+
+            return *this;
+        }
+
+        Color& operator/= (const float rhs)
+        {
+            assert(rhs != 0.0f);
+
+            float fInv = 1.0f / rhs;
+
+            r *= rhs;
+            g *= rhs;
+            b *= rhs;
+            a *= rhs;
+
+            return *this;
+        }
+
+		/** 
+		 * Set a colour value from Hue, Saturation and Brightness.
+		 *
+		 * @param[in] hue			Hue value, scaled to the [0,1] range.
+		 * @param[in] saturation	Saturation level, [0,1].
+		 * @param[in] brightness	Brightness level, [0,1].
+		 */
+		void setHSB(float hue, float saturation, float brightness);
+
+		/** 
+		 * Convert the current color to Hue, Saturation and Brightness values. 
+		 * 
+		 * @param[in] hue			Output hue value, scaled to the [0,1] range.
+		 * @param[in] saturation	Output saturation level, [0,1].
+		 * @param[in] brightness	Output brightness level, [0,1].
+		 */
+		void getHSB(float* hue, float* saturation, float* brightness) const;
+
+		float r, g, b, a;
+    };
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Color);
+	/** @endcond */
+
+	/** @} */
+}
+
+/** @cond SPECIALIZATIONS */
+
+/** Hash value generator for Color. */
+template<> 
+struct std::hash<BansheeEngine::Color>
+{
+	size_t operator()(const BansheeEngine::Color& color) const
+	{
+		size_t hash = 0;
+		BansheeEngine::hash_combine(hash, color.r);
+		BansheeEngine::hash_combine(hash, color.g);
+		BansheeEngine::hash_combine(hash, color.b);
+		BansheeEngine::hash_combine(hash, color.a);
+
+		return hash;
+	}
+};
+
+/** @endcond */

+ 86 - 83
Source/BansheeUtility/Include/BsCrashHandler.h

@@ -1,84 +1,87 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#define BS_MAX_STACKTRACE_DEPTH 200
-#define BS_MAX_STACKTRACE_NAME_BYTES 1024
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup Error
-	 *  @{
-	 */
-
-	/** Saves crash data and notifies the user when a crash occurs. */
-	// TODO - Crashes are reported in the same process as the main application. This can be a problem if the crash was caused
-	// by heap. Any further use of the heap by the reporting methods will cause a silent crash, failing to log it. A more appropriate
-	// way of doing it should be to resume another process to actually handle the crash.
-	class BS_UTILITY_EXPORT CrashHandler
-	{
-	public:
-		CrashHandler();
-		~CrashHandler();
-
-		/** Constructs and starts the module. */
-		static void startUp() { _instance() = bs_new<CrashHandler>(); }
-
-		/** Shuts down this module and frees any resources it is using. */
-		static void shutDown() { bs_delete(_instance()); }
-
-		/** Returns a reference to the module instance. */
-		static CrashHandler& instance() { return *_instance(); }
-
-		/**
-		 * Records a crash with a custom error message.
-		 * 			
-		 * @param[in]	type		Type of the crash that occurred. e.g. "InvalidParameter".
-		 * @param[in]	description	More detailed description of the issue that caused the crash.
-		 * @param[in]	function	Optional name of the function where the error occurred.
-		 * @param[in]	file		Optional name of the source code file in which the code that crashed the program exists.
-		 * @param[in]	line		Optional source code line at which the crash was triggered at.
-		 */
-		void reportCrash(const String& type, const String& description, const String& function = StringUtil::BLANK,
-			const String& file = StringUtil::BLANK, UINT32 line = 0) const;
-
-#if BS_PLATFORM == BS_PLATFORM_WIN32
-		/**
-		 * Records a crash resulting from a Windows-specific SEH exception. 
-		 * 			
-		 * @param[in]	exceptionData	Exception data returned from GetExceptionInformation()
-		 * @return						Code that signals the __except exception handler on how to proceed.
-		 *
-		 * @note	Available in Windows builds only.
-		 */
-		int reportCrash(void* exceptionData) const;
-#endif
-
-		/**
-		 * Returns a string containing a current stack trace. If function can be found in the symbol table its readable 
-		 * name will be present in the stack trace, otherwise just its address.
-		 * 						
-		 * @return	String containing the call stack with each function on its own line.
-		 */
-		static String getStackTrace();
-	private:
-		/** Returns path to the folder into which to store the crash reports. */
-		Path getCrashFolder() const;
-
-		/** Returns a singleton instance of this module. */
-		static CrashHandler*& _instance() { static CrashHandler* inst = nullptr; return inst; }
-
-		static const wchar_t* CrashReportFolder;
-		static const wchar_t* CrashLogName;
-
-		struct Data;
-		Data* m;
-	};
-
-	/** Easier way of accessing the CrashHandler. */
-	BS_UTILITY_EXPORT CrashHandler& gCrashHandler();
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#define BS_MAX_STACKTRACE_DEPTH 200
+#define BS_MAX_STACKTRACE_NAME_BYTES 1024
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Error-Internal
+	 *  @{
+	 */
+
+	/** Saves crash data and notifies the user when a crash occurs. */
+	// TODO - Crashes are reported in the same process as the main application. This can be a problem if the crash was caused
+	// by heap. Any further use of the heap by the reporting methods will cause a silent crash, failing to log it. A more appropriate
+	// way of doing it should be to resume another process to actually handle the crash.
+	class BS_UTILITY_EXPORT CrashHandler
+	{
+	public:
+		CrashHandler();
+		~CrashHandler();
+
+		/** Constructs and starts the module. */
+		static void startUp() { _instance() = bs_new<CrashHandler>(); }
+
+		/** Shuts down this module and frees any resources it is using. */
+		static void shutDown() { bs_delete(_instance()); }
+
+		/** Returns a reference to the module instance. */
+		static CrashHandler& instance() { return *_instance(); }
+
+		/**
+		 * Records a crash with a custom error message.
+		 * 			
+		 * @param[in]	type		Type of the crash that occurred. For example "InvalidParameter".
+		 * @param[in]	description	More detailed description of the issue that caused the crash.
+		 * @param[in]	function	Optional name of the function where the error occurred.
+		 * @param[in]	file		Optional name of the source code file in which the code that crashed the program exists.
+		 * @param[in]	line		Optional source code line at which the crash was triggered at.
+		 */
+		void reportCrash(const String& type, const String& description, const String& function = StringUtil::BLANK,
+			const String& file = StringUtil::BLANK, UINT32 line = 0) const;
+
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+		/**
+		 * Records a crash resulting from a Windows-specific SEH exception. 
+		 * 			
+		 * @param[in]	exceptionData	Exception data returned from GetExceptionInformation()
+		 * @return						Code that signals the __except exception handler on how to proceed.
+		 *
+		 * @note	Available in Windows builds only.
+		 */
+		int reportCrash(void* exceptionData) const;
+#endif
+
+		/**
+		 * Returns a string containing a current stack trace. If function can be found in the symbol table its readable 
+		 * name will be present in the stack trace, otherwise just its address.
+		 * 						
+		 * @return	String containing the call stack with each function on its own line.
+		 */
+		static String getStackTrace();
+	private:
+		/** Returns path to the folder into which to store the crash reports. */
+		Path getCrashFolder() const;
+
+		/** Returns a singleton instance of this module. */
+		static CrashHandler*& _instance() { static CrashHandler* inst = nullptr; return inst; }
+
+		static const wchar_t* CrashReportFolder;
+		static const wchar_t* CrashLogName;
+
+		struct Data;
+		Data* m;
+	};
+
+	/** Easier way of accessing the CrashHandler. */
+	BS_UTILITY_EXPORT CrashHandler& gCrashHandler();
+
+	/** @} */
+	/** @} */
 }

+ 4 - 2
Source/BansheeUtility/Include/BsDebug.h

@@ -69,7 +69,9 @@ namespace BansheeEngine
 		Event<void()> onLogModified;
 
 	public: // ***** INTERNAL ******
-		/** @cond INTERNAL */
+		/** @name Internal
+		 *  @{
+		 */
 
 		/**
 		 * Triggers callbacks that notify external code that a log entry was added.
@@ -78,7 +80,7 @@ namespace BansheeEngine
 		 */
 		void _triggerCallbacks();
 
-		/** @endcond */
+		/** @} */
 	private:
 		UINT64 mLogHash = 0;
 		Log mLog;

+ 75 - 73
Source/BansheeUtility/Include/BsDynLib.h

@@ -1,73 +1,75 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-/** @addtogroup General
- *  @{
- */
-
-#if BS_PLATFORM == BS_PLATFORM_WIN32
-#    define DYNLIB_HANDLE hInstance
-#    define DYNLIB_LOAD( a ) LoadLibraryEx( a, NULL, LOAD_WITH_ALTERED_SEARCH_PATH )
-#    define DYNLIB_GETSYM( a, b ) GetProcAddress( a, b )
-#    define DYNLIB_UNLOAD( a ) !FreeLibrary( a )
-
-struct HINSTANCE__;
-typedef struct HINSTANCE__* hInstance;
-
-#elif BS_PLATFORM == BS_PLATFORM_LINUX
-#    define DYNLIB_HANDLE void*
-#    define DYNLIB_LOAD( a ) dlopen( a, RTLD_LAZY | RTLD_GLOBAL)
-#    define DYNLIB_GETSYM( a, b ) dlsym( a, b )
-#    define DYNLIB_UNLOAD( a ) dlclose( a )
-
-#elif BS_PLATFORM == BS_PLATFORM_APPLE
-#    define DYNLIB_HANDLE void*
-#    define DYNLIB_LOAD( a ) mac_loadDylib( a )
-#    define DYNLIB_GETSYM( a, b ) dlsym( a, b )
-#    define DYNLIB_UNLOAD( a ) dlclose( a )
-
-#endif
-
-namespace BansheeEngine 
-{
-    /** Class that holds data about a dynamic library. */
-	class BS_UTILITY_EXPORT DynLib
-    {
-    public:
-		/** Constructs the dynamic library object and loads the library with the specified name. */
-		DynLib(const String& name);
-        ~DynLib();
-
-		/** Loads the library. Does nothing if library is already loaded. */
-        void load();
-
-		/** Unloads the library. Does nothing if library is not loaded. */
-        void unload();
-
-		/** 	Get the name of the library. */
-		const String& getName() const { return mName; }
-
-        /**
-		 * Returns the address of the given symbol from the loaded library.
-		 *
-		 * @param[in] strName	The name of the symbol to search for.
-         * @return				If the function succeeds, the returned value is a handle to the symbol. Otherwise null.
-         */
-        void* getSymbol(const String& strName) const;
-
-	protected:
-		friend class DynLibManager;
-
-		/** Gets the last loading error. */
-        String dynlibError();
-
-    protected:
-		String mName;
-        DYNLIB_HANDLE m_hInst; // Handle to the loaded library.
-    };
-}
-
-/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+	struct HINSTANCE__;
+	typedef struct HINSTANCE__* hInstance;
+#endif
+
+namespace BansheeEngine 
+{
+	/** @addtogroup General
+	 *  @{
+	 */
+
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+#    define DYNLIB_HANDLE hInstance
+#    define DYNLIB_LOAD( a ) LoadLibraryEx( a, NULL, LOAD_WITH_ALTERED_SEARCH_PATH )
+#    define DYNLIB_GETSYM( a, b ) GetProcAddress( a, b )
+#    define DYNLIB_UNLOAD( a ) !FreeLibrary( a )
+
+#elif BS_PLATFORM == BS_PLATFORM_LINUX
+#    define DYNLIB_HANDLE void*
+#    define DYNLIB_LOAD( a ) dlopen( a, RTLD_LAZY | RTLD_GLOBAL)
+#    define DYNLIB_GETSYM( a, b ) dlsym( a, b )
+#    define DYNLIB_UNLOAD( a ) dlclose( a )
+
+#elif BS_PLATFORM == BS_PLATFORM_APPLE
+#    define DYNLIB_HANDLE void*
+#    define DYNLIB_LOAD( a ) mac_loadDylib( a )
+#    define DYNLIB_GETSYM( a, b ) dlsym( a, b )
+#    define DYNLIB_UNLOAD( a ) dlclose( a )
+
+#endif
+
+    /** Class that holds data about a dynamic library. */
+	class BS_UTILITY_EXPORT DynLib
+    {
+    public:
+		/** Constructs the dynamic library object and loads the library with the specified name. */
+		DynLib(const String& name);
+        ~DynLib();
+
+		/** Loads the library. Does nothing if library is already loaded. */
+        void load();
+
+		/** Unloads the library. Does nothing if library is not loaded. */
+        void unload();
+
+		/** Get the name of the library. */
+		const String& getName() const { return mName; }
+
+        /**
+		 * Returns the address of the given symbol from the loaded library.
+		 *
+		 * @param[in] strName	The name of the symbol to search for.
+         * @return				If the function succeeds, the returned value is a handle to the symbol. Otherwise null.
+         */
+        void* getSymbol(const String& strName) const;
+
+	protected:
+		friend class DynLibManager;
+
+		/** Gets the last loading error. */
+        String dynlibError();
+
+    protected:
+		String mName;
+        DYNLIB_HANDLE m_hInst; // Handle to the loaded library.
+    };
+
+	/** @} */
+}

+ 43 - 43
Source/BansheeUtility/Include/BsDynLibManager.h

@@ -1,44 +1,44 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsModule.h"
-
-namespace BansheeEngine 
-{
-	/** @addtogroup General
-	 *  @{
-	 */
-
-    /**
-	 * This manager keeps a track of all the open dynamic-loading libraries, opens them and returns references to 
-	 * already-open libraries.
-	 *			
-	 * @note	Not thread safe.
-     */
-    class BS_UTILITY_EXPORT DynLibManager : public Module<DynLibManager>
-    {
-    public:
-        DynLibManager();
-        virtual ~DynLibManager();
-
-        /**
-         * Loads the given file as a dynamic library.
-         *
-         * @param[in]	filename	The name of the library. The extension can be omitted.
-         */
-        DynLib* load(const String& name);
-
-		/** Unloads the given library. */
-		void unload(DynLib* lib);
-
-	protected:
-		Map<String, DynLib*> mLoadedLibraries;
-    };
-
-	/** Easy way of accessing DynLibManager. */
-	BS_UTILITY_EXPORT DynLibManager& gDynLibManager();
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsModule.h"
+
+namespace BansheeEngine 
+{
+	/** @addtogroup General
+	 *  @{
+	 */
+
+    /**
+	 * This manager keeps a track of all the open dynamic-loading libraries, opens them and returns references to 
+	 * already-open libraries.
+	 *			
+	 * @note	Not thread safe.
+     */
+    class BS_UTILITY_EXPORT DynLibManager : public Module<DynLibManager>
+    {
+    public:
+        DynLibManager();
+        virtual ~DynLibManager();
+
+        /**
+         * Loads the given file as a dynamic library.
+         *
+         * @param[in]	name	The name of the library. The extension can be omitted.
+         */
+        DynLib* load(const String& name);
+
+		/** Unloads the given library. */
+		void unload(DynLib* lib);
+
+	protected:
+		Map<String, DynLib*> mLoadedLibraries;
+    };
+
+	/** Easy way of accessing DynLibManager. */
+	BS_UTILITY_EXPORT DynLibManager& gDynLibManager();
+
+	/** @} */
 }

+ 368 - 336
Source/BansheeUtility/Include/BsEvent.h

@@ -1,336 +1,368 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-/** @addtogroup General
- *  @{
- */
-
-namespace BansheeEngine
-{
-	/** Data common to all event connections. */
-	class BaseConnectionData
-	{
-	public:
-		BaseConnectionData()
-			:prev(nullptr), next(nullptr), isActive(true),
-			handleLinks(0)
-		{
-			
-		}
-
-		virtual ~BaseConnectionData()
-		{
-			assert(!handleLinks && !isActive);
-		}
-
-		virtual void deactivate()
-		{
-			isActive = false;
-		}
-
-		BaseConnectionData* prev;
-		BaseConnectionData* next;
-		bool isActive;
-		UINT32 handleLinks;
-	};
-
-	/** Internal data for an Event, storing all connections. */
-	struct EventInternalData
-	{
-		EventInternalData()
-			:mConnections(nullptr), mFreeConnections(nullptr)
-		{ }
-
-		~EventInternalData()
-		{
-			BaseConnectionData* conn = mConnections;
-			while (conn != nullptr)
-			{
-				BaseConnectionData* next = conn->next;
-				bs_free(conn);
-
-				conn = next;
-			}
-
-			conn = mFreeConnections;
-			while (conn != nullptr)
-			{
-				BaseConnectionData* next = conn->next;
-				bs_free(conn);
-
-				conn = next;
-			}
-		}
-
-		/**
-		 * Disconnects the connection with the specified data, ensuring the event doesn't call its callback again.
-		 *
-		 * @note	Only call this once.
-		 */
-		void disconnect(BaseConnectionData* conn)
-		{
-			BS_LOCK_RECURSIVE_MUTEX(mMutex);
-
-			conn->deactivate();
-			conn->handleLinks--;
-
-			if (conn->handleLinks == 0)
-				free(conn);
-		}
-
-		/** Disconnects all connections in the event. */
-		void clear()
-		{
-			BS_LOCK_RECURSIVE_MUTEX(mMutex);
-
-			BaseConnectionData* conn = mConnections;
-			while (conn != nullptr)
-			{
-				BaseConnectionData* next = conn->next;
-				conn->deactivate();
-
-				if (conn->handleLinks == 0)
-					free(conn);
-
-				conn = next;
-			}
-		}
-
-		/**
-		 * Called when the event handle no longer keeps a reference to the connection data. This means we might be able to 
-		 * free (and reuse) its memory if the event is done with it too.
-		 */
-		void freeHandle(BaseConnectionData* conn)
-		{
-			BS_LOCK_RECURSIVE_MUTEX(mMutex);
-
-			conn->handleLinks--;
-
-			if (conn->handleLinks == 0 && !conn->isActive)
-				free(conn);
-		}
-
-		/** Releases connection data and makes it available for re-use when next connection is formed. */
-		void free(BaseConnectionData* conn)
-		{
-			if (conn->prev != nullptr)
-				conn->prev->next = conn->next;
-			else
-				mConnections = conn->next;
-
-			if (conn->next != nullptr)
-				conn->next->prev = conn->prev;
-
-			conn->prev = nullptr;
-			conn->next = nullptr;
-
-			if (mFreeConnections != nullptr)
-			{
-				conn->next = mFreeConnections;
-				mFreeConnections->prev = conn;
-			}
-
-			mFreeConnections = conn;
-			mFreeConnections->~BaseConnectionData();
-		}
-
-		BaseConnectionData* mConnections;
-		BaseConnectionData* mFreeConnections;
-
-		BS_RECURSIVE_MUTEX(mMutex);
-	};
-
-	/** Event handle. Allows you to track to which events you subscribed to and disconnect from them when needed. */
-	class HEvent
-	{
-	public:
-		HEvent()
-			:mConnection(nullptr)
-		{ }
-
-		explicit HEvent(const SPtr<EventInternalData>& eventData, BaseConnectionData* connection)
-			:mConnection(connection), mEventData(eventData)
-		{
-			connection->handleLinks++;
-		}
-
-		~HEvent()
-		{
-			if (mConnection != nullptr)
-				mEventData->freeHandle(mConnection);
-		}
-
-		/** Disconnect from the event you are subscribed to. */
-		void disconnect()
-		{
-			if (mConnection != nullptr)
-			{
-				mEventData->disconnect(mConnection);
-				mConnection = nullptr;
-				mEventData = nullptr;
-			}
-		}
-
-		struct Bool_struct
-		{
-			int _Member;
-		};
-
-		/**
-		* Allows direct conversion of a handle to bool.
-		*
-		* @note		
-		* Additional struct is needed because we can't directly convert to bool since then we can assign pointer to bool 
-		* and that's wrong.
-		*/
-		operator int Bool_struct::*() const
-		{
-			return (mConnection != nullptr ? &Bool_struct::_Member : 0);
-		}
-
-		HEvent& operator=(const HEvent& rhs)
-		{
-			mConnection = rhs.mConnection;
-			mEventData = rhs.mEventData;
-
-			if (mConnection != nullptr)
-				mConnection->handleLinks++;
-
-			return *this;
-		}
-
-	private:
-		BaseConnectionData* mConnection;
-		SPtr<EventInternalData> mEventData;
-	};	
-
-	/**
-	 * Events allows you to register method callbacks that get notified when the event is triggered.
-	 *
-	 * @note	Callback method return value is ignored.
-	 */
-	// Note: I could create a policy template argument that allows creation of 
-	// lockable and non-lockable events in the case mutex is causing too much overhead.
-	template <class RetType, class... Args>
-	class TEvent
-	{
-		struct ConnectionData : BaseConnectionData
-		{
-		public:
-			void deactivate() override
-			{
-				func = nullptr;
-
-				BaseConnectionData::deactivate();
-			}
-
-			std::function<RetType(Args...)> func;
-		};
-
-	public:
-		TEvent()
-			:mInternalData(bs_shared_ptr_new<EventInternalData>())
-		{ }
-
-		~TEvent()
-		{
-			clear();
-		}
-
-		/** Register a new callback that will get notified once the event is triggered. */
-		HEvent connect(std::function<RetType(Args...)> func)
-		{
-			BS_LOCK_RECURSIVE_MUTEX(mInternalData->mMutex);
-
-			ConnectionData* connData = nullptr;
-			if (mInternalData->mFreeConnections != nullptr)
-			{
-				connData = static_cast<ConnectionData*>(mInternalData->mFreeConnections);
-				mInternalData->mFreeConnections = connData->next;
-
-				new (connData)ConnectionData();
-				if (connData->next != nullptr)
-					connData->next->prev = nullptr;
-
-				connData->isActive = true;
-			}
-
-			if (connData == nullptr)
-				connData = bs_new<ConnectionData>();
-
-			connData->next = mInternalData->mConnections;
-
-			if (mInternalData->mConnections != nullptr)
-				mInternalData->mConnections->prev = connData;
-
-			mInternalData->mConnections = connData;
-			connData->func = func;
-
-			return HEvent(mInternalData, connData);
-		}
-
-		/** Trigger the event, notifying all register callback methods. */
-		void operator() (Args... args)
-		{
-			// Increase ref count to ensure this event data isn't destroyed if one of the callbacks
-			// deletes the event itself.
-			std::shared_ptr<EventInternalData> internalData = mInternalData;
-
-			BS_LOCK_RECURSIVE_MUTEX(internalData->mMutex);
-
-			// Hidden dependency: If any new connections are made during these callbacks they must be
-			// inserted at the start of the linked list so that we don't trigger them here.
-			ConnectionData* conn = static_cast<ConnectionData*>(internalData->mConnections);
-			while (conn != nullptr)
-			{
-				// Save next here in case the callback itself disconnects this connection
-				ConnectionData* next = static_cast<ConnectionData*>(conn->next);
-				
-				if (conn->func != nullptr)
-					conn->func(std::forward<Args>(args)...);
-
-				conn = next;
-			}
-		}
-
-		/** Clear all callbacks from the event. */
-		void clear()
-		{
-			mInternalData->clear();
-		}
-
-		/**
-		 * Check if event has any callbacks registered.
-		 *
-		 * @note	It is safe to trigger an event even if no callbacks are registered.
-		 */
-		bool empty() const
-		{
-			BS_LOCK_RECURSIVE_MUTEX(mInternalData->mMutex);
-
-			return mInternalData->mConnections == nullptr;
-		}
-
-	private:
-		SPtr<EventInternalData> mInternalData;
-	};
-
-	/************************************************************************/
-	/* 							SPECIALIZATIONS                      		*/
-	/* 	SO YOU MAY USE FUNCTION LIKE SYNTAX FOR DECLARING EVENT SIGNATURE   */
-	/************************************************************************/
-	
-	/** @copydoc TEvent */
-	template <typename Signature>
-	class Event;
-
-	/** @copydoc TEvent */
-	template <class RetType, class... Args>
-	class Event<RetType(Args...) > : public TEvent <RetType, Args...>
-	{ };
-}
-
-/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup General-Internal
+	 *  @{
+	 */
+
+	/** Data common to all event connections. */
+	class BaseConnectionData
+	{
+	public:
+		BaseConnectionData()
+			:prev(nullptr), next(nullptr), isActive(true),
+			handleLinks(0)
+		{
+			
+		}
+
+		virtual ~BaseConnectionData()
+		{
+			assert(!handleLinks && !isActive);
+		}
+
+		virtual void deactivate()
+		{
+			isActive = false;
+		}
+
+		BaseConnectionData* prev;
+		BaseConnectionData* next;
+		bool isActive;
+		UINT32 handleLinks;
+	};
+
+	/** Internal data for an Event, storing all connections. */
+	struct EventInternalData
+	{
+		EventInternalData()
+			:mConnections(nullptr), mFreeConnections(nullptr)
+		{ }
+
+		~EventInternalData()
+		{
+			BaseConnectionData* conn = mConnections;
+			while (conn != nullptr)
+			{
+				BaseConnectionData* next = conn->next;
+				bs_free(conn);
+
+				conn = next;
+			}
+
+			conn = mFreeConnections;
+			while (conn != nullptr)
+			{
+				BaseConnectionData* next = conn->next;
+				bs_free(conn);
+
+				conn = next;
+			}
+		}
+
+		/**
+		 * Disconnects the connection with the specified data, ensuring the event doesn't call its callback again.
+		 *
+		 * @note	Only call this once.
+		 */
+		void disconnect(BaseConnectionData* conn)
+		{
+			BS_LOCK_RECURSIVE_MUTEX(mMutex);
+
+			conn->deactivate();
+			conn->handleLinks--;
+
+			if (conn->handleLinks == 0)
+				free(conn);
+		}
+
+		/** Disconnects all connections in the event. */
+		void clear()
+		{
+			BS_LOCK_RECURSIVE_MUTEX(mMutex);
+
+			BaseConnectionData* conn = mConnections;
+			while (conn != nullptr)
+			{
+				BaseConnectionData* next = conn->next;
+				conn->deactivate();
+
+				if (conn->handleLinks == 0)
+					free(conn);
+
+				conn = next;
+			}
+		}
+
+		/**
+		 * Called when the event handle no longer keeps a reference to the connection data. This means we might be able to 
+		 * free (and reuse) its memory if the event is done with it too.
+		 */
+		void freeHandle(BaseConnectionData* conn)
+		{
+			BS_LOCK_RECURSIVE_MUTEX(mMutex);
+
+			conn->handleLinks--;
+
+			if (conn->handleLinks == 0 && !conn->isActive)
+				free(conn);
+		}
+
+		/** Releases connection data and makes it available for re-use when next connection is formed. */
+		void free(BaseConnectionData* conn)
+		{
+			if (conn->prev != nullptr)
+				conn->prev->next = conn->next;
+			else
+				mConnections = conn->next;
+
+			if (conn->next != nullptr)
+				conn->next->prev = conn->prev;
+
+			conn->prev = nullptr;
+			conn->next = nullptr;
+
+			if (mFreeConnections != nullptr)
+			{
+				conn->next = mFreeConnections;
+				mFreeConnections->prev = conn;
+			}
+
+			mFreeConnections = conn;
+			mFreeConnections->~BaseConnectionData();
+		}
+
+		BaseConnectionData* mConnections;
+		BaseConnectionData* mFreeConnections;
+
+		BS_RECURSIVE_MUTEX(mMutex);
+	};
+
+	/** @} */
+	/** @} */
+
+	/** @addtogroup General
+	 *  @{
+	 */
+
+	/** Event handle. Allows you to track to which events you subscribed to and disconnect from them when needed. */
+	class HEvent
+	{
+	public:
+		HEvent()
+			:mConnection(nullptr)
+		{ }
+
+		explicit HEvent(const SPtr<EventInternalData>& eventData, BaseConnectionData* connection)
+			:mConnection(connection), mEventData(eventData)
+		{
+			connection->handleLinks++;
+		}
+
+		~HEvent()
+		{
+			if (mConnection != nullptr)
+				mEventData->freeHandle(mConnection);
+		}
+
+		/** Disconnect from the event you are subscribed to. */
+		void disconnect()
+		{
+			if (mConnection != nullptr)
+			{
+				mEventData->disconnect(mConnection);
+				mConnection = nullptr;
+				mEventData = nullptr;
+			}
+		}
+
+		/** @cond IGNORE */
+
+		struct Bool_struct
+		{
+			int _Member;
+		};
+
+		/** @endcond */
+
+		/**
+		* Allows direct conversion of a handle to bool.
+		*
+		* @note		
+		* Additional struct is needed because we can't directly convert to bool since then we can assign pointer to bool 
+		* and that's wrong.
+		*/
+		operator int Bool_struct::*() const
+		{
+			return (mConnection != nullptr ? &Bool_struct::_Member : 0);
+		}
+
+		HEvent& operator=(const HEvent& rhs)
+		{
+			mConnection = rhs.mConnection;
+			mEventData = rhs.mEventData;
+
+			if (mConnection != nullptr)
+				mConnection->handleLinks++;
+
+			return *this;
+		}
+
+	private:
+		BaseConnectionData* mConnection;
+		SPtr<EventInternalData> mEventData;
+	};	
+
+	/** @} */
+
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup General-Internal
+	 *  @{
+	 */
+
+	/**
+	 * Events allows you to register method callbacks that get notified when the event is triggered.
+	 *
+	 * @note	Callback method return value is ignored.
+	 */
+	// Note: I could create a policy template argument that allows creation of 
+	// lockable and non-lockable events in the case mutex is causing too much overhead.
+	template <class RetType, class... Args>
+	class TEvent
+	{
+		struct ConnectionData : BaseConnectionData
+		{
+		public:
+			void deactivate() override
+			{
+				func = nullptr;
+
+				BaseConnectionData::deactivate();
+			}
+
+			std::function<RetType(Args...)> func;
+		};
+
+	public:
+		TEvent()
+			:mInternalData(bs_shared_ptr_new<EventInternalData>())
+		{ }
+
+		~TEvent()
+		{
+			clear();
+		}
+
+		/** Register a new callback that will get notified once the event is triggered. */
+		HEvent connect(std::function<RetType(Args...)> func)
+		{
+			BS_LOCK_RECURSIVE_MUTEX(mInternalData->mMutex);
+
+			ConnectionData* connData = nullptr;
+			if (mInternalData->mFreeConnections != nullptr)
+			{
+				connData = static_cast<ConnectionData*>(mInternalData->mFreeConnections);
+				mInternalData->mFreeConnections = connData->next;
+
+				new (connData)ConnectionData();
+				if (connData->next != nullptr)
+					connData->next->prev = nullptr;
+
+				connData->isActive = true;
+			}
+
+			if (connData == nullptr)
+				connData = bs_new<ConnectionData>();
+
+			connData->next = mInternalData->mConnections;
+
+			if (mInternalData->mConnections != nullptr)
+				mInternalData->mConnections->prev = connData;
+
+			mInternalData->mConnections = connData;
+			connData->func = func;
+
+			return HEvent(mInternalData, connData);
+		}
+
+		/** Trigger the event, notifying all register callback methods. */
+		void operator() (Args... args)
+		{
+			// Increase ref count to ensure this event data isn't destroyed if one of the callbacks
+			// deletes the event itself.
+			std::shared_ptr<EventInternalData> internalData = mInternalData;
+
+			BS_LOCK_RECURSIVE_MUTEX(internalData->mMutex);
+
+			// Hidden dependency: If any new connections are made during these callbacks they must be
+			// inserted at the start of the linked list so that we don't trigger them here.
+			ConnectionData* conn = static_cast<ConnectionData*>(internalData->mConnections);
+			while (conn != nullptr)
+			{
+				// Save next here in case the callback itself disconnects this connection
+				ConnectionData* next = static_cast<ConnectionData*>(conn->next);
+				
+				if (conn->func != nullptr)
+					conn->func(std::forward<Args>(args)...);
+
+				conn = next;
+			}
+		}
+
+		/** Clear all callbacks from the event. */
+		void clear()
+		{
+			mInternalData->clear();
+		}
+
+		/**
+		 * Check if event has any callbacks registered.
+		 *
+		 * @note	It is safe to trigger an event even if no callbacks are registered.
+		 */
+		bool empty() const
+		{
+			BS_LOCK_RECURSIVE_MUTEX(mInternalData->mMutex);
+
+			return mInternalData->mConnections == nullptr;
+		}
+
+	private:
+		SPtr<EventInternalData> mInternalData;
+	};
+
+	/** @} */
+	/** @} */
+
+	/** @addtogroup General
+	 *  @{
+	 */
+
+	/************************************************************************/
+	/* 							SPECIALIZATIONS                      		*/
+	/* 	SO YOU MAY USE FUNCTION LIKE SYNTAX FOR DECLARING EVENT SIGNATURE   */
+	/************************************************************************/
+	
+	/** @copydoc TEvent */
+	template <typename Signature>
+	class Event;
+
+	/** @copydoc TEvent */
+	template <class RetType, class... Args>
+	class Event<RetType(Args...) > : public TEvent <RetType, Args...>
+	{ };
+
+	/** @} */
+}

+ 189 - 189
Source/BansheeUtility/Include/BsException.h

@@ -1,189 +1,189 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-#if defined(_MSC_VER)
-#undef __PRETTY_FUNCTION__
-#define __PRETTY_FUNCTION__ __FUNCSIG__
-#endif
-
-namespace BansheeEngine
-{
-	/** @addtogroup Error
-	 *  @{
-	 */
-
-	/**
-	 * Base class for all Banshee exceptions. 
-	 *
-	 * @note	Banshee doesn't perform exception handling, but these classes remain here in case others wish to enable them.
-	 */
-	class Exception : public std::exception
-    {
-    public:
-		Exception(const char* type, const String& description, const String& source)
-			:mLine(0), mTypeName(type), mDescription(description), mSource(source)
-		{ }
-
-		Exception(const char* type, const String& description, const String& source, const char* file, long line)
-			: mLine(line), mTypeName(type), mDescription(description), mSource(source), mFile(file)
-		{ }
-
-        Exception(const Exception& rhs)
-			: mLine(rhs.mLine), mTypeName(rhs.mTypeName), mDescription(rhs.mDescription),
-			mSource(rhs.mSource), mFile(rhs.mFile)
-		{ }
-
-		~Exception() throw() {}
-
-        void operator = (const Exception& rhs)
-		{
-			mDescription = rhs.mDescription;
-			mSource = rhs.mSource;
-			mFile = rhs.mFile;
-			mLine = rhs.mLine;
-			mTypeName = rhs.mTypeName;
-		}
-
-		/**
-		 * Returns a string with the full description of the exception.
-		 *
-		 * @note	
-		 * The description contains the error number, the description supplied by the thrower, what routine threw the 
-		 * exception, and will also supply extra platform-specific information where applicable.
-		 */
-		virtual const String& getFullDescription() const
-		{
-			if (mFullDesc.empty())
-			{
-				StringStream desc;
-
-				desc << "BANSHEE EXCEPTION(" << mTypeName << "): "
-					<< mDescription
-					<< " in " << mSource;
-
-				if (mLine > 0)
-				{
-					desc << " at " << mFile << " (line " << mLine << ")";
-				}
-
-				mFullDesc = desc.str();
-			}
-
-			return mFullDesc;
-		}
-
-		/** Gets the source function that threw the exception. */
-		virtual const String& getSource() const { return mSource; }
-
-		/** Gets the source file name in which the exception was thrown. */
-		virtual const String& getFile() const { return mFile; }
-
-        /** Gets line number on which the exception was thrown. */
-        virtual long getLine() const { return mLine; }
-
-		/** Gets a short description about the exception. */
-		virtual const String& getDescription(void) const { return mDescription; }
-
-		/** Overriden std::exception::what. Returns the same value as getFullDescription(). */
-		const char* what() const override { return getFullDescription().c_str(); }
-
-	protected:
-		long mLine;
-		String mTypeName;
-		String mDescription;
-		String mSource;
-		String mFile;
-		mutable String mFullDesc;
-    };
-
-	/** Exception for signaling not implemented parts of the code. */
-	class NotImplementedException : public Exception 
-	{
-	public:
-		NotImplementedException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
-			: Exception("NotImplementedException", inDescription, inSource, inFile, inLine) {}
-	};
-
-	/** Exception for signaling file system errors when file could not be found. */
-	class FileNotFoundException : public Exception
-	{
-	public:
-		FileNotFoundException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
-			: Exception("FileNotFoundException", inDescription, inSource, inFile, inLine) {}
-	};
-
-	/** Exception for signaling general IO errors.
-	 * 			
-	 * @note	An example being failed to open a file or a network connection.
-	 */
-	class IOException : public Exception
-	{
-	public:
-		IOException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
-			: Exception("IOException", inDescription, inSource, inFile, inLine) {}
-	};
-
-	/** Exception for signaling not currently executing code in not in a valid state. */
-	class InvalidStateException : public Exception
-	{
-	public:
-		InvalidStateException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
-			: Exception("InvalidStateException", inDescription, inSource, inFile, inLine) {}
-	};
-
-	/** Exception for signaling not some parameters you have provided are not valid. */
-	class InvalidParametersException : public Exception
-	{
-	public:
-		InvalidParametersException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
-			: Exception("InvalidParametersException", inDescription, inSource, inFile, inLine) {}
-	};
-
-	/**
-	 * Exception for signaling an internal error, normally something that shouldn't have happened or wasn't anticipated by 
-	 * the programmers of that system.
-	 */
-	class InternalErrorException : public Exception
-	{
-	public:
-		InternalErrorException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
-			: Exception("InternalErrorException", inDescription, inSource, inFile, inLine) {}
-	};
-
-	/** Exception for signaling an error in a rendering API. */
-	class RenderingAPIException : public Exception
-	{
-	public:
-		RenderingAPIException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
-			: Exception("RenderingAPIException", inDescription, inSource, inFile, inLine) {}
-	};
-
-	/** Exception for signaling an error in an unit test. */
-	class UnitTestException : public Exception
-	{
-	public:
-		UnitTestException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
-			: Exception("UnitTestException", inDescription, inSource, inFile, inLine) {}
-	};
-
-	/**
-	 * Macro for throwing exceptions that will automatically fill out function name, file name and line number of the 
-	 * exception.
-	 */
-	// The exception thrown at the end isn't actually ever getting executed, it is just to notify the compiler that execution
-	// won't continue past this point (e.g. if a function needs to return a value otherwise).
-#ifndef BS_EXCEPT
-#define BS_EXCEPT(type, desc)	\
-		{                           \
-	static_assert((std::is_base_of<BansheeEngine::Exception, type>::value), "Invalid exception type (" #type ") for BS_EXCEPT macro. It needs to derive from BansheeEngine::Exception."); \
-	gCrashHandler().reportCrash(#type, desc, __PRETTY_FUNCTION__, __FILE__, __LINE__); \
-	PlatformUtility::terminate(true); \
-	}
-#endif
-
-	/** @} */
-}
-
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+#if defined(_MSC_VER)
+#undef __PRETTY_FUNCTION__
+#define __PRETTY_FUNCTION__ __FUNCSIG__
+#endif
+
+namespace BansheeEngine
+{
+	/** @addtogroup Error
+	 *  @{
+	 */
+
+	/**
+	 * Base class for all Banshee exceptions. 
+	 *
+	 * @note	Banshee doesn't perform exception handling, but these classes remain here in case others wish to enable them.
+	 */
+	class Exception : public std::exception
+    {
+    public:
+		Exception(const char* type, const String& description, const String& source)
+			:mLine(0), mTypeName(type), mDescription(description), mSource(source)
+		{ }
+
+		Exception(const char* type, const String& description, const String& source, const char* file, long line)
+			: mLine(line), mTypeName(type), mDescription(description), mSource(source), mFile(file)
+		{ }
+
+        Exception(const Exception& rhs)
+			: mLine(rhs.mLine), mTypeName(rhs.mTypeName), mDescription(rhs.mDescription),
+			mSource(rhs.mSource), mFile(rhs.mFile)
+		{ }
+
+		~Exception() throw() {}
+
+        void operator = (const Exception& rhs)
+		{
+			mDescription = rhs.mDescription;
+			mSource = rhs.mSource;
+			mFile = rhs.mFile;
+			mLine = rhs.mLine;
+			mTypeName = rhs.mTypeName;
+		}
+
+		/**
+		 * Returns a string with the full description of the exception.
+		 *
+		 * @note	
+		 * The description contains the error number, the description supplied by the thrower, what routine threw the 
+		 * exception, and will also supply extra platform-specific information where applicable.
+		 */
+		virtual const String& getFullDescription() const
+		{
+			if (mFullDesc.empty())
+			{
+				StringStream desc;
+
+				desc << "BANSHEE EXCEPTION(" << mTypeName << "): "
+					<< mDescription
+					<< " in " << mSource;
+
+				if (mLine > 0)
+				{
+					desc << " at " << mFile << " (line " << mLine << ")";
+				}
+
+				mFullDesc = desc.str();
+			}
+
+			return mFullDesc;
+		}
+
+		/** Gets the source function that threw the exception. */
+		virtual const String& getSource() const { return mSource; }
+
+		/** Gets the source file name in which the exception was thrown. */
+		virtual const String& getFile() const { return mFile; }
+
+        /** Gets line number on which the exception was thrown. */
+        virtual long getLine() const { return mLine; }
+
+		/** Gets a short description about the exception. */
+		virtual const String& getDescription(void) const { return mDescription; }
+
+		/** Overriden std::exception::what. Returns the same value as getFullDescription(). */
+		const char* what() const override { return getFullDescription().c_str(); }
+
+	protected:
+		long mLine;
+		String mTypeName;
+		String mDescription;
+		String mSource;
+		String mFile;
+		mutable String mFullDesc;
+    };
+
+	/** Exception for signaling not implemented parts of the code. */
+	class NotImplementedException : public Exception 
+	{
+	public:
+		NotImplementedException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception("NotImplementedException", inDescription, inSource, inFile, inLine) {}
+	};
+
+	/** Exception for signaling file system errors when file could not be found. */
+	class FileNotFoundException : public Exception
+	{
+	public:
+		FileNotFoundException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception("FileNotFoundException", inDescription, inSource, inFile, inLine) {}
+	};
+
+	/** Exception for signaling general IO errors.
+	 * 			
+	 * @note	An example being failed to open a file or a network connection.
+	 */
+	class IOException : public Exception
+	{
+	public:
+		IOException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception("IOException", inDescription, inSource, inFile, inLine) {}
+	};
+
+	/** Exception for signaling not currently executing code in not in a valid state. */
+	class InvalidStateException : public Exception
+	{
+	public:
+		InvalidStateException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception("InvalidStateException", inDescription, inSource, inFile, inLine) {}
+	};
+
+	/** Exception for signaling not some parameters you have provided are not valid. */
+	class InvalidParametersException : public Exception
+	{
+	public:
+		InvalidParametersException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception("InvalidParametersException", inDescription, inSource, inFile, inLine) {}
+	};
+
+	/**
+	 * Exception for signaling an internal error, normally something that shouldn't have happened or wasn't anticipated by 
+	 * the programmers of that system.
+	 */
+	class InternalErrorException : public Exception
+	{
+	public:
+		InternalErrorException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception("InternalErrorException", inDescription, inSource, inFile, inLine) {}
+	};
+
+	/** Exception for signaling an error in a rendering API. */
+	class RenderingAPIException : public Exception
+	{
+	public:
+		RenderingAPIException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception("RenderingAPIException", inDescription, inSource, inFile, inLine) {}
+	};
+
+	/** Exception for signaling an error in an unit test. */
+	class UnitTestException : public Exception
+	{
+	public:
+		UnitTestException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
+			: Exception("UnitTestException", inDescription, inSource, inFile, inLine) {}
+	};
+
+	/**
+	 * Macro for throwing exceptions that will automatically fill out function name, file name and line number of the 
+	 * exception.
+	 */
+	// The exception thrown at the end isn't actually ever getting executed, it is just to notify the compiler that execution
+	// won't continue past this point (for example if a function needs to return a value otherwise).
+#ifndef BS_EXCEPT
+#define BS_EXCEPT(type, desc)	\
+		{                           \
+	static_assert((std::is_base_of<BansheeEngine::Exception, type>::value), "Invalid exception type (" #type ") for BS_EXCEPT macro. It needs to derive from BansheeEngine::Exception."); \
+	gCrashHandler().reportCrash(#type, desc, __PRETTY_FUNCTION__, __FILE__, __LINE__); \
+	PlatformUtility::terminate(true); \
+	}
+#endif
+
+	/** @} */
+}
+

+ 210 - 207
Source/BansheeUtility/Include/BsFrameAlloc.h

@@ -1,208 +1,211 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup Memory
-	 *  @{
-	 */
-
-	/**
-	 * Frame allocator. Performs very fast allocations but can only free all of its memory at once. Perfect for allocations 
-	 * that last just a single frame.
-	 * 			
-	 * @note	Not thread safe with an exception. alloc() and clear() methods need to be called from the same thread.
-	 * 			dealloc() is thread safe and can be called from any thread.
-	 */
-	class BS_UTILITY_EXPORT FrameAlloc
-	{
-	private:
-		/** A single block of memory within a frame allocator. */
-		class MemBlock
-		{
-		public:
-			MemBlock(UINT32 size);
-			~MemBlock();
-
-			/** Allocates a piece of memory within the block. Caller must ensure the block has enough empty space. */
-			UINT8* alloc(UINT32 amount);
-
-			/** Releases all allocations within a block but doesn't actually free the memory. */
-			void clear();
-
-			UINT8* mData;
-			UINT32 mFreePtr;
-			UINT32 mSize;
-		};
-
-	public:
-		FrameAlloc(UINT32 blockSize = 1024 * 1024);
-		~FrameAlloc();
-
-		/**
-		 * Allocates a new block of memory of the specified size.
-		 *
-		 * @param[in]	amount	Amount of memory to allocate, in bytes.
-		 * 					
-		 * @note	Not thread safe.
-		 */
-		UINT8* alloc(UINT32 amount);
-
-		/**
-		 * Allocates a new block of memory of the specified size aligned to the specified boundary. If the aligment is less
-		 * or equal to 16 it is more efficient to use the allocAligned16() alternative of this method.
-		 *
-		 * @param[in]	amount		Amount of memory to allocate, in bytes.
-		 * @param[in]	alignment	Alignment of the allocated memory. Must be power of two.
-		 * 					
-		 * @note	Not thread safe.
-		 */
-		UINT8* allocAligned(UINT32 amount, UINT32 alignment);
-
-		/**
-		 * Allocates and constructs a new object.
-		 *	
-		 * @note	Not thread safe.
-		 */
-		template<class T, class... Args>
-		T* alloc(Args &&...args)
-		{
-			return new ((T*)alloc(sizeof(T))) T(std::forward<Args>(args)...);
-		}
-
-		/**
-		 * Deallocates a previously allocated block of memory.
-		 *
-		 * @note
-		 * No deallocation is actually done here. This method is only used for debug purposes so it is easier to track 
-		 * down memory leaks and corruption.
-		 * @note
-		 * Thread safe.
-		 */
-		void dealloc(UINT8* data);
-
-		/**
-		 * Deallocates and destructs a previously allocated object.
-		 *
-		 * @note	
-		 * No deallocation is actually done here. This method is only used to call the destructor and for debug purposes 
-		 * so it is easier to track down memory leaks and corruption.
-		 * @note
-		 * Thread safe.
-		 */
-		template<class T>
-		void dealloc(T* obj)
-		{
-			if (obj != nullptr)
-				obj->~T();
-
-			dealloc((UINT8*)obj);
-		}
-
-		/** Starts a new frame. Next call to ::clear will only clear memory allocated past this point. */
-		void markFrame();
-
-		/**
-		 * Deallocates all allocated memory since the last call to markFrame() (or all the memory if there was no call 
-		 * to markFrame()).
-		 * 			
-		 * @note	Not thread safe.
-		 */
-		void clear();
-
-		/**
-		 * Changes the frame allocator owner thread. After the owner thread has changed only allocations from that thread 
-		 * can be made.
-		 */
-		void setOwnerThread(BS_THREAD_ID_TYPE thread);
-
-	private:
-		UINT32 mBlockSize;
-		Vector<MemBlock*> mBlocks;
-		MemBlock* mFreeBlock;
-		UINT32 mNextBlockIdx;
-		std::atomic<UINT32> mTotalAllocBytes;
-		void* mLastFrame;
-
-#if BS_DEBUG_MODE
-		BS_THREAD_ID_TYPE mOwnerThread;
-#endif
-
-		/**
-		 * Allocates a dynamic block of memory of the wanted size. The exact allocation size might be slightly higher in 
-		 * order to store block meta data.
-		 */
-		MemBlock* allocBlock(UINT32 wantedSize);
-
-		/** Frees a memory block. */
-		void deallocBlock(MemBlock* block);
-	};
-
-	/** Allocator for the standard library that internally uses a frame allocator. */
-	template <class T>
-	class StdFrameAlloc
-	{
-	public:
-		typedef T value_type;
-
-		StdFrameAlloc() noexcept 
-			:mFrameAlloc(nullptr)
-		{ }
-
-		StdFrameAlloc(FrameAlloc* alloc) noexcept
-			:mFrameAlloc(alloc)
-		{ }
-
-		template<class T> StdFrameAlloc(const StdFrameAlloc<T>& alloc) noexcept
-			:mFrameAlloc(alloc.mFrameAlloc)
-		{ }
-
-		template<class T> bool operator==(const StdFrameAlloc<T>&) const noexcept { return true; }
-		template<class T> bool operator!=(const StdFrameAlloc<T>&) const noexcept { return false; }
-
-		/** Allocate but don't initialize number elements of type T.*/
-		T* allocate(const size_t num) const
-		{
-			if (num == 0)
-				return nullptr;
-
-			if (num > static_cast<size_t>(-1) / sizeof(T))
-				throw std::bad_array_new_length();
-
-			void* const pv = mFrameAlloc->alloc((UINT32)(num * sizeof(T)));
-			if (!pv)
-				throw std::bad_alloc();
-
-			return static_cast<T*>(pv);
-		}
-
-		/** Deallocate storage p of deleted elements. */
-		void deallocate(T* p, size_t num) const noexcept
-		{
-			mFrameAlloc->dealloc((UINT8*)p);
-		}
-
-		FrameAlloc* mFrameAlloc;
-	};
-
-	/** Return that all specializations of this allocator are interchangeable. */
-	template <class T1, class T2>
-	bool operator== (const StdFrameAlloc<T1>&,
-		const StdFrameAlloc<T2>&) throw() {
-		return true;
-	}
-
-	/** Return that all specializations of this allocator are interchangeable. */
-	template <class T1, class T2>
-	bool operator!= (const StdFrameAlloc<T1>&,
-		const StdFrameAlloc<T2>&) throw() {
-		return false;
-	}
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Memory-Internal
+	 *  @{
+	 */
+
+	/**
+	 * Frame allocator. Performs very fast allocations but can only free all of its memory at once. Perfect for allocations 
+	 * that last just a single frame.
+	 * 			
+	 * @note	Not thread safe with an exception. alloc() and clear() methods need to be called from the same thread.
+	 * 			dealloc() is thread safe and can be called from any thread.
+	 */
+	class BS_UTILITY_EXPORT FrameAlloc
+	{
+	private:
+		/** A single block of memory within a frame allocator. */
+		class MemBlock
+		{
+		public:
+			MemBlock(UINT32 size);
+			~MemBlock();
+
+			/** Allocates a piece of memory within the block. Caller must ensure the block has enough empty space. */
+			UINT8* alloc(UINT32 amount);
+
+			/** Releases all allocations within a block but doesn't actually free the memory. */
+			void clear();
+
+			UINT8* mData;
+			UINT32 mFreePtr;
+			UINT32 mSize;
+		};
+
+	public:
+		FrameAlloc(UINT32 blockSize = 1024 * 1024);
+		~FrameAlloc();
+
+		/**
+		 * Allocates a new block of memory of the specified size.
+		 *
+		 * @param[in]	amount	Amount of memory to allocate, in bytes.
+		 * 					
+		 * @note	Not thread safe.
+		 */
+		UINT8* alloc(UINT32 amount);
+
+		/**
+		 * Allocates a new block of memory of the specified size aligned to the specified boundary. If the aligment is less
+		 * or equal to 16 it is more efficient to use the allocAligned16() alternative of this method.
+		 *
+		 * @param[in]	amount		Amount of memory to allocate, in bytes.
+		 * @param[in]	alignment	Alignment of the allocated memory. Must be power of two.
+		 * 					
+		 * @note	Not thread safe.
+		 */
+		UINT8* allocAligned(UINT32 amount, UINT32 alignment);
+
+		/**
+		 * Allocates and constructs a new object.
+		 *	
+		 * @note	Not thread safe.
+		 */
+		template<class T, class... Args>
+		T* alloc(Args &&...args)
+		{
+			return new ((T*)alloc(sizeof(T))) T(std::forward<Args>(args)...);
+		}
+
+		/**
+		 * Deallocates a previously allocated block of memory.
+		 *
+		 * @note
+		 * No deallocation is actually done here. This method is only used for debug purposes so it is easier to track 
+		 * down memory leaks and corruption.
+		 * @note
+		 * Thread safe.
+		 */
+		void dealloc(UINT8* data);
+
+		/**
+		 * Deallocates and destructs a previously allocated object.
+		 *
+		 * @note	
+		 * No deallocation is actually done here. This method is only used to call the destructor and for debug purposes 
+		 * so it is easier to track down memory leaks and corruption.
+		 * @note
+		 * Thread safe.
+		 */
+		template<class T>
+		void dealloc(T* obj)
+		{
+			if (obj != nullptr)
+				obj->~T();
+
+			dealloc((UINT8*)obj);
+		}
+
+		/** Starts a new frame. Next call to clear() will only clear memory allocated past this point. */
+		void markFrame();
+
+		/**
+		 * Deallocates all allocated memory since the last call to markFrame() (or all the memory if there was no call 
+		 * to markFrame()).
+		 * 			
+		 * @note	Not thread safe.
+		 */
+		void clear();
+
+		/**
+		 * Changes the frame allocator owner thread. After the owner thread has changed only allocations from that thread 
+		 * can be made.
+		 */
+		void setOwnerThread(BS_THREAD_ID_TYPE thread);
+
+	private:
+		UINT32 mBlockSize;
+		Vector<MemBlock*> mBlocks;
+		MemBlock* mFreeBlock;
+		UINT32 mNextBlockIdx;
+		std::atomic<UINT32> mTotalAllocBytes;
+		void* mLastFrame;
+
+#if BS_DEBUG_MODE
+		BS_THREAD_ID_TYPE mOwnerThread;
+#endif
+
+		/**
+		 * Allocates a dynamic block of memory of the wanted size. The exact allocation size might be slightly higher in 
+		 * order to store block meta data.
+		 */
+		MemBlock* allocBlock(UINT32 wantedSize);
+
+		/** Frees a memory block. */
+		void deallocBlock(MemBlock* block);
+	};
+
+	/** Allocator for the standard library that internally uses a frame allocator. */
+	template <class T>
+	class StdFrameAlloc
+	{
+	public:
+		typedef T value_type;
+
+		StdFrameAlloc() noexcept 
+			:mFrameAlloc(nullptr)
+		{ }
+
+		StdFrameAlloc(FrameAlloc* alloc) noexcept
+			:mFrameAlloc(alloc)
+		{ }
+
+		template<class T> StdFrameAlloc(const StdFrameAlloc<T>& alloc) noexcept
+			:mFrameAlloc(alloc.mFrameAlloc)
+		{ }
+
+		template<class T> bool operator==(const StdFrameAlloc<T>&) const noexcept { return true; }
+		template<class T> bool operator!=(const StdFrameAlloc<T>&) const noexcept { return false; }
+
+		/** Allocate but don't initialize number elements of type T.*/
+		T* allocate(const size_t num) const
+		{
+			if (num == 0)
+				return nullptr;
+
+			if (num > static_cast<size_t>(-1) / sizeof(T))
+				throw std::bad_array_new_length();
+
+			void* const pv = mFrameAlloc->alloc((UINT32)(num * sizeof(T)));
+			if (!pv)
+				throw std::bad_alloc();
+
+			return static_cast<T*>(pv);
+		}
+
+		/** Deallocate storage p of deleted elements. */
+		void deallocate(T* p, size_t num) const noexcept
+		{
+			mFrameAlloc->dealloc((UINT8*)p);
+		}
+
+		FrameAlloc* mFrameAlloc;
+	};
+
+	/** Return that all specializations of this allocator are interchangeable. */
+	template <class T1, class T2>
+	bool operator== (const StdFrameAlloc<T1>&,
+		const StdFrameAlloc<T2>&) throw() {
+		return true;
+	}
+
+	/** Return that all specializations of this allocator are interchangeable. */
+	template <class T1, class T2>
+	bool operator!= (const StdFrameAlloc<T1>&,
+		const StdFrameAlloc<T2>&) throw() {
+		return false;
+	}
+
+	/** @} */
+	/** @} */
 }

+ 126 - 120
Source/BansheeUtility/Include/BsFwdDeclUtil.h

@@ -1,121 +1,127 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-// Contains forward declares used as a convenience
-
-namespace BansheeEngine 
-{
-	/** @addtogroup Math
-	 *  @{
-	 */
-
-	/** Values that represent in which order are euler angles applied when used in transformations. */
-	enum class EulerAngleOrder
-	{
-		XYZ,
-		XZY,
-		YXZ,
-		YZX,
-		ZXY,
-		ZYX
-	};
-
-	/**	Enum that defines possible window border styles. */
-	enum class WindowBorder
-	{
-		Normal,
-		None,
-		Fixed
-	};
-
-	/** @} */
-
-	class Angle;
-	class AABox;
-	class Degree;
-	class Math;
-	class Matrix3;
-	class Matrix4;
-	class Plane;
-	class Quaternion;
-	class Radian;
-	class Ray;
-	class Capsule;
-	class Sphere;
-	class Vector2;
-	class Vector3;
-	class Vector4;
-	struct Vector2I;
-	class Rect2I;
-	class Rect2;
-	class Rect3;
-	class Color;
-	class DynLib;
-	class DynLibManager;
-	class DataStream;
-	class MemoryDataStream;
-	class FileDataStream;
-	class MeshData;
-	class FileSystem;
-	class Timer;
-	class Task;
-	class GpuResourceData;
-	class PixelData;
-	class HString;
-	class StringTable;
-	struct LocalizedStringData;
-	class Path;
-	class HThread;
-	class TestSuite;
-	class TestOutput;
-	class AsyncOpSyncData;
-	struct RTTIField;
-	struct RTTIReflectablePtrFieldBase;
-	struct SerializedObject;
-	struct SerializedInstance;
-	class FrameAlloc;
-	class LogEntry;
-	// Reflection
-	class IReflectable;
-	class RTTITypeBase;
-	// Serialization
-	class ISerializable;
-	class SerializableType;
-
-	typedef std::shared_ptr<DataStream> DataStreamPtr;
-	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
-	typedef std::shared_ptr<FileDataStream> FileDataStreamPtr;
-	typedef std::shared_ptr<MeshData> MeshDataPtr;
-	typedef std::shared_ptr<PixelData> PixelDataPtr;
-	typedef std::shared_ptr<GpuResourceData> GpuResourceDataPtr;
-	typedef std::shared_ptr<DataStream> DataStreamPtr;
-	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
-	typedef std::shared_ptr<Task> TaskPtr;
-	typedef std::shared_ptr<TestSuite> TestSuitePtr;
-	typedef std::shared_ptr<AsyncOpSyncData> AsyncOpSyncDataPtr;
-
-	typedef List<DataStreamPtr> DataStreamList;
-	typedef std::shared_ptr<DataStreamList> DataStreamListPtr;
-
-	enum TypeID_Utility
-	{
-		TID_Abstract = 50, // Special type ID used for Abstract classes. Only type ID that may be used by more than one class.
-		TID_WString = 51,
-		TID_Path = 52,
-		TID_Vector = 53,
-		TID_Map = 54,
-		TID_UnorderedMap = 55,
-		TID_Pair = 56,
-		TID_Set = 57,
-		TID_StringID = 58,
-		TID_SerializedInstance = 59,
-		TID_SerializedField = 60,
-		TID_SerializedObject = 61,
-		TID_SerializedArray = 62,
-		TID_SerializedEntry = 63,
-		TID_SerializedArrayEntry = 64,
-		TID_SerializedSubObject = 65,
-		TID_UnorderedSet = 66,
-	};
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+// Contains forward declares used as a convenience
+
+namespace BansheeEngine 
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** Values that represent in which order are euler angles applied when used in transformations. */
+	enum class EulerAngleOrder
+	{
+		XYZ,
+		XZY,
+		YXZ,
+		YZX,
+		ZXY,
+		ZYX
+	};
+
+	/** @} */
+
+	/** @addtogroup Platform-Utility
+	 *  @{
+	 */
+
+	/**	Enum that defines possible window border styles. */
+	enum class WindowBorder
+	{
+		Normal,
+		None,
+		Fixed
+	};
+
+	/** @} */
+
+	class Angle;
+	class AABox;
+	class Degree;
+	class Math;
+	class Matrix3;
+	class Matrix4;
+	class Plane;
+	class Quaternion;
+	class Radian;
+	class Ray;
+	class Capsule;
+	class Sphere;
+	class Vector2;
+	class Vector3;
+	class Vector4;
+	struct Vector2I;
+	class Rect2I;
+	class Rect2;
+	class Rect3;
+	class Color;
+	class DynLib;
+	class DynLibManager;
+	class DataStream;
+	class MemoryDataStream;
+	class FileDataStream;
+	class MeshData;
+	class FileSystem;
+	class Timer;
+	class Task;
+	class GpuResourceData;
+	class PixelData;
+	class HString;
+	class StringTable;
+	struct LocalizedStringData;
+	class Path;
+	class HThread;
+	class TestSuite;
+	class TestOutput;
+	class AsyncOpSyncData;
+	struct RTTIField;
+	struct RTTIReflectablePtrFieldBase;
+	struct SerializedObject;
+	struct SerializedInstance;
+	class FrameAlloc;
+	class LogEntry;
+	// Reflection
+	class IReflectable;
+	class RTTITypeBase;
+	// Serialization
+	class ISerializable;
+	class SerializableType;
+
+	typedef std::shared_ptr<DataStream> DataStreamPtr;
+	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
+	typedef std::shared_ptr<FileDataStream> FileDataStreamPtr;
+	typedef std::shared_ptr<MeshData> MeshDataPtr;
+	typedef std::shared_ptr<PixelData> PixelDataPtr;
+	typedef std::shared_ptr<GpuResourceData> GpuResourceDataPtr;
+	typedef std::shared_ptr<DataStream> DataStreamPtr;
+	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
+	typedef std::shared_ptr<Task> TaskPtr;
+	typedef std::shared_ptr<TestSuite> TestSuitePtr;
+	typedef std::shared_ptr<AsyncOpSyncData> AsyncOpSyncDataPtr;
+
+	typedef List<DataStreamPtr> DataStreamList;
+	typedef std::shared_ptr<DataStreamList> DataStreamListPtr;
+
+	enum TypeID_Utility
+	{
+		TID_Abstract = 50, // Special type ID used for Abstract classes. Only type ID that may be used by more than one class.
+		TID_WString = 51,
+		TID_Path = 52,
+		TID_Vector = 53,
+		TID_Map = 54,
+		TID_UnorderedMap = 55,
+		TID_Pair = 56,
+		TID_Set = 57,
+		TID_StringID = 58,
+		TID_SerializedInstance = 59,
+		TID_SerializedField = 60,
+		TID_SerializedObject = 61,
+		TID_SerializedArray = 62,
+		TID_SerializedEntry = 63,
+		TID_SerializedArrayEntry = 64,
+		TID_SerializedSubObject = 65,
+		TID_UnorderedSet = 66,
+	};
 }

+ 235 - 228
Source/BansheeUtility/Include/BsGlobalFrameAlloc.h

@@ -1,229 +1,236 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsStdHeaders.h"
-#include "BsThreadDefines.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Memory
-	 *  @{
-	 */
-
-	class FrameAlloc;
-
-	/**
-	 * Returns a global, application wide frame allocator. Each thread gets its own frame allocator.
-	 *
-	 * @note	Thread safe.
-	 */
-	inline BS_UTILITY_EXPORT FrameAlloc& gFrameAlloc();
-
-	/**
-	 * Allocates some memory using the global frame allocator.
-	 *
-	 * @param[in]	numBytes	Number of bytes to allocate.
-	 */
-	inline BS_UTILITY_EXPORT UINT8* bs_frame_alloc(UINT32 numBytes);
-
-	/** 
-	 * Allocates the specified number of bytes aligned to the provided boundary, using the global frame allocator. Boundary
-	 * is in bytes and must be a power of two.
-	 */
-	inline BS_UTILITY_EXPORT UINT8* bs_frame_alloc_aligned(UINT32 count, UINT32 align);
-
-	/**
-	 * Deallocates memory allocated with the global frame allocator.
-	 *
-	 * @note	Must be called on the same thread the memory was allocated on.
-	 */
-	inline BS_UTILITY_EXPORT void bs_frame_free(void* data);
-
-	/** 
-	 * Frees memory previously allocated with bs_frame_alloc_aligned(). 
-	 *
-	 * @note	Must be called on the same thread the memory was allocated on.
-	 */
-	inline BS_UTILITY_EXPORT void bs_frame_free_aligned(void* data);
-
-	/**
-	 * Allocates enough memory to hold the object of specified type using the global frame allocator, but does not 
-	 * construct the object. 
-	 */
-	template<class T>
-	T* bs_frame_alloc()
-	{
-		return (T*)bs_frame_alloc(sizeof(T));
-	}
-
-	/**
-	 * Allocates enough memory to hold N objects of specified type using the global frame allocator, but does not 
-	 * construct the object. 
-	 */
-	template<class T>
-	T* bs_frame_alloc(UINT32 count)
-	{
-		return (T*)bs_frame_alloc(sizeof(T) * count);
-	}
-
-	/**
-	 * Allocates enough memory to hold the object(s) of specified type using the global frame allocator, 
-	 * and constructs them.
-	 */
-	template<class T>
-	T* bs_frame_new(UINT32 count = 0)
-	{
-		T* data = bs_frame_alloc<T>(count);
-
-		for(unsigned int i = 0; i < count; i++)
-			new ((void*)&data[i]) T;
-
-		return data;
-	}
-
-	/**
-	 * Allocates enough memory to hold the object(s) of specified type using the global frame allocator, and constructs them.
-	 */
-	template<class T, class... Args>
-	T* bs_frame_new(Args &&...args, UINT32 count = 0)
-	{
-		T* data = bs_frame_alloc<T>(count);
-
-		for(unsigned int i = 0; i < count; i++)
-			new ((void*)&data[i]) T(std::forward<Args>(args)...);
-
-		return data;
-	}
-
-	/**
-	 * Destructs and deallocates an object allocated with the global frame allocator.
-	 *
-	 * @note	Must be called on the same thread the memory was allocated on.
-	 */
-	template<class T>
-	void bs_frame_delete(T* data)
-	{
-		data->~T();
-
-		bs_frame_free((UINT8*)data);
-	}
-
-	/**
-	 * Destructs and deallocates an array of objects allocated with the global frame allocator.
-	 *
-	 * @note	Must be called on the same thread the memory was allocated on.
-	 */
-	template<class T>
-	void bs_frame_delete(T* data, UINT32 count)
-	{
-		for(unsigned int i = 0; i < count; i++)
-			data[i].~T();
-
-		bs_frame_free((UINT8*)data);
-	}
-
-	/** @copydoc FrameAlloc::markFrame */
-	inline BS_UTILITY_EXPORT void bs_frame_mark();
-
-	/** @copydoc FrameAlloc::clear */
-	inline BS_UTILITY_EXPORT void bs_frame_clear();
-
-	/** String allocated with a frame allocator. */
-	typedef std::basic_string<char, std::char_traits<char>, StdAlloc<char, FrameAlloc>> FrameString;
-
-	/** WString allocated with a frame allocator. */
-	typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, StdAlloc<wchar_t, FrameAlloc>> FrameWString;
-
-	/** Vector allocated with a frame allocator. */
-	template <typename T, typename A = StdAlloc<T, FrameAlloc>>
-	using FrameVector = std::vector < T, A > ;
-
-	/** Stack allocated with a frame allocator. */
-	template <typename T, typename A = StdAlloc<T, FrameAlloc>>
-	using FrameStack = std::stack < T, std::deque<T, A> > ;
-
-	/** Set allocated with a frame allocator. */
-	template <typename T, typename P = std::less<T>, typename A = StdAlloc<T, FrameAlloc>>
-	using FrameSet = std::set < T, P, A > ;
-
-	/** Map allocated with a frame allocator. */
-	template <typename K, typename V, typename P = std::less<K>, typename A = StdAlloc<std::pair<const K, V>, FrameAlloc>>
-	using FrameMap = std::map < K, V, P, A >;
-
-	/** UnorderedSet allocated with a frame allocator. */
-	template <typename T, typename H = std::hash<T>, typename C = std::equal_to<T>, typename A = StdAlloc<T, FrameAlloc>>
-	using FrameUnorderedSet = std::unordered_set < T, H, C, A >;
-
-	/** UnorderedMap allocated with a frame allocator. */
-	template <typename K, typename V, typename H = std::hash<K>, typename C = std::equal_to<K>, typename A = StdAlloc<std::pair<const K, V>, FrameAlloc>>
-	using FrameUnorderedMap = std::unordered_map < K, V, H, C, A >;
-
-	/** @cond INTERNAL */
-
-	extern BS_THREADLOCAL FrameAlloc* _GlobalFrameAlloc;
-
-	/**
-	 * Specialized memory allocator implementations that allows use of a global frame allocator in normal 
-	 * new/delete/free/dealloc operators.
-	 */
-	template<>
-	class MemoryAllocator<FrameAlloc> : public MemoryAllocatorBase
-	{
-	public:
-		/** @copydoc MemoryAllocator<T>::allocate */
-		static void* allocate(size_t bytes)
-		{
-			return bs_frame_alloc((UINT32)bytes);
-		}
-
-		/** @copydoc MemoryAllocator<T>::allocateAligned */
-		static void* allocateAligned(size_t bytes, size_t alignment)
-		{
-#if BS_PROFILING_ENABLED
-			incAllocCount();
-#endif
-
-			return bs_frame_alloc_aligned((UINT32)bytes, (UINT32)alignment);
-		}
-
-		/** @copydoc MemoryAllocator<T>::allocateAligned16 */
-		static void* allocateAligned16(size_t bytes)
-		{
-#if BS_PROFILING_ENABLED
-			incAllocCount();
-#endif
-
-			return bs_frame_alloc_aligned((UINT32)bytes, 16);
-		}
-
-		/** @copydoc MemoryAllocator<T>::free */
-		static void free(void* ptr)
-		{
-			bs_frame_free(ptr);
-		}
-
-		/** @copydoc MemoryAllocator<T>::freeAligned */
-		static void freeAligned(void* ptr)
-		{
-#if BS_PROFILING_ENABLED
-			incFreeCount();
-#endif
-
-			bs_frame_free_aligned(ptr);
-		}
-
-		/** @copydoc MemoryAllocator<T>::freeAligned16 */
-		static void freeAligned16(void* ptr)
-		{
-#if BS_PROFILING_ENABLED
-			incFreeCount();
-#endif
-
-			bs_frame_free_aligned(ptr);
-		}
-	};
-
-	/** @endcond */
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsStdHeaders.h"
+#include "BsThreadDefines.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Memory
+	 *  @{
+	 */
+
+	class FrameAlloc;
+
+	/**
+	 * Returns a global, application wide frame allocator. Each thread gets its own frame allocator.
+	 *
+	 * @note	Thread safe.
+	 */
+	inline BS_UTILITY_EXPORT FrameAlloc& gFrameAlloc();
+
+	/**
+	 * Allocates some memory using the global frame allocator.
+	 *
+	 * @param[in]	numBytes	Number of bytes to allocate.
+	 */
+	inline BS_UTILITY_EXPORT UINT8* bs_frame_alloc(UINT32 numBytes);
+
+	/** 
+	 * Allocates the specified number of bytes aligned to the provided boundary, using the global frame allocator. Boundary
+	 * is in bytes and must be a power of two.
+	 */
+	inline BS_UTILITY_EXPORT UINT8* bs_frame_alloc_aligned(UINT32 count, UINT32 align);
+
+	/**
+	 * Deallocates memory allocated with the global frame allocator.
+	 *
+	 * @note	Must be called on the same thread the memory was allocated on.
+	 */
+	inline BS_UTILITY_EXPORT void bs_frame_free(void* data);
+
+	/** 
+	 * Frees memory previously allocated with bs_frame_alloc_aligned(). 
+	 *
+	 * @note	Must be called on the same thread the memory was allocated on.
+	 */
+	inline BS_UTILITY_EXPORT void bs_frame_free_aligned(void* data);
+
+	/**
+	 * Allocates enough memory to hold the object of specified type using the global frame allocator, but does not 
+	 * construct the object. 
+	 */
+	template<class T>
+	T* bs_frame_alloc()
+	{
+		return (T*)bs_frame_alloc(sizeof(T));
+	}
+
+	/**
+	 * Allocates enough memory to hold N objects of specified type using the global frame allocator, but does not 
+	 * construct the object. 
+	 */
+	template<class T>
+	T* bs_frame_alloc(UINT32 count)
+	{
+		return (T*)bs_frame_alloc(sizeof(T) * count);
+	}
+
+	/**
+	 * Allocates enough memory to hold the object(s) of specified type using the global frame allocator, 
+	 * and constructs them.
+	 */
+	template<class T>
+	T* bs_frame_new(UINT32 count = 0)
+	{
+		T* data = bs_frame_alloc<T>(count);
+
+		for(unsigned int i = 0; i < count; i++)
+			new ((void*)&data[i]) T;
+
+		return data;
+	}
+
+	/**
+	 * Allocates enough memory to hold the object(s) of specified type using the global frame allocator, and constructs them.
+	 */
+	template<class T, class... Args>
+	T* bs_frame_new(Args &&...args, UINT32 count = 0)
+	{
+		T* data = bs_frame_alloc<T>(count);
+
+		for(unsigned int i = 0; i < count; i++)
+			new ((void*)&data[i]) T(std::forward<Args>(args)...);
+
+		return data;
+	}
+
+	/**
+	 * Destructs and deallocates an object allocated with the global frame allocator.
+	 *
+	 * @note	Must be called on the same thread the memory was allocated on.
+	 */
+	template<class T>
+	void bs_frame_delete(T* data)
+	{
+		data->~T();
+
+		bs_frame_free((UINT8*)data);
+	}
+
+	/**
+	 * Destructs and deallocates an array of objects allocated with the global frame allocator.
+	 *
+	 * @note	Must be called on the same thread the memory was allocated on.
+	 */
+	template<class T>
+	void bs_frame_delete(T* data, UINT32 count)
+	{
+		for(unsigned int i = 0; i < count; i++)
+			data[i].~T();
+
+		bs_frame_free((UINT8*)data);
+	}
+
+	/** @copydoc FrameAlloc::markFrame */
+	inline BS_UTILITY_EXPORT void bs_frame_mark();
+
+	/** @copydoc FrameAlloc::clear */
+	inline BS_UTILITY_EXPORT void bs_frame_clear();
+
+	/** String allocated with a frame allocator. */
+	typedef std::basic_string<char, std::char_traits<char>, StdAlloc<char, FrameAlloc>> FrameString;
+
+	/** WString allocated with a frame allocator. */
+	typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, StdAlloc<wchar_t, FrameAlloc>> FrameWString;
+
+	/** Vector allocated with a frame allocator. */
+	template <typename T, typename A = StdAlloc<T, FrameAlloc>>
+	using FrameVector = std::vector < T, A > ;
+
+	/** Stack allocated with a frame allocator. */
+	template <typename T, typename A = StdAlloc<T, FrameAlloc>>
+	using FrameStack = std::stack < T, std::deque<T, A> > ;
+
+	/** Set allocated with a frame allocator. */
+	template <typename T, typename P = std::less<T>, typename A = StdAlloc<T, FrameAlloc>>
+	using FrameSet = std::set < T, P, A > ;
+
+	/** Map allocated with a frame allocator. */
+	template <typename K, typename V, typename P = std::less<K>, typename A = StdAlloc<std::pair<const K, V>, FrameAlloc>>
+	using FrameMap = std::map < K, V, P, A >;
+
+	/** UnorderedSet allocated with a frame allocator. */
+	template <typename T, typename H = std::hash<T>, typename C = std::equal_to<T>, typename A = StdAlloc<T, FrameAlloc>>
+	using FrameUnorderedSet = std::unordered_set < T, H, C, A >;
+
+	/** UnorderedMap allocated with a frame allocator. */
+	template <typename K, typename V, typename H = std::hash<K>, typename C = std::equal_to<K>, typename A = StdAlloc<std::pair<const K, V>, FrameAlloc>>
+	using FrameUnorderedMap = std::unordered_map < K, V, H, C, A >;
+
+	/** @} */
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Memory-Internal
+	 *  @{
+	 */
+
+	extern BS_THREADLOCAL FrameAlloc* _GlobalFrameAlloc;
+
+	/**
+	 * Specialized memory allocator implementations that allows use of a global frame allocator in normal 
+	 * new/delete/free/dealloc operators.
+	 */
+	template<>
+	class MemoryAllocator<FrameAlloc> : public MemoryAllocatorBase
+	{
+	public:
+		/** @copydoc MemoryAllocator::allocate */
+		static void* allocate(size_t bytes)
+		{
+			return bs_frame_alloc((UINT32)bytes);
+		}
+
+		/** @copydoc MemoryAllocator::allocateAligned */
+		static void* allocateAligned(size_t bytes, size_t alignment)
+		{
+#if BS_PROFILING_ENABLED
+			incAllocCount();
+#endif
+
+			return bs_frame_alloc_aligned((UINT32)bytes, (UINT32)alignment);
+		}
+
+		/** @copydoc MemoryAllocator::allocateAligned16 */
+		static void* allocateAligned16(size_t bytes)
+		{
+#if BS_PROFILING_ENABLED
+			incAllocCount();
+#endif
+
+			return bs_frame_alloc_aligned((UINT32)bytes, 16);
+		}
+
+		/** @copydoc MemoryAllocator::free */
+		static void free(void* ptr)
+		{
+			bs_frame_free(ptr);
+		}
+
+		/** @copydoc MemoryAllocator::freeAligned */
+		static void freeAligned(void* ptr)
+		{
+#if BS_PROFILING_ENABLED
+			incFreeCount();
+#endif
+
+			bs_frame_free_aligned(ptr);
+		}
+
+		/** @copydoc MemoryAllocator::freeAligned16 */
+		static void freeAligned16(void* ptr)
+		{
+#if BS_PROFILING_ENABLED
+			incFreeCount();
+#endif
+
+			bs_frame_free_aligned(ptr);
+		}
+	};
+
+	/** @} */
+	/** @} */
 }

+ 94 - 94
Source/BansheeUtility/Include/BsIReflectable.h

@@ -1,95 +1,95 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsAny.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup RTTI
-	 *  @{
-	 */
-
-	/**
-	 * Interface implemented by classes that provide run time type information.
-	 * 			
-	 * @note	
-	 * Any class implementing this interface must implement the getRTTI() method, as well as a static getRTTIStatic() 
-	 * method, returning the same value as getRTTI(). Object returned by those methods is used for retrieving actual RTTI 
-	 * data about the class.
-	 */
-	class BS_UTILITY_EXPORT IReflectable
-	{
-	public:
-		virtual ~IReflectable() {}
-
-		/**
-		 * Returns an interface you can use to access class' Run Time Type Information.
-		 *
-		 * @note	
-		 * You must derive your own version of RTTITypeBase, in which you may encapsulate all reflection specific operations. 
-		 */
-		virtual RTTITypeBase* getRTTI() const = 0;
-
-		/** Returns all classes deriving directly from IReflectable. */
-		static Vector<RTTITypeBase*>& getDerivedClasses()
-		{
-			static Vector<RTTITypeBase*> mRTTIDerivedClasses;
-			return mRTTIDerivedClasses;
-		}
-
-		/** Returns true if current RTTI class is derived from @p base (Or if it is the same type as base). */
-		bool isDerivedFrom(RTTITypeBase* base);
-
-		/** Returns an unique type identifier of the class. */
-		UINT32 getTypeId() const;
-
-		/**
-		 * Returns the type name of the class.
-		 *
-		 * @note	Name is not necessarily unique.
-		 */
-		const String& getTypeName() const;
-
-		/** Creates an empty instance of a class from a type identifier. */
-		static std::shared_ptr<IReflectable> createInstanceFromTypeId(UINT32 rttiTypeId);
-
-		/**
-		 * Called by each type deriving from IReflectable, on program load.
-		 *
-		 * @note	Internal method.
-		 */
-		static void _registerDerivedClass(RTTITypeBase* derivedClass);
-
-		/**
-		 * Returns class' RTTI type from type id.
-		 *
-		 * @note	Internal method.
-		 */
-		static RTTITypeBase* _getRTTIfromTypeId(UINT32 rttiTypeId);
-
-		/**
-		 * Checks if the provided type id is unique.
-		 *
-		 * @note	Internal method.
-		 */
-		static bool _isTypeIdDuplicate(UINT32 typeId);
-
-		/**
-		 * Iterates over all RTTI types and reports any circular references (e.g. one type having a field referencing
-		 * another type, and that type having a field referencing the first type). Circular references are problematic
-		 * because when serializing the system cannot determine in which order they should be resolved. In that case user
-		 * should use RTTI_Flag_WeakRef to mark one of the references as weak. This flags tells the system that the reference
-		 * may be resolved in an undefined order, but also no longer guarantees that object assigned to that field during
-		 * deserialization will be fully deserialized itself, as that might be delayed to a later time.
-		 */
-		static void _checkForCircularReferences();
-
-	protected:
-		Any mRTTIData; /**< Temporary per-instance data storage used during various RTTI operations.
-					    Needed since there is one RTTI class instance per type and sometimes we need per-instance data. */
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsAny.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup RTTI
+	 *  @{
+	 */
+
+	/**
+	 * Interface implemented by classes that provide run time type information.
+	 * 			
+	 * @note	
+	 * Any class implementing this interface must implement the getRTTI() method, as well as a static getRTTIStatic() 
+	 * method, returning the same value as getRTTI(). Object returned by those methods is used for retrieving actual RTTI 
+	 * data about the class.
+	 */
+	class BS_UTILITY_EXPORT IReflectable
+	{
+	public:
+		virtual ~IReflectable() {}
+
+		/**
+		 * Returns an interface you can use to access class' Run Time Type Information.
+		 *
+		 * @note	
+		 * You must derive your own version of RTTITypeBase, in which you may encapsulate all reflection specific operations. 
+		 */
+		virtual RTTITypeBase* getRTTI() const = 0;
+
+		/** Returns all classes deriving directly from IReflectable. */
+		static Vector<RTTITypeBase*>& getDerivedClasses()
+		{
+			static Vector<RTTITypeBase*> mRTTIDerivedClasses;
+			return mRTTIDerivedClasses;
+		}
+
+		/** Returns true if current RTTI class is derived from @p base (Or if it is the same type as base). */
+		bool isDerivedFrom(RTTITypeBase* base);
+
+		/** Returns an unique type identifier of the class. */
+		UINT32 getTypeId() const;
+
+		/**
+		 * Returns the type name of the class.
+		 *
+		 * @note	Name is not necessarily unique.
+		 */
+		const String& getTypeName() const;
+
+		/** Creates an empty instance of a class from a type identifier. */
+		static std::shared_ptr<IReflectable> createInstanceFromTypeId(UINT32 rttiTypeId);
+
+		/**
+		 * Called by each type deriving from IReflectable, on program load.
+		 *
+		 * @note	Internal method.
+		 */
+		static void _registerDerivedClass(RTTITypeBase* derivedClass);
+
+		/**
+		 * Returns class' RTTI type from type id.
+		 *
+		 * @note	Internal method.
+		 */
+		static RTTITypeBase* _getRTTIfromTypeId(UINT32 rttiTypeId);
+
+		/**
+		 * Checks if the provided type id is unique.
+		 *
+		 * @note	Internal method.
+		 */
+		static bool _isTypeIdDuplicate(UINT32 typeId);
+
+		/**
+		 * Iterates over all RTTI types and reports any circular references (for example one type having a field referencing
+		 * another type, and that type having a field referencing the first type). Circular references are problematic
+		 * because when serializing the system cannot determine in which order they should be resolved. In that case user
+		 * should use RTTI_Flag_WeakRef to mark one of the references as weak. This flags tells the system that the reference
+		 * may be resolved in an undefined order, but also no longer guarantees that object assigned to that field during
+		 * deserialization will be fully deserialized itself, as that might be delayed to a later time.
+		 */
+		static void _checkForCircularReferences();
+
+	protected:
+		Any mRTTIData; /**< Temporary per-instance data storage used during various RTTI operations.
+					    Needed since there is one RTTI class instance per type and sometimes we need per-instance data. */
+	};
+
+	/** @} */
 }

+ 607 - 593
Source/BansheeUtility/Include/BsMath.h

@@ -1,593 +1,607 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsDegree.h"
-#include "BsRadian.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Math
-	 *  @{
-	 */
-
-    /** Utility class providing common scalar math operations. */
-    class BS_UTILITY_EXPORT Math 
-    {
-    public:
-		static Radian acos(float val);
-		static Radian asin(float val);
-		static Radian atan(float val) { return Radian(std::atan(val)); }
-		static Radian atan2(float y, float x) { return Radian(std::atan2(y,x)); }
-
-        static float cos(const Radian& val) { return (float)std::cos(val.valueRadians()); }
-        static float cos(float val) { return (float)std::cos(val); }
-
-        static float sin(const Radian& val) { return (float)std::sin(val.valueRadians()); }
-        static float sin(float val) { return (float)std::sin(val); }
-
-		static float tan(const Radian& val) { return (float)std::tan(val.valueRadians()); }
-		static float tan(float val) { return (float)std::tan(val); }
-
-		static float sqrt(float val) { return (float)std::sqrt(val); }
-        static Radian sqrt(const Radian& val) { return Radian(std::sqrt(val.valueRadians())); }
-        static Degree sqrt(const Degree& val) { return Degree(std::sqrt(val.valueDegrees())); }
-
-		static float invSqrt(float val);
-		static float sqr(float val) { return val*val; }
-
-		static float pow(float base, float exponent) { return (float)std::pow(base, exponent); }
-		static float exp(float val) { return (float)std::exp(val); }
-
-		static float log(float val) { return (float)std::log(val); }
-		static float log2(float val) { return (float)(std::log(val)/LOG2); }
-		static float logN(float base, float val) { return (float)(std::log(val)/std::log(base)); }
-
-		static float sign(float val);
-		static Radian sign(const Radian& val) { return Radian(sign(val.valueRadians())); }
-		static Degree sign(const Degree& val) { return Degree(sign(val.valueDegrees())); }
-
-		static float abs(float val) { return float(std::fabs(val)); }
-		static Degree abs(const Degree& val) { return Degree(std::fabs(val.valueDegrees())); }
-		static Radian abs(const Radian& val) { return Radian(std::fabs(val.valueRadians())); }
-
-		static float ceil(float val) { return (float)std::ceil(val); }
-		static int ceilToInt(float val) { return (int)std::ceil(val); }
-
-		static float round(float val) { return (float)std::floor(val + 0.5f); }
-		static int roundToInt(float val) { return (int)std::floor(val + 0.5f); }
-
-		static float floor(float val) { return (float)std::floor(val); }
-		static int floorToInt(float val) { return (int)std::floor(val); }
-
-		/** Clamp a value within an inclusive range. */
-		template <typename T>
-		static T clamp(T val, T minval, T maxval)
-		{
-			assert (minval <= maxval && "Invalid clamp range");
-			return std::max(std::min(val, maxval), minval);
-		}
-
-		/** Clamp a value within an inclusive range [0..1]. */
-		template <typename T>
-		static T clamp01(T val)
-		{
-			return std::max(std::min(val, (T)1), (T)0);
-		}
-
-		/** Checks is the specified value a power of two. Only works on integer values. */
-		template <typename T>
-		static bool isPow2(T val)
-		{
-			return (val & (val - 1)) == 0;
-		}
-
-		static bool isNaN(float f)
-		{
-			return f != f;
-		}
-
-        /** Compare two floats, using tolerance for inaccuracies. */
-        static bool approxEquals(float a, float b, 
-			float tolerance = std::numeric_limits<float>::epsilon())
-		{
-			return fabs(b - a) <= tolerance;
-		}
-
-        /** Compare two doubles, using tolerance for inaccuracies. */
-		static bool approxEquals(double a, double b, 
-			double tolerance = std::numeric_limits<double>::epsilon())
-		{
-			return fabs(b - a) <= tolerance;
-		}
-
-		/** Compare two 2D vectors, using tolerance for inaccuracies. */
-		static bool approxEquals(const Vector2& a, const Vector2& b, 
-			float tolerance = std::numeric_limits<float>::epsilon());
-
-		/** Compare two 3D vectors, using tolerance for inaccuracies. */
-		static bool approxEquals(const Vector3& a, const Vector3& b, 
-			float tolerance = std::numeric_limits<float>::epsilon());
-
-		/** Compare two 4D vectors, using tolerance for inaccuracies. */
-		static bool approxEquals(const Vector4& a, const Vector4& b, 
-			float tolerance = std::numeric_limits<float>::epsilon());
-
-		/** Compare two quaternions, using tolerance for inaccuracies. */
-		static bool approxEquals(const Quaternion& a, const Quaternion& b, 
-			float tolerance = std::numeric_limits<float>::epsilon());
-
-        /** Calculates the tangent space vector for a given set of positions / texture coords. */
-        static Vector3 calculateTriTangent(const Vector3& position1, const Vector3& position2, 
-			const Vector3& position3, float u1, float v1, float u2, float v2, float u3, float v3);
-
-		/************************************************************************/
-		/* 							TRIG APPROXIMATIONS                      	*/
-		/************************************************************************/
-
-		/**
-		 * Sine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastSin0(const Radian& val) { return (float)fastASin0(val.valueRadians()); }
-
-		/**
-		 * Sine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastSin0(float val);
-
-		/**
-		 * Sine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/2].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastSin0.
-		 */
-		static float fastSin1(const Radian& val) { return (float)fastASin1(val.valueRadians()); }
-
-		/**
-		 * Sine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/2].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastSin0.
-		 */
-		static float fastSin1(float val);
-
-		/**
-		 * Cosine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastCos0(const Radian& val) { return (float)fastACos0(val.valueRadians()); }
-
-		/**
-		 * Cosine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/2].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastCos0(float val);
-
-		/**
-		 * Cosine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/2].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastCos0.
-		 */
-		static float fastCos1(const Radian& val) { return (float)fastACos1(val.valueRadians()); }
-
-		/**
-		 * Cosine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/2].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastCos0.
-		 */
-		static float fastCos1(float val);
-
-		/**
-		 * Tangent function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/4].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastTan0(const Radian& val) { return (float)fastATan0(val.valueRadians()); }
-
-		/**
-		 * Tangent function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/4].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastTan0(float val);
-
-		/**
-		 * Tangent function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/4].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastTan0.
-		 */
-		static float fastTan1(const Radian& val) { return (float)fastATan1(val.valueRadians()); }
-
-		/**
-		 * Tangent function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, pi/4].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastTan0.
-		 */
-		static float fastTan1(float val);
-
-		/**
-		 * Inverse sine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastASin0(const Radian& val) { return (float)fastASin0(val.valueRadians()); }
-
-		/**
-		 * Inverse sine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastASin0(float val);
-
-		/**
-		 * Inverse sine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, 1].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastASin0.
-		 */
-		static float fastASin1(const Radian& val) { return (float)fastASin1(val.valueRadians()); }
-
-		/**
-		 * Inverse sine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, 1].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastASin0.
-		 */
-		static float fastASin1(float val);
-
-		/**
-		 * Inverse cosine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastACos0(const Radian& val) { return (float)fastACos0(val.valueRadians()); }
-
-		/**
-		 * Inverse cosine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastACos0(float val);
-
-		/**
-		 * Inverse cosine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, 1].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastACos0.
-		 */
-		static float fastACos1(const Radian& val) { return (float)fastACos1(val.valueRadians()); }
-
-		/**
-		 * Inverse cosine function approximation.
-		 *
-		 * @param[in]	val	Angle in range [0, 1].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastACos0.
-		 */
-		static float fastACos1(float val);
-
-		/**
-		 * Inverse tangent function approximation.
-		 *
-		 * @param[in]	val	Angle in range [-1, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastATan0(const Radian& val) { return (float)fastATan0(val.valueRadians()); }
-
-		/**
-		 * Inverse tangent function approximation.
-		 *
-		 * @param[in]	val	Angle in range [-1, 1].
-		 *
-		 * @note	Evaluates trigonometric functions using polynomial approximations.
-		 */
-		static float fastATan0(float val);
-
-		/**
-		 * Inverse tangent function approximation.
-		 *
-		 * @param[in]	val	Angle in range [-1, 1].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastATan0.
-		 */
-		static float fastATan1(const Radian& val) { return (float)fastATan1(val.valueRadians()); }
-
-		/**
-		 * Inverse tangent function approximation.
-		 *
-		 * @param[in]	val	Angle in range [-1, 1].
-		 *
-		 * @note	
-		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastATan0.
-		 */
-		static float fastATan1(float val);
-
-		/**
-		 * Interpolates between min and max. Returned value is in [0, 1] range where min = 0, max = 1 and 0.5 is 
-		 * the average of min and max.
-		 */
-		template <typename T>
-		static float lerp01(T val, T min, T max)
-		{
-			return clamp01((val - min) / std::max(max - min, 0.0001F));
-		}
-
-		/**
-		 * Solves the linear equation with the parameters A, B. Returns number of roots found and the roots themselves will
-		 * be output in the @p roots array.
-		 *
-		 * @param[out]	roots	Must be at least size of 1.
-		 *
-		 * @note	Only returns real roots.
-		 */
-		template <typename T>
-		static UINT32 solveLinear(T A, T B, T* roots)
-		{
-			if (!approxEquals(A, (T)0))
-			{
-				roots[0] = -B / A;
-				return 1;
-			}
-
-			roots[0] = 0.0f;
-			return 1;
-		}
-
-		/**
-		 * Solves the quadratic equation with the parameters A, B, C. Returns number of roots found and the roots themselves
-		 * will be output in the @p roots array.
-		 *
-		 * @param[out]	roots	Must be at least size of 2.
-		 *
-		 * @note	Only returns real roots.
-		 */
-		template <typename T>
-		static UINT32 solveQuadratic(T A, T B, T C, T* roots)
-		{
-			if (!approxEquals(A, (T)0))
-			{
-				T p = B / (2 * A);
-				T q = C / A;
-				T D = p * p - q;
-
-				if (!approxEquals(D, (T)0))
-				{
-					if (D < (T)0)
-						return 0;
-					
-					T sqrtD = sqrt(D);
-					roots[0] = sqrtD - p;
-					roots[1] = -sqrtD - p;
-
-					return 2;
-				}
-				else
-				{
-					roots[0] = -p;
-					roots[1] = -p;
-
-					return 1;
-				}
-			}
-			else
-			{
-				return solveLinear(B, C, roots);
-			}
-		}
-
-		/**
-		 * Solves the cubic equation with the parameters A, B, C, D. Returns number of roots found and the roots themselves 
-		 * will be output in the @p roots array.
-		 *
-		 * @param[out]	roots	Must be at least size of 3.
-		 *
-		 * @note	Only returns real roots.
-		 */
-		template <typename T>
-		static UINT32 solveCubic(T A, T B, T C, T D, T* roots)
-		{
-			static const T THIRD = (1 / (T)3);
-
-			T invA = 1 / A;
-			A = B * invA;
-			B = C * invA;
-			C = D * invA;
-
-			T sqA = A * A;
-			T p = THIRD * (-THIRD * sqA + B);
-			T q = ((T)0.5) * ((2 / (T)27) * A * sqA - THIRD * A * B + C);
-
-			T cbp = p * p * p;
-			D = q * q + cbp;
-
-			UINT32 numRoots = 0;
-			if (!approxEquals(D, (T)0))
-			{
-				if (D < 0.0)
-				{
-					T phi = THIRD * ::acos(-q / sqrt(-cbp));
-					T t = 2 * sqrt(-p);
-
-					roots[0] = t * cos(phi);
-					roots[1] = -t * cos(phi + PI * THIRD);
-					roots[2] = -t * cos(phi - PI * THIRD);
-
-					numRoots = 3;
-				}
-				else
-				{
-					T sqrtD = sqrt(D);
-					T u = cbrt(sqrtD + fabs(q));
-
-					if (q > (T)0)
-						roots[0] = -u + p / u;
-					else
-						roots[0] = u - p / u;
-
-					numRoots = 1;
-				}
-			}
-			else
-			{
-				if (!approxEquals(q, (T)0))
-				{
-					T u = cbrt(-q);
-					roots[0] = 2 * u;
-					roots[1] = -u;
-
-					numRoots = 2;
-				}
-				else
-				{
-					roots[0] = 0.0f;
-					numRoots = 1;
-				}
-			}
-
-			T sub = THIRD * A;
-			for (UINT32 i = 0; i < numRoots; i++)
-				roots[i] -= sub;
-
-			return numRoots;
-		}
-
-		/**
-		 * Solves the quartic equation with the parameters A, B, C, D, E. Returns number of roots found and the roots 
-		 * themselves will be output in the @p roots array.
-		 *
-		 * @param[out]	roots	Must be at least size of 4.
-		 *
-		 * @note	Only returns real roots.
-		 */
-		template <typename T>
-		static UINT32 solveQuartic(T A, T B, T C, T D, T E, T* roots)
-		{
-			T invA = 1 / A;
-			A = B * invA;
-			B = C * invA;
-			C = D * invA;
-			D = E * invA;
-
-			T sqA = A*A;
-			T p = -(3 / (T)8) * sqA + B;
-			T q = (1 / (T)8) * sqA * A - (T)0.5 * A * B + C;
-			T r = -(3 / (T)256) * sqA * sqA + (1 / (T)16) * sqA * B - (1 / (T)4) * A * C + D;
-
-			UINT32 numRoots = 0;
-			if (!approxEquals(r, (T)0))
-			{
-				T cubicA = 1;
-				T cubicB = -(T)0.5 * p ;
-				T cubicC = -r;
-				T cubicD = (T)0.5 * r * p - (1 / (T)8) * q * q;
-
-				solveCubic(cubicA, cubicB, cubicC, cubicD, roots);
-				T z = roots[0];
-
-				T u = z * z - r;
-				T v = 2 * z - p;
-
-				if (approxEquals(u, T(0)))
-					u = 0;
-				else if (u > 0)
-					u = sqrt(u);
-				else
-					return 0;
-
-				if (approxEquals(v, T(0)))
-					v = 0;
-				else if (v > 0)
-					v = sqrt(v);
-				else
-					return 0;
-
-				T quadraticA = 1;
-				T quadraticB = q < 0 ? -v : v;
-				T quadraticC = z - u;
-
-				numRoots = solveQuadratic(quadraticA, quadraticB, quadraticC, roots);
-
-				quadraticA = 1;
-				quadraticB = q < 0 ? v : -v;
-				quadraticC = z + u;
-
-				numRoots += solveQuadratic(quadraticA, quadraticB, quadraticC, roots + numRoots);
-			}
-			else
-			{
-				numRoots = solveCubic(q, p, (T)0, (T)1, roots);
-				roots[numRoots++] = 0;
-			}
-
-			T sub = (1/(T)4) * A;
-			for (UINT32 i = 0; i < numRoots; i++)
-				roots[i] -= sub;
-
-			return numRoots;
-		}
-
-        static const float POS_INFINITY;
-        static const float NEG_INFINITY;
-        static const float PI;
-        static const float TWO_PI;
-        static const float HALF_PI;
-		static const float DEG2RAD;
-		static const float RAD2DEG;
-		static const float LOG2;
-    };
-
-	/** @} */
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsDegree.h"
+#include "BsRadian.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+    /** Utility class providing common scalar math operations. */
+    class BS_UTILITY_EXPORT Math 
+    {
+    public:
+		static Radian acos(float val);
+		static Radian asin(float val);
+		static Radian atan(float val) { return Radian(std::atan(val)); }
+		static Radian atan2(float y, float x) { return Radian(std::atan2(y,x)); }
+
+        static float cos(const Radian& val) { return (float)std::cos(val.valueRadians()); }
+        static float cos(float val) { return (float)std::cos(val); }
+
+        static float sin(const Radian& val) { return (float)std::sin(val.valueRadians()); }
+        static float sin(float val) { return (float)std::sin(val); }
+
+		static float tan(const Radian& val) { return (float)std::tan(val.valueRadians()); }
+		static float tan(float val) { return (float)std::tan(val); }
+
+		static float sqrt(float val) { return (float)std::sqrt(val); }
+        static Radian sqrt(const Radian& val) { return Radian(std::sqrt(val.valueRadians())); }
+        static Degree sqrt(const Degree& val) { return Degree(std::sqrt(val.valueDegrees())); }
+
+		static float invSqrt(float val);
+		static float sqr(float val) { return val*val; }
+
+		static float pow(float base, float exponent) { return (float)std::pow(base, exponent); }
+		static float exp(float val) { return (float)std::exp(val); }
+
+		static float log(float val) { return (float)std::log(val); }
+		static float log2(float val) { return (float)(std::log(val)/LOG2); }
+		static float logN(float base, float val) { return (float)(std::log(val)/std::log(base)); }
+
+		static float sign(float val);
+		static Radian sign(const Radian& val) { return Radian(sign(val.valueRadians())); }
+		static Degree sign(const Degree& val) { return Degree(sign(val.valueDegrees())); }
+
+		static float abs(float val) { return float(std::fabs(val)); }
+		static Degree abs(const Degree& val) { return Degree(std::fabs(val.valueDegrees())); }
+		static Radian abs(const Radian& val) { return Radian(std::fabs(val.valueRadians())); }
+
+		static float ceil(float val) { return (float)std::ceil(val); }
+		static int ceilToInt(float val) { return (int)std::ceil(val); }
+
+		static float round(float val) { return (float)std::floor(val + 0.5f); }
+		static int roundToInt(float val) { return (int)std::floor(val + 0.5f); }
+
+		static float floor(float val) { return (float)std::floor(val); }
+		static int floorToInt(float val) { return (int)std::floor(val); }
+
+		/** Clamp a value within an inclusive range. */
+		template <typename T>
+		static T clamp(T val, T minval, T maxval)
+		{
+			assert (minval <= maxval && "Invalid clamp range");
+			return std::max(std::min(val, maxval), minval);
+		}
+
+		/** Clamp a value within an inclusive range [0..1]. */
+		template <typename T>
+		static T clamp01(T val)
+		{
+			return std::max(std::min(val, (T)1), (T)0);
+		}
+
+		/** Checks is the specified value a power of two. Only works on integer values. */
+		template <typename T>
+		static bool isPow2(T val)
+		{
+			return (val & (val - 1)) == 0;
+		}
+
+		static bool isNaN(float f)
+		{
+			return f != f;
+		}
+
+        /** Compare two floats, using tolerance for inaccuracies. */
+        static bool approxEquals(float a, float b, 
+			float tolerance = std::numeric_limits<float>::epsilon())
+		{
+			return fabs(b - a) <= tolerance;
+		}
+
+        /** Compare two doubles, using tolerance for inaccuracies. */
+		static bool approxEquals(double a, double b, 
+			double tolerance = std::numeric_limits<double>::epsilon())
+		{
+			return fabs(b - a) <= tolerance;
+		}
+
+		/** Compare two 2D vectors, using tolerance for inaccuracies. */
+		static bool approxEquals(const Vector2& a, const Vector2& b, 
+			float tolerance = std::numeric_limits<float>::epsilon());
+
+		/** Compare two 3D vectors, using tolerance for inaccuracies. */
+		static bool approxEquals(const Vector3& a, const Vector3& b, 
+			float tolerance = std::numeric_limits<float>::epsilon());
+
+		/** Compare two 4D vectors, using tolerance for inaccuracies. */
+		static bool approxEquals(const Vector4& a, const Vector4& b, 
+			float tolerance = std::numeric_limits<float>::epsilon());
+
+		/** Compare two quaternions, using tolerance for inaccuracies. */
+		static bool approxEquals(const Quaternion& a, const Quaternion& b, 
+			float tolerance = std::numeric_limits<float>::epsilon());
+
+        /** Calculates the tangent space vector for a given set of positions / texture coords. */
+        static Vector3 calculateTriTangent(const Vector3& position1, const Vector3& position2, 
+			const Vector3& position3, float u1, float v1, float u2, float v2, float u3, float v3);
+
+		/************************************************************************/
+		/* 							TRIG APPROXIMATIONS                      	*/
+		/************************************************************************/
+
+		/**
+		 * Sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastSin0(const Radian& val) { return (float)fastASin0(val.valueRadians()); }
+
+		/**
+		 * Sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastSin0(float val);
+
+		/**
+		 * Sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastSin0.
+		 */
+		static float fastSin1(const Radian& val) { return (float)fastASin1(val.valueRadians()); }
+
+		/**
+		 * Sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastSin0.
+		 */
+		static float fastSin1(float val);
+
+		/**
+		 * Cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastCos0(const Radian& val) { return (float)fastACos0(val.valueRadians()); }
+
+		/**
+		 * Cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastCos0(float val);
+
+		/**
+		 * Cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastCos0.
+		 */
+		static float fastCos1(const Radian& val) { return (float)fastACos1(val.valueRadians()); }
+
+		/**
+		 * Cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/2].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastCos0.
+		 */
+		static float fastCos1(float val);
+
+		/**
+		 * Tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/4].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastTan0(const Radian& val) { return (float)fastATan0(val.valueRadians()); }
+
+		/**
+		 * Tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/4].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastTan0(float val);
+
+		/**
+		 * Tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/4].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastTan0.
+		 */
+		static float fastTan1(const Radian& val) { return (float)fastATan1(val.valueRadians()); }
+
+		/**
+		 * Tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, pi/4].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastTan0.
+		 */
+		static float fastTan1(float val);
+
+		/**
+		 * Inverse sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastASin0(const Radian& val) { return (float)fastASin0(val.valueRadians()); }
+
+		/**
+		 * Inverse sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastASin0(float val);
+
+		/**
+		 * Inverse sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastASin0.
+		 */
+		static float fastASin1(const Radian& val) { return (float)fastASin1(val.valueRadians()); }
+
+		/**
+		 * Inverse sine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastASin0.
+		 */
+		static float fastASin1(float val);
+
+		/**
+		 * Inverse cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastACos0(const Radian& val) { return (float)fastACos0(val.valueRadians()); }
+
+		/**
+		 * Inverse cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastACos0(float val);
+
+		/**
+		 * Inverse cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastACos0.
+		 */
+		static float fastACos1(const Radian& val) { return (float)fastACos1(val.valueRadians()); }
+
+		/**
+		 * Inverse cosine function approximation.
+		 *
+		 * @param[in]	val	Angle in range [0, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastACos0.
+		 */
+		static float fastACos1(float val);
+
+		/**
+		 * Inverse tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [-1, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastATan0(const Radian& val) { return (float)fastATan0(val.valueRadians()); }
+
+		/**
+		 * Inverse tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [-1, 1].
+		 *
+		 * @note	Evaluates trigonometric functions using polynomial approximations.
+		 */
+		static float fastATan0(float val);
+
+		/**
+		 * Inverse tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [-1, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastATan0.
+		 */
+		static float fastATan1(const Radian& val) { return (float)fastATan1(val.valueRadians()); }
+
+		/**
+		 * Inverse tangent function approximation.
+		 *
+		 * @param[in]	val	Angle in range [-1, 1].
+		 *
+		 * @note	
+		 * Evaluates trigonometric functions using polynomial approximations. Slightly better (and slower) than fastATan0.
+		 */
+		static float fastATan1(float val);
+
+		/**
+		 * Interpolates between min and max. Returned value is in [0, 1] range where min = 0, max = 1 and 0.5 is 
+		 * the average of min and max.
+		 */
+		template <typename T>
+		static float lerp01(T val, T min, T max)
+		{
+			return clamp01((val - min) / std::max(max - min, 0.0001F));
+		}
+
+		/**
+		 * Solves the linear equation with the parameters A, B. Returns number of roots found and the roots themselves will
+		 * be output in the @p roots array.
+		 *
+		 * @param[in]	A		First variable.
+		 * @param[in]	B		Second variable.
+		 * @param[out]	roots	Must be at least size of 1.
+		 *
+		 * @note	Only returns real roots.
+		 */
+		template <typename T>
+		static UINT32 solveLinear(T A, T B, T* roots)
+		{
+			if (!approxEquals(A, (T)0))
+			{
+				roots[0] = -B / A;
+				return 1;
+			}
+
+			roots[0] = 0.0f;
+			return 1;
+		}
+
+		/**
+		 * Solves the quadratic equation with the parameters A, B, C. Returns number of roots found and the roots themselves
+		 * will be output in the @p roots array.
+		 *
+		 * @param[in]	A		First variable.
+		 * @param[in]	B		Second variable.
+		 * @param[in]	C		Third variable.
+		 * @param[out]	roots	Must be at least size of 2.
+		 *
+		 * @note	Only returns real roots.
+		 */
+		template <typename T>
+		static UINT32 solveQuadratic(T A, T B, T C, T* roots)
+		{
+			if (!approxEquals(A, (T)0))
+			{
+				T p = B / (2 * A);
+				T q = C / A;
+				T D = p * p - q;
+
+				if (!approxEquals(D, (T)0))
+				{
+					if (D < (T)0)
+						return 0;
+					
+					T sqrtD = sqrt(D);
+					roots[0] = sqrtD - p;
+					roots[1] = -sqrtD - p;
+
+					return 2;
+				}
+				else
+				{
+					roots[0] = -p;
+					roots[1] = -p;
+
+					return 1;
+				}
+			}
+			else
+			{
+				return solveLinear(B, C, roots);
+			}
+		}
+
+		/**
+		 * Solves the cubic equation with the parameters A, B, C, D. Returns number of roots found and the roots themselves 
+		 * will be output in the @p roots array.
+		 *
+		 * @param[in]	A		First variable.
+		 * @param[in]	B		Second variable.
+		 * @param[in]	C		Third variable.
+		 * @param[in]	D		Fourth variable.
+		 * @param[out]	roots	Must be at least size of 3.
+		 *
+		 * @note	Only returns real roots.
+		 */
+		template <typename T>
+		static UINT32 solveCubic(T A, T B, T C, T D, T* roots)
+		{
+			static const T THIRD = (1 / (T)3);
+
+			T invA = 1 / A;
+			A = B * invA;
+			B = C * invA;
+			C = D * invA;
+
+			T sqA = A * A;
+			T p = THIRD * (-THIRD * sqA + B);
+			T q = ((T)0.5) * ((2 / (T)27) * A * sqA - THIRD * A * B + C);
+
+			T cbp = p * p * p;
+			D = q * q + cbp;
+
+			UINT32 numRoots = 0;
+			if (!approxEquals(D, (T)0))
+			{
+				if (D < 0.0)
+				{
+					T phi = THIRD * ::acos(-q / sqrt(-cbp));
+					T t = 2 * sqrt(-p);
+
+					roots[0] = t * cos(phi);
+					roots[1] = -t * cos(phi + PI * THIRD);
+					roots[2] = -t * cos(phi - PI * THIRD);
+
+					numRoots = 3;
+				}
+				else
+				{
+					T sqrtD = sqrt(D);
+					T u = cbrt(sqrtD + fabs(q));
+
+					if (q > (T)0)
+						roots[0] = -u + p / u;
+					else
+						roots[0] = u - p / u;
+
+					numRoots = 1;
+				}
+			}
+			else
+			{
+				if (!approxEquals(q, (T)0))
+				{
+					T u = cbrt(-q);
+					roots[0] = 2 * u;
+					roots[1] = -u;
+
+					numRoots = 2;
+				}
+				else
+				{
+					roots[0] = 0.0f;
+					numRoots = 1;
+				}
+			}
+
+			T sub = THIRD * A;
+			for (UINT32 i = 0; i < numRoots; i++)
+				roots[i] -= sub;
+
+			return numRoots;
+		}
+
+		/**
+		 * Solves the quartic equation with the parameters A, B, C, D, E. Returns number of roots found and the roots 
+		 * themselves will be output in the @p roots array.
+		 *
+		 * @param[in]	A		First variable.
+		 * @param[in]	B		Second variable.
+		 * @param[in]	C		Third variable.
+		 * @param[in]	D		Fourth variable.
+		 * @param[in]	E		Fifth variable.
+		 * @param[out]	roots	Must be at least size of 4.
+		 *
+		 * @note	Only returns real roots.
+		 */
+		template <typename T>
+		static UINT32 solveQuartic(T A, T B, T C, T D, T E, T* roots)
+		{
+			T invA = 1 / A;
+			A = B * invA;
+			B = C * invA;
+			C = D * invA;
+			D = E * invA;
+
+			T sqA = A*A;
+			T p = -(3 / (T)8) * sqA + B;
+			T q = (1 / (T)8) * sqA * A - (T)0.5 * A * B + C;
+			T r = -(3 / (T)256) * sqA * sqA + (1 / (T)16) * sqA * B - (1 / (T)4) * A * C + D;
+
+			UINT32 numRoots = 0;
+			if (!approxEquals(r, (T)0))
+			{
+				T cubicA = 1;
+				T cubicB = -(T)0.5 * p ;
+				T cubicC = -r;
+				T cubicD = (T)0.5 * r * p - (1 / (T)8) * q * q;
+
+				solveCubic(cubicA, cubicB, cubicC, cubicD, roots);
+				T z = roots[0];
+
+				T u = z * z - r;
+				T v = 2 * z - p;
+
+				if (approxEquals(u, T(0)))
+					u = 0;
+				else if (u > 0)
+					u = sqrt(u);
+				else
+					return 0;
+
+				if (approxEquals(v, T(0)))
+					v = 0;
+				else if (v > 0)
+					v = sqrt(v);
+				else
+					return 0;
+
+				T quadraticA = 1;
+				T quadraticB = q < 0 ? -v : v;
+				T quadraticC = z - u;
+
+				numRoots = solveQuadratic(quadraticA, quadraticB, quadraticC, roots);
+
+				quadraticA = 1;
+				quadraticB = q < 0 ? v : -v;
+				quadraticC = z + u;
+
+				numRoots += solveQuadratic(quadraticA, quadraticB, quadraticC, roots + numRoots);
+			}
+			else
+			{
+				numRoots = solveCubic(q, p, (T)0, (T)1, roots);
+				roots[numRoots++] = 0;
+			}
+
+			T sub = (1/(T)4) * A;
+			for (UINT32 i = 0; i < numRoots; i++)
+				roots[i] -= sub;
+
+			return numRoots;
+		}
+
+        static const float POS_INFINITY;
+        static const float NEG_INFINITY;
+        static const float PI;
+        static const float TWO_PI;
+        static const float HALF_PI;
+		static const float DEG2RAD;
+		static const float RAD2DEG;
+		static const float LOG2;
+    };
+
+	/** @} */
+}

+ 41 - 38
Source/BansheeUtility/Include/BsMemAllocProfiler.h

@@ -1,39 +1,42 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup Memory
-	 *  @{
-	 */
-
-	/**
-	 * Specialized allocator for profiler so we can avoid tracking internal profiler memory allocations which would skew 
-	 * profiler results.
-	 */
-	class ProfilerAlloc
-	{};
-
-	/** Memory allocator providing a generic implementation. Specialize for specific categories as needed. */
-	template<>
-	class MemoryAllocator<ProfilerAlloc> : public MemoryAllocatorBase
-	{
-	public:
-		/** Allocates the given number of bytes. */
-		static void* allocate(size_t bytes)
-		{
-			return malloc(bytes);
-		}
-
-		/** Frees memory previously allocated with allocate(). */
-		static void free(void* ptr)
-		{
-			::free(ptr);
-		}
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Memory-Internal
+	 *  @{
+	 */
+
+	/**
+	 * Specialized allocator for profiler so we can avoid tracking internal profiler memory allocations which would skew 
+	 * profiler results.
+	 */
+	class ProfilerAlloc
+	{};
+
+	/** Memory allocator providing a generic implementation. Specialize for specific categories as needed. */
+	template<>
+	class MemoryAllocator<ProfilerAlloc> : public MemoryAllocatorBase
+	{
+	public:
+		/** Allocates the given number of bytes. */
+		static void* allocate(size_t bytes)
+		{
+			return malloc(bytes);
+		}
+
+		/** Frees memory previously allocated with allocate(). */
+		static void free(void* ptr)
+		{
+			::free(ptr);
+		}
+	};
+
+	/** @} */
+	/** @} */
 }

+ 29 - 12
Source/BansheeUtility/Include/BsMemStack.h

@@ -9,14 +9,16 @@
 
 namespace BansheeEngine
 {
-	/** @addtogroup Memory
+	/** @addtogroup Internal-Utility
 	 *  @{
 	 */
 
-	 /** @cond INTERNAL */
+	/** @addtogroup Memory-Internal
+	 *  @{
+	 */
 
 	/**
-	 * Describes a memory stack of a certain block capacity. See ::MemStack for more information.
+	 * Describes a memory stack of a certain block capacity. See MemStack for more information.
 	 *
 	 * @tparam	BlockCapacity Minimum size of a block. Larger blocks mean less memory allocations, but also potentially
 	 *						  more wasted memory. If an allocation requests more bytes than BlockCapacity, first largest 
@@ -26,8 +28,9 @@ namespace BansheeEngine
 	class MemStackInternal
 	{
 	private:
-		/** A single block of memory of BlockCapacity size. A pointer to the first free address is stored, and a remaining 
-		 *  size. 
+		/** 
+		 * A single block of memory of BlockCapacity size. A pointer to the first free address is stored, and a remaining 
+		 * size. 
 		 */
 		class MemBlock
 		{
@@ -242,7 +245,7 @@ namespace BansheeEngine
 		static BS_UTILITY_EXPORT void endThread();
 
 		/** @copydoc MemStackInternal::alloc() */
-		static BS_UTILITY_EXPORT UINT8* alloc(UINT32 numBytes);
+		static BS_UTILITY_EXPORT UINT8* alloc(UINT32 amount);
 
 		/** @copydoc MemStackInternal::dealloc() */
 		static BS_UTILITY_EXPORT void deallocLast(UINT8* data);
@@ -251,10 +254,15 @@ namespace BansheeEngine
 		static BS_THREADLOCAL MemStackInternal<1024 * 1024>* ThreadMemStack;
 	};
 
-	/** @endcond */
+	/** @} */
+	/** @} */
+
+	/** @addtogroup Memory
+	 *  @{
+	 */
 
 	/** @copydoc MemStackInternal::alloc() */
-	BS_UTILITY_EXPORT inline void* bs_stack_alloc(UINT32 numBytes);
+	BS_UTILITY_EXPORT inline void* bs_stack_alloc(UINT32 amount);
 
 	/**
 	 * Allocates enough memory to hold the specified type, on the stack, but does not initialize the object. 
@@ -270,12 +278,14 @@ namespace BansheeEngine
 	/**
 	 * Allocates enough memory to hold N objects of the specified type, on the stack, but does not initialize the objects. 
 	 *
+	 * @param[in]	amount	Number of entries of the requested type to allocate.
+	 *
 	 * @see	MemStackInternal::alloc()
 	 */
 	template<class T>
-	T* bs_stack_alloc(UINT32 count)
+	T* bs_stack_alloc(UINT32 amount)
 	{
-		return (T*)MemStack::alloc(sizeof(T) * count);
+		return (T*)MemStack::alloc(sizeof(T) * amount);
 	}
 
 	/**
@@ -340,7 +350,14 @@ namespace BansheeEngine
 	/** @copydoc MemStackInternal::dealloc() */
 	BS_UTILITY_EXPORT inline void bs_stack_free(void* data);
 
-	/** @cond INTERNAL */
+	/** @} */
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Memory-Internal
+	 *  @{
+	 */
 
 	/**
 	 * Allows use of a stack allocator by using normal new/delete/free/dealloc operators.
@@ -371,6 +388,6 @@ namespace BansheeEngine
 		}
 	};
 
-	/** @endcond */
+	/** @} */
 	/** @} */
 }

+ 414 - 404
Source/BansheeUtility/Include/BsMemoryAllocator.h

@@ -1,405 +1,415 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#undef min
-#undef max
-
-#include <atomic>
-
-/** @addtogroup Memory
- *  @{
- */
-
-namespace BansheeEngine
-{
-	class MemoryAllocatorBase;
-
-	/** @cond INTERNAL */
-
-#if BS_PLATFORM == BS_PLATFORM_WIN32
-	inline void* platformAlignedAlloc16(size_t size)
-	{
-		return _aligned_malloc(size, 16);
-	}
-
-	inline void platformAlignedFree16(void* ptr)
-	{
-		_aligned_free(ptr);
-	}
-
-	inline void* platformAlignedAlloc(size_t size, size_t alignment)
-	{
-		return _aligned_malloc(size, alignment);
-	}
-
-	inline void platformAlignedFree(void* ptr)
-	{
-		_aligned_free(ptr);
-	}
-#elif BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_ANDROID
-	inline void* platformAlignedAlloc16(size_t size)
-	{
-		return ::memalign(16, size);
-	}
-
-	inline void platformAlignedFree16(void* ptr)
-	{
-		::free(ptr);
-	}
-
-	inline void* platformAlignedAlloc(size_t size, size_t alignment)
-	{
-		return ::memalign(alignment, size);
-	}
-
-	inline void platformAlignedFree(void* ptr)
-	{
-		::free(ptr);
-	}
-#else // 16 byte aligment by default
-	inline void* platformAlignedAlloc16(size_t size)
-	{
-		return ::malloc(size);
-	}
-
-	inline void platformAlignedFree16(void* ptr)
-	{
-		::free(ptr);
-	}
-
-	inline void* platformAlignedAlloc(size_t size, size_t alignment)
-	{
-		void* data = ::malloc(size + (alignment - 1) + sizeof(void*));
-		if (data == nullptr)
-			return nullptr;
-
-		UINT8* alignedData = ((UINT8*)data) + sizeof(void*);
-		alignedData += alignment - ((uintptr_t)alignedData) & (alignment - 1);
-
-		((void**)alignedData)[-1] = data;
-		return alignedData;
-	}
-
-	inline void platformAlignedFree(void* ptr)
-	{
-		::free(((void**)ptr)[-1]);
-	}
-#endif
-
-	/**
-	 * Thread safe class used for storing total number of memory allocations and deallocations, primarily for statistic 
-	 * purposes.
-	 */
-	class MemoryCounter
-	{
-	public:
-		static BS_UTILITY_EXPORT UINT64 getNumAllocs()
-		{
-			return Allocs;
-		}
-
-		static BS_UTILITY_EXPORT UINT64 getNumFrees()
-		{
-			return Frees;
-		}
-		
-	private:
-		friend class MemoryAllocatorBase;
-
-		// Threadlocal data can't be exported, so some magic to make it accessible from MemoryAllocator
-		static BS_UTILITY_EXPORT void incAllocCount() { Allocs++; }
-		static BS_UTILITY_EXPORT void incFreeCount() { Frees++; }
-
-		static BS_THREADLOCAL UINT64 Allocs;
-		static BS_THREADLOCAL UINT64 Frees;
-	};
-
-	/** Base class all memory allocators need to inherit. Provides allocation and free counting. */
-	class MemoryAllocatorBase
-	{
-	protected:
-		static void incAllocCount() { MemoryCounter::incAllocCount(); }
-		static void incFreeCount() { MemoryCounter::incFreeCount(); }
-	};
-
-	/**
-	 * Memory allocator providing a generic implementation. Specialize for specific categories as needed.
-	 * 			
-	 * @note	For example you might implement a pool allocator for specific types in order
-	 * 			to reduce allocation overhead. By default standard malloc/free are used.
-	 */
-	template<class T>
-	class MemoryAllocator : public MemoryAllocatorBase
-	{
-	public:
-		/** Allocates @p bytes bytes. */
-		static void* allocate(size_t bytes)
-		{
-#if BS_PROFILING_ENABLED
-			incAllocCount();
-#endif
-
-			return malloc(bytes);
-		}
-
-		/** 
-		 * Allocates @p bytes and aligns them to the specified boundary (in bytes). If the aligment is less or equal to
-		 * 16 it is more efficient to use the allocateAligned16() alternative of this method. Alignment must be power of two.
-		 */
-		static void* allocateAligned(size_t bytes, size_t alignment)
-		{
-#if BS_PROFILING_ENABLED
-			incAllocCount();
-#endif
-
-			return platformAlignedAlloc(bytes, alignment);
-		}
-
-		/** Allocates @p bytes and aligns them to a 16 byte boundary. */
-		static void* allocateAligned16(size_t bytes)
-		{
-#if BS_PROFILING_ENABLED
-			incAllocCount();
-#endif
-
-			return platformAlignedAlloc16(bytes);
-		}
-
-		/** Frees the memory at the specified location. */
-		static void free(void* ptr)
-		{
-#if BS_PROFILING_ENABLED
-			incFreeCount();
-#endif
-
-			::free(ptr);
-		}
-
-		/** Frees memory allocated with allocateAligned() */
-		static void freeAligned(void* ptr)
-		{
-#if BS_PROFILING_ENABLED
-			incFreeCount();
-#endif
-
-			platformAlignedFree(ptr);
-		}
-
-		/** Frees memory allocated with allocateAligned16() */
-		static void freeAligned16(void* ptr)
-		{
-#if BS_PROFILING_ENABLED
-			incFreeCount();
-#endif
-
-			platformAlignedFree16(ptr);
-		}
-	};
-
-	/**
-	 * General allocator provided by the OS. Use for persistent long term allocations, and allocations that don't 
-	 * happen often.
-	 */
-	class GenAlloc
-	{ };
-
-	/** @endcond */
-
-	/** Allocates the specified number of bytes. */
-	template<class Alloc> 
-	inline void* bs_alloc(UINT32 count)
-	{
-		return MemoryAllocator<Alloc>::allocate(count);
-	}
-
-	/** Allocates enough bytes to hold the specified type, but doesn't construct it. */
-	template<class T, class Alloc> 
-	inline T* bs_alloc()
-	{
-		return (T*)MemoryAllocator<Alloc>::allocate(sizeof(T));
-	}
-
-	/** Creates and constructs an array of @p count elements. */
-	template<class T, class Alloc> 
-	inline T* bs_newN(UINT32 count)
-	{
-		T* ptr = (T*)MemoryAllocator<Alloc>::allocate(sizeof(T) * count);
-
-		for(unsigned int i = 0; i < count; i++)
-			new ((void*)&ptr[i]) T;
-
-		return ptr;
-	}
-
-	/** Create a new object with the specified allocator and the specified parameters. */
-	template<class Type, class Alloc, class... Args>
-	Type* bs_new(Args &&...args)
-	{
-		return new (bs_alloc<Alloc>(sizeof(Type))) Type(std::forward<Args>(args)...);
-	}
-
-	/** Frees all the bytes allocated at the specified location. */
-	template<class Alloc> 
-	inline void bs_free(void* ptr)
-	{
-		MemoryAllocator<Alloc>::free(ptr);
-	}
-
-	/** Destructs and frees the specified object. */
-	template<class T, class Alloc = GenAlloc>
-	inline void bs_delete(T* ptr)
-	{
-		(ptr)->~T();
-
-		MemoryAllocator<Alloc>::free(ptr);
-	}
-
-	/** Destructs and frees the specified array of objects. */
-	template<class T, class Alloc = GenAlloc>
-	inline void bs_deleteN(T* ptr, UINT32 count)
-	{
-		for(unsigned int i = 0; i < count; i++)
-			ptr[i].~T();
-
-		MemoryAllocator<Alloc>::free(ptr);
-	}
-
-	/*****************************************************************************/
-	/* Default versions of all alloc/free/new/delete methods which call GenAlloc */
-	/*****************************************************************************/
-
-	/** Allocates the specified number of bytes. */
-	inline void* bs_alloc(UINT32 count)
-	{
-		return MemoryAllocator<GenAlloc>::allocate(count);
-	}
-
-	/** Allocates enough bytes to hold the specified type, but doesn't construct it. */
-	template<class T> 
-	inline T* bs_alloc()
-	{
-		return (T*)MemoryAllocator<GenAlloc>::allocate(sizeof(T));
-	}
-
-	/** 
-	 * Allocates the specified number of bytes aligned to the provided boundary. Boundary is in bytes and must be a power 
-	 * of two.
-	 */
-	inline void* bs_alloc_aligned(UINT32 count, UINT32 align)
-	{
-		return MemoryAllocator<GenAlloc>::allocateAligned(count, align);
-	}
-
-
-	/** Allocates the specified number of bytes aligned to a 16 bytes boundary. */
-	inline void* bs_alloc_aligned16(UINT32 count)
-	{
-		return MemoryAllocator<GenAlloc>::allocateAligned16(count);
-	}
-
-	/** Allocates enough bytes to hold an array of @p count elements the specified type, but doesn't construct them. */
-	template<class T> 
-	inline T* bs_allocN(UINT32 count)
-	{
-		return (T*)MemoryAllocator<GenAlloc>::allocate(count * sizeof(T));
-	}
-
-	/** Creates and constructs an array of @p count elements. */
-	template<class T> 
-	inline T* bs_newN(UINT32 count)
-	{
-		T* ptr = (T*)MemoryAllocator<GenAlloc>::allocate(count * sizeof(T));
-
-		for(unsigned int i = 0; i < count; i++)
-			new ((void*)&ptr[i]) T;
-
-		return ptr;
-	}
-
-	/** Create a new object with the specified allocator and the specified parameters. */
-	template<class Type, class... Args>
-	Type* bs_new(Args &&...args)
-	{
-		return new (bs_alloc<GenAlloc>(sizeof(Type))) Type(std::forward<Args>(args)...);
-	}
-
-	/** Frees all the bytes allocated at the specified location. */
-	inline void bs_free(void* ptr)
-	{
-		MemoryAllocator<GenAlloc>::free(ptr);
-	}
-
-	/** Frees memory previously allocated with bs_alloc_aligned(). */
-	inline void bs_free_aligned(void* ptr)
-	{
-		MemoryAllocator<GenAlloc>::freeAligned(ptr);
-	}
-
-	/** Frees memory previously allocated with bs_alloc_aligned16(). */
-	inline void bs_free_aligned16(void* ptr)
-	{
-		MemoryAllocator<GenAlloc>::freeAligned16(ptr);
-	}
-
-/************************************************************************/
-/* 							MACRO VERSIONS                      		*/
-/* You will almost always want to use the template versions but in some */
-/* cases (private destructor) it is not possible. In which case you may	*/
-/* use these instead.												    */
-/************************************************************************/
-#define BS_PVT_DELETE(T, ptr) \
-	(ptr)->~T(); \
-	MemoryAllocator<GenAlloc>::free(ptr);
-
-#define BS_PVT_DELETE_A(T, ptr, Alloc) \
-	(ptr)->~T(); \
-	MemoryAllocator<Alloc>::free(ptr);
-}
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-
-    /** Allocator for the standard library that internally uses Banshee memory allocator. */
-    template <class T, class Alloc = GenAlloc>
-	class StdAlloc 
-	{
-	public:
-		typedef T value_type;
-		StdAlloc() noexcept {}
-		template<class T, class Alloc> StdAlloc(const StdAlloc<T, Alloc>&) noexcept {}
-		template<class T, class Alloc> bool operator==(const StdAlloc<T, Alloc>&) const noexcept { return true; }
-		template<class T, class Alloc> bool operator!=(const StdAlloc<T, Alloc>&) const noexcept { return false; }
-
-		/** Allocate but don't initialize number elements of type T. */
-		T* allocate(const size_t num) const
-		{
-			if (num == 0)
-				return nullptr;
-
-			if (num > static_cast<size_t>(-1) / sizeof(T))
-				return nullptr; // Error
-
-			void* const pv = bs_alloc<Alloc>((UINT32)(num * sizeof(T)));
-			if (!pv)
-				return nullptr; // Error
-
-			return static_cast<T*>(pv);
-		}
-
-		/** Deallocate storage p of deleted elements. */
-		void deallocate(T* p, size_t num) const noexcept
-		{
-			bs_free<Alloc>((void*)p);
-		}
-	};
-
-	/** @endcond */
-}
-
-/** @} */
-
-#include "BsMemStack.h"
-#include "BsGlobalFrameAlloc.h"
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#undef min
+#undef max
+
+#include <atomic>
+
+namespace BansheeEngine
+{
+	class MemoryAllocatorBase;
+
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Memory-Internal
+	 *  @{
+	 */
+
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+	inline void* platformAlignedAlloc16(size_t size)
+	{
+		return _aligned_malloc(size, 16);
+	}
+
+	inline void platformAlignedFree16(void* ptr)
+	{
+		_aligned_free(ptr);
+	}
+
+	inline void* platformAlignedAlloc(size_t size, size_t alignment)
+	{
+		return _aligned_malloc(size, alignment);
+	}
+
+	inline void platformAlignedFree(void* ptr)
+	{
+		_aligned_free(ptr);
+	}
+#elif BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_ANDROID
+	inline void* platformAlignedAlloc16(size_t size)
+	{
+		return ::memalign(16, size);
+	}
+
+	inline void platformAlignedFree16(void* ptr)
+	{
+		::free(ptr);
+	}
+
+	inline void* platformAlignedAlloc(size_t size, size_t alignment)
+	{
+		return ::memalign(alignment, size);
+	}
+
+	inline void platformAlignedFree(void* ptr)
+	{
+		::free(ptr);
+	}
+#else // 16 byte aligment by default
+	inline void* platformAlignedAlloc16(size_t size)
+	{
+		return ::malloc(size);
+	}
+
+	inline void platformAlignedFree16(void* ptr)
+	{
+		::free(ptr);
+	}
+
+	inline void* platformAlignedAlloc(size_t size, size_t alignment)
+	{
+		void* data = ::malloc(size + (alignment - 1) + sizeof(void*));
+		if (data == nullptr)
+			return nullptr;
+
+		UINT8* alignedData = ((UINT8*)data) + sizeof(void*);
+		alignedData += alignment - ((uintptr_t)alignedData) & (alignment - 1);
+
+		((void**)alignedData)[-1] = data;
+		return alignedData;
+	}
+
+	inline void platformAlignedFree(void* ptr)
+	{
+		::free(((void**)ptr)[-1]);
+	}
+#endif
+
+	/**
+	 * Thread safe class used for storing total number of memory allocations and deallocations, primarily for statistic 
+	 * purposes.
+	 */
+	class MemoryCounter
+	{
+	public:
+		static BS_UTILITY_EXPORT UINT64 getNumAllocs()
+		{
+			return Allocs;
+		}
+
+		static BS_UTILITY_EXPORT UINT64 getNumFrees()
+		{
+			return Frees;
+		}
+		
+	private:
+		friend class MemoryAllocatorBase;
+
+		// Threadlocal data can't be exported, so some magic to make it accessible from MemoryAllocator
+		static BS_UTILITY_EXPORT void incAllocCount() { Allocs++; }
+		static BS_UTILITY_EXPORT void incFreeCount() { Frees++; }
+
+		static BS_THREADLOCAL UINT64 Allocs;
+		static BS_THREADLOCAL UINT64 Frees;
+	};
+
+	/** Base class all memory allocators need to inherit. Provides allocation and free counting. */
+	class MemoryAllocatorBase
+	{
+	protected:
+		static void incAllocCount() { MemoryCounter::incAllocCount(); }
+		static void incFreeCount() { MemoryCounter::incFreeCount(); }
+	};
+
+	/**
+	 * Memory allocator providing a generic implementation. Specialize for specific categories as needed.
+	 * 			
+	 * @note	For example you might implement a pool allocator for specific types in order
+	 * 			to reduce allocation overhead. By default standard malloc/free are used.
+	 */
+	template<class T>
+	class MemoryAllocator : public MemoryAllocatorBase
+	{
+	public:
+		/** Allocates @p bytes bytes. */
+		static void* allocate(size_t bytes)
+		{
+#if BS_PROFILING_ENABLED
+			incAllocCount();
+#endif
+
+			return malloc(bytes);
+		}
+
+		/** 
+		 * Allocates @p bytes and aligns them to the specified boundary (in bytes). If the aligment is less or equal to
+		 * 16 it is more efficient to use the allocateAligned16() alternative of this method. Alignment must be power of two.
+		 */
+		static void* allocateAligned(size_t bytes, size_t alignment)
+		{
+#if BS_PROFILING_ENABLED
+			incAllocCount();
+#endif
+
+			return platformAlignedAlloc(bytes, alignment);
+		}
+
+		/** Allocates @p bytes and aligns them to a 16 byte boundary. */
+		static void* allocateAligned16(size_t bytes)
+		{
+#if BS_PROFILING_ENABLED
+			incAllocCount();
+#endif
+
+			return platformAlignedAlloc16(bytes);
+		}
+
+		/** Frees the memory at the specified location. */
+		static void free(void* ptr)
+		{
+#if BS_PROFILING_ENABLED
+			incFreeCount();
+#endif
+
+			::free(ptr);
+		}
+
+		/** Frees memory allocated with allocateAligned() */
+		static void freeAligned(void* ptr)
+		{
+#if BS_PROFILING_ENABLED
+			incFreeCount();
+#endif
+
+			platformAlignedFree(ptr);
+		}
+
+		/** Frees memory allocated with allocateAligned16() */
+		static void freeAligned16(void* ptr)
+		{
+#if BS_PROFILING_ENABLED
+			incFreeCount();
+#endif
+
+			platformAlignedFree16(ptr);
+		}
+	};
+
+	/**
+	 * General allocator provided by the OS. Use for persistent long term allocations, and allocations that don't 
+	 * happen often.
+	 */
+	class GenAlloc
+	{ };
+
+	/** @} */
+	/** @} */
+
+	/** @addtogroup Memory
+	 *  @{
+	 */
+
+	/** Allocates the specified number of bytes. */
+	template<class Alloc> 
+	inline void* bs_alloc(UINT32 count)
+	{
+		return MemoryAllocator<Alloc>::allocate(count);
+	}
+
+	/** Allocates enough bytes to hold the specified type, but doesn't construct it. */
+	template<class T, class Alloc> 
+	inline T* bs_alloc()
+	{
+		return (T*)MemoryAllocator<Alloc>::allocate(sizeof(T));
+	}
+
+	/** Creates and constructs an array of @p count elements. */
+	template<class T, class Alloc> 
+	inline T* bs_newN(UINT32 count)
+	{
+		T* ptr = (T*)MemoryAllocator<Alloc>::allocate(sizeof(T) * count);
+
+		for(unsigned int i = 0; i < count; i++)
+			new ((void*)&ptr[i]) T;
+
+		return ptr;
+	}
+
+	/** Create a new object with the specified allocator and the specified parameters. */
+	template<class Type, class Alloc, class... Args>
+	Type* bs_new(Args &&...args)
+	{
+		return new (bs_alloc<Alloc>(sizeof(Type))) Type(std::forward<Args>(args)...);
+	}
+
+	/** Frees all the bytes allocated at the specified location. */
+	template<class Alloc> 
+	inline void bs_free(void* ptr)
+	{
+		MemoryAllocator<Alloc>::free(ptr);
+	}
+
+	/** Destructs and frees the specified object. */
+	template<class T, class Alloc = GenAlloc>
+	inline void bs_delete(T* ptr)
+	{
+		(ptr)->~T();
+
+		MemoryAllocator<Alloc>::free(ptr);
+	}
+
+	/** Destructs and frees the specified array of objects. */
+	template<class T, class Alloc = GenAlloc>
+	inline void bs_deleteN(T* ptr, UINT32 count)
+	{
+		for(unsigned int i = 0; i < count; i++)
+			ptr[i].~T();
+
+		MemoryAllocator<Alloc>::free(ptr);
+	}
+
+	/*****************************************************************************/
+	/* Default versions of all alloc/free/new/delete methods which call GenAlloc */
+	/*****************************************************************************/
+
+	/** Allocates the specified number of bytes. */
+	inline void* bs_alloc(UINT32 count)
+	{
+		return MemoryAllocator<GenAlloc>::allocate(count);
+	}
+
+	/** Allocates enough bytes to hold the specified type, but doesn't construct it. */
+	template<class T> 
+	inline T* bs_alloc()
+	{
+		return (T*)MemoryAllocator<GenAlloc>::allocate(sizeof(T));
+	}
+
+	/** 
+	 * Allocates the specified number of bytes aligned to the provided boundary. Boundary is in bytes and must be a power 
+	 * of two.
+	 */
+	inline void* bs_alloc_aligned(UINT32 count, UINT32 align)
+	{
+		return MemoryAllocator<GenAlloc>::allocateAligned(count, align);
+	}
+
+
+	/** Allocates the specified number of bytes aligned to a 16 bytes boundary. */
+	inline void* bs_alloc_aligned16(UINT32 count)
+	{
+		return MemoryAllocator<GenAlloc>::allocateAligned16(count);
+	}
+
+	/** Allocates enough bytes to hold an array of @p count elements the specified type, but doesn't construct them. */
+	template<class T> 
+	inline T* bs_allocN(UINT32 count)
+	{
+		return (T*)MemoryAllocator<GenAlloc>::allocate(count * sizeof(T));
+	}
+
+	/** Creates and constructs an array of @p count elements. */
+	template<class T> 
+	inline T* bs_newN(UINT32 count)
+	{
+		T* ptr = (T*)MemoryAllocator<GenAlloc>::allocate(count * sizeof(T));
+
+		for(unsigned int i = 0; i < count; i++)
+			new ((void*)&ptr[i]) T;
+
+		return ptr;
+	}
+
+	/** Create a new object with the specified allocator and the specified parameters. */
+	template<class Type, class... Args>
+	Type* bs_new(Args &&...args)
+	{
+		return new (bs_alloc<GenAlloc>(sizeof(Type))) Type(std::forward<Args>(args)...);
+	}
+
+	/** Frees all the bytes allocated at the specified location. */
+	inline void bs_free(void* ptr)
+	{
+		MemoryAllocator<GenAlloc>::free(ptr);
+	}
+
+	/** Frees memory previously allocated with bs_alloc_aligned(). */
+	inline void bs_free_aligned(void* ptr)
+	{
+		MemoryAllocator<GenAlloc>::freeAligned(ptr);
+	}
+
+	/** Frees memory previously allocated with bs_alloc_aligned16(). */
+	inline void bs_free_aligned16(void* ptr)
+	{
+		MemoryAllocator<GenAlloc>::freeAligned16(ptr);
+	}
+
+/************************************************************************/
+/* 							MACRO VERSIONS                      		*/
+/* You will almost always want to use the template versions but in some */
+/* cases (private destructor) it is not possible. In which case you may	*/
+/* use these instead.												    */
+/************************************************************************/
+#define BS_PVT_DELETE(T, ptr) \
+	(ptr)->~T(); \
+	MemoryAllocator<GenAlloc>::free(ptr);
+
+#define BS_PVT_DELETE_A(T, ptr, Alloc) \
+	(ptr)->~T(); \
+	MemoryAllocator<Alloc>::free(ptr);
+
+	/** @} */
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Memory-Internal
+	 *  @{
+	 */
+
+    /** Allocator for the standard library that internally uses Banshee memory allocator. */
+    template <class T, class Alloc = GenAlloc>
+	class StdAlloc 
+	{
+	public:
+		typedef T value_type;
+		StdAlloc() noexcept {}
+		template<class T, class Alloc> StdAlloc(const StdAlloc<T, Alloc>&) noexcept {}
+		template<class T, class Alloc> bool operator==(const StdAlloc<T, Alloc>&) const noexcept { return true; }
+		template<class T, class Alloc> bool operator!=(const StdAlloc<T, Alloc>&) const noexcept { return false; }
+
+		/** Allocate but don't initialize number elements of type T. */
+		T* allocate(const size_t num) const
+		{
+			if (num == 0)
+				return nullptr;
+
+			if (num > static_cast<size_t>(-1) / sizeof(T))
+				return nullptr; // Error
+
+			void* const pv = bs_alloc<Alloc>((UINT32)(num * sizeof(T)));
+			if (!pv)
+				return nullptr; // Error
+
+			return static_cast<T*>(pv);
+		}
+
+		/** Deallocate storage p of deleted elements. */
+		void deallocate(T* p, size_t num) const noexcept
+		{
+			bs_free<Alloc>((void*)p);
+		}
+	};
+
+	/** @} */
+	/** @} */
+}
+
+#include "BsMemStack.h"
+#include "BsGlobalFrameAlloc.h"
 #include "BsMemAllocProfiler.h"

+ 65 - 66
Source/BansheeUtility/Include/BsMessageHandlerFwd.h

@@ -1,67 +1,66 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-namespace BansheeEngine
-{
-	/** @addtogroup General
-	 *  @{
-	 */
-
-	/**
-	 * Identifier for message used with the global messaging system.
-	 *
-	 * @note	
-	 * Primary purpose of this class is to avoid expensive string compare (i.e. button names), and instead use a unique 
-	 * message identifier for compare. Generally you want to create one of these using the message name, and then store it 
-	 * for later use.
-	 * @note
-	 * This class is not thread safe and should only be used on the sim thread.
-	 */
-	class BS_UTILITY_EXPORT MessageId
-	{
-	public:
-		MessageId();
-		MessageId(const String& name);
-
-		bool operator== (const MessageId& rhs) const
-		{
-			return (mMsgIdentifier == rhs.mMsgIdentifier);
-		}
-	private:
-		friend class MessageHandler;
-
-		static Map<String, UINT32> UniqueMessageIds;
-		static UINT32 NextMessageId;
-
-		UINT32 mMsgIdentifier;
-	};
-
-	/** Handle to a subscription for a specific message in the global messaging system. */
-	class BS_UTILITY_EXPORT HMessage
-	{
-	public:
-		HMessage();
-
-		/** Disconnects the message listener so it will no longer receive events from the messaging system. */
-		void disconnect();
-
-	private:
-		friend class MessageHandler;
-
-		HMessage(UINT32 id);
-
-		UINT32 mId;
-	};
-
-	/**
-	 * Sends a message using the global messaging system.
-	 *
-	 * @note	Sim thread only.
-	 */
-	void BS_UTILITY_EXPORT sendMessage(MessageId message);
-
-	class MessageHandler;
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+namespace BansheeEngine
+{
+	/** @addtogroup General
+	 *  @{
+	 */
+
+	/**
+	 * Identifier for message used with the global messaging system.
+	 *
+	 * @note	
+	 * Primary purpose of this class is to avoid expensive string compare, and instead use a unique message identifier for
+	 * compare. Generally you want to create one of these using the message name, and then store it for later use.
+	 * @note
+	 * This class is not thread safe and should only be used on the sim thread.
+	 */
+	class BS_UTILITY_EXPORT MessageId
+	{
+	public:
+		MessageId();
+		MessageId(const String& name);
+
+		bool operator== (const MessageId& rhs) const
+		{
+			return (mMsgIdentifier == rhs.mMsgIdentifier);
+		}
+	private:
+		friend class MessageHandler;
+
+		static Map<String, UINT32> UniqueMessageIds;
+		static UINT32 NextMessageId;
+
+		UINT32 mMsgIdentifier;
+	};
+
+	/** Handle to a subscription for a specific message in the global messaging system. */
+	class BS_UTILITY_EXPORT HMessage
+	{
+	public:
+		HMessage();
+
+		/** Disconnects the message listener so it will no longer receive events from the messaging system. */
+		void disconnect();
+
+	private:
+		friend class MessageHandler;
+
+		HMessage(UINT32 id);
+
+		UINT32 mId;
+	};
+
+	/**
+	 * Sends a message using the global messaging system.
+	 *
+	 * @note	Sim thread only.
+	 */
+	void BS_UTILITY_EXPORT sendMessage(MessageId message);
+
+	class MessageHandler;
+
+	/** @} */
 }

+ 35 - 20
Source/BansheeUtility/Include/BsPath.h

@@ -2,12 +2,12 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #pragma once
 
-/** @addtogroup Filesystem
- *  @{
- */
-
 namespace BansheeEngine
 {
+	/** @addtogroup Filesystem
+	 *  @{
+	 */
+
 	/**
 	 * Class for storing and manipulating file paths. Paths may be parsed from and to raw strings according to various 
 	 * platform specific path types.
@@ -33,6 +33,7 @@ namespace BansheeEngine
 		/**
 		 * Constructs a path by parsing the provided path string. Throws exception if provided path is not valid.
 		 *
+		 * @param[in]	pathStr	String containing the path.
 		 * @param[in]	type	If set to default path will be parsed according to the rules of the platform the application
 		 *						is being compiled to. Otherwise it will be parsed according to provided type.
 		 */
@@ -41,6 +42,7 @@ namespace BansheeEngine
 		/**
 		 * Constructs a path by parsing the provided path string. Throws exception if provided path is not valid.
 		 *
+		 * @param[in]	pathStr	String containing the path.
 		 * @param[in]	type	If set to default path will be parsed according to the rules of the platform the application
 		 *						is being compiled to. Otherwise it will be parsed according to provided type.
 		 */
@@ -50,6 +52,7 @@ namespace BansheeEngine
 		 * Constructs a path by parsing the provided path null terminated string. Throws exception if provided path is not 
 		 * valid.
 		 *
+		 * @param[in]	pathStr	Null-terminated string containing the path.
 		 * @param[in]	type	If set to default path will be parsed according to the rules of the platform the application
 		 *						is being compiled to. Otherwise it will be parsed according to provided type.
 		 */
@@ -59,6 +62,7 @@ namespace BansheeEngine
 		 * Constructs a path by parsing the provided path null terminated string. Throws exception if provided path is 
 		 * not valid.
 		 *
+		 * @param[in]	pathStr	Null-terminated string containing the path.
 		 * @param[in]	type	If set to default path will be parsed according to the rules of the platform the application
 		 *						is being compiled to. Otherwise it will be parsed according to provided type.
 		 */
@@ -115,6 +119,7 @@ namespace BansheeEngine
 		/**
 		 * Constructs a path by parsing the provided path string. Throws exception if provided path is not valid.
 		 *
+		 * @param[in]	pathStr	String containing the path.
 		 * @param[in]	type	If set to default path will be parsed according to the rules of the platform the application
 		 *						is being compiled to. Otherwise it will be parsed according to provided type.
 		 */
@@ -123,6 +128,7 @@ namespace BansheeEngine
 		/**
 		 * Constructs a path by parsing the provided path string. Throws exception if provided path is not valid.
 		 *
+		 * @param[in]	pathStr	String containing the path.
 		 * @param[in]	type	If set to default path will be parsed according to the rules of the platform the application 
 		 *						is being compiled to. Otherwise it will be parsed according to provided type.
 		 */
@@ -132,8 +138,10 @@ namespace BansheeEngine
 		 * Constructs a path by parsing the provided path null terminated string. Throws exception if provided path is not 
 		 * valid.
 		 *
-		 * @param[in]	type	If set to default path will be parsed according to the rules of the platform the application
-		 *						is being compiled to. Otherwise it will be parsed according to provided type.
+		 * @param[in]	pathStr		Null-terminated string containing the path.
+		 * @param[in]	type		If set to default path will be parsed according to the rules of the platform the
+		 *							application is being compiled to. Otherwise it will be parsed according to provided
+		 *							type.
 		 */
 		void assign(const wchar_t* pathStr, PathType type = PathType::Default);
 
@@ -141,8 +149,10 @@ namespace BansheeEngine
 		 * Constructs a path by parsing the provided path null terminated string. Throws exception if provided path is not 
 		 * valid.
 		 *
-		 * @param[in]	type	If set to default path will be parsed according to the rules of the platform the application 
-		 *						is being compiled to. Otherwise it will be parsed according to provided type.
+		 * @param[in]	pathStr		Null-terminated string containing the path.
+		 * @param[in]	type		If set to default path will be parsed according to the rules of the platform the
+		 *							application is being compiled to. Otherwise it will be parsed according to provided
+		 *							type.
 		 */
 		void assign(const char* pathStr, PathType type = PathType::Default);
 
@@ -293,16 +303,16 @@ namespace BansheeEngine
 		/** Gets a directory name with the specified index from the path. */
 		String getDirectory(UINT32 idx) const;
 
-		/** Returns path device (e.g. drive, volume, etc.) if one exists in the path. */
+		/** Returns path device (for example drive, volume, etc.) if one exists in the path. */
 		const WString& getWDevice() const { return mDevice; }
 
-		/** Returns path device (e.g. drive, volume, etc.) if one exists in the path. */
+		/** Returns path device (for example drive, volume, etc.) if one exists in the path. */
 		String getDevice() const { return BansheeEngine::toString(mDevice); }
 
-		/** Returns path node (e.g. network name) if one exists in the path. */
+		/** Returns path node (for example network name) if one exists in the path. */
 		const WString& getWNode() const { return mNode; }
 
-		/** Returns path node (e.g. network name) if one exists in the path. */
+		/** Returns path node (for example network name) if one exists in the path. */
 		String getNode() const { return BansheeEngine::toString(mNode); }
 
 		/**
@@ -335,7 +345,7 @@ namespace BansheeEngine
 		/** Concatenates two paths. */
 		Path& operator+= (const Path& rhs);
 
-		/** Compares two path elements (i.e. filenames, directory names, etc.). */
+		/** Compares two path elements (filenames, directory names, etc.). */
 		static bool comparePathElem(const WString& left, const WString& right);
 
 		/** Combines two paths and returns the result. Right path should be relative. */
@@ -346,16 +356,22 @@ namespace BansheeEngine
 		/**
 		 * Constructs a path by parsing the provided raw string data. Throws exception if provided path is not valid.
 		 *
-		 * @param[in]	type	If set to default path will be parsed according to the rules of the platform the application 
-		 *						is being compiled to. Otherwise it will be parsed according to provided type.
+		 * @param[in]	pathStr		String containing the path.
+		 * @param[in]	numChars	Number of character in the provided path string.
+		 * @param[in]	type		If set to default path will be parsed according to the rules of the platform the 
+		 *							application is being compiled to. Otherwise it will be parsed according to provided 
+		 *							type.
 		 */
 		void assign(const wchar_t* pathStr, UINT32 numChars, PathType type = PathType::Default);
 
 		/**
 		 * Constructs a path by parsing the provided raw string data. Throws exception if provided path is not valid.
 		 *
-		 * @param[in]	type	If set to default path will be parsed according to the rules of the platform the application
-		 *						is being compiled to. Otherwise it will be parsed according to provided type.
+		 * @param[in]	pathStr		String containing the path.
+		 * @param[in]	numChars	Number of character in the provided path string.
+		 * @param[in]	type		If set to default path will be parsed according to the rules of the platform the
+		 *							application is being compiled to. Otherwise it will be parsed according to provided
+		 *							type.
 		 */
 		void assign(const char* pathStr, UINT32 numChars, PathType type = PathType::Default);
 
@@ -596,6 +612,7 @@ namespace BansheeEngine
 	};
 
 	/** @endcond */
+	/** @} */
 }
 
 /** @cond STDLIB */
@@ -618,6 +635,4 @@ struct std::hash<BansheeEngine::Path>
 	}
 };
 
-/** @endcond */
-
-/** @} */
+/** @endcond */

+ 234 - 187
Source/BansheeUtility/Include/BsPrerequisitesUtil.h

@@ -1,188 +1,235 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include <assert.h>
-
-/** @defgroup Utility Utility
- *	Lowest layer of the engine containing a collection of very decoupled and separate systems that are 
- *  likely to be used throughout all of the higher layers.
- *  @{
- */
-
-/** @defgroup Math Math
- *	Math utility library containing a variety of general purpose math functionality.
- */
-
-/** @defgroup RTTI RTTI
- *  A set of systems for defining and using run-time type information.
- */
-
- /** @defgroup Serialization Serialization
- *  A set of systems for serializing and deserializing native objects.
- */
-
-/** @defgroup Memory Memory
- *  A set of methods and classes meant to manipulate memory.
- */
-
-/** @defgroup Containers Containers
- *  Contains a set of templated commonly used containers.
- */
-
-/** @defgroup Debug Debug
- *  Contains functionality used to help with debugging.
- */
-
-/** @defgroup Error Error handling
- *  Contains functionality used for handling and reporting errors.
- */
-
-/** @defgroup Filesystem File system
- *  Contains functionality used for manipulating, reading and writing files.
- */
-
-/** @defgroup General General
- *  Contains general utility functionality that doesn't fit in any other category.
- */
-
-/** @defgroup Image Image
- *  Contains various utility methods for manipulating images.
- */
-
-/** @defgroup String String
- *  Contains functionality for manipulating strings.
- */
-
-/** @defgroup Testing Testing
- *  Contains functionality for running unit tests.
- */
-
- /** @defgroup Threading Threading
- *  Contains functionality for manipulating threads and thread synchronization.
- */
-
-/** @defgroup RTTI-Impl-Utility RTTI types
- *  Types containing RTTI for specific classes.
- */
-
-/** @defgroup Platform-Utility Platform
- *  Platform specific functionality.
- */
-
-/** @} */
-
-/** @defgroup Plugins Plugins
- *	Contains all the interchangeable high level systems that are built upon abstractions provided by the engine core.
- */
-
-/** @defgroup Implementation Implementation
- *	Contains various base and helper types that used by an implementation of some other type. These shouldn't even be part
- *  of the class list but due to limitations in the documentation generation system they need to be somewhere. All elements 
- *  listed here should instead be found by browsing the public interfaces of the types that use them.
- */
-
-// 0 - No thread support
-// 1 - Render system is thread safe (TODO: NOT WORKING and will probably be removed)
-// 2 - Thread support but render system can only be accessed from main thread
-#define BS_THREAD_SUPPORT 2
-
-#define BS_PROFILING_ENABLED 1
-
-// Versions
-
-#define BS_VER_DEV 1
-#define BS_VER_PREVIEW 2
-
-#define BS_VER BS_VER_DEV
-
-// Platform-specific stuff
-#include "BsPlatformDefines.h"
-
-#if BS_COMPILER == BS_COMPILER_MSVC
-
-// TODO - This is not deactivated anywhere, therefore it applies to any file that includes this header.
-//      - Right now I don't have an easier way to apply these warnings globally so I'm keeping it this way.
-
-// Secure versions aren't multiplatform, so we won't be using them
-#define _CRT_SECURE_NO_WARNINGS
-
-// disable: "<type> needs to have dll-interface to be used by clients'
-// Happens on STL member variables which are not public therefore is ok
-#   pragma warning (disable: 4251)
-
-// disable: 'X' Function call with parameters that may be unsafe
-#	pragma warning(disable: 4996) 
-
-// disable: decorated name length exceeded, name was truncated
-// Happens with really long type names. Even fairly standard use
-// of std::unordered_map with custom parameters, meaning I can't
-// really do much to avoid it. It shouldn't effect execution
-// but might cause problems if you compile library
-// with one compiler and use it in another.
-#	pragma warning(disable: 4503)
-
-// disable: C++ exception handler used, but unwind semantics are not enabled
-// We don't care about this as any exception is meant to crash the program.
-#	pragma warning(disable: 4530)
-
-#endif
-
-// Windows Settings
-#if BS_PLATFORM == BS_PLATFORM_WIN32
-// Win32 compilers use _DEBUG for specifying debug builds.
-// for MinGW, we set DEBUG
-#   if defined(_DEBUG) || defined(DEBUG)
-#       define BS_DEBUG_MODE 1
-#   else
-#       define BS_DEBUG_MODE 0
-#   endif
-
-#endif
-
-// Linux/Apple Settings
-#if BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_OSX
-// A quick define to overcome different names for the same function
-#   define stricmp strcasecmp
-
-#   ifdef DEBUG
-#       define BS_DEBUG_MODE 1
-#   else
-#       define BS_DEBUG_MODE 0
-#   endif
-
-#endif
-
-#if BS_DEBUG_MODE
-#define BS_DEBUG_ONLY(x) x
-#define BS_ASSERT(x) assert(x)
-#else
-#define BS_DEBUG_ONLY(x)
-#define BS_ASSERT(x)
-#endif
-
-// Short-hand names for various built-in types
-#include "BsTypes.h"
-
-#include "BsMemoryAllocator.h"
-
-// Useful threading defines
-#include "BsThreadDefines.h"
-
-// Commonly used standard headers
-#include "BsStdHeaders.h"
-
-// Forward declarations
-#include "BsFwdDeclUtil.h"
-
-#include "BsRTTIPrerequisites.h"
-
-#include "BsFlags.h"
-#include "BsString.h"
-#include "BsMessageHandlerFwd.h"
-#include "BsUtil.h"
-#include "BsPath.h"
-#include "BsStringID.h"
-#include "BsEvent.h"
-#include "BsPlatformUtility.h"
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include <assert.h>
+
+/** @defgroup Layers Layers 
+ *	Core layers of the engine. 
+ *  @{
+ */
+
+/** @defgroup Utility Utility
+ *	Lowest layer of the engine containing a collection of very decoupled and separate systems that are 
+ *  likely to be used throughout all of the higher layers.
+ *  @{
+ */
+
+/** @defgroup Math Math
+ *	Variety of general purpose math functionality.
+ */
+
+/** @defgroup RTTI RTTI
+ *  Run-time type information defining and querying.
+ */
+
+/** @defgroup Serialization Serialization
+ *  Serialization and deserialization of native objects.
+ */
+
+/** @defgroup Memory Memory
+ *  Allocators, deallocators and memory manipulation.
+ */
+
+/** @defgroup Containers Containers
+ *  Templated commonly used containers.
+ */
+
+/** @defgroup Debug Debug
+ *  Various debugging helpers.
+ */
+
+/** @defgroup Error Error handling
+ *  Handling and reporting errors.
+ */
+
+/** @defgroup Filesystem File system
+ *  Manipulating, reading and writing files.
+ */
+
+/** @defgroup General General
+ *  General utility functionality that doesn't fit in any other category.
+ */
+
+/** @defgroup Image Image
+ *  Manipulating images.
+ */
+
+/** @defgroup String String
+ *  String manipulation.
+ */
+
+/** @defgroup Testing Testing
+ *  Running unit tests.
+ */
+
+/** @defgroup Threading Threading
+ *  Thread manipulation and synchronization.
+ */
+
+/** @cond RTTI */
+/** @defgroup RTTI-Impl-Utility RTTI types
+ *  Types containing RTTI for specific classes.
+ */
+/** @endcond */
+
+/** @defgroup Platform-Utility Platform
+ *  Platform specific functionality.
+ */
+
+/** @defgroup Internal-Utility [INTERNAL]
+ *	Low-level classes and methods not meant for normal use, useful for those that are modifying the engine.
+ *  @{
+ */
+
+/** @defgroup Error-Internal Error handling
+ *  Handling and reporting errors.
+ */
+
+/** @defgroup General-Internal General
+ *  Utility functionality that doesn't fit in any other category.
+ */
+
+/** @defgroup Memory-Internal Memory
+ *  Allocators, deallocators and memory manipulation.
+ */
+
+/** @defgroup Platform-Utility-Internal Platform
+ *  Platform specific functionality.
+ */
+
+/** @defgroup RTTI-Internal RTTI
+ *  Run-time type information defining and querying.
+ */
+
+/** @defgroup Serialization-Internal Serialization
+*  Serialization and deserialization of native objects.
+ */
+
+/** @defgroup String-Internal String
+ *  String manipulation.
+ */
+
+/** @defgroup Threading-Internal Threading
+ *  Thread manipulation and synchronization.
+ */
+
+/** @} */
+
+/** @} */
+/** @} */
+
+/** @defgroup Plugins Plugins
+ *	Implementations of various systems defined in the core layers.
+ */
+
+/** @defgroup Implementation Implementation
+ *	Contains various base and helper types that used by an implementation of some other type. These shouldn't even be part
+ *  of the class list but due to limitations in the documentation generation system they need to be somewhere. All elements 
+ *  listed here should instead be found by browsing the public interfaces of the types that use them.
+ */
+
+// 0 - No thread support
+// 1 - Render system is thread safe (TODO: NOT WORKING and will probably be removed)
+// 2 - Thread support but render system can only be accessed from main thread
+#define BS_THREAD_SUPPORT 2
+
+#define BS_PROFILING_ENABLED 1
+
+// Versions
+
+#define BS_VER_DEV 1
+#define BS_VER_PREVIEW 2
+
+#define BS_VER BS_VER_DEV
+
+// Platform-specific stuff
+#include "BsPlatformDefines.h"
+
+#if BS_COMPILER == BS_COMPILER_MSVC
+
+// TODO - This is not deactivated anywhere, therefore it applies to any file that includes this header.
+//      - Right now I don't have an easier way to apply these warnings globally so I'm keeping it this way.
+
+// Secure versions aren't multiplatform, so we won't be using them
+#define _CRT_SECURE_NO_WARNINGS
+
+// disable: "<type> needs to have dll-interface to be used by clients'
+// Happens on STL member variables which are not public therefore is ok
+#   pragma warning (disable: 4251)
+
+// disable: 'X' Function call with parameters that may be unsafe
+#	pragma warning(disable: 4996) 
+
+// disable: decorated name length exceeded, name was truncated
+// Happens with really long type names. Even fairly standard use
+// of std::unordered_map with custom parameters, meaning I can't
+// really do much to avoid it. It shouldn't effect execution
+// but might cause problems if you compile library
+// with one compiler and use it in another.
+#	pragma warning(disable: 4503)
+
+// disable: C++ exception handler used, but unwind semantics are not enabled
+// We don't care about this as any exception is meant to crash the program.
+#	pragma warning(disable: 4530)
+
+#endif
+
+// Windows Settings
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+// Win32 compilers use _DEBUG for specifying debug builds.
+// for MinGW, we set DEBUG
+#   if defined(_DEBUG) || defined(DEBUG)
+#       define BS_DEBUG_MODE 1
+#   else
+#       define BS_DEBUG_MODE 0
+#   endif
+
+#endif
+
+// Linux/Apple Settings
+#if BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_OSX
+// A quick define to overcome different names for the same function
+#   define stricmp strcasecmp
+
+#   ifdef DEBUG
+#       define BS_DEBUG_MODE 1
+#   else
+#       define BS_DEBUG_MODE 0
+#   endif
+
+#endif
+
+#if BS_DEBUG_MODE
+#define BS_DEBUG_ONLY(x) x
+#define BS_ASSERT(x) assert(x)
+#else
+#define BS_DEBUG_ONLY(x)
+#define BS_ASSERT(x)
+#endif
+
+// Short-hand names for various built-in types
+#include "BsTypes.h"
+
+#include "BsMemoryAllocator.h"
+
+// Useful threading defines
+#include "BsThreadDefines.h"
+
+// Commonly used standard headers
+#include "BsStdHeaders.h"
+
+// Forward declarations
+#include "BsFwdDeclUtil.h"
+
+#include "BsRTTIPrerequisites.h"
+
+#include "BsFlags.h"
+#include "BsString.h"
+#include "BsMessageHandlerFwd.h"
+#include "BsUtil.h"
+#include "BsPath.h"
+#include "BsStringID.h"
+#include "BsEvent.h"
+#include "BsPlatformUtility.h"
 #include "BsCrashHandler.h"

+ 194 - 189
Source/BansheeUtility/Include/BsRTTIField.h

@@ -1,190 +1,195 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include <string>
-
-#include <type_traits>
-
-#include "BsPrerequisitesUtil.h"
-#include "BsIReflectable.h"
-#include "BsManagedDataBlock.h"
-#include "BsException.h"
-#include "BsAny.h"
-
-namespace BansheeEngine
-{
-	class RTTITypeBase;
-
-	/** @cond INTERNAL */
-	/** @addtogroup RTTI
-	 *  @{
-	 */
-
-	/**
-	 * Types of fields we can serialize:
-	 * 			
-	 * - Plain - Native data types, POD (Plain old data) structures, or in general types we don't want to (or can't) inherit from IReflectable.   
-	 *			 Type must be copyable by memcpy.
-	 *			  
-	 * - DataBlock - Array of bytes of a certain size. When returning a data block you may specify if its managed or unmanaged.  
-	 *				 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.
-	 *				 
-	 * - Reflectable - Field that is of IReflectable type. Cannot be a pointer to IReflectable and must be actual value type.   
-	 *				   Type and its fields are serialized recursively. Supports versioning so you may add/remove fields from the type
-	 *				   without breaking previously serialized data.
-	 * 
-	 * - ReflectablePtr - A pointer to IReflectable. Same as "Reflectable" except that data isn't serialized as a value type,  
-	 *					  but as a pointer, which may be referenced by multiple other instances. All references are saved upon
-	 *					  serialization and restored upon deserialization.
-	 */
-	enum SerializableFieldType
-	{
-		SerializableFT_Plain,
-		SerializableFT_DataBlock,
-		SerializableFT_Reflectable,
-		SerializableFT_ReflectablePtr
-	};
-
-	/** 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,
-		/** This flags signals various systems that the flagged field should not be searched when looking for 
-		 * object references. This normally means the value of this field will no be retrieved during reference
-		 * searches but it will likely still be retrieved during other operations (e.g. serialization).
-		 * This is used as an optimization to avoid retrieving values of potentially very expensive fields that
-		 * would not contribute to the reference search anyway. Whether or not a field contributes to the reference
-		 * search depends on the search and should be handled on a case by case basis.
-		 */
-		RTTI_Flag_SkipInReferenceSearch = 0x02
-	};
-
-	/**
-	 * Structure that keeps meta-data concerning a single class field. You can use this data for setting and getting values 
-	 * for that field on a specific class instance.
-	 * 			
-	 * Class also contains an unique field name, and an unique field ID. Fields may contain single types or an array of types. 
-	 * See SerializableFieldType for information about specific field types.
-	 * 			
-	 * @note	
-	 * Most of the methods for retrieving and setting data accept "void *" for both the data and the owning class instance. 
-	 * It is up to the caller to ensure that pointer is of proper type.
-	 */
-	struct BS_UTILITY_EXPORT RTTIField
-	{
-		Any valueGetter;
-		Any valueSetter;
-
-		Any arraySizeGetter;
-		Any arraySizeSetter;
-
-		String mName;
-		UINT16 mUniqueId;
-		bool mIsVectorType;
-		SerializableFieldType mType;
-		UINT64 mFlags;
-
-		bool isPlainType() const { return mType == SerializableFT_Plain; }
-		bool isDataBlockType() const { return mType == SerializableFT_DataBlock; }
-		bool isReflectableType() const { return mType == SerializableFT_Reflectable; }
-		bool isReflectablePtrType() const { return mType == SerializableFT_ReflectablePtr; }
-		bool isArray() const { return mIsVectorType; }
-
-		/** Returns flags that were set in the field meta-data. */
-		UINT64 getFlags() const { return mFlags; }
-
-		/**
-		 * Gets the size of an array contained by the field, if the field represents an array. Throws exception if field 
-		 * is not an array.
-		 */
-		virtual UINT32 getArraySize(void* object) = 0;
-
-		/**
-		 * Changes the size of an array contained by the field, if the field represents an array. Throws exception if field 
-		 * is not an array.
-		 */
-		virtual void setArraySize(void* object, UINT32 size) = 0;
-
-		/** Returns the type id for the type used in this field. */
-		virtual UINT32 getTypeSize() = 0;
-
-		/**
-		 * Query if the field has dynamic size. 
-		 *
-		 * @note	
-		 * Field should have dynamic size if:
-		 *  - The field can have varying size  
-		 * 	- The field size is over 255  
-		 * @note			 
-		 * Types like integers, floats, bools, POD structs dont have dynamic size.
-		 * Types like strings, vectors, maps do.
-		 * @note		
-		 * If your type has a static size but that size exceeds 255 bytes you also need to
-		 * use dynamic field size. (You will be warned during compilation if you don't follow this rule)
-		 */
-		virtual bool hasDynamicSize() = 0;
-
-		/**
-		 * Throws an exception if this field doesn't contain a plain value.
-		 *
-		 * @param[in]	array	If true then the field must support plain array type.
-		 */
-		void checkIsPlain(bool array);
-
-		/**
-		 * Throws an exception if this field doesn't contain a complex value.
-		 *
-		 * @param[in]	array	If true then the field must support complex array type.
-		 */
-		void checkIsComplex(bool array);
-
-		/**
-		 * Throws an exception if this field doesn't contain a complex pointer value.
-		 *
-		 * @param[in]	array	If true then the field must support complex pointer array type.
-		 */
-		void checkIsComplexPtr(bool array);
-
-		/**
-		 * Throws an exception depending if the field is or isn't an array.
-		 *
-		 * @param[in]	array	If true, then exception will be thrown if field is not an array.
-		 * 						If false, then it will be thrown if field is an array.
-		 */
-		void checkIsArray(bool array);
-
-		/** Throws an exception if this field doesn't contain a data block value. */
-		void checkIsDataBlock();
-
-	protected:
-		void initAll(Any valueGetter, Any valueSetter, Any arraySizeGetter, Any arraySizeSetter,
-			String mName, UINT16 mUniqueId, bool mIsVectorType, SerializableFieldType type, UINT64 flags)
-		{
-			this->valueGetter = valueGetter;
-			this->valueSetter = valueSetter;
-			this->arraySizeGetter = arraySizeGetter;
-			this->arraySizeSetter = arraySizeSetter;
-			this->mName = mName;
-			this->mUniqueId = mUniqueId;
-			this->mIsVectorType = mIsVectorType;
-			this->mType = type;
-			this->mFlags = flags;
-		}
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include <string>
+
+#include <type_traits>
+
+#include "BsPrerequisitesUtil.h"
+#include "BsIReflectable.h"
+#include "BsManagedDataBlock.h"
+#include "BsException.h"
+#include "BsAny.h"
+
+namespace BansheeEngine
+{
+	class RTTITypeBase;
+
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup RTTI-Internal
+	 *  @{
+	 */
+
+	/**
+	 * Types of fields we can serialize:
+	 * 			
+	 * - Plain - Native data types, POD (Plain old data) structures, or in general types we don't want to (or can't) inherit from IReflectable.   
+	 *			 Type must be copyable by memcpy.
+	 *			  
+	 * - DataBlock - Array of bytes of a certain size. When returning a data block you may specify if its managed or unmanaged.  
+	 *				 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.
+	 *				 
+	 * - Reflectable - Field that is of IReflectable type. Cannot be a pointer to IReflectable and must be actual value type.   
+	 *				   Type and its fields are serialized recursively. Supports versioning so you may add/remove fields from the type
+	 *				   without breaking previously serialized data.
+	 * 
+	 * - ReflectablePtr - A pointer to IReflectable. Same as "Reflectable" except that data isn't serialized as a value type,  
+	 *					  but as a pointer, which may be referenced by multiple other instances. All references are saved upon
+	 *					  serialization and restored upon deserialization.
+	 */
+	enum SerializableFieldType
+	{
+		SerializableFT_Plain,
+		SerializableFT_DataBlock,
+		SerializableFT_Reflectable,
+		SerializableFT_ReflectablePtr
+	};
+
+	/** 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,
+		/** 
+		 * This flags signals various systems that the flagged field should not be searched when looking for 
+		 * object references. This normally means the value of this field will no be retrieved during reference
+		 * searches but it will likely still be retrieved during other operations (for example serialization).
+		 * This is used as an optimization to avoid retrieving values of potentially very expensive fields that
+		 * would not contribute to the reference search anyway. Whether or not a field contributes to the reference
+		 * search depends on the search and should be handled on a case by case basis.
+		 */
+		RTTI_Flag_SkipInReferenceSearch = 0x02
+	};
+
+	/**
+	 * Structure that keeps meta-data concerning a single class field. You can use this data for setting and getting values 
+	 * for that field on a specific class instance.
+	 * 			
+	 * Class also contains an unique field name, and an unique field ID. Fields may contain single types or an array of types. 
+	 * See SerializableFieldType for information about specific field types.
+	 * 			
+	 * @note	
+	 * Most of the methods for retrieving and setting data accept "void *" for both the data and the owning class instance. 
+	 * It is up to the caller to ensure that pointer is of proper type.
+	 */
+	struct BS_UTILITY_EXPORT RTTIField
+	{
+		Any valueGetter;
+		Any valueSetter;
+
+		Any arraySizeGetter;
+		Any arraySizeSetter;
+
+		String mName;
+		UINT16 mUniqueId;
+		bool mIsVectorType;
+		SerializableFieldType mType;
+		UINT64 mFlags;
+
+		bool isPlainType() const { return mType == SerializableFT_Plain; }
+		bool isDataBlockType() const { return mType == SerializableFT_DataBlock; }
+		bool isReflectableType() const { return mType == SerializableFT_Reflectable; }
+		bool isReflectablePtrType() const { return mType == SerializableFT_ReflectablePtr; }
+		bool isArray() const { return mIsVectorType; }
+
+		/** Returns flags that were set in the field meta-data. */
+		UINT64 getFlags() const { return mFlags; }
+
+		/**
+		 * Gets the size of an array contained by the field, if the field represents an array. Throws exception if field 
+		 * is not an array.
+		 */
+		virtual UINT32 getArraySize(void* object) = 0;
+
+		/**
+		 * Changes the size of an array contained by the field, if the field represents an array. Throws exception if field 
+		 * is not an array.
+		 */
+		virtual void setArraySize(void* object, UINT32 size) = 0;
+
+		/** Returns the type id for the type used in this field. */
+		virtual UINT32 getTypeSize() = 0;
+
+		/**
+		 * Query if the field has dynamic size. 
+		 *
+		 * @note	
+		 * Field should have dynamic size if:
+		 *  - The field can have varying size  
+		 * 	- The field size is over 255  
+		 * @note			 
+		 * Types like integers, floats, bools, POD structs dont have dynamic size.
+		 * Types like strings, vectors, maps do.
+		 * @note		
+		 * If your type has a static size but that size exceeds 255 bytes you also need to
+		 * use dynamic field size. (You will be warned during compilation if you don't follow this rule)
+		 */
+		virtual bool hasDynamicSize() = 0;
+
+		/**
+		 * Throws an exception if this field doesn't contain a plain value.
+		 *
+		 * @param[in]	array	If true then the field must support plain array type.
+		 */
+		void checkIsPlain(bool array);
+
+		/**
+		 * Throws an exception if this field doesn't contain a complex value.
+		 *
+		 * @param[in]	array	If true then the field must support complex array type.
+		 */
+		void checkIsComplex(bool array);
+
+		/**
+		 * Throws an exception if this field doesn't contain a complex pointer value.
+		 *
+		 * @param[in]	array	If true then the field must support complex pointer array type.
+		 */
+		void checkIsComplexPtr(bool array);
+
+		/**
+		 * Throws an exception depending if the field is or isn't an array.
+		 *
+		 * @param[in]	array	If true, then exception will be thrown if field is not an array.
+		 * 						If false, then it will be thrown if field is an array.
+		 */
+		void checkIsArray(bool array);
+
+		/** Throws an exception if this field doesn't contain a data block value. */
+		void checkIsDataBlock();
+
+	protected:
+		void initAll(Any valueGetter, Any valueSetter, Any arraySizeGetter, Any arraySizeSetter,
+			String mName, UINT16 mUniqueId, bool mIsVectorType, SerializableFieldType type, UINT64 flags)
+		{
+			this->valueGetter = valueGetter;
+			this->valueSetter = valueSetter;
+			this->arraySizeGetter = arraySizeGetter;
+			this->arraySizeSetter = arraySizeSetter;
+			this->mName = mName;
+			this->mUniqueId = mUniqueId;
+			this->mIsVectorType = mIsVectorType;
+			this->mType = type;
+			this->mFlags = flags;
+		}
+	};
+
+	/** @} */
+	/** @} */
 }

+ 124 - 121
Source/BansheeUtility/Include/BsRTTIManagedDataBlockField.h

@@ -1,122 +1,125 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsRTTIField.h"
-#include "BsManagedDataBlock.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup RTTI
-	 *  @{
-	 */
-
-	/**
-	 * Base class containing common functionality for a managed data block class field. 
-	 * 			
-	 * @note	
-	 * Managed data blocks are just blocks of memory that may, or may not be released automatically when they are no longer 
-	 * referenced. They are useful when wanting to return some temporary data only for serialization purposes.
-	 */
-	struct RTTIManagedDataBlockFieldBase : public RTTIField
-	{
-		Any mCustomAllocator;
-
-		/** Retrieves a managed data block from the specified instance. */
-		virtual ManagedDataBlock getValue(void* object) = 0;
-
-		/** Sets a managed data block on the specified instance. */
-		virtual void setValue(void* object, ManagedDataBlock value) = 0;
-
-		/**
-		 * Allocate memory for the managed data block. Used primarily to allocate memory before sending it to 
-		 * setValue() method.
-		 */
-		virtual UINT8* allocate(void* object, UINT32 bytes) = 0;
-	};
-
-	/** Class containing a managed data block field containing a specific type. */
-	template <class DataType, class ObjectType>
-	struct RTTIManagedDataBlockField : public RTTIManagedDataBlockFieldBase
-	{
-		/**
-		 * Initializes a field that returns a block of bytes. Can be used for serializing pretty much anything.
-		 *
-		 * @param[in]	name			Name of the field.
-		 * @param[in]	uniqueId		Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *								small data type that can be used for efficiently serializing data to disk and similar. 
-		 *								It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  		The getter method for the field. Must be a specific signature: SerializableDataBlock(ObjectType*)
-		 * @param[in]	setter  		The setter method for the field. Must be a specific signature: void(ObjectType*, SerializableDataBlock)	
-		 * @param[in]	flags			Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
-		 * @param[in]	customAllocator (optional) Custom allocator that will be used when de-serializing DataBlock memory.
-		 */
-		void initSingle(const String& name, UINT16 uniqueId, Any getter, Any setter, UINT64 flags, Any customAllocator = Any())
-		{
-			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_DataBlock, flags);
-			mCustomAllocator = customAllocator;
-		}
-
-		/** @copydoc RTTIField::getTypeSize */
-		virtual UINT32 getTypeSize() override
-		{
-			return 0; // Data block types don't store size the conventional way
-		}
-
-		/** @copydoc RTTIField::hasDynamicSize */
-		virtual bool hasDynamicSize() override
-		{
-			return true;
-		}
-
-		/** @copydoc RTTIField::getArraySize */
-		virtual UINT32 getArraySize(void* object) override
-		{
-			BS_EXCEPT(InternalErrorException, 
-				"Data block types don't support arrays.");
-
-			return 0;
-		}
-
-		/** @copydoc RTTIField::setArraySize */
-		virtual void setArraySize(void* object, UINT32 size) override
-		{
-			BS_EXCEPT(InternalErrorException, 
-				"Data block types don't support arrays.");
-		}
-
-		/** @copydoc RTTIManagedDataBlockFieldBase::getValue */
-		virtual ManagedDataBlock getValue(void* object) override
-		{
-			ObjectType* castObj = static_cast<ObjectType*>(object);
-			std::function<ManagedDataBlock(ObjectType*)> f = any_cast<std::function<ManagedDataBlock(ObjectType*)>>(valueGetter);
-			return f(castObj);
-		}
-
-		/** @copydoc RTTIManagedDataBlockFieldBase::setValue */
-		virtual void setValue(void* object, ManagedDataBlock value) override
-		{
-			ObjectType* castObj = static_cast<ObjectType*>(object);
-			std::function<void(ObjectType*, ManagedDataBlock)> f = any_cast<std::function<void(ObjectType*, ManagedDataBlock)>>(valueSetter);
-			f(castObj, value);
-		}
-
-		/** @copydoc RTTIManagedDataBlockFieldBase::allocate */
-		virtual UINT8* allocate(void* object, UINT32 bytes) override
-		{
-			if(mCustomAllocator.empty())
-				return (UINT8*)bs_alloc(bytes);
-			else
-			{
-				ObjectType* castObj = static_cast<ObjectType*>(object);
-				std::function<UINT8*(ObjectType*, UINT32)> f = any_cast<std::function<UINT8*(ObjectType*, UINT32)>>(mCustomAllocator);
-				return f(castObj, bytes);
-			}
-		}
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsRTTIField.h"
+#include "BsManagedDataBlock.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup RTTI-Internal
+	 *  @{
+	 */
+
+	/**
+	 * Base class containing common functionality for a managed data block class field. 
+	 * 			
+	 * @note	
+	 * Managed data blocks are just blocks of memory that may, or may not be released automatically when they are no longer 
+	 * referenced. They are useful when wanting to return some temporary data only for serialization purposes.
+	 */
+	struct RTTIManagedDataBlockFieldBase : public RTTIField
+	{
+		Any mCustomAllocator;
+
+		/** Retrieves a managed data block from the specified instance. */
+		virtual ManagedDataBlock getValue(void* object) = 0;
+
+		/** Sets a managed data block on the specified instance. */
+		virtual void setValue(void* object, ManagedDataBlock value) = 0;
+
+		/**
+		 * Allocate memory for the managed data block. Used primarily to allocate memory before sending it to 
+		 * setValue() method.
+		 */
+		virtual UINT8* allocate(void* object, UINT32 bytes) = 0;
+	};
+
+	/** Class containing a managed data block field containing a specific type. */
+	template <class DataType, class ObjectType>
+	struct RTTIManagedDataBlockField : public RTTIManagedDataBlockFieldBase
+	{
+		/**
+		 * Initializes a field that returns a block of bytes. Can be used for serializing pretty much anything.
+		 *
+		 * @param[in]	name			Name of the field.
+		 * @param[in]	uniqueId		Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *								small data type that can be used for efficiently serializing data to disk and similar. 
+		 *								It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  		The getter method for the field. Must be a specific signature: SerializableDataBlock(ObjectType*)
+		 * @param[in]	setter  		The setter method for the field. Must be a specific signature: void(ObjectType*, SerializableDataBlock)	
+		 * @param[in]	flags			Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
+		 * @param[in]	customAllocator (optional) Custom allocator that will be used when de-serializing DataBlock memory.
+		 */
+		void initSingle(const String& name, UINT16 uniqueId, Any getter, Any setter, UINT64 flags, Any customAllocator = Any())
+		{
+			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_DataBlock, flags);
+			mCustomAllocator = customAllocator;
+		}
+
+		/** @copydoc RTTIField::getTypeSize */
+		virtual UINT32 getTypeSize() override
+		{
+			return 0; // Data block types don't store size the conventional way
+		}
+
+		/** @copydoc RTTIField::hasDynamicSize */
+		virtual bool hasDynamicSize() override
+		{
+			return true;
+		}
+
+		/** @copydoc RTTIField::getArraySize */
+		virtual UINT32 getArraySize(void* object) override
+		{
+			BS_EXCEPT(InternalErrorException, 
+				"Data block types don't support arrays.");
+
+			return 0;
+		}
+
+		/** @copydoc RTTIField::setArraySize */
+		virtual void setArraySize(void* object, UINT32 size) override
+		{
+			BS_EXCEPT(InternalErrorException, 
+				"Data block types don't support arrays.");
+		}
+
+		/** @copydoc RTTIManagedDataBlockFieldBase::getValue */
+		virtual ManagedDataBlock getValue(void* object) override
+		{
+			ObjectType* castObj = static_cast<ObjectType*>(object);
+			std::function<ManagedDataBlock(ObjectType*)> f = any_cast<std::function<ManagedDataBlock(ObjectType*)>>(valueGetter);
+			return f(castObj);
+		}
+
+		/** @copydoc RTTIManagedDataBlockFieldBase::setValue */
+		virtual void setValue(void* object, ManagedDataBlock value) override
+		{
+			ObjectType* castObj = static_cast<ObjectType*>(object);
+			std::function<void(ObjectType*, ManagedDataBlock)> f = any_cast<std::function<void(ObjectType*, ManagedDataBlock)>>(valueSetter);
+			f(castObj, value);
+		}
+
+		/** @copydoc RTTIManagedDataBlockFieldBase::allocate */
+		virtual UINT8* allocate(void* object, UINT32 bytes) override
+		{
+			if(mCustomAllocator.empty())
+				return (UINT8*)bs_alloc(bytes);
+			else
+			{
+				ObjectType* castObj = static_cast<ObjectType*>(object);
+				std::function<UINT8*(ObjectType*, UINT32)> f = any_cast<std::function<UINT8*(ObjectType*, UINT32)>>(mCustomAllocator);
+				return f(castObj, bytes);
+			}
+		}
+	};
+
+	/** @} */
+	/** @} */
 }

+ 293 - 288
Source/BansheeUtility/Include/BsRTTIPlainField.h

@@ -1,289 +1,294 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsRTTIField.h"
-#include "BsException.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup RTTI
-	 *  @{
-	 */
-
-	/**
-	 * Base class containing common functionality for a plain class field. 
-	 * 			
-	 * @note	
-	 * Plain fields are considered those that may be serialized directly by copying their memory. (All built-in types, 
-	 * strings, etc.)
-	 */
-	struct RTTIPlainFieldBase : public RTTIField
-	{
-		/** Throws an exception if the current field type and provided template types don't match. */
-		template<class DataType>
-		void checkType()
-		{
-			// TODO: Low priority. Because I wanted to get rid of SerializableType I have no way of checking the actual
-			// type of the field and the type provided to get/set methods matches
-
-			/*if(mType.id != SerializableType<DataType>().id)
-			{
-				BS_EXCEPT(InternalErrorException,
-					"Invalid field type.",
-					"SerializableSimpleTypeFieldBase::checkType()");
-			}*/
-		}
-		
-		/** @copydoc RTTIField::getTypeId */
-		virtual UINT32 getTypeId()
-		{
-			return 0;
-		}
-
-		/** @copydoc RTTIField::hasDynamicSize */
-		bool hasDynamicSize() override
-		{
-			return false;
-		}
-
-		/** Gets the dynamic size of the object. If object has no dynamic size, static size of the object is returned. */
-		virtual UINT32 getDynamicSize(void* object)
-		{
-			return 0;
-		}
-
-		/**
-		 * Gets the dynamic size of an array element. If the element has no dynamic size, static size of the element 
-		 * is returned.
-		 */
-		virtual UINT32 getArrayElemDynamicSize(void* object, int index)
-		{
-			return 0;
-		}
-
-		/**
-		 * Retrieves the value from the provided field of the provided object, and copies it into the buffer. It does not 
-		 * check if buffer is large enough.
-		 */
-		virtual void toBuffer(void* object, void* buffer) = 0;
-
-		/**
-		 * Retrieves the value at the specified array index on the provided field of the provided object, and copies it into
-		 * the buffer. It does not check if buffer is large enough.
-		 */
-		virtual void arrayElemToBuffer(void* object, int index, void* buffer) = 0;
-
-		/**
-		 * Sets the value on the provided field of the provided object. Value is copied from the buffer. It does not check 
-		 * the value in the buffer in any way. You must make sure buffer points to the proper location and contains the 
-		 * proper type.
-		 */
-		virtual void fromBuffer(void* object, void* buffer) = 0;
-
-		/**
-		 * Sets the value at the specified array index on the provided field of the provided object. Value is copied from 
-		 * the buffer. It does not check the value in the buffer in any way. You must make sure buffer points to the proper 
-		 * location and contains the proper type.
-		 */
-		virtual void arrayElemFromBuffer(void* object, int index, void* buffer) = 0;
-	};
-
-	/** Represents a plain class field containing a specific type. */
-	template <class DataType, class ObjectType>
-	struct RTTIPlainField : public RTTIPlainFieldBase
-	{
-		/**
-		 * Initializes a plain field containing a single value.
-		 *
-		 * @param[in]	name		Name of the field.
-		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *							small data type that can be used for efficiently serializing data to disk and similar. 
-		 *							It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  	The getter method for the field. Must be a specific signature: DataType(ObjectType*).
-		 * @param[in]	setter  	The setter method for the field. Must be a specific signature: void(ObjectType*, DataType)
-		 * @param[in]	flags		Various flags you can use to specialize how outside systems handle this field. See "RTTIFieldFlag".
-		 */
-		void initSingle(const String& name, UINT16 uniqueId, Any getter, Any setter, UINT64 flags)
-		{
-			static_assert(sizeof(RTTIPlainType<DataType>::id) > 0, "Type has no RTTI ID."); // Just making sure provided type has a type ID
-
-			static_assert((RTTIPlainType<DataType>::hasDynamicSize != 0 || (sizeof(DataType) <= 255)), 
-				"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.");
-
-			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_Plain, flags);
-		}
-
-		/**
-		 * Initializes a plain field containing multiple values in an array. 
-		 *
-		 * @param[in]	name		Name of the field.
-		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *							small data type that can be used for efficiently serializing data to disk and similar. 
-		 *							It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  	The getter method for the field. Must be a specific signature: DataType(ObjectType*, UINT32)
-		 * @param[in]	getSize 	Getter method that returns the size of an array. Must be a specific signature: UINT32(ObjectType*)
-		 * @param[in]	setter  	The setter method for the field. Must be a specific signature: void(ObjectType*, UINT32, DataType)
-		 * @param[in]	setSize 	Setter method that allows you to resize an array. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
-		 * @param[in]	flags		Various flags you can use to specialize how outside systems handle this field. See "RTTIFieldFlag".
-		 */
-		void initArray(const String& name, UINT16 uniqueId, Any getter,
-			Any getSize, Any setter, Any setSize, UINT64 flags)
-		{
-			int typeId = RTTIPlainType<DataType>::id; // Just making sure provided type has a type ID
-
-			static_assert((RTTIPlainType<DataType>::hasDynamicSize != 0 || (sizeof(DataType) <= 255)), 
-				"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.");
-
-			initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_Plain, flags);
-		}
-
-		/** @copydoc RTTIField::getTypeSize */
-		UINT32 getTypeSize() override
-		{
-			return sizeof(DataType);
-		}
-
-		/** @copydoc RTTIPlainFieldBase::getTypeId */
-		UINT32 getTypeId() override
-		{
-			return RTTIPlainType<DataType>::id;
-		}
-
-		/** @copydoc RTTIPlainFieldBase::hasDynamicSize */
-		bool hasDynamicSize() override
-		{
-			return RTTIPlainType<DataType>::hasDynamicSize != 0;
-		}
-
-		/** @copydoc RTTIPlainFieldBase::getDynamicSize */
-		UINT32 getDynamicSize(void* object) override
-		{
-			checkIsArray(false);
-			checkType<DataType>();
-
-			ObjectType* castObject = static_cast<ObjectType*>(object);
-
-			std::function<DataType&(ObjectType*)> f = any_cast<std::function<DataType&(ObjectType*)>>(valueGetter);
-			DataType value = f(castObject);
-
-			return RTTIPlainType<DataType>::getDynamicSize(value);
-		}
-
-		/** @copydoc RTTIPlainFieldBase::getArrayElemDynamicSize */
-		UINT32 getArrayElemDynamicSize(void* object, int index) override
-		{
-			checkIsArray(true);
-			checkType<DataType>();
-
-			ObjectType* castObject = static_cast<ObjectType*>(object);
-
-			std::function<DataType&(ObjectType*, UINT32)> f = any_cast<std::function<DataType&(ObjectType*, UINT32)>>(valueGetter);
-			DataType value = f(castObject, index);
-
-			return RTTIPlainType<DataType>::getDynamicSize(value);
-		}
-
-		/*** @copydoc RTTIPlainField::getArraySize */
-		UINT32 getArraySize(void* object) override
-		{
-			checkIsArray(true);
-
-			std::function<UINT32(ObjectType*)> f = any_cast<std::function<UINT32(ObjectType*)>>(arraySizeGetter);
-			ObjectType* castObject = static_cast<ObjectType*>(object);
-			return f(castObject);
-		}
-
-		/** @copydoc RTTIPlainField::setArraySize */
-		void setArraySize(void* object, UINT32 size) override
-		{
-			checkIsArray(true);
-
-			if(arraySizeSetter.empty())
-			{
-				BS_EXCEPT(InternalErrorException, "Specified field (" + mName + ") has no array size setter.");
-			}
-
-			std::function<void(ObjectType*, UINT32)> f = any_cast<std::function<void(ObjectType*, UINT32)>>(arraySizeSetter);
-			ObjectType* castObject = static_cast<ObjectType*>(object);
-			f(castObject, size);
-		}
-
-		/** @copydoc RTTIPlainFieldBase::toBuffer */
-		void toBuffer(void* object, void* buffer) override
-		{
-			checkIsArray(false);
-			checkType<DataType>();
-
-			ObjectType* castObject = static_cast<ObjectType*>(object);
-
-			std::function<DataType&(ObjectType*)> f = any_cast<std::function<DataType&(ObjectType*)>>(valueGetter);
-			DataType value = f(castObject);
-
-			RTTIPlainType<DataType>::toMemory(value, (char*)buffer);
-		}
-
-		/** @copydoc RTTIPlainFieldBase::arrayElemToBuffer */
-		void arrayElemToBuffer(void* object, int index, void* buffer) override
-		{
-			checkIsArray(true);
-			checkType<DataType>();
-
-			ObjectType* castObject = static_cast<ObjectType*>(object);
-
-			std::function<DataType&(ObjectType*, UINT32)> f = any_cast<std::function<DataType&(ObjectType*, UINT32)>>(valueGetter);
-			DataType value = f(castObject, index);
-
-			RTTIPlainType<DataType>::toMemory(value, (char*)buffer);
-		}
-
-		/** @copydoc RTTIPlainFieldBase::fromBuffer */
-		void fromBuffer(void* object, void* buffer) override
-		{
-			checkIsArray(false);
-			checkType<DataType>();
-
-			ObjectType* castObject = static_cast<ObjectType*>(object);
-
-			DataType value;
-			RTTIPlainType<DataType>::fromMemory(value, (char*)buffer);
-
-			if(valueSetter.empty())
-			{
-				BS_EXCEPT(InternalErrorException,
-					"Specified field (" + mName + ") has no setter.");
-			}
-
-			std::function<void(ObjectType*, DataType&)> f = any_cast<std::function<void(ObjectType*, DataType&)>>(valueSetter);
-			f(castObject, value);
-		}
-
-		/** @copydoc RTTIPlainFieldBase::arrayElemFromBuffer */
-		void arrayElemFromBuffer(void* object, int index, void* buffer) override
-		{
-			checkIsArray(true);
-			checkType<DataType>();
-
-			ObjectType* castObject = static_cast<ObjectType*>(object);
-
-			DataType value;
-			RTTIPlainType<DataType>::fromMemory(value, (char*)buffer);
-
-			if(valueSetter.empty())
-			{
-				BS_EXCEPT(InternalErrorException, 
-					"Specified field (" + mName + ") has no setter.");
-			}
-
-			std::function<void(ObjectType*, UINT32, DataType&)> f = any_cast<std::function<void(ObjectType*, UINT32, DataType&)>>(valueSetter);
-			f(castObject, index, value);
-		}
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsRTTIField.h"
+#include "BsException.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup RTTI-Internal
+	 *  @{
+	 */
+
+	/**
+	 * Base class containing common functionality for a plain class field. 
+	 * 			
+	 * @note	
+	 * Plain fields are considered those that may be serialized directly by copying their memory. (All built-in types, 
+	 * strings, etc.)
+	 */
+	struct RTTIPlainFieldBase : public RTTIField
+	{
+		virtual ~RTTIPlainFieldBase() { }
+
+		/** Throws an exception if the current field type and provided template types don't match. */
+		template<class DataType>
+		void checkType()
+		{
+			// TODO: Low priority. Because I wanted to get rid of SerializableType I have no way of checking the actual
+			// type of the field and the type provided to get/set methods matches
+
+			/*if(mType.id != SerializableType<DataType>().id)
+			{
+				BS_EXCEPT(InternalErrorException,
+					"Invalid field type.",
+					"SerializableSimpleTypeFieldBase::checkType()");
+			}*/
+		}
+		
+		/** Returns the unique identifier for the type owned by the field. */
+		virtual UINT32 getTypeId()
+		{
+			return 0;
+		}
+
+		/** @copydoc RTTIField::hasDynamicSize */
+		bool hasDynamicSize() override
+		{
+			return false;
+		}
+
+		/** Gets the dynamic size of the object. If object has no dynamic size, static size of the object is returned. */
+		virtual UINT32 getDynamicSize(void* object)
+		{
+			return 0;
+		}
+
+		/**
+		 * Gets the dynamic size of an array element. If the element has no dynamic size, static size of the element 
+		 * is returned.
+		 */
+		virtual UINT32 getArrayElemDynamicSize(void* object, int index)
+		{
+			return 0;
+		}
+
+		/**
+		 * Retrieves the value from the provided field of the provided object, and copies it into the buffer. It does not 
+		 * check if buffer is large enough.
+		 */
+		virtual void toBuffer(void* object, void* buffer) = 0;
+
+		/**
+		 * Retrieves the value at the specified array index on the provided field of the provided object, and copies it into
+		 * the buffer. It does not check if buffer is large enough.
+		 */
+		virtual void arrayElemToBuffer(void* object, int index, void* buffer) = 0;
+
+		/**
+		 * Sets the value on the provided field of the provided object. Value is copied from the buffer. It does not check 
+		 * the value in the buffer in any way. You must make sure buffer points to the proper location and contains the 
+		 * proper type.
+		 */
+		virtual void fromBuffer(void* object, void* buffer) = 0;
+
+		/**
+		 * Sets the value at the specified array index on the provided field of the provided object. Value is copied from 
+		 * the buffer. It does not check the value in the buffer in any way. You must make sure buffer points to the proper 
+		 * location and contains the proper type.
+		 */
+		virtual void arrayElemFromBuffer(void* object, int index, void* buffer) = 0;
+	};
+
+	/** Represents a plain class field containing a specific type. */
+	template <class DataType, class ObjectType>
+	struct RTTIPlainField : public RTTIPlainFieldBase
+	{
+		/**
+		 * Initializes a plain field containing a single value.
+		 *
+		 * @param[in]	name		Name of the field.
+		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *							small data type that can be used for efficiently serializing data to disk and similar. 
+		 *							It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  	The getter method for the field. Must be a specific signature: DataType(ObjectType*).
+		 * @param[in]	setter  	The setter method for the field. Must be a specific signature: void(ObjectType*, DataType)
+		 * @param[in]	flags		Various flags you can use to specialize how outside systems handle this field. See "RTTIFieldFlag".
+		 */
+		void initSingle(const String& name, UINT16 uniqueId, Any getter, Any setter, UINT64 flags)
+		{
+			static_assert(sizeof(RTTIPlainType<DataType>::id) > 0, "Type has no RTTI ID."); // Just making sure provided type has a type ID
+
+			static_assert((RTTIPlainType<DataType>::hasDynamicSize != 0 || (sizeof(DataType) <= 255)), 
+				"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.");
+
+			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_Plain, flags);
+		}
+
+		/**
+		 * Initializes a plain field containing multiple values in an array. 
+		 *
+		 * @param[in]	name		Name of the field.
+		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *							small data type that can be used for efficiently serializing data to disk and similar. 
+		 *							It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  	The getter method for the field. Must be a specific signature: DataType(ObjectType*, UINT32)
+		 * @param[in]	getSize 	Getter method that returns the size of an array. Must be a specific signature: UINT32(ObjectType*)
+		 * @param[in]	setter  	The setter method for the field. Must be a specific signature: void(ObjectType*, UINT32, DataType)
+		 * @param[in]	setSize 	Setter method that allows you to resize an array. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
+		 * @param[in]	flags		Various flags you can use to specialize how outside systems handle this field. See "RTTIFieldFlag".
+		 */
+		void initArray(const String& name, UINT16 uniqueId, Any getter,
+			Any getSize, Any setter, Any setSize, UINT64 flags)
+		{
+			int typeId = RTTIPlainType<DataType>::id; // Just making sure provided type has a type ID
+
+			static_assert((RTTIPlainType<DataType>::hasDynamicSize != 0 || (sizeof(DataType) <= 255)), 
+				"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.");
+
+			initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_Plain, flags);
+		}
+
+		/** @copydoc RTTIField::getTypeSize */
+		UINT32 getTypeSize() override
+		{
+			return sizeof(DataType);
+		}
+
+		/** @copydoc RTTIPlainFieldBase::getTypeId */
+		UINT32 getTypeId() override
+		{
+			return RTTIPlainType<DataType>::id;
+		}
+
+		/** @copydoc RTTIPlainFieldBase::hasDynamicSize */
+		bool hasDynamicSize() override
+		{
+			return RTTIPlainType<DataType>::hasDynamicSize != 0;
+		}
+
+		/** @copydoc RTTIPlainFieldBase::getDynamicSize */
+		UINT32 getDynamicSize(void* object) override
+		{
+			checkIsArray(false);
+			checkType<DataType>();
+
+			ObjectType* castObject = static_cast<ObjectType*>(object);
+
+			std::function<DataType&(ObjectType*)> f = any_cast<std::function<DataType&(ObjectType*)>>(valueGetter);
+			DataType value = f(castObject);
+
+			return RTTIPlainType<DataType>::getDynamicSize(value);
+		}
+
+		/** @copydoc RTTIPlainFieldBase::getArrayElemDynamicSize */
+		UINT32 getArrayElemDynamicSize(void* object, int index) override
+		{
+			checkIsArray(true);
+			checkType<DataType>();
+
+			ObjectType* castObject = static_cast<ObjectType*>(object);
+
+			std::function<DataType&(ObjectType*, UINT32)> f = any_cast<std::function<DataType&(ObjectType*, UINT32)>>(valueGetter);
+			DataType value = f(castObject, index);
+
+			return RTTIPlainType<DataType>::getDynamicSize(value);
+		}
+
+		/** Returns the size of the array managed by the field. */
+		UINT32 getArraySize(void* object) override
+		{
+			checkIsArray(true);
+
+			std::function<UINT32(ObjectType*)> f = any_cast<std::function<UINT32(ObjectType*)>>(arraySizeGetter);
+			ObjectType* castObject = static_cast<ObjectType*>(object);
+			return f(castObject);
+		}
+
+		/** Changes the size of the array managed by the field. Array must be re-populated after. */
+		void setArraySize(void* object, UINT32 size) override
+		{
+			checkIsArray(true);
+
+			if(arraySizeSetter.empty())
+			{
+				BS_EXCEPT(InternalErrorException, "Specified field (" + mName + ") has no array size setter.");
+			}
+
+			std::function<void(ObjectType*, UINT32)> f = any_cast<std::function<void(ObjectType*, UINT32)>>(arraySizeSetter);
+			ObjectType* castObject = static_cast<ObjectType*>(object);
+			f(castObject, size);
+		}
+
+		/** @copydoc RTTIPlainFieldBase::toBuffer */
+		void toBuffer(void* object, void* buffer) override
+		{
+			checkIsArray(false);
+			checkType<DataType>();
+
+			ObjectType* castObject = static_cast<ObjectType*>(object);
+
+			std::function<DataType&(ObjectType*)> f = any_cast<std::function<DataType&(ObjectType*)>>(valueGetter);
+			DataType value = f(castObject);
+
+			RTTIPlainType<DataType>::toMemory(value, (char*)buffer);
+		}
+
+		/** @copydoc RTTIPlainFieldBase::arrayElemToBuffer */
+		void arrayElemToBuffer(void* object, int index, void* buffer) override
+		{
+			checkIsArray(true);
+			checkType<DataType>();
+
+			ObjectType* castObject = static_cast<ObjectType*>(object);
+
+			std::function<DataType&(ObjectType*, UINT32)> f = any_cast<std::function<DataType&(ObjectType*, UINT32)>>(valueGetter);
+			DataType value = f(castObject, index);
+
+			RTTIPlainType<DataType>::toMemory(value, (char*)buffer);
+		}
+
+		/** @copydoc RTTIPlainFieldBase::fromBuffer */
+		void fromBuffer(void* object, void* buffer) override
+		{
+			checkIsArray(false);
+			checkType<DataType>();
+
+			ObjectType* castObject = static_cast<ObjectType*>(object);
+
+			DataType value;
+			RTTIPlainType<DataType>::fromMemory(value, (char*)buffer);
+
+			if(valueSetter.empty())
+			{
+				BS_EXCEPT(InternalErrorException,
+					"Specified field (" + mName + ") has no setter.");
+			}
+
+			std::function<void(ObjectType*, DataType&)> f = any_cast<std::function<void(ObjectType*, DataType&)>>(valueSetter);
+			f(castObject, value);
+		}
+
+		/** @copydoc RTTIPlainFieldBase::arrayElemFromBuffer */
+		void arrayElemFromBuffer(void* object, int index, void* buffer) override
+		{
+			checkIsArray(true);
+			checkType<DataType>();
+
+			ObjectType* castObject = static_cast<ObjectType*>(object);
+
+			DataType value;
+			RTTIPlainType<DataType>::fromMemory(value, (char*)buffer);
+
+			if(valueSetter.empty())
+			{
+				BS_EXCEPT(InternalErrorException, 
+					"Specified field (" + mName + ") has no setter.");
+			}
+
+			std::function<void(ObjectType*, UINT32, DataType&)> f = any_cast<std::function<void(ObjectType*, UINT32, DataType&)>>(valueSetter);
+			f(castObject, index, value);
+		}
+	};
+
+	/** @} */
+	/** @} */
 }

+ 616 - 616
Source/BansheeUtility/Include/BsRTTIPrerequisites.h

@@ -1,617 +1,617 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-namespace BansheeEngine
-{
-	/** @addtogroup Utility 
-	 *  @{
-	 */
-
-	/** @addtogroup RTTI
-	 *  @{
-	 */
-
-	/**
-	 * Helper method when serializing known data types that have valid
-	 * RTTIPlainType specialization.
-	 * 			
-	 * Returns the size of the element. If elements serializable type is 
-	 * specialized with hasDynamicSize == true, the dynamic size is calculated, 
-	 * otherwise sizeof() is used.
-	 */
-	template<class ElemType>
-	UINT32 rttiGetElemSize(const ElemType& data)
-	{
-		if(RTTIPlainType<ElemType>::hasDynamicSize == 1)
-			return RTTIPlainType<ElemType>::getDynamicSize(data);
-		else
-			return sizeof(ElemType);
-	}
-
-	/**
-	 * Helper method when serializing known data types that have valid
-	 * RTTIPlainType specialization.
-	 * 			
-	 * Writes the specified data into memory, advances the memory pointer by the
-	 * bytes written and returns pointer to new memory.
-	 */
-	template<class ElemType>
-	char* rttiWriteElem(const ElemType& data, char* memory)
-	{
-		RTTIPlainType<ElemType>::toMemory(data, memory);
-
-		return memory + rttiGetElemSize(data);
-	}
-
-	/**
-	 * Helper method when serializing known data types that have valid
-	 * RTTIPlainType specialization.
-	 * 			
-	 * Writes the specified data into memory, advances the memory pointer by the
-	 * bytes written and returns pointer to new memory. Also increases the size 
-	 * value by the size of the written element.
-	 */
-	template<class ElemType>
-	char* rttiWriteElem(const ElemType& data, char* memory, UINT32& size)
-	{
-		RTTIPlainType<ElemType>::toMemory(data, memory);
-
-		UINT32 elemSize = rttiGetElemSize(data);
-		size += elemSize;
-
-		return memory + elemSize;
-	}
-
-	/**
-	 * Helper method when serializing known data types that have valid
-	 * RTTIPlainType specialization.
-	 * 			
-	 * Reads the specified data into memory, advances the memory pointer by the
-	 * bytes read and returns pointer to new memory.
-	 */
-	template<class ElemType>
-	char* rttiReadElem(ElemType& data, char* memory)
-	{
-		RTTIPlainType<ElemType>::fromMemory(data, memory);
-
-		return memory + rttiGetElemSize(data);
-	}
-
-	/**
-	 * Helper method when serializing known data types that have valid
-	 * RTTIPlainType specialization.
-	 * 			
-	 * Reads the specified data into memory, advances the memory pointer by the
-	 * bytes read and returns pointer to new memory. Also increases the size 
-	 * value by the size of the read element.
-	 */
-	template<class ElemType>
-	char* rttiReadElem(ElemType& data, char* memory, UINT32& size)
-	{
-		RTTIPlainType<ElemType>::fromMemory(data, memory);
-
-		UINT32 elemSize = rttiGetElemSize(data);
-		size += elemSize;
-
-		return memory + elemSize;
-	}
-
-	/**
-	 * Template that you may specialize with a class if you want to provide simple serialization for it. 
-	 * 			
-	 * Any type that uses the "plain" field in the RTTI system must specialize this class.
-	 * 			
-	 * @note	
-	 * Normally you will want to implement IReflectable interface if you want to provide serialization
-	 * as that interface properly handles versioning, nested objects, pointer handling and more.
-	 *
-	 * @note			
-	 * This class is useful for types you can easily serialize using a memcpy (built-in types like int/float/etc), or
-	 * types you cannot modify so they implement IReflectable interface (like std::string or std::vector).
-	 *			
-	 * @see		RTTITypeBase
-	 * @see		RTTIField
-	 */
-	template<class T>
-	struct RTTIPlainType 
-	{ 
-		static_assert(std::is_pod<T>::value, 
-			"Provided type isn't plain-old-data. You need to specialize RTTIPlainType template in order to serialize this type. "\
-			" (Or call BS_ALLOW_MEMCPY_SERIALIZATION(type) macro if you are sure the type can be properly serialized using just memcpy.)");
-
-		enum { id = 0 /**< Unique id for the serializable type. */ }; 
-		enum { hasDynamicSize = 0 /**< 0 (Object has static size less than 255 bytes, e.g. int) or 1 (Dynamic size with no size restriction, e.g. string) */ };
-
-		/** Serializes the provided object into the provided pre-allocated memory buffer. */
-		static void toMemory(const T& data, char* memory)	
-		{ 
-			memcpy(memory, &data, sizeof(T)); 
-		}
-
-		/** 
-		 *  Deserializes a previously allocated object from the provided memory buffer. Return the number of bytes read 
-		 *  from the memory buffer.
-		 */
-		static UINT32 fromMemory(T& data, char* memory)
-		{
-			memcpy(&data, memory, sizeof(T)); 
-			return sizeof(T);
-		}
-
-		/** Returns the size of the provided object. (Works for both static and dynamic size types) */
-		static UINT32 getDynamicSize(const T& data)
-		{ 
-			return sizeof(T);
-		}
-	};
-
-	/**
-	 * Tell the RTTI system that the specified type may be serialized just by using a memcpy.
-	 *
-	 * @note	Internally this creates a basic RTTIPlainType specialization for the type.
-	 * 
-	 * @see		RTTIPlainType
-	 */
-#define BS_ALLOW_MEMCPY_SERIALIZATION(type)					\
-	template<> struct RTTIPlainType<type>					\
-	{	enum { id=0 }; enum { hasDynamicSize = 0 };			\
-	static void toMemory(const type& data, char* memory)	\
-	{ memcpy(memory, &data, sizeof(type)); }				\
-	static UINT32 fromMemory(type& data, char* memory)		\
-	{ memcpy(&data, memory, sizeof(type)); return sizeof(type); }	\
-	static UINT32 getDynamicSize(const type& data)			\
-	{ return sizeof(type); }								\
-	}; 
-
-	/** @cond SPECIALIZATIONS */
-
-	/**
-	 * RTTIPlainType for std::vector.
-	 * 			
-	 * @see		RTTIPlainType
-	 */
-	template<class T> struct RTTIPlainType<std::vector<T, StdAlloc<T>>>
-	{	
-		enum { id = TID_Vector }; enum { hasDynamicSize = 1 };
-
-		/** @copydoc RTTIPlainType::toMemory */
-		static void toMemory(const std::vector<T, StdAlloc<T>>& data, char* memory)
-		{ 
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 numElements = (UINT32)data.size();
-			memcpy(memory, &numElements, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size += sizeof(UINT32);
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				UINT32 elementSize = RTTIPlainType<T>::getDynamicSize(*iter);
-				RTTIPlainType<T>::toMemory(*iter, memory);
-
-				memory += elementSize;
-				size += elementSize;
-			}
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/** @copydoc RTTIPlainType::toMemory */
-		static UINT32 fromMemory(std::vector<T, StdAlloc<T>>& data, char* memory)
-		{ 
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			UINT32 numElements;
-			memcpy(&numElements, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			for(UINT32 i = 0; i < numElements; i++)
-			{
-				T element;
-				UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory);
-				data.push_back(element);
-
-				memory += elementSize;
-			}
-
-			return size;
-		}
-
-		/** @copydoc RTTIPlainType::toMemory */
-		static UINT32 getDynamicSize(const std::vector<T, StdAlloc<T>>& data)	
-		{ 
-			UINT64 dataSize = sizeof(UINT32) * 2;
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-				dataSize += RTTIPlainType<T>::getDynamicSize(*iter);		
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}	
-	}; 
-
-	/**
-	 * RTTIPlainType for std::set.
-	 * 			
-	 * @see		RTTIPlainType
-	 */
-	template<class T> struct RTTIPlainType<std::set<T, std::less<T>, StdAlloc<T>>>
-	{	
-		enum { id = TID_Set }; enum { hasDynamicSize = 1 };
-
-		/** @copydoc RTTIPlainType::toMemory */
-		static void toMemory(const std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory)
-		{ 
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 numElements = (UINT32)data.size();
-			memcpy(memory, &numElements, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size += sizeof(UINT32);
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				UINT32 elementSize = RTTIPlainType<T>::getDynamicSize(*iter);
-				RTTIPlainType<T>::toMemory(*iter, memory);
-
-				memory += elementSize;
-				size += elementSize;
-			}
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/** @copydoc RTTIPlainType::toMemory */
-		static UINT32 fromMemory(std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory)
-		{ 
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			UINT32 numElements;
-			memcpy(&numElements, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			for(UINT32 i = 0; i < numElements; i++)
-			{
-				T element;
-				UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory);
-				data.insert(element);
-
-				memory += elementSize;
-			}
-
-			return size;
-		}
-
-		/** @copydoc RTTIPlainType::toMemory */
-		static UINT32 getDynamicSize(const std::set<T, std::less<T>, StdAlloc<T>>& data)
-		{ 
-			UINT64 dataSize = sizeof(UINT32) * 2;
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-				dataSize += RTTIPlainType<T>::getDynamicSize(*iter);		
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}	
-	}; 
-
-	/**
-	 * RTTIPlainType for std::map.
-	 * 			
-	 * @see		RTTIPlainType
-	 */
-	template<class Key, class Value> struct RTTIPlainType<std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>>
-	{	
-		enum { id = TID_Map }; enum { hasDynamicSize = 1 };
-
-		/** @copydoc RTTIPlainType::toMemory */
-		static void toMemory(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
-		{ 
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 numElements = (UINT32)data.size();
-			memcpy(memory, &numElements, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size += sizeof(UINT32);
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(iter->first);
-				RTTIPlainType<Key>::toMemory(iter->first, memory);
-
-				memory += keySize;
-				size += keySize;
-
-				UINT32 valueSize = RTTIPlainType<Value>::getDynamicSize(iter->second);
-				RTTIPlainType<Value>::toMemory(iter->second, memory);
-
-				memory += valueSize;
-				size += valueSize;
-			}
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/** @copydoc RTTIPlainType::fromMemory */
-		static UINT32 fromMemory(std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
-		{ 
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			UINT32 numElements;
-			memcpy(&numElements, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			for(UINT32 i = 0; i < numElements; i++)
-			{
-				Key key;
-				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
-				memory += keySize;
-
-				Value value;
-				UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory);
-				memory += valueSize;
-
-				data[key] = value; 
-			}
-
-			return size;
-		}
-
-		/** @copydoc RTTIPlainType::getDynamicSize */
-		static UINT32 getDynamicSize(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data)	
-		{ 
-			UINT64 dataSize = sizeof(UINT32) * 2;
-
-			for(auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				dataSize += RTTIPlainType<Key>::getDynamicSize(iter->first);		
-				dataSize += RTTIPlainType<Value>::getDynamicSize(iter->second);
-			}
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}	
-	}; 
-
-	/**
-	 * RTTIPlainType for std::unordered_map.
-	 *
-	 * @see		RTTIPlainType
-	 */
-	template<class Key, class Value> 
-	struct RTTIPlainType<std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>>>
-	{
-		enum { id = TID_UnorderedMap }; enum { hasDynamicSize = 1 };
-
-		typedef std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>> MapType;
-
-		/** @copydoc RTTIPlainType::toMemory */
-		static void toMemory(MapType& data, char* memory)
-		{
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 numElements = (UINT32)data.size();
-			memcpy(memory, &numElements, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size += sizeof(UINT32);
-
-			for (auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(iter->first);
-				RTTIPlainType<Key>::toMemory(iter->first, memory);
-
-				memory += keySize;
-				size += keySize;
-
-				UINT32 valueSize = RTTIPlainType<Value>::getDynamicSize(iter->second);
-				RTTIPlainType<Value>::toMemory(iter->second, memory);
-
-				memory += valueSize;
-				size += valueSize;
-			}
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/** @copydoc RTTIPlainType::fromMemory */
-		static UINT32 fromMemory(MapType& data, char* memory)
-		{
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32));
-			memory += sizeof(UINT32);
-
-			UINT32 numElements;
-			memcpy(&numElements, memory, sizeof(UINT32));
-			memory += sizeof(UINT32);
-
-			for (UINT32 i = 0; i < numElements; i++)
-			{
-				Key key;
-				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
-				memory += keySize;
-
-				Value value;
-				UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory);
-				memory += valueSize;
-
-				data[key] = value;
-			}
-
-			return size;
-		}
-
-		/** @copydoc RTTIPlainType::getDynamicSize */
-		static UINT32 getDynamicSize(const MapType& data)
-		{
-			UINT64 dataSize = sizeof(UINT32)* 2;
-
-			for (auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				dataSize += RTTIPlainType<Key>::getDynamicSize(iter->first);
-				dataSize += RTTIPlainType<Value>::getDynamicSize(iter->second);
-			}
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}
-	};
-
-	/**
-	 * RTTIPlainType for std::unordered_set.
-	 *
-	 * @see		RTTIPlainType
-	 */
-	template<class Key> 
-	struct RTTIPlainType<std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>, StdAlloc<Key>>>
-	{
-		enum { id = TID_UnorderedSet }; enum { hasDynamicSize = 1 };
-
-		typedef std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>, StdAlloc<Key>> MapType;
-
-		/** @copydoc RTTIPlainType::toMemory */
-		static void toMemory(MapType& data, char* memory)
-		{
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 numElements = (UINT32)data.size();
-			memcpy(memory, &numElements, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size += sizeof(UINT32);
-
-			for (auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(*iter);
-				RTTIPlainType<Key>::toMemory(*iter, memory);
-
-				memory += keySize;
-				size += keySize;
-			}
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/** @copydoc RTTIPlainType::fromMemory */
-		static UINT32 fromMemory(MapType& data, char* memory)
-		{
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32));
-			memory += sizeof(UINT32);
-
-			UINT32 numElements;
-			memcpy(&numElements, memory, sizeof(UINT32));
-			memory += sizeof(UINT32);
-
-			for (UINT32 i = 0; i < numElements; i++)
-			{
-				Key key;
-				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
-				memory += keySize;
-
-				data.insert(key);
-			}
-
-			return size;
-		}
-
-		/** @copydoc RTTIPlainType::getDynamicSize */
-		static UINT32 getDynamicSize(const MapType& data)
-		{
-			UINT64 dataSize = sizeof(UINT32)* 2;
-
-			for (auto iter = data.begin(); iter != data.end(); ++iter)
-			{
-				dataSize += RTTIPlainType<Key>::getDynamicSize(*iter);
-			}
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}
-	};
-
-	/**
-	 * RTTIPlainType for std::pair.
-	 * 			
-	 * @see		RTTIPlainType
-	 */
-	template<class A, class B> struct RTTIPlainType<std::pair<A, B>>
-	{	
-		enum { id = TID_Pair }; enum { hasDynamicSize = 1 };
-
-		/** @copydoc RTTIPlainType::toMemory */
-		static void toMemory(const std::pair<A, B>& data, char* memory)
-		{ 
-			UINT32 size = sizeof(UINT32);
-			char* memoryStart = memory;
-			memory += sizeof(UINT32);
-
-			UINT32 firstSize = RTTIPlainType<A>::getDynamicSize(data.first);
-			RTTIPlainType<A>::toMemory(data.first, memory);
-
-			memory += firstSize;
-			size += firstSize;
-
-			UINT32 secondSize = RTTIPlainType<B>::getDynamicSize(data.second);
-			RTTIPlainType<B>::toMemory(data.second, memory);
-
-			memory += secondSize;
-			size += secondSize;
-
-			memcpy(memoryStart, &size, sizeof(UINT32));
-		}
-
-		/** @copydoc RTTIPlainType::fromMemory */
-		static UINT32 fromMemory(std::pair<A, B>& data, char* memory)
-		{ 
-			UINT32 size = 0;
-			memcpy(&size, memory, sizeof(UINT32));
-			memory += sizeof(UINT32);
-
-			UINT32 firstSize = RTTIPlainType<A>::fromMemory(data.first, memory);
-			memory += firstSize;
-
-			UINT32 secondSize = RTTIPlainType<B>::fromMemory(data.second, memory);
-			memory += secondSize;
-
-			return size;
-		}
-
-		/** @copydoc RTTIPlainType::getDynamicSize */
-		static UINT32 getDynamicSize(const std::pair<A, B>& data)	
-		{ 
-			UINT64 dataSize = sizeof(UINT32);
-			dataSize += RTTIPlainType<A>::getDynamicSize(data.first);		
-			dataSize += RTTIPlainType<B>::getDynamicSize(data.second);
-
-			assert(dataSize <= std::numeric_limits<UINT32>::max());
-
-			return (UINT32)dataSize;
-		}	
-	}; 
-
-	/** @endcond */
-
-	/** @} */
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+namespace BansheeEngine
+{
+	/** @addtogroup Utility 
+	 *  @{
+	 */
+
+	/** @addtogroup RTTI
+	 *  @{
+	 */
+
+	/**
+	 * Helper method when serializing known data types that have valid
+	 * RTTIPlainType specialization.
+	 * 			
+	 * Returns the size of the element. If elements serializable type is 
+	 * specialized with hasDynamicSize == true, the dynamic size is calculated, 
+	 * otherwise sizeof() is used.
+	 */
+	template<class ElemType>
+	UINT32 rttiGetElemSize(const ElemType& data)
+	{
+		if(RTTIPlainType<ElemType>::hasDynamicSize == 1)
+			return RTTIPlainType<ElemType>::getDynamicSize(data);
+		else
+			return sizeof(ElemType);
+	}
+
+	/**
+	 * Helper method when serializing known data types that have valid
+	 * RTTIPlainType specialization.
+	 * 			
+	 * Writes the specified data into memory, advances the memory pointer by the
+	 * bytes written and returns pointer to new memory.
+	 */
+	template<class ElemType>
+	char* rttiWriteElem(const ElemType& data, char* memory)
+	{
+		RTTIPlainType<ElemType>::toMemory(data, memory);
+
+		return memory + rttiGetElemSize(data);
+	}
+
+	/**
+	 * Helper method when serializing known data types that have valid
+	 * RTTIPlainType specialization.
+	 * 			
+	 * Writes the specified data into memory, advances the memory pointer by the
+	 * bytes written and returns pointer to new memory. Also increases the size 
+	 * value by the size of the written element.
+	 */
+	template<class ElemType>
+	char* rttiWriteElem(const ElemType& data, char* memory, UINT32& size)
+	{
+		RTTIPlainType<ElemType>::toMemory(data, memory);
+
+		UINT32 elemSize = rttiGetElemSize(data);
+		size += elemSize;
+
+		return memory + elemSize;
+	}
+
+	/**
+	 * Helper method when serializing known data types that have valid
+	 * RTTIPlainType specialization.
+	 * 			
+	 * Reads the specified data into memory, advances the memory pointer by the
+	 * bytes read and returns pointer to new memory.
+	 */
+	template<class ElemType>
+	char* rttiReadElem(ElemType& data, char* memory)
+	{
+		RTTIPlainType<ElemType>::fromMemory(data, memory);
+
+		return memory + rttiGetElemSize(data);
+	}
+
+	/**
+	 * Helper method when serializing known data types that have valid
+	 * RTTIPlainType specialization.
+	 * 			
+	 * Reads the specified data into memory, advances the memory pointer by the
+	 * bytes read and returns pointer to new memory. Also increases the size 
+	 * value by the size of the read element.
+	 */
+	template<class ElemType>
+	char* rttiReadElem(ElemType& data, char* memory, UINT32& size)
+	{
+		RTTIPlainType<ElemType>::fromMemory(data, memory);
+
+		UINT32 elemSize = rttiGetElemSize(data);
+		size += elemSize;
+
+		return memory + elemSize;
+	}
+
+	/**
+	 * Template that you may specialize with a class if you want to provide simple serialization for it. 
+	 * 			
+	 * Any type that uses the "plain" field in the RTTI system must specialize this class.
+	 * 			
+	 * @note	
+	 * Normally you will want to implement IReflectable interface if you want to provide serialization
+	 * as that interface properly handles versioning, nested objects, pointer handling and more.
+	 *
+	 * @note			
+	 * This class is useful for types you can easily serialize using a memcpy (built-in types like int/float/etc), or
+	 * types you cannot modify so they implement IReflectable interface (like std::string or std::vector).
+	 *			
+	 * @see		RTTITypeBase
+	 * @see		RTTIField
+	 */
+	template<class T>
+	struct RTTIPlainType 
+	{ 
+		static_assert(std::is_pod<T>::value, 
+			"Provided type isn't plain-old-data. You need to specialize RTTIPlainType template in order to serialize this type. "\
+			" (Or call BS_ALLOW_MEMCPY_SERIALIZATION(type) macro if you are sure the type can be properly serialized using just memcpy.)");
+
+		enum { id = 0 /**< Unique id for the serializable type. */ }; 
+		enum { hasDynamicSize = 0 /**< 0 (Object has static size less than 255 bytes, for example int) or 1 (Dynamic size with no size restriction, for example string) */ };
+
+		/** Serializes the provided object into the provided pre-allocated memory buffer. */
+		static void toMemory(const T& data, char* memory)	
+		{ 
+			memcpy(memory, &data, sizeof(T)); 
+		}
+
+		/** 
+		 *  Deserializes a previously allocated object from the provided memory buffer. Return the number of bytes read 
+		 *  from the memory buffer.
+		 */
+		static UINT32 fromMemory(T& data, char* memory)
+		{
+			memcpy(&data, memory, sizeof(T)); 
+			return sizeof(T);
+		}
+
+		/** Returns the size of the provided object. (Works for both static and dynamic size types) */
+		static UINT32 getDynamicSize(const T& data)
+		{ 
+			return sizeof(T);
+		}
+	};
+
+	/**
+	 * Tell the RTTI system that the specified type may be serialized just by using a memcpy.
+	 *
+	 * @note	Internally this creates a basic RTTIPlainType specialization for the type.
+	 * 
+	 * @see		RTTIPlainType
+	 */
+#define BS_ALLOW_MEMCPY_SERIALIZATION(type)					\
+	template<> struct RTTIPlainType<type>					\
+	{	enum { id=0 }; enum { hasDynamicSize = 0 };			\
+	static void toMemory(const type& data, char* memory)	\
+	{ memcpy(memory, &data, sizeof(type)); }				\
+	static UINT32 fromMemory(type& data, char* memory)		\
+	{ memcpy(&data, memory, sizeof(type)); return sizeof(type); }	\
+	static UINT32 getDynamicSize(const type& data)			\
+	{ return sizeof(type); }								\
+	}; 
+
+	/** @cond SPECIALIZATIONS */
+
+	/**
+	 * RTTIPlainType for std::vector.
+	 * 			
+	 * @see		RTTIPlainType
+	 */
+	template<class T> struct RTTIPlainType<std::vector<T, StdAlloc<T>>>
+	{	
+		enum { id = TID_Vector }; enum { hasDynamicSize = 1 };
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(const std::vector<T, StdAlloc<T>>& data, char* memory)
+		{ 
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 numElements = (UINT32)data.size();
+			memcpy(memory, &numElements, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size += sizeof(UINT32);
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				UINT32 elementSize = RTTIPlainType<T>::getDynamicSize(*iter);
+				RTTIPlainType<T>::toMemory(*iter, memory);
+
+				memory += elementSize;
+				size += elementSize;
+			}
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static UINT32 fromMemory(std::vector<T, StdAlloc<T>>& data, char* memory)
+		{ 
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			UINT32 numElements;
+			memcpy(&numElements, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			for(UINT32 i = 0; i < numElements; i++)
+			{
+				T element;
+				UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory);
+				data.push_back(element);
+
+				memory += elementSize;
+			}
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static UINT32 getDynamicSize(const std::vector<T, StdAlloc<T>>& data)	
+		{ 
+			UINT64 dataSize = sizeof(UINT32) * 2;
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+				dataSize += RTTIPlainType<T>::getDynamicSize(*iter);		
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
+	/**
+	 * RTTIPlainType for std::set.
+	 * 			
+	 * @see		RTTIPlainType
+	 */
+	template<class T> struct RTTIPlainType<std::set<T, std::less<T>, StdAlloc<T>>>
+	{	
+		enum { id = TID_Set }; enum { hasDynamicSize = 1 };
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(const std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory)
+		{ 
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 numElements = (UINT32)data.size();
+			memcpy(memory, &numElements, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size += sizeof(UINT32);
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				UINT32 elementSize = RTTIPlainType<T>::getDynamicSize(*iter);
+				RTTIPlainType<T>::toMemory(*iter, memory);
+
+				memory += elementSize;
+				size += elementSize;
+			}
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static UINT32 fromMemory(std::set<T, std::less<T>, StdAlloc<T>>& data, char* memory)
+		{ 
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			UINT32 numElements;
+			memcpy(&numElements, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			for(UINT32 i = 0; i < numElements; i++)
+			{
+				T element;
+				UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory);
+				data.insert(element);
+
+				memory += elementSize;
+			}
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static UINT32 getDynamicSize(const std::set<T, std::less<T>, StdAlloc<T>>& data)
+		{ 
+			UINT64 dataSize = sizeof(UINT32) * 2;
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+				dataSize += RTTIPlainType<T>::getDynamicSize(*iter);		
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
+	/**
+	 * RTTIPlainType for std::map.
+	 * 			
+	 * @see		RTTIPlainType
+	 */
+	template<class Key, class Value> struct RTTIPlainType<std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>>
+	{	
+		enum { id = TID_Map }; enum { hasDynamicSize = 1 };
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
+		{ 
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 numElements = (UINT32)data.size();
+			memcpy(memory, &numElements, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size += sizeof(UINT32);
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(iter->first);
+				RTTIPlainType<Key>::toMemory(iter->first, memory);
+
+				memory += keySize;
+				size += keySize;
+
+				UINT32 valueSize = RTTIPlainType<Value>::getDynamicSize(iter->second);
+				RTTIPlainType<Value>::toMemory(iter->second, memory);
+
+				memory += valueSize;
+				size += valueSize;
+			}
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::fromMemory */
+		static UINT32 fromMemory(std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
+		{ 
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			UINT32 numElements;
+			memcpy(&numElements, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			for(UINT32 i = 0; i < numElements; i++)
+			{
+				Key key;
+				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
+				memory += keySize;
+
+				Value value;
+				UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory);
+				memory += valueSize;
+
+				data[key] = value; 
+			}
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::getDynamicSize */
+		static UINT32 getDynamicSize(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data)	
+		{ 
+			UINT64 dataSize = sizeof(UINT32) * 2;
+
+			for(auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				dataSize += RTTIPlainType<Key>::getDynamicSize(iter->first);		
+				dataSize += RTTIPlainType<Value>::getDynamicSize(iter->second);
+			}
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
+	/**
+	 * RTTIPlainType for std::unordered_map.
+	 *
+	 * @see		RTTIPlainType
+	 */
+	template<class Key, class Value> 
+	struct RTTIPlainType<std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>>>
+	{
+		enum { id = TID_UnorderedMap }; enum { hasDynamicSize = 1 };
+
+		typedef std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>> MapType;
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(MapType& data, char* memory)
+		{
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 numElements = (UINT32)data.size();
+			memcpy(memory, &numElements, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size += sizeof(UINT32);
+
+			for (auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(iter->first);
+				RTTIPlainType<Key>::toMemory(iter->first, memory);
+
+				memory += keySize;
+				size += keySize;
+
+				UINT32 valueSize = RTTIPlainType<Value>::getDynamicSize(iter->second);
+				RTTIPlainType<Value>::toMemory(iter->second, memory);
+
+				memory += valueSize;
+				size += valueSize;
+			}
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::fromMemory */
+		static UINT32 fromMemory(MapType& data, char* memory)
+		{
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32));
+			memory += sizeof(UINT32);
+
+			UINT32 numElements;
+			memcpy(&numElements, memory, sizeof(UINT32));
+			memory += sizeof(UINT32);
+
+			for (UINT32 i = 0; i < numElements; i++)
+			{
+				Key key;
+				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
+				memory += keySize;
+
+				Value value;
+				UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory);
+				memory += valueSize;
+
+				data[key] = value;
+			}
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::getDynamicSize */
+		static UINT32 getDynamicSize(const MapType& data)
+		{
+			UINT64 dataSize = sizeof(UINT32)* 2;
+
+			for (auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				dataSize += RTTIPlainType<Key>::getDynamicSize(iter->first);
+				dataSize += RTTIPlainType<Value>::getDynamicSize(iter->second);
+			}
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}
+	};
+
+	/**
+	 * RTTIPlainType for std::unordered_set.
+	 *
+	 * @see		RTTIPlainType
+	 */
+	template<class Key> 
+	struct RTTIPlainType<std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>, StdAlloc<Key>>>
+	{
+		enum { id = TID_UnorderedSet }; enum { hasDynamicSize = 1 };
+
+		typedef std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>, StdAlloc<Key>> MapType;
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(MapType& data, char* memory)
+		{
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 numElements = (UINT32)data.size();
+			memcpy(memory, &numElements, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size += sizeof(UINT32);
+
+			for (auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(*iter);
+				RTTIPlainType<Key>::toMemory(*iter, memory);
+
+				memory += keySize;
+				size += keySize;
+			}
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::fromMemory */
+		static UINT32 fromMemory(MapType& data, char* memory)
+		{
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32));
+			memory += sizeof(UINT32);
+
+			UINT32 numElements;
+			memcpy(&numElements, memory, sizeof(UINT32));
+			memory += sizeof(UINT32);
+
+			for (UINT32 i = 0; i < numElements; i++)
+			{
+				Key key;
+				UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
+				memory += keySize;
+
+				data.insert(key);
+			}
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::getDynamicSize */
+		static UINT32 getDynamicSize(const MapType& data)
+		{
+			UINT64 dataSize = sizeof(UINT32)* 2;
+
+			for (auto iter = data.begin(); iter != data.end(); ++iter)
+			{
+				dataSize += RTTIPlainType<Key>::getDynamicSize(*iter);
+			}
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}
+	};
+
+	/**
+	 * RTTIPlainType for std::pair.
+	 * 			
+	 * @see		RTTIPlainType
+	 */
+	template<class A, class B> struct RTTIPlainType<std::pair<A, B>>
+	{	
+		enum { id = TID_Pair }; enum { hasDynamicSize = 1 };
+
+		/** @copydoc RTTIPlainType::toMemory */
+		static void toMemory(const std::pair<A, B>& data, char* memory)
+		{ 
+			UINT32 size = sizeof(UINT32);
+			char* memoryStart = memory;
+			memory += sizeof(UINT32);
+
+			UINT32 firstSize = RTTIPlainType<A>::getDynamicSize(data.first);
+			RTTIPlainType<A>::toMemory(data.first, memory);
+
+			memory += firstSize;
+			size += firstSize;
+
+			UINT32 secondSize = RTTIPlainType<B>::getDynamicSize(data.second);
+			RTTIPlainType<B>::toMemory(data.second, memory);
+
+			memory += secondSize;
+			size += secondSize;
+
+			memcpy(memoryStart, &size, sizeof(UINT32));
+		}
+
+		/** @copydoc RTTIPlainType::fromMemory */
+		static UINT32 fromMemory(std::pair<A, B>& data, char* memory)
+		{ 
+			UINT32 size = 0;
+			memcpy(&size, memory, sizeof(UINT32));
+			memory += sizeof(UINT32);
+
+			UINT32 firstSize = RTTIPlainType<A>::fromMemory(data.first, memory);
+			memory += firstSize;
+
+			UINT32 secondSize = RTTIPlainType<B>::fromMemory(data.second, memory);
+			memory += secondSize;
+
+			return size;
+		}
+
+		/** @copydoc RTTIPlainType::getDynamicSize */
+		static UINT32 getDynamicSize(const std::pair<A, B>& data)	
+		{ 
+			UINT64 dataSize = sizeof(UINT32);
+			dataSize += RTTIPlainType<A>::getDynamicSize(data.first);		
+			dataSize += RTTIPlainType<B>::getDynamicSize(data.second);
+
+			assert(dataSize <= std::numeric_limits<UINT32>::max());
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
+	/** @endcond */
+
+	/** @} */
+	/** @} */
 }

+ 6 - 3
Source/BansheeUtility/Include/BsRTTIReflectableField.h

@@ -8,8 +8,11 @@
 
 namespace BansheeEngine
 {
-	/** @cond INTERNAL */
-	/** @addtogroup RTTI
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup RTTI-Internal
 	 *  @{
 	 */
 
@@ -203,5 +206,5 @@ namespace BansheeEngine
 	};
 
 	/** @} */
-	/** @endcond */
+	/** @} */
 }

+ 231 - 228
Source/BansheeUtility/Include/BsRTTIReflectablePtrField.h

@@ -1,229 +1,232 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsRTTIField.h"
-#include "BsIReflectable.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup RTTI
-	 *  @{
-	 */
-
-	/**
-	 * Base class containing common functionality for a reflectable pointer class field. 
-	 * 			
-	 * @note	
-	 * Reflectable fields are fields containing complex types deriving from IReflectable. They are serialized recursively 
-	 * and you may add/remove fields from them without breaking the serialized data.
-	 * @note
-	 * ReflectablePtr fields are different from Reflectable fields because other types may reference the same Reflectable 
-	 * object using a ReflectablePtr, while normal Reflectable fields are only referenced by a single field they're declared on.
-	 */
-	struct RTTIReflectablePtrFieldBase : public RTTIField
-	{
-		/**
-		 * Retrieves the IReflectable value from the provided instance.
-		 * 			
-		 * @note	Field type must not be an array.
-		 */
-		virtual std::shared_ptr<IReflectable> getValue(void* object) = 0;
-
-		/**
-		 * Retrieves the IReflectable value from an array on the provided instance and index.
-		 * 			
-		 * @note	Field type must be an array.
-		 */
-		virtual std::shared_ptr<IReflectable> getArrayValue(void* object, UINT32 index) = 0;
-
-		/**
-		 * Sets the IReflectable value in the provided instance.
-		 * 			
-		 * @note	Field type must not be an array.
-		 */
-		virtual void setValue(void* object, std::shared_ptr<IReflectable> value) = 0;
-
-		/**
-		 * Sets the IReflectable value in an array on the provided instance and index.
-		 * 			
-		 * @note	Field type must be an array.
-		 */
-		virtual void setArrayValue(void* object, UINT32 index, std::shared_ptr<IReflectable> value) = 0;
-
-		/** Creates a new object of the field type. */
-		virtual std::shared_ptr<IReflectable> newObject() = 0;
-
-		/** Returns the RTTI identifier of the class owning the field. */
-		virtual UINT32 getRTTIId() = 0;
-
-		/** Returns the name of the class owning the field. */
-		virtual const String& getRTTIName() = 0;
-
-		/** @copydoc RTTIField::hasDynamicSize */
-		bool hasDynamicSize() override { return true; }
-
-		/** Retrieves the RTTI object for the type the field contains. */
-		virtual RTTITypeBase* getType() = 0;
-	};
-
-	/** Reflectable field containing a pointer to a specific type with RTTI implemented.  */
-	template <class DataType, class ObjectType>
-	struct RTTIReflectablePtrField : public RTTIReflectablePtrFieldBase
-	{
-		/**
-		 * Initializes a field pointing to a single data type implementing IReflectable interface.
-		 *
-		 * @param[in]	name		Name of the field.
-		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *							small data type that can be used for efficiently serializing data to disk and similar. 
-		 *							It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  	The getter method for the field. Must be a specific signature: DataType*(ObjectType*)
-		 * @param[in]	setter  	The setter method for the field. Must be a specific signature: void(ObjectType*, DataType*)
-		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See "RTTIFieldFlag".
-		 */
-		void initSingle(const String& name, UINT16 uniqueId, Any getter, Any setter, UINT64 flags)
-		{
-			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_ReflectablePtr, flags);
-		}
-
-		/**
-		 * Initializes a field containing an array of pointers to data types implementing IReflectable interface.
-		 *
-		 * @param[in]	name		Name of the field.
-		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *							small data type that can be used for efficiently serializing data to disk and similar. 
-		 *							It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  	The getter method for the field. Must be a specific signature: DataType*(ObjectType*, UINT32)
-		 * @param[in]	getSize 	Getter method that returns the size of an array. Must be a specific signature: UINT32(ObjectType*)
-		 * @param[in]	setter  	The setter method for the field. Must be a specific signature: void(ObjectType*, UINT32, DataType*)
-		 * @param[in]	setSize 	Setter method that allows you to resize an array. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
-		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See "RTTIFieldFlag".
-		 */
-		void initArray(const String& name, UINT16 uniqueId, Any getter,
-			Any getSize, Any setter, Any setSize, UINT64 flags)
-		{
-			initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_ReflectablePtr, flags);
-		}
-
-		/** @copydoc RTTIField::getTypeSize */
-		UINT32 getTypeSize() override
-		{
-			return 0; // Complex types don't store size the conventional way
-		}
-
-		/** @copydoc RTTIReflectablePtrFieldBase::getValue */
-		std::shared_ptr<IReflectable> getValue(void* object) override
-		{
-			checkIsArray(false);
-
-			ObjectType* castObjType = static_cast<ObjectType*>(object);
-			std::function<std::shared_ptr<DataType>(ObjectType*)> f = any_cast<std::function<std::shared_ptr<DataType>(ObjectType*)>>(valueGetter);
-			std::shared_ptr<IReflectable> castDataType = f(castObjType);
-
-			return castDataType;
-		}
-
-		/** @copydoc RTTIReflectablePtrFieldBase::getArrayValue */
-		std::shared_ptr<IReflectable> getArrayValue(void* object, UINT32 index) override
-		{
-			checkIsArray(true);
-
-			ObjectType* castObjType = static_cast<ObjectType*>(object);
-			std::function<std::shared_ptr<DataType>(ObjectType*, UINT32)> f = any_cast<std::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>>(valueGetter);
-
-			std::shared_ptr<IReflectable> castDataType = f(castObjType, index);
-			return castDataType;
-		}
-
-		/** @copydoc RTTIReflectablePtrFieldBase::setValue */
-		void setValue(void* object, std::shared_ptr<IReflectable> value) override
-		{
-			checkIsArray(false);
-
-			if(valueSetter.empty())
-			{
-				BS_EXCEPT(InternalErrorException,
-					"Specified field (" + mName + ") has no setter.");
-			}
-
-			ObjectType* castObjType = static_cast<ObjectType*>(object);
-			std::shared_ptr<DataType> castDataObj = std::static_pointer_cast<DataType>(value);
-			std::function<void(ObjectType*, std::shared_ptr<DataType>)> f = any_cast<std::function<void(ObjectType*, std::shared_ptr<DataType>)>>(valueSetter);
-			f(castObjType, castDataObj);
-		}
-
-		/** @copydoc RTTIReflectablePtrFieldBase::setArrayValue */
-		void setArrayValue(void* object, UINT32 index, std::shared_ptr<IReflectable> value) override
-		{
-			checkIsArray(true);
-
-			if(valueSetter.empty())
-			{
-				BS_EXCEPT(InternalErrorException, 
-					"Specified field (" + mName + ") has no setter.");
-			}
-
-			ObjectType* castObjType = static_cast<ObjectType*>(object);
-			std::shared_ptr<DataType> castDataObj = std::static_pointer_cast<DataType>(value);
-			std::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)> f = any_cast<std::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>>(valueSetter);
-			f(castObjType, index, castDataObj);
-		}
-
-		/** @copydoc RTTIField::setArraySize */
-		UINT32 getArraySize(void* object) override
-		{
-			checkIsArray(true);
-
-			std::function<UINT32(ObjectType*)> f = any_cast<std::function<UINT32(ObjectType*)>>(arraySizeGetter);
-			ObjectType* castObject = static_cast<ObjectType*>(object);
-			return f(castObject);
-		}
-
-		/** @copydoc RTTIField::setArraySize */
-		void setArraySize(void* object, UINT32 size) override
-		{
-			checkIsArray(true);
-
-			if(arraySizeSetter.empty())
-			{
-				BS_EXCEPT(InternalErrorException, 
-					"Specified field (" + mName + ") has no array size setter.");
-			}
-
-			std::function<void(ObjectType*, UINT32)> f = any_cast<std::function<void(ObjectType*, UINT32)>>(arraySizeSetter);
-			ObjectType* castObject = static_cast<ObjectType*>(object);
-			f(castObject, size);
-		}
-
-		/** @copydoc RTTIReflectablePtrFieldBase::newObject */
-		std::shared_ptr<IReflectable> newObject() override
-		{
-			return std::shared_ptr<IReflectable>(DataType::getRTTIStatic()->newRTTIObject());
-		}
-
-		/** @copydoc RTTIReflectablePtrFieldBase::getRTTIId */
-		UINT32 getRTTIId() override
-		{
-			return DataType::getRTTIStatic()->getRTTIId();
-		}
-
-		/** @copydoc RTTIReflectablePtrFieldBase::getRTTIName */
-		const String& getRTTIName() override
-		{
-			return DataType::getRTTIStatic()->getRTTIName();
-		}
-
-
-		/** @copydoc RTTIReflectablePtrFieldBase::getType */
-		RTTITypeBase* getType() override
-		{
-			return DataType::getRTTIStatic();
-		}
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsRTTIField.h"
+#include "BsIReflectable.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup RTTI-Internal
+	 *  @{
+	 */
+
+	/**
+	 * Base class containing common functionality for a reflectable pointer class field. 
+	 * 			
+	 * @note	
+	 * Reflectable fields are fields containing complex types deriving from IReflectable. They are serialized recursively 
+	 * and you may add/remove fields from them without breaking the serialized data.
+	 * @note
+	 * ReflectablePtr fields are different from Reflectable fields because other types may reference the same Reflectable 
+	 * object using a ReflectablePtr, while normal Reflectable fields are only referenced by a single field they're declared on.
+	 */
+	struct RTTIReflectablePtrFieldBase : public RTTIField
+	{
+		/**
+		 * Retrieves the IReflectable value from the provided instance.
+		 * 			
+		 * @note	Field type must not be an array.
+		 */
+		virtual std::shared_ptr<IReflectable> getValue(void* object) = 0;
+
+		/**
+		 * Retrieves the IReflectable value from an array on the provided instance and index.
+		 * 			
+		 * @note	Field type must be an array.
+		 */
+		virtual std::shared_ptr<IReflectable> getArrayValue(void* object, UINT32 index) = 0;
+
+		/**
+		 * Sets the IReflectable value in the provided instance.
+		 * 			
+		 * @note	Field type must not be an array.
+		 */
+		virtual void setValue(void* object, std::shared_ptr<IReflectable> value) = 0;
+
+		/**
+		 * Sets the IReflectable value in an array on the provided instance and index.
+		 * 			
+		 * @note	Field type must be an array.
+		 */
+		virtual void setArrayValue(void* object, UINT32 index, std::shared_ptr<IReflectable> value) = 0;
+
+		/** Creates a new object of the field type. */
+		virtual std::shared_ptr<IReflectable> newObject() = 0;
+
+		/** Returns the RTTI identifier of the class owning the field. */
+		virtual UINT32 getRTTIId() = 0;
+
+		/** Returns the name of the class owning the field. */
+		virtual const String& getRTTIName() = 0;
+
+		/** @copydoc RTTIField::hasDynamicSize */
+		bool hasDynamicSize() override { return true; }
+
+		/** Retrieves the RTTI object for the type the field contains. */
+		virtual RTTITypeBase* getType() = 0;
+	};
+
+	/** Reflectable field containing a pointer to a specific type with RTTI implemented.  */
+	template <class DataType, class ObjectType>
+	struct RTTIReflectablePtrField : public RTTIReflectablePtrFieldBase
+	{
+		/**
+		 * Initializes a field pointing to a single data type implementing IReflectable interface.
+		 *
+		 * @param[in]	name		Name of the field.
+		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *							small data type that can be used for efficiently serializing data to disk and similar. 
+		 *							It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  	The getter method for the field. Must be a specific signature: DataType*(ObjectType*)
+		 * @param[in]	setter  	The setter method for the field. Must be a specific signature: void(ObjectType*, DataType*)
+		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See "RTTIFieldFlag".
+		 */
+		void initSingle(const String& name, UINT16 uniqueId, Any getter, Any setter, UINT64 flags)
+		{
+			initAll(getter, setter, nullptr, nullptr, name, uniqueId, false, SerializableFT_ReflectablePtr, flags);
+		}
+
+		/**
+		 * Initializes a field containing an array of pointers to data types implementing IReflectable interface.
+		 *
+		 * @param[in]	name		Name of the field.
+		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *							small data type that can be used for efficiently serializing data to disk and similar. 
+		 *							It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  	The getter method for the field. Must be a specific signature: DataType*(ObjectType*, UINT32)
+		 * @param[in]	getSize 	Getter method that returns the size of an array. Must be a specific signature: UINT32(ObjectType*)
+		 * @param[in]	setter  	The setter method for the field. Must be a specific signature: void(ObjectType*, UINT32, DataType*)
+		 * @param[in]	setSize 	Setter method that allows you to resize an array. Can be null. Must be a specific signature: void(ObjectType*, UINT32)
+		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See "RTTIFieldFlag".
+		 */
+		void initArray(const String& name, UINT16 uniqueId, Any getter,
+			Any getSize, Any setter, Any setSize, UINT64 flags)
+		{
+			initAll(getter, setter, getSize, setSize, name, uniqueId, true, SerializableFT_ReflectablePtr, flags);
+		}
+
+		/** @copydoc RTTIField::getTypeSize */
+		UINT32 getTypeSize() override
+		{
+			return 0; // Complex types don't store size the conventional way
+		}
+
+		/** @copydoc RTTIReflectablePtrFieldBase::getValue */
+		std::shared_ptr<IReflectable> getValue(void* object) override
+		{
+			checkIsArray(false);
+
+			ObjectType* castObjType = static_cast<ObjectType*>(object);
+			std::function<std::shared_ptr<DataType>(ObjectType*)> f = any_cast<std::function<std::shared_ptr<DataType>(ObjectType*)>>(valueGetter);
+			std::shared_ptr<IReflectable> castDataType = f(castObjType);
+
+			return castDataType;
+		}
+
+		/** @copydoc RTTIReflectablePtrFieldBase::getArrayValue */
+		std::shared_ptr<IReflectable> getArrayValue(void* object, UINT32 index) override
+		{
+			checkIsArray(true);
+
+			ObjectType* castObjType = static_cast<ObjectType*>(object);
+			std::function<std::shared_ptr<DataType>(ObjectType*, UINT32)> f = any_cast<std::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>>(valueGetter);
+
+			std::shared_ptr<IReflectable> castDataType = f(castObjType, index);
+			return castDataType;
+		}
+
+		/** @copydoc RTTIReflectablePtrFieldBase::setValue */
+		void setValue(void* object, std::shared_ptr<IReflectable> value) override
+		{
+			checkIsArray(false);
+
+			if(valueSetter.empty())
+			{
+				BS_EXCEPT(InternalErrorException,
+					"Specified field (" + mName + ") has no setter.");
+			}
+
+			ObjectType* castObjType = static_cast<ObjectType*>(object);
+			std::shared_ptr<DataType> castDataObj = std::static_pointer_cast<DataType>(value);
+			std::function<void(ObjectType*, std::shared_ptr<DataType>)> f = any_cast<std::function<void(ObjectType*, std::shared_ptr<DataType>)>>(valueSetter);
+			f(castObjType, castDataObj);
+		}
+
+		/** @copydoc RTTIReflectablePtrFieldBase::setArrayValue */
+		void setArrayValue(void* object, UINT32 index, std::shared_ptr<IReflectable> value) override
+		{
+			checkIsArray(true);
+
+			if(valueSetter.empty())
+			{
+				BS_EXCEPT(InternalErrorException, 
+					"Specified field (" + mName + ") has no setter.");
+			}
+
+			ObjectType* castObjType = static_cast<ObjectType*>(object);
+			std::shared_ptr<DataType> castDataObj = std::static_pointer_cast<DataType>(value);
+			std::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)> f = any_cast<std::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>>(valueSetter);
+			f(castObjType, index, castDataObj);
+		}
+
+		/** @copydoc RTTIField::setArraySize */
+		UINT32 getArraySize(void* object) override
+		{
+			checkIsArray(true);
+
+			std::function<UINT32(ObjectType*)> f = any_cast<std::function<UINT32(ObjectType*)>>(arraySizeGetter);
+			ObjectType* castObject = static_cast<ObjectType*>(object);
+			return f(castObject);
+		}
+
+		/** @copydoc RTTIField::setArraySize */
+		void setArraySize(void* object, UINT32 size) override
+		{
+			checkIsArray(true);
+
+			if(arraySizeSetter.empty())
+			{
+				BS_EXCEPT(InternalErrorException, 
+					"Specified field (" + mName + ") has no array size setter.");
+			}
+
+			std::function<void(ObjectType*, UINT32)> f = any_cast<std::function<void(ObjectType*, UINT32)>>(arraySizeSetter);
+			ObjectType* castObject = static_cast<ObjectType*>(object);
+			f(castObject, size);
+		}
+
+		/** @copydoc RTTIReflectablePtrFieldBase::newObject */
+		std::shared_ptr<IReflectable> newObject() override
+		{
+			return std::shared_ptr<IReflectable>(DataType::getRTTIStatic()->newRTTIObject());
+		}
+
+		/** @copydoc RTTIReflectablePtrFieldBase::getRTTIId */
+		UINT32 getRTTIId() override
+		{
+			return DataType::getRTTIStatic()->getRTTIId();
+		}
+
+		/** @copydoc RTTIReflectablePtrFieldBase::getRTTIName */
+		const String& getRTTIName() override
+		{
+			return DataType::getRTTIStatic()->getRTTIName();
+		}
+
+
+		/** @copydoc RTTIReflectablePtrFieldBase::getType */
+		RTTITypeBase* getType() override
+		{
+			return DataType::getRTTIStatic();
+		}
+	};
+
+	/** @} */
+	/** @} */
 }

+ 15 - 3
Source/BansheeUtility/Include/BsRTTIType.h

@@ -85,7 +85,14 @@ namespace BansheeEngine
 	addReflectablePtrArrayField(#name, id##, &MyType::get##name, &MyType::getSize##name, \
 	&MyType::set##name, &MyType::setSize##name);
 
-	/** @cond INTERNAL */
+	/** @} */
+
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+	/** @addtogroup RTTI-Internal
+	 *  @{
+	 */
 
 	/**
 	 * Provides an interface for accessing fields of a certain class.
@@ -547,7 +554,12 @@ namespace BansheeEngine
 		RTTITypeBase* operator()() { return nullptr; }
 	};
 
-	/** @endcond */
+	/** @} */
+	/** @} */
+
+	/** @addtogroup RTTI
+	 *  @{
+	 */
 
 	/**
 	 * Allows you to provide a run-time type information for a specific class, along with support for 
@@ -623,7 +635,7 @@ namespace BansheeEngine
 			return false;
 		}
 
-		/** @copydoc	RTTITypeBase::_registerDerivedClass */
+		/** @copydoc RTTITypeBase::_registerDerivedClass */
 		void _registerDerivedClass(RTTITypeBase* derivedClass) override
 		{
 			if(IReflectable::_isTypeIdDuplicate(derivedClass->getRTTIId()))

+ 77 - 76
Source/BansheeUtility/Include/BsSphere.h

@@ -1,77 +1,78 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector3.h"
-
-namespace BansheeEngine 
-{
-	/** @addtogroup Math
-	 *  @{
-	 */
-
-    /** A sphere represented by a center point and a radius. */
-    class BS_UTILITY_EXPORT Sphere
-    {
-    public:
-        /** Default constructor. Creates a unit sphere around the origin. */
-        Sphere() : mRadius(1.0), mCenter(Vector3::ZERO) 
-		{ }
-
-        Sphere(const Vector3& center, float radius)
-            :mRadius(radius), mCenter(center) 
-		{ }
-
-        /** Returns the radius of the sphere. */
-        float getRadius(void) const { return mRadius; }
-
-        /** Sets the radius of the sphere. */
-        void setRadius(float radius) { mRadius = radius; }
-
-        /** Returns the center point of the sphere. */
-        const Vector3& getCenter(void) const { return mCenter; }
-
-        /** Sets the center point of the sphere. */
-        void setCenter(const Vector3& center) { mCenter = center; }
-
-		/** Merges the two spheres, creating a new sphere that encapsulates them both. */
-		void merge(const Sphere& rhs);
-
-		/** Expands the sphere so it includes the provided point. */
-		void merge(const Vector3& point);
-
-		/** Transforms the sphere by the given matrix. */
-		void transform(const Matrix4& matrix);
-
-		/** Returns whether or not this sphere contains the provided point. */
-		inline bool contains(const Vector3& v) const;
-
-		/** Returns whether or not this sphere intersects another sphere. */
-		bool intersects(const Sphere& s) const;
-
-		/** Returns whether or not this sphere intersects a box. */
-		bool intersects(const AABox& box) const;
-
-		/** Returns whether or not this sphere intersects a plane. */
-		bool intersects(const Plane& plane) const;
-
-		/**
-		 * Ray/sphere intersection, returns boolean result and distance to nearest intersection.
-		 * 			
-		 * @param[in]	discardInside	(optional) If true the intersection will be discarded if ray origin
-		 * 								is located within the sphere.
-		 */
-		std::pair<bool, float> intersects(const Ray& ray, bool discardInside = true) const;
-
-	private:
-		float mRadius;
-		Vector3 mCenter;
-    };
-
-	/** @} */
-
-	/** @cond SPECIALIZATIONS */
-	BS_ALLOW_MEMCPY_SERIALIZATION(Sphere);
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine 
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+    /** A sphere represented by a center point and a radius. */
+    class BS_UTILITY_EXPORT Sphere
+    {
+    public:
+        /** Default constructor. Creates a unit sphere around the origin. */
+        Sphere() : mRadius(1.0), mCenter(Vector3::ZERO) 
+		{ }
+
+        Sphere(const Vector3& center, float radius)
+            :mRadius(radius), mCenter(center) 
+		{ }
+
+        /** Returns the radius of the sphere. */
+        float getRadius(void) const { return mRadius; }
+
+        /** Sets the radius of the sphere. */
+        void setRadius(float radius) { mRadius = radius; }
+
+        /** Returns the center point of the sphere. */
+        const Vector3& getCenter(void) const { return mCenter; }
+
+        /** Sets the center point of the sphere. */
+        void setCenter(const Vector3& center) { mCenter = center; }
+
+		/** Merges the two spheres, creating a new sphere that encapsulates them both. */
+		void merge(const Sphere& rhs);
+
+		/** Expands the sphere so it includes the provided point. */
+		void merge(const Vector3& point);
+
+		/** Transforms the sphere by the given matrix. */
+		void transform(const Matrix4& matrix);
+
+		/** Returns whether or not this sphere contains the provided point. */
+		inline bool contains(const Vector3& v) const;
+
+		/** Returns whether or not this sphere intersects another sphere. */
+		bool intersects(const Sphere& s) const;
+
+		/** Returns whether or not this sphere intersects a box. */
+		bool intersects(const AABox& box) const;
+
+		/** Returns whether or not this sphere intersects a plane. */
+		bool intersects(const Plane& plane) const;
+
+		/**
+		 * Ray/sphere intersection, returns boolean result and distance to nearest intersection.
+		 * 			
+		 * @param[in]	ray				Ray to intersect with the sphere.
+		 * @param[in]	discardInside	(optional) If true the intersection will be discarded if ray origin
+		 * 								is located within the sphere.
+		 */
+		std::pair<bool, float> intersects(const Ray& ray, bool discardInside = true) const;
+
+	private:
+		float mRadius;
+		Vector3 mCenter;
+    };
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Sphere);
+	/** @endcond */
 }

+ 268 - 266
Source/BansheeUtility/Include/BsStaticAlloc.h

@@ -1,267 +1,269 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-
-	/** @addtogroup Memory
-	 *  @{
-	 */
-
-	/**
-	 * Static allocator that attempts to perform zero heap allocations by always keeping an active stack-allocated buffer. 
-	 * If the size of allocated data goes over the set limit dynamic allocations will occur however.
-	 *
-	 * @note	This kind of allocator is only able to free all of its memory at once. Freeing individual elements
-	 *			will not free the memory until a call to clear().
-	 * 			
-	 * @tparam	BlockSize			Size of the initially allocated static block, and minimum size of any dynamically allocated memory.
-	 * @tparam	MaxDynamicMemory	Maximum amount of unused memory allowed in the buffer after a call to clear(). Keeping active dynamic 
-	 *								buffers can help prevent further memory allocations at the cost of memory. This is not relevant
-	 *								if you stay within the bounds of the statically allocated memory.
-	 */
-	template<int BlockSize = 512, int MaxDynamicMemory = 512>
-	class StaticAlloc
-	{
-	private:
-		/** A single block of memory within a static allocator. */
-		class MemBlock
-		{
-		public:
-			MemBlock(UINT8* data, UINT32 size) 
-				:mData(data), mFreePtr(0), mSize(size),
-				mPrevBlock(nullptr), mNextBlock(nullptr)
-			{ }
-
-			/** Allocates a piece of memory within the block. Caller must ensure the block has enough empty space. */
-			UINT8* alloc(UINT32 amount)
-			{
-				UINT8* freePtr = &mData[mFreePtr];
-				mFreePtr += amount;
-
-				return freePtr;
-			}
-
-			/** Releases all allocations within a block but doesn't actually free the memory. */
-			void clear()
-			{
-				mFreePtr = 0;
-			}
-
-			UINT8* mData;
-			UINT32 mFreePtr;
-			UINT32 mSize;
-			MemBlock* mPrevBlock;
-			MemBlock* mNextBlock;
-		};
-
-	public:
-		StaticAlloc()
-			:mStaticBlock(mStaticData, BlockSize), mFreeBlock(&mStaticBlock),
-			mTotalAllocBytes(0)
-		{
-
-		}
-
-		~StaticAlloc()
-		{
-			assert(mFreeBlock == &mStaticBlock && mStaticBlock.mFreePtr == 0);
-
-			freeBlocks(mFreeBlock);
-		}
-
-		/**
-		 * Allocates a new piece of memory of the specified size.
-		 *
-		 * @param[in]	amount	Amount of memory to allocate, in bytes.
-		 */
-		UINT8* alloc(UINT32 amount)
-		{
-			if (amount == 0)
-				return nullptr;
-
-#if BS_DEBUG_MODE
-			amount += sizeof(UINT32);
-#endif
-
-			UINT32 freeMem = mFreeBlock->mSize - mFreeBlock->mFreePtr;
-			if (amount > freeMem)
-				allocBlock(amount);
-
-			UINT8* data = mFreeBlock->alloc(amount);
-
-#if BS_DEBUG_MODE
-			mTotalAllocBytes += amount;
-
-			UINT32* storedSize = reinterpret_cast<UINT32*>(data);
-			*storedSize = amount;
-
-			return data + sizeof(UINT32);
-#else
-			return data;
-#endif
-		}
-
-		/** Deallocates a previously allocated piece of memory. */
-		void free(void* data)
-		{
-			if (data == nullptr)
-				return;
-
-			// Dealloc is only used for debug and can be removed if needed. All the actual deallocation
-			// happens in clear()
-
-#if BS_DEBUG_MODE
-			UINT8* dataPtr = (UINT8*)data;
-			dataPtr -= sizeof(UINT32);
-
-			UINT32* storedSize = (UINT32*)(dataPtr);
-			mTotalAllocBytes -= *storedSize;
-#endif
-		}
-
-		/**
-		 * Allocates enough memory to hold the object(s) of specified type using the static allocator, and constructs them.
-		 */
-		template<class T>
-		T* construct(UINT32 count = 0)
-		{
-			T* data = (T*)alloc(sizeof(T) * count);
-
-			for(unsigned int i = 0; i < count; i++)
-				new ((void*)&data[i]) T;
-
-			return data;
-		}
-
-		/**
-		 * Allocates enough memory to hold the object(s) of specified type using the static allocator, and constructs them.
-		 */
-		template<class T, class... Args>
-		T* construct(Args &&...args, UINT32 count = 0)
-		{
-			T* data = (T*)alloc(sizeof(T) * count);
-
-			for(unsigned int i = 0; i < count; i++)
-				new ((void*)&data[i]) T(std::forward<Args>(args)...);
-
-			return data;
-		}
-
-		/** Destructs and deallocates an object allocated with the static allocator. */
-		template<class T>
-		void destruct(T* data)
-		{
-			data->~T();
-
-			free(data);
-		}
-
-		/** Destructs and deallocates an array of objects allocated with the static frame allocator. */
-		template<class T>
-		void destruct(T* data, UINT32 count)
-		{
-			for(unsigned int i = 0; i < count; i++)
-				data[i].~T();
-
-			free(data);
-		}
-
-		/** Frees the internal memory buffers. All external allocations must be freed before calling this. */
-		void clear()
-		{
-			assert(mTotalAllocBytes == 0);
-
-			MemBlock* dynamicBlock = mStaticBlock.mNextBlock;
-			INT32 totalDynamicMemAmount = 0;
-			UINT32 numDynamicBlocks = 0;
-
-			while (dynamicBlock != nullptr)
-			{
-				totalDynamicMemAmount += dynamicBlock->mFreePtr;
-				dynamicBlock->clear();
-			
-				dynamicBlock = dynamicBlock->mNextBlock;
-				numDynamicBlocks++;
-			}
-
-			mFreeBlock = &mStaticBlock;
-			mStaticBlock.clear();
-
-			if (numDynamicBlocks > 1)
-			{
-				freeBlocks(&mStaticBlock);
-				allocBlock(std::min(totalDynamicMemAmount, MaxDynamicMemory));
-				mFreeBlock = &mStaticBlock;
-			}
-			else if (numDynamicBlocks == 1 && MaxDynamicMemory == 0)
-			{
-				freeBlocks(&mStaticBlock);
-			}
-		}
-
-	private:
-		UINT8 mStaticData[BlockSize];
-		MemBlock mStaticBlock;
-
-		MemBlock* mFreeBlock;
-		UINT32 mTotalAllocBytes;
-
-		/**
-		 * Allocates a dynamic block of memory of the wanted size. The exact allocation size might be slightly higher in 
-		 * order to store block meta data.
-		 */
-		MemBlock* allocBlock(UINT32 wantedSize)
-		{
-			UINT32 blockSize = BlockSize;
-			if (wantedSize > blockSize)
-				blockSize = wantedSize;
-
-			MemBlock* dynamicBlock = mFreeBlock->mNextBlock;
-			MemBlock* newBlock = nullptr;
-			while (dynamicBlock != nullptr)
-			{
-				if (dynamicBlock->mSize >= blockSize)
-				{
-					newBlock = dynamicBlock;
-					break;
-				}
-
-				dynamicBlock = dynamicBlock->mNextBlock;
-			}
-
-			if (newBlock == nullptr)
-			{
-				UINT8* data = (UINT8*)reinterpret_cast<UINT8*>(bs_alloc(blockSize + sizeof(MemBlock)));
-				newBlock = new (data)MemBlock(data + sizeof(MemBlock), blockSize);
-				newBlock->mPrevBlock = mFreeBlock;
-				mFreeBlock->mNextBlock = newBlock;
-			}
-
-			mFreeBlock = newBlock;
-			return newBlock;
-		}
-
-		/** Releases memory for any dynamic blocks following the provided block (if there are any). */
-		void freeBlocks(MemBlock* start)
-		{
-			MemBlock* dynamicBlock = start->mNextBlock;
-			while (dynamicBlock != nullptr)
-			{
-				MemBlock* nextBlock = dynamicBlock->mNextBlock;
-
-				dynamicBlock->~MemBlock();
-				bs_free(dynamicBlock);
-
-				dynamicBlock = nextBlock;
-			}
-
-			start->mNextBlock = nullptr;
-		}
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Memory-Internal
+	 *  @{
+	 */
+
+	/**
+	 * Static allocator that attempts to perform zero heap allocations by always keeping an active stack-allocated buffer. 
+	 * If the size of allocated data goes over the set limit dynamic allocations will occur however.
+	 *
+	 * @note	This kind of allocator is only able to free all of its memory at once. Freeing individual elements
+	 *			will not free the memory until a call to clear().
+	 * 			
+	 * @tparam	BlockSize			Size of the initially allocated static block, and minimum size of any dynamically allocated memory.
+	 * @tparam	MaxDynamicMemory	Maximum amount of unused memory allowed in the buffer after a call to clear(). Keeping active dynamic 
+	 *								buffers can help prevent further memory allocations at the cost of memory. This is not relevant
+	 *								if you stay within the bounds of the statically allocated memory.
+	 */
+	template<int BlockSize = 512, int MaxDynamicMemory = 512>
+	class StaticAlloc
+	{
+	private:
+		/** A single block of memory within a static allocator. */
+		class MemBlock
+		{
+		public:
+			MemBlock(UINT8* data, UINT32 size) 
+				:mData(data), mFreePtr(0), mSize(size),
+				mPrevBlock(nullptr), mNextBlock(nullptr)
+			{ }
+
+			/** Allocates a piece of memory within the block. Caller must ensure the block has enough empty space. */
+			UINT8* alloc(UINT32 amount)
+			{
+				UINT8* freePtr = &mData[mFreePtr];
+				mFreePtr += amount;
+
+				return freePtr;
+			}
+
+			/** Releases all allocations within a block but doesn't actually free the memory. */
+			void clear()
+			{
+				mFreePtr = 0;
+			}
+
+			UINT8* mData;
+			UINT32 mFreePtr;
+			UINT32 mSize;
+			MemBlock* mPrevBlock;
+			MemBlock* mNextBlock;
+		};
+
+	public:
+		StaticAlloc()
+			:mStaticBlock(mStaticData, BlockSize), mFreeBlock(&mStaticBlock),
+			mTotalAllocBytes(0)
+		{
+
+		}
+
+		~StaticAlloc()
+		{
+			assert(mFreeBlock == &mStaticBlock && mStaticBlock.mFreePtr == 0);
+
+			freeBlocks(mFreeBlock);
+		}
+
+		/**
+		 * Allocates a new piece of memory of the specified size.
+		 *
+		 * @param[in]	amount	Amount of memory to allocate, in bytes.
+		 */
+		UINT8* alloc(UINT32 amount)
+		{
+			if (amount == 0)
+				return nullptr;
+
+#if BS_DEBUG_MODE
+			amount += sizeof(UINT32);
+#endif
+
+			UINT32 freeMem = mFreeBlock->mSize - mFreeBlock->mFreePtr;
+			if (amount > freeMem)
+				allocBlock(amount);
+
+			UINT8* data = mFreeBlock->alloc(amount);
+
+#if BS_DEBUG_MODE
+			mTotalAllocBytes += amount;
+
+			UINT32* storedSize = reinterpret_cast<UINT32*>(data);
+			*storedSize = amount;
+
+			return data + sizeof(UINT32);
+#else
+			return data;
+#endif
+		}
+
+		/** Deallocates a previously allocated piece of memory. */
+		void free(void* data)
+		{
+			if (data == nullptr)
+				return;
+
+			// Dealloc is only used for debug and can be removed if needed. All the actual deallocation
+			// happens in clear()
+
+#if BS_DEBUG_MODE
+			UINT8* dataPtr = (UINT8*)data;
+			dataPtr -= sizeof(UINT32);
+
+			UINT32* storedSize = (UINT32*)(dataPtr);
+			mTotalAllocBytes -= *storedSize;
+#endif
+		}
+
+		/**
+		 * Allocates enough memory to hold the object(s) of specified type using the static allocator, and constructs them.
+		 */
+		template<class T>
+		T* construct(UINT32 count = 0)
+		{
+			T* data = (T*)alloc(sizeof(T) * count);
+
+			for(unsigned int i = 0; i < count; i++)
+				new ((void*)&data[i]) T;
+
+			return data;
+		}
+
+		/**
+		 * Allocates enough memory to hold the object(s) of specified type using the static allocator, and constructs them.
+		 */
+		template<class T, class... Args>
+		T* construct(Args &&...args, UINT32 count = 0)
+		{
+			T* data = (T*)alloc(sizeof(T) * count);
+
+			for(unsigned int i = 0; i < count; i++)
+				new ((void*)&data[i]) T(std::forward<Args>(args)...);
+
+			return data;
+		}
+
+		/** Destructs and deallocates an object allocated with the static allocator. */
+		template<class T>
+		void destruct(T* data)
+		{
+			data->~T();
+
+			free(data);
+		}
+
+		/** Destructs and deallocates an array of objects allocated with the static frame allocator. */
+		template<class T>
+		void destruct(T* data, UINT32 count)
+		{
+			for(unsigned int i = 0; i < count; i++)
+				data[i].~T();
+
+			free(data);
+		}
+
+		/** Frees the internal memory buffers. All external allocations must be freed before calling this. */
+		void clear()
+		{
+			assert(mTotalAllocBytes == 0);
+
+			MemBlock* dynamicBlock = mStaticBlock.mNextBlock;
+			INT32 totalDynamicMemAmount = 0;
+			UINT32 numDynamicBlocks = 0;
+
+			while (dynamicBlock != nullptr)
+			{
+				totalDynamicMemAmount += dynamicBlock->mFreePtr;
+				dynamicBlock->clear();
+			
+				dynamicBlock = dynamicBlock->mNextBlock;
+				numDynamicBlocks++;
+			}
+
+			mFreeBlock = &mStaticBlock;
+			mStaticBlock.clear();
+
+			if (numDynamicBlocks > 1)
+			{
+				freeBlocks(&mStaticBlock);
+				allocBlock(std::min(totalDynamicMemAmount, MaxDynamicMemory));
+				mFreeBlock = &mStaticBlock;
+			}
+			else if (numDynamicBlocks == 1 && MaxDynamicMemory == 0)
+			{
+				freeBlocks(&mStaticBlock);
+			}
+		}
+
+	private:
+		UINT8 mStaticData[BlockSize];
+		MemBlock mStaticBlock;
+
+		MemBlock* mFreeBlock;
+		UINT32 mTotalAllocBytes;
+
+		/**
+		 * Allocates a dynamic block of memory of the wanted size. The exact allocation size might be slightly higher in 
+		 * order to store block meta data.
+		 */
+		MemBlock* allocBlock(UINT32 wantedSize)
+		{
+			UINT32 blockSize = BlockSize;
+			if (wantedSize > blockSize)
+				blockSize = wantedSize;
+
+			MemBlock* dynamicBlock = mFreeBlock->mNextBlock;
+			MemBlock* newBlock = nullptr;
+			while (dynamicBlock != nullptr)
+			{
+				if (dynamicBlock->mSize >= blockSize)
+				{
+					newBlock = dynamicBlock;
+					break;
+				}
+
+				dynamicBlock = dynamicBlock->mNextBlock;
+			}
+
+			if (newBlock == nullptr)
+			{
+				UINT8* data = (UINT8*)reinterpret_cast<UINT8*>(bs_alloc(blockSize + sizeof(MemBlock)));
+				newBlock = new (data)MemBlock(data + sizeof(MemBlock), blockSize);
+				newBlock->mPrevBlock = mFreeBlock;
+				mFreeBlock->mNextBlock = newBlock;
+			}
+
+			mFreeBlock = newBlock;
+			return newBlock;
+		}
+
+		/** Releases memory for any dynamic blocks following the provided block (if there are any). */
+		void freeBlocks(MemBlock* start)
+		{
+			MemBlock* dynamicBlock = start->mNextBlock;
+			while (dynamicBlock != nullptr)
+			{
+				MemBlock* nextBlock = dynamicBlock->mNextBlock;
+
+				dynamicBlock->~MemBlock();
+				bs_free(dynamicBlock);
+
+				dynamicBlock = nextBlock;
+			}
+
+			start->mNextBlock = nullptr;
+		}
+	};
+
+	/** @} */
+	/** @} */
 }

+ 905 - 895
Source/BansheeUtility/Include/BsString.h

@@ -1,895 +1,905 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-/** @addtogroup String
- *  @{
- */
-
-namespace BansheeEngine
-{
-	/** Basic string that uses Banshee memory allocators. */
-	template <typename T>
-	using BasicString = std::basic_string < T, std::char_traits<T>, StdAlloc<T> > ;
-
-	/**	Basic string stream that uses Banshee memory allocators. */
-	template <typename T>
-	using BasicStringStream = std::basic_stringstream < T, std::char_traits<T>, StdAlloc<T> > ;
-
-	/** Wide string used primarily for handling Unicode text. */
-	typedef BasicString<wchar_t> WString;
-
-	/** Narrow string used primarily for handling ASCII text. */
-	typedef BasicString<char> String;
-
-	/** Wide string stream used for primarily for constructing strings consisting of Unicode text. */
-	typedef BasicStringStream<wchar_t> WStringStream;
-
-	/** Wide string stream used for primarily for constructing strings consisting of ASCII text. */
-	typedef BasicStringStream<char> StringStream;
-}
-
-#include "BsStringFormat.h"
-
-namespace BansheeEngine
-{
-    /** Utility class for manipulating Strings. */
-    class BS_UTILITY_EXPORT StringUtil
-    {
-	public:
-        /** Removes any whitespace characters from beginning or end of the string. */
-        static void trim(String& str, bool left = true, bool right = true);
-
-        /** @copydoc StringUtil::trim(String&, bool, bool) */
-        static void trim(WString& str, bool left = true, bool right = true);
-
-        /**	Removes specified characters from beginning or end of the string. */
-        static void trim(String& str, const String& delims, bool left = true, bool right = true);
-
-		/** @copydoc StringUtil::trim(String&, const String&, bool, bool) */
-        static void trim(WString& str, const WString& delims, bool left = true, bool right = true);
-
-		/**
-		 * Returns a vector of strings containing all the substrings delimited by the provided delimiter characters.
-		 *
-		 * @param[in]	str		 	The string to split.
-		 * @param[in]	delims   	(optional) Delimiter characters to split the string by. They will not
-		 * 							be included in resulting substrings.
-		 * @param[in]	maxSplits	(optional) The maximum number of splits to perform (0 for unlimited splits). If this
-		 *							parameters is > 0, the splitting process will stop after this many splits, left to right.
-		 */
-		static Vector<String> split(const String& str, const String& delims = "\t\n ", unsigned int maxSplits = 0);
-
-		/** @copydoc StringUtil::split(const String&, const String&, unsigned int) */
-		static Vector<WString> split(const WString& str, const WString& delims = L"\t\n ", unsigned int maxSplits = 0);
-
-		/**
-		 * Returns a vector of strings containing all the substrings delimited by the provided delimiter characters, or the 
-		 * double delimiters used for including normal delimiter characters in the tokenized string. 
-		 *
-		 * @param[in]	str		 		The string to split.
-		 * @param[in]	delims   		(optional) Delimiter characters to split the string by. They will not
-		 * 								be included in resulting substrings.
-		 * @params[in]	doubleDelims	(optional) Delimiter character you may use to surround other normal delimiters, 
-		 *								in order to include them in the tokensized string.
-		 * @param[in]	maxSplits		(optional) The maximum number of splits to perform (0 for unlimited splits). 
-		 *								If this parameters is > 0, the splitting process will stop after this many splits, 
-		 *								left to right.
-		 */
-		static Vector<String> tokenise(const String& str, const String& delims = "\t\n ", const String& doubleDelims = "\"", unsigned int maxSplits = 0);
-
-		/** @copydoc StringUtil::tokenise(const String&, const String&, const String&, unsigned int) */
-		static Vector<WString> tokenise(const WString& str, const WString& delims = L"\t\n ", const WString& doubleDelims = L"\"", unsigned int maxSplits = 0);
-
-        /** Converts all the characters in the string to lower case. */
-        static void toLowerCase(String& str);
-
-        /** Converts all the characters in the string to lower case. */
-        static void toLowerCase(WString& str);
-
-        /** Converts all the characters in the string to upper case. */
-        static void toUpperCase(String& str);
-
-        /**	Converts all the characters in the string to upper case. */
-        static void toUpperCase(WString& str);
-
-        /**
-         * Returns whether the string begins with the pattern passed in.
-         *
-         * @param[in]	str		 	String to compare.
-         * @param[in]	pattern		Pattern to compare with.
-		 * @param[in]	lowerCase	(optional) If true, the start of the string will be lower cased before comparison, and 
-		 *							the pattern should also be in lower case.
-         */
-        static bool startsWith(const String& str, const String& pattern, bool lowerCase = true);
-
-        /** @copydoc startsWidth(const String&, const String&, bool) */
-        static bool startsWith(const WString& str, const WString& pattern, bool lowerCase = true);
-
-        /**
-         * Returns whether the string end with the pattern passed in.
-         *
-         * @param[in]	str		 	String to compare.
-         * @param[in]	pattern		Pattern to compare with.
-		 * @param[in]	lowerCase	(optional) If true, the start of the string will be lower cased before comparison, and 
-		 *							the pattern should also be in lower case.
-         */
-        static bool endsWith(const String& str, const String& pattern, bool lowerCase = true);
-
-        /** @copydoc endsWith(const String&, const String&, bool) */
-        static bool endsWith(const WString& str, const WString& pattern, bool lowerCase = true);
-
-        /**
-         * Returns true if the string matches the provided pattern. Pattern may use a "*" wildcard for matching any 
-		 * characters.
-         *
-         * @param[in]	str			 	The string to test.
-         * @param[in]	pattern		 	Patterns to look for.
-         * @param[in]	caseSensitive	(optional) Should the match be case sensitive or not.
-         */
-        static bool match(const String& str, const String& pattern, bool caseSensitive = true);
-
-		/** @copydoc match(const String&, const String&, bool) */
-        static bool match(const WString& str, const WString& pattern, bool caseSensitive = true);
-
-		/**
-		 * Replace all instances of a substring with a another substring.
-		 *
-		 * @param[in]	source		   	String to search.
-		 * @param[in]	replaceWhat	   	Substring to find and replace
-		 * @param[in]	replaceWithWhat	Substring to replace with (the new sub-string)
-		 *
-		 * @return	An updated string with the substrings replaced.
-		 */
-		static const String replaceAll(const String& source, const String& replaceWhat, const String& replaceWithWhat);
-
-		/** @copydoc replaceAll(const String&, const String&, const String&) */
-		static const WString replaceAll(const WString& source, const WString& replaceWhat, const WString& replaceWithWhat);
-
-		/**
-		 * Compares two strings. Returns 0 if the two compare equal, <0 if the value of the left string is lower than of 
-		 * the right string, or >0 if the value of the left string is higher than the right string.
-		 *
-		 * @param[in]	lhs				Left string to compare.
-		 * @param[in]	rhs				Right string to compare.
-		 * @param[in]	caseSensitive	If true the comparison will consider uppercase and lowercase characters different.
-		 */
-		template <class T>
-		static int compare(const BasicString<T>& lhs, const BasicString<T>& rhs, bool caseSensitive = true)
-		{
-			if (caseSensitive)
-				return (int)lhs.compare(rhs);
-
-			int size = (int)std::min(lhs.size(), rhs.size());
-			for (int i = 0; i < size; i++)
-			{
-				if (toupper(lhs[i]) < toupper(rhs[i])) return -1;
-				if (toupper(lhs[i]) > toupper(rhs[i])) return 1;
-			}
-
-			return (lhs.size() < rhs.size() ? -1 : (lhs.size() == rhs.size() ? 0 : 1));
-		}
-
-		/** @copydoc StringFormat::format */
-		template<class T, class... Args>
-		static BasicString<T> format(const BasicString<T>& source, Args&& ...args)
-		{
-			return StringFormat::format(source.c_str(), std::forward<Args>(args)...);
-		}
-
-		/** @copydoc StringFormat::format */
-		template<class T, class... Args>
-		static BasicString<T> format(const T* source, Args&& ...args)
-		{
-			return StringFormat::format(source, std::forward<Args>(args)...);
-		}
-
-		/** Constant blank string, useful for returning by ref where local does not exist. */
-        static const String BLANK;
-
-		/**	Constant blank wide string, useful for returning by ref where local does not exist. */
-		static const WString WBLANK;
-
-	private:
-		template <class T>
-		static Vector<BasicString<T>> splitInternal(const BasicString<T>& str, const BasicString<T>& delims, unsigned int maxSplits)
-		{
-			Vector<BasicString<T>> ret;
-			// Pre-allocate some space for performance
-			ret.reserve(maxSplits ? maxSplits+1 : 10);    // 10 is guessed capacity for most case
-
-			unsigned int numSplits = 0;
-
-			// Use STL methods 
-			size_t start, pos;
-			start = 0;
-			do 
-			{
-				pos = str.find_first_of(delims, start);
-				if (pos == start)
-				{
-					// Do nothing
-					start = pos + 1;
-				}
-				else if (pos == BasicString<T>::npos || (maxSplits && numSplits == maxSplits))
-				{
-					// Copy the rest of the string
-					ret.push_back(str.substr(start));
-					break;
-				}
-				else
-				{
-					// Copy up to delimiter
-					ret.push_back(str.substr(start, pos - start));
-					start = pos + 1;
-				}
-				// parse up to next real data
-				start = str.find_first_not_of(delims, start);
-				++numSplits;
-
-			} while (pos != BasicString<T>::npos);
-
-			return ret;
-		}
-
-		template <class T>
-		static Vector<BasicString<T>> tokeniseInternal(const BasicString<T>& str, const BasicString<T>& singleDelims, 
-			const BasicString<T>& doubleDelims, unsigned int maxSplits)
-		{
-			Vector<BasicString<T>> ret;
-			// Pre-allocate some space for performance
-			ret.reserve(maxSplits ? maxSplits + 1 : 10);    // 10 is guessed capacity for most case
-
-			unsigned int numSplits = 0;
-			BasicString<T> delims = singleDelims + doubleDelims;
-
-			// Use STL methods 
-			size_t start, pos;
-			T curDoubleDelim = 0;
-			start = 0;
-			do 
-			{
-				if (curDoubleDelim != 0)
-				{
-					pos = str.find(curDoubleDelim, start);
-				}
-				else
-				{
-					pos = str.find_first_of(delims, start);
-				}
-
-				if (pos == start)
-				{
-					T curDelim = str.at(pos);
-					if (doubleDelims.find_first_of(curDelim) != BasicString<T>::npos)
-					{
-						curDoubleDelim = curDelim;
-					}
-					// Do nothing
-					start = pos + 1;
-				}
-				else if (pos == BasicString<T>::npos || (maxSplits && numSplits == maxSplits))
-				{
-					if (curDoubleDelim != 0)
-					{
-						//Missing closer. Warn or throw exception?
-					}
-					// Copy the rest of the string
-					ret.push_back( str.substr(start) );
-					break;
-				}
-				else
-				{
-					if (curDoubleDelim != 0)
-					{
-						curDoubleDelim = 0;
-					}
-
-					// Copy up to delimiter
-					ret.push_back( str.substr(start, pos - start) );
-					start = pos + 1;
-				}
-				if (curDoubleDelim == 0)
-				{
-					// parse up to next real data
-					start = str.find_first_not_of(singleDelims, start);
-				}
-
-				++numSplits;
-
-			} while (pos != BasicString<T>::npos);
-
-			return ret;
-		}
-
-		template <class T>
-		static bool startsWithInternal(const BasicString<T>& str, const BasicString<T>& pattern, bool lowerCase)
-		{
-			size_t thisLen = str.length();
-			size_t patternLen = pattern.length();
-			if (thisLen < patternLen || patternLen == 0)
-				return false;
-
-			BasicString<T> startOfThis = str.substr(0, patternLen);
-			if (lowerCase)
-				StringUtil::toLowerCase(startOfThis);
-
-			return (startOfThis == pattern);
-		}
-
-		template <class T>
-		static bool endsWithInternal(const BasicString<T>& str, const BasicString<T>& pattern, bool lowerCase)
-		{
-			size_t thisLen = str.length();
-			size_t patternLen = pattern.length();
-			if (thisLen < patternLen || patternLen == 0)
-				return false;
-
-			BasicString<T> endOfThis = str.substr(thisLen - patternLen, patternLen);
-			if (lowerCase)
-				StringUtil::toLowerCase(endOfThis);
-
-			return (endOfThis == pattern);
-		}
-
-		template <class T>
-		static bool matchInternal(const BasicString<T>& str, const BasicString<T>& pattern, bool caseSensitive)
-		{
-			BasicString<T> tmpStr = str;
-			BasicString<T> tmpPattern = pattern;
-			if (!caseSensitive)
-			{
-				StringUtil::toLowerCase(tmpStr);
-				StringUtil::toLowerCase(tmpPattern);
-			}
-
-			BasicString<T>::const_iterator strIt = tmpStr.begin();
-			BasicString<T>::const_iterator patIt = tmpPattern.begin();
-			BasicString<T>::const_iterator lastWildCardIt = tmpPattern.end();
-			while (strIt != tmpStr.end() && patIt != tmpPattern.end())
-			{
-				if (*patIt == '*')
-				{
-					lastWildCardIt = patIt;
-					// Skip over looking for next character
-					++patIt;
-					if (patIt == tmpPattern.end())
-					{
-						// Skip right to the end since * matches the entire rest of the string
-						strIt = tmpStr.end();
-					}
-					else
-					{
-						// scan until we find next pattern character
-						while(strIt != tmpStr.end() && *strIt != *patIt)
-							++strIt;
-					}
-				}
-				else
-				{
-					if (*patIt != *strIt)
-					{
-						if (lastWildCardIt != tmpPattern.end())
-						{
-							// The last wildcard can match this incorrect sequence
-							// rewind pattern to wildcard and keep searching
-							patIt = lastWildCardIt;
-							lastWildCardIt = tmpPattern.end();
-						}
-						else
-						{
-							// no wildwards left
-							return false;
-						}
-					}
-					else
-					{
-						++patIt;
-						++strIt;
-					}
-				}
-
-			}
-
-			// If we reached the end of both the pattern and the string, we succeeded
-			if (patIt == tmpPattern.end() && strIt == tmpStr.end())
-				return true;
-			else
-				return false;
-		}
-
-		template <class T>
-		static BasicString<T> replaceAllInternal(const BasicString<T>& source, 
-			const BasicString<T>& replaceWhat, const BasicString<T>& replaceWithWhat)
-		{
-			BasicString<T> result = source;
-			BasicString<T>::size_type pos = 0;
-			while(1)
-			{
-				pos = result.find(replaceWhat,pos);
-				if (pos == BasicString<T>::npos) break;
-				result.replace(pos,replaceWhat.size(), replaceWithWhat);
-				pos += replaceWithWhat.size();
-			}
-			return result;
-		}
-    };
-
-	/** Converts a narrow string to a wide string. */
-	BS_UTILITY_EXPORT WString toWString(const String& source);
-
-	/**	Converts a narrow string to a wide string. */
-	BS_UTILITY_EXPORT WString toWString(const char* source);
-
-	/** Converts a float to a string. */
-    BS_UTILITY_EXPORT WString toWString(float val, unsigned short precision = 6, 
-        unsigned short width = 0, char fill = ' ', 
-        std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/** Converts a double to a string. */
-	BS_UTILITY_EXPORT WString toWString(double val, unsigned short precision = 6, 
-		unsigned short width = 0, char fill = ' ', 
-		std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/** Converts a Radian to a string. */
-    BS_UTILITY_EXPORT WString toWString(Radian val, unsigned short precision = 6, 
-        unsigned short width = 0, char fill = ' ', 
-        std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/** Converts a Degree to a string. */
-    BS_UTILITY_EXPORT WString toWString(Degree val, unsigned short precision = 6, 
-        unsigned short width = 0, char fill = ' ', 
-        std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts an int to a string. */
-    BS_UTILITY_EXPORT WString toWString(int val, unsigned short width = 0, 
-        char fill = ' ', 
-        std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts an unsigned int to a string. */
-    BS_UTILITY_EXPORT WString toWString(unsigned int val, 
-        unsigned short width = 0, char fill = ' ', 
-        std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts an 64bit integer to a string. */
-	BS_UTILITY_EXPORT WString toWString(INT64 val, 
-		unsigned short width = 0, char fill = ' ', 
-		std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts an 64bit unsigned to a string. */
-	BS_UTILITY_EXPORT WString toWString(UINT64 val, 
-		unsigned short width = 0, char fill = ' ', 
-		std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts an narrow char unsigned to a string. */
-	BS_UTILITY_EXPORT WString toWString(char val,
-		unsigned short width = 0, char fill = ' ',
-		std::ios::fmtflags flags = std::ios::fmtflags(0));
-
-	/**	Converts an wide bit char unsigned to a string. */
-	BS_UTILITY_EXPORT WString toWString(wchar_t val,
-		unsigned short width = 0, char fill = ' ',
-		std::ios::fmtflags flags = std::ios::fmtflags(0));
-
-    /**
-     * Converts a boolean to a string.
-     *
-     * @param[in]	val  	Value to convert.
-     * @param[in]	yesNo	(optional) If set to true, result is "yes" or "no" instead of "true" or "false".
-     */
-    BS_UTILITY_EXPORT WString toWString(bool val, bool yesNo = false);
-
-    /**
-     * Converts a 2 dimensional vector to a string.
-     * 			
-	 * @note	Format is "x y".
-     */
-    BS_UTILITY_EXPORT WString toWString(const Vector2& val);
-
-    /**
-     * Converts a 2 dimensional integer vector to a string.
-     * 			
-	 * @note	Format is "x y".
-     */
-    BS_UTILITY_EXPORT WString toWString(const Vector2I& val);
-
-    /**
-     * Converts a 3 dimensional vector to a string.
-     * 			
-	 * @note	Format is "x y z".
-     */
-    BS_UTILITY_EXPORT WString toWString(const Vector3& val);
-
-    /**
-     * Converts a 4 dimensional vector to a string.
-     * 			
-	 * @note	Format is "x y z w".
-     */
-    BS_UTILITY_EXPORT WString toWString(const Vector4& val);
-
-    /**
-     * Converts a 3x3 matrix to a string.
-     * 			
-	 * @note	Format is "00 01 02 10 11 12 20 21 22".
-     */
-    BS_UTILITY_EXPORT WString toWString(const Matrix3& val);
-
-    /**
-     * Converts a 4x4 matrix to a string.
-     * 			
-	 * @note	Format is "00 01 02 03 10 11 12 13 20 21 22 23 30 31 32 33".
-     */
-    BS_UTILITY_EXPORT WString toWString(const Matrix4& val);
-
-    /**
-     * Converts a Quaternion to a string.
-     * 			
-	 * @note	Format is "w x y z".
-     */
-    BS_UTILITY_EXPORT WString toWString(const Quaternion& val);
-
-    /**
-     * Converts a color to a string.
-     * 			
-	 * @note	Format is "r g b a".
-     */
-    BS_UTILITY_EXPORT WString toWString(const Color& val);
-
-    /** Converts a vector of strings into a single string where the substrings are delimited by spaces. */
-    BS_UTILITY_EXPORT WString toWString(const Vector<BansheeEngine::WString>& val);
-
-	/** Converts a wide string to a narrow string. */
-	BS_UTILITY_EXPORT String toString(const WString& source);
-
-	/**	Converts a wide string to a narrow string. */
-	BS_UTILITY_EXPORT String toString(const wchar_t* source);
-
-	/**	Converts a float to a string. */
-    BS_UTILITY_EXPORT String toString(float val, unsigned short precision = 6, 
-        unsigned short width = 0, char fill = ' ', 
-        std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts a double to a string. */
-	BS_UTILITY_EXPORT String toString(double val, unsigned short precision = 6, 
-		unsigned short width = 0, char fill = ' ', 
-		std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts a Radian to a string. */
-    BS_UTILITY_EXPORT String toString(Radian val, unsigned short precision = 6, 
-        unsigned short width = 0, char fill = ' ', 
-        std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts a Degree to a string. */
-    BS_UTILITY_EXPORT String toString(Degree val, unsigned short precision = 6, 
-        unsigned short width = 0, char fill = ' ', 
-        std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts an int to a string. */
-    BS_UTILITY_EXPORT String toString(int val, unsigned short width = 0, 
-        char fill = ' ', 
-        std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts an unsigned int to a string. */
-    BS_UTILITY_EXPORT String toString(unsigned int val, 
-        unsigned short width = 0, char fill = ' ', 
-        std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts a 64bit int to a string. */
-	BS_UTILITY_EXPORT String toString(INT64 val, 
-		unsigned short width = 0, char fill = ' ', 
-		std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-	/**	Converts an 64bit unsigned int to a string. */
-	BS_UTILITY_EXPORT String toString(UINT64 val, 
-		unsigned short width = 0, char fill = ' ', 
-		std::ios::fmtflags flags = std::ios::fmtflags(0) );
-
-    /**
-     * Converts a boolean to a string.
-     *
-     * @param[in]	val  	true to value.
-     * @param[in]	yesNo	(optional) If set to true, result is "yes" or "no" instead of "true" or "false".
-     */
-    BS_UTILITY_EXPORT String toString(bool val, bool yesNo = false);
-
-    /**
-     * Converts a 2 dimensional vector to a string.
-     * 			
-	 * @note	Format is "x y".
-     */
-    BS_UTILITY_EXPORT String toString(const Vector2& val);
-
-    /**
-     * Converts a 2 dimensional integer vector to a string.
-     * 			
-	 * @note	Format is "x y".
-     */
-    BS_UTILITY_EXPORT String toString(const Vector2I& val);
-
-    /**
-     * Converts a 3 dimensional vector to a string.
-     * 			
-	 * @note	Format is "x y z".
-     */
-    BS_UTILITY_EXPORT String toString(const Vector3& val);
-
-    /**
-     * Converts a 4 dimensional vector to a string.
-     * 			
-	 * @note	Format is "x y z w".
-     */
-    BS_UTILITY_EXPORT String toString(const Vector4& val);
-
-    /**
-     * Converts a 3x3 matrix to a string.
-     * 			
-	 * @note	Format is "00 01 02 10 11 12 20 21 22".
-     */
-    BS_UTILITY_EXPORT String toString(const Matrix3& val);
-
-    /**
-     * Converts a 4x4 matrix to a string.
-     * 			
-	 * @note	Format is "00 01 02 03 10 11 12 13 20 21 22 23 30 31 32 33".
-     */
-    BS_UTILITY_EXPORT String toString(const Matrix4& val);
-
-    /**
-     * Converts a Quaternion to a string.
-     * 			
-	 * @note	Format is "w x y z".
-     */
-    BS_UTILITY_EXPORT String toString(const Quaternion& val);
-
-    /**
-     * Converts a color to a string.
-     * 			
-	 * @note	Format is "r g b a".
-     */
-    BS_UTILITY_EXPORT String toString(const Color& val);
-
-    /**
-     * Converts a vector of strings into a single string where the substrings are delimited by spaces.
-     */
-    BS_UTILITY_EXPORT String toString(const Vector<BansheeEngine::String>& val);
-
-    /**
-     * Converts a String to a float.
-     *
-     * @note	0.0f if the value could not be parsed, otherwise the numeric version of the string.
-     */
-    BS_UTILITY_EXPORT float parseFloat(const String& val, float defaultValue = 0);
-
-    /**
-     * Converts a String to a whole number.
-     *
-     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
-     */
-    BS_UTILITY_EXPORT INT32 parseINT32(const String& val, INT32 defaultValue = 0);
-
-    /**
-     * Converts a String to a whole number.
-     *
-     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
-     */
-    BS_UTILITY_EXPORT UINT32 parseUINT32(const String& val, UINT32 defaultValue = 0);
-
-    /**
-     * Converts a String to a whole number.
-     *
-     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
-     */
-    BS_UTILITY_EXPORT INT64 parseINT64(const String& val, INT64 defaultValue = 0);
-
-    /**
-     * Converts a String to a whole number.
-     *
-     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
-     */
-    BS_UTILITY_EXPORT UINT64 parseUINT64(const String& val, UINT64 defaultValue = 0);
-
-    /**
-     * Converts a String to a boolean.
-     *
-	 * @note	Returns true if case-insensitive match of the start of the string matches "true", "yes" or "1", 
-	 *			false otherwise.
-     */
-    BS_UTILITY_EXPORT bool parseBool(const String& val, bool defaultValue = 0);
-
-    /** Checks the String is a valid number value. */
-    BS_UTILITY_EXPORT bool isNumber(const String& val);
-
-    /**
-     * Converts a WString to a float.
-     *
-     * @note	0.0f if the value could not be parsed, otherwise the numeric version of the string.
-     */
-    BS_UTILITY_EXPORT float parseFloat(const WString& val, float defaultValue = 0);
-
-    /**
-     * Converts a WString to a whole number.
-     *
-     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
-     */
-    BS_UTILITY_EXPORT INT32 parseINT32(const WString& val, INT32 defaultValue = 0);
-
-    /**
-     * Converts a WString to a whole number.
-     *
-     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
-     */
-    BS_UTILITY_EXPORT UINT32 parseUINT32(const WString& val, UINT32 defaultValue = 0);
-
-    /**
-     * Converts a WString to a whole number.
-     *
-     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
-     */
-    BS_UTILITY_EXPORT INT64 parseINT64(const WString& val, INT64 defaultValue = 0);
-
-    /**
-     * Converts a WString to a whole number.
-     *
-     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
-     */
-    BS_UTILITY_EXPORT UINT64 parseUINT64(const WString& val, UINT64 defaultValue = 0);
-
-    /**
-     * Converts a WString to a boolean.
-     *
-	 * @note	Returns true if case-insensitive match of the start of the string
-	 *			matches "true", "yes" or "1", false otherwise.
-     */
-    BS_UTILITY_EXPORT bool parseBool(const WString& val, bool defaultValue = 0);
-
-    /**
-     * Checks the WString is a valid number value.
-     */
-    BS_UTILITY_EXPORT bool isNumber(const WString& val);
-
-	/** @cond INTERNAL */
-
-	/** Helper method that throws an exception regarding a data overflow. */
-	void BS_UTILITY_EXPORT __string_throwDataOverflowException();
-
-	/** @endcond */
-	/** @cond SPECIALIZATIONS */
-
-	/**
-	 * RTTIPlainType specialization for String that allows strings be serialized as value types.
-	 * 			
-	 * @see		RTTIPlainType
-	 */
-	template<> struct RTTIPlainType<String>
-	{	
-		enum { id = 20 }; enum { hasDynamicSize = 1 };
-
-		static void toMemory(const 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 UINT32 fromMemory(String& data, char* memory)
-		{ 
-			UINT32 size;
-			memcpy(&size, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			UINT32 stringSize = size - sizeof(UINT32);
-			char* buffer = (char*)bs_alloc(stringSize + 1);
-			memcpy(buffer, memory, stringSize); 
-			buffer[stringSize] = '\0';
-			data = String(buffer);
-
-			bs_free(buffer);
-
-			return size;
-		}
-
-		static UINT32 getDynamicSize(const String& data)	
-		{ 
-			UINT64 dataSize = data.size() * sizeof(String::value_type) + sizeof(UINT32);
-
-#if BS_DEBUG_MODE
-			if(dataSize > std::numeric_limits<UINT32>::max())
-			{
-				__string_throwDataOverflowException();
-			}
-#endif
-
-			return (UINT32)dataSize;
-		}	
-	}; 
-
-	/**
-	 * RTTIPlainType specialization for WString that allows strings be serialized as value types.
-	 * 			
-	 * @see		RTTIPlainType
-	 */
-	template<> struct RTTIPlainType<WString>
-	{	
-		enum { id = TID_WString }; enum { hasDynamicSize = 1 };
-
-		static void toMemory(const WString& data, char* memory)
-		{ 
-			UINT32 size = getDynamicSize(data);
-
-			memcpy(memory, &size, sizeof(UINT32));
-			memory += sizeof(UINT32);
-			size -= sizeof(UINT32);
-			memcpy(memory, data.data(), size); 
-		}
-
-		static UINT32 fromMemory(WString& data, char* memory)
-		{ 
-			UINT32 size;
-			memcpy(&size, memory, sizeof(UINT32)); 
-			memory += sizeof(UINT32);
-
-			UINT32 stringSize = size - sizeof(UINT32);
-			WString::value_type* buffer = (WString::value_type*)bs_alloc(stringSize + sizeof(WString::value_type));
-			memcpy(buffer, memory, stringSize); 
-
-			UINT32 numChars =  stringSize / sizeof(WString::value_type);
-			buffer[numChars] = L'\0';
-
-			data = WString(buffer);
-
-			bs_free(buffer);
-
-			return size;
-		}
-
-		static UINT32 getDynamicSize(const WString& data)	
-		{ 
-			UINT64 dataSize = data.size() * sizeof(WString::value_type) + sizeof(UINT32);
-
-#if BS_DEBUG_MODE
-			if(dataSize > std::numeric_limits<UINT32>::max())
-			{
-				__string_throwDataOverflowException();
-			}
-#endif
-
-			return (UINT32)dataSize;
-		}	
-	}; 
-
-	/** @endcond */
-}
-
-/** @cond STDLIB */
-
-/** Hash value generator for String. */
-template<> 
-struct std::hash<BansheeEngine::String>
-{
-	size_t operator()(const BansheeEngine::String& string) const
-	{
-		size_t hash = 0;
-		for(size_t i = 0; i < string.size(); i++) 
-			hash = 65599 * hash + string[i];
-		return hash ^ (hash >> 16);
-	}
-};
-
-/**	Hash value generator for WString. */
-template<> 
-struct std::hash<BansheeEngine::WString>
-{
-	size_t operator()(const BansheeEngine::WString& string) const
-	{
-		size_t hash = 0;
-		for(size_t i = 0; i < string.size(); i++) 
-			hash = 65599 * hash + string[i];
-		return hash ^ (hash >> 16);
-	}
-};
-
-/** @endcond */
-/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+
+
+namespace BansheeEngine
+{
+	/** @addtogroup String
+	 *  @{
+	 */
+
+	/** Basic string that uses Banshee memory allocators. */
+	template <typename T>
+	using BasicString = std::basic_string < T, std::char_traits<T>, StdAlloc<T> > ;
+
+	/**	Basic string stream that uses Banshee memory allocators. */
+	template <typename T>
+	using BasicStringStream = std::basic_stringstream < T, std::char_traits<T>, StdAlloc<T> > ;
+
+	/** Wide string used primarily for handling Unicode text. */
+	typedef BasicString<wchar_t> WString;
+
+	/** Narrow string used primarily for handling ASCII text. */
+	typedef BasicString<char> String;
+
+	/** Wide string stream used for primarily for constructing strings consisting of Unicode text. */
+	typedef BasicStringStream<wchar_t> WStringStream;
+
+	/** Wide string stream used for primarily for constructing strings consisting of ASCII text. */
+	typedef BasicStringStream<char> StringStream;
+
+	/** @} */
+}
+
+#include "BsStringFormat.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup String
+	 *  @{
+	 */
+
+    /** Utility class for manipulating Strings. */
+    class BS_UTILITY_EXPORT StringUtil
+    {
+	public:
+        /** Removes any whitespace characters from beginning or end of the string. */
+        static void trim(String& str, bool left = true, bool right = true);
+
+        /** @copydoc StringUtil::trim(String&, bool, bool) */
+        static void trim(WString& str, bool left = true, bool right = true);
+
+        /**	Removes specified characters from beginning or end of the string. */
+        static void trim(String& str, const String& delims, bool left = true, bool right = true);
+
+		/** @copydoc StringUtil::trim(String&, const String&, bool, bool) */
+        static void trim(WString& str, const WString& delims, bool left = true, bool right = true);
+
+		/**
+		 * Returns a vector of strings containing all the substrings delimited by the provided delimiter characters.
+		 *
+		 * @param[in]	str		 	The string to split.
+		 * @param[in]	delims   	(optional) Delimiter characters to split the string by. They will not
+		 * 							be included in resulting substrings.
+		 * @param[in]	maxSplits	(optional) The maximum number of splits to perform (0 for unlimited splits). If this
+		 *							parameters is > 0, the splitting process will stop after this many splits, left to right.
+		 */
+		static Vector<String> split(const String& str, const String& delims = "\t\n ", unsigned int maxSplits = 0);
+
+		/** @copydoc StringUtil::split(const String&, const String&, unsigned int) */
+		static Vector<WString> split(const WString& str, const WString& delims = L"\t\n ", unsigned int maxSplits = 0);
+
+		/**
+		 * Returns a vector of strings containing all the substrings delimited by the provided delimiter characters, or the 
+		 * double delimiters used for including normal delimiter characters in the tokenized string. 
+		 *
+		 * @param[in]	str		 		The string to split.
+		 * @param[in]	delims   		(optional) Delimiter characters to split the string by. They will not
+		 * 								be included in resulting substrings.
+		 * @param[in]	doubleDelims	(optional) Delimiter character you may use to surround other normal delimiters, 
+		 *								in order to include them in the tokensized string.
+		 * @param[in]	maxSplits		(optional) The maximum number of splits to perform (0 for unlimited splits). 
+		 *								If this parameters is > 0, the splitting process will stop after this many splits, 
+		 *								left to right.
+		 */
+		static Vector<String> tokenise(const String& str, const String& delims = "\t\n ", const String& doubleDelims = "\"", unsigned int maxSplits = 0);
+
+		/** @copydoc StringUtil::tokenise(const String&, const String&, const String&, unsigned int) */
+		static Vector<WString> tokenise(const WString& str, const WString& delims = L"\t\n ", const WString& doubleDelims = L"\"", unsigned int maxSplits = 0);
+
+        /** Converts all the characters in the string to lower case. */
+        static void toLowerCase(String& str);
+
+        /** Converts all the characters in the string to lower case. */
+        static void toLowerCase(WString& str);
+
+        /** Converts all the characters in the string to upper case. */
+        static void toUpperCase(String& str);
+
+        /**	Converts all the characters in the string to upper case. */
+        static void toUpperCase(WString& str);
+
+        /**
+         * Returns whether the string begins with the pattern passed in.
+         *
+         * @param[in]	str		 	String to compare.
+         * @param[in]	pattern		Pattern to compare with.
+		 * @param[in]	lowerCase	(optional) If true, the start of the string will be lower cased before comparison, and 
+		 *							the pattern should also be in lower case.
+         */
+        static bool startsWith(const String& str, const String& pattern, bool lowerCase = true);
+
+        /** @copydoc startsWith(const String&, const String&, bool) */
+        static bool startsWith(const WString& str, const WString& pattern, bool lowerCase = true);
+
+        /**
+         * Returns whether the string end with the pattern passed in.
+         *
+         * @param[in]	str		 	String to compare.
+         * @param[in]	pattern		Pattern to compare with.
+		 * @param[in]	lowerCase	(optional) If true, the start of the string will be lower cased before comparison, and 
+		 *							the pattern should also be in lower case.
+         */
+        static bool endsWith(const String& str, const String& pattern, bool lowerCase = true);
+
+        /** @copydoc endsWith(const String&, const String&, bool) */
+        static bool endsWith(const WString& str, const WString& pattern, bool lowerCase = true);
+
+        /**
+         * Returns true if the string matches the provided pattern. Pattern may use a "*" wildcard for matching any 
+		 * characters.
+         *
+         * @param[in]	str			 	The string to test.
+         * @param[in]	pattern		 	Patterns to look for.
+         * @param[in]	caseSensitive	(optional) Should the match be case sensitive or not.
+         */
+        static bool match(const String& str, const String& pattern, bool caseSensitive = true);
+
+		/** @copydoc match(const String&, const String&, bool) */
+        static bool match(const WString& str, const WString& pattern, bool caseSensitive = true);
+
+		/**
+		 * Replace all instances of a substring with a another substring.
+		 *
+		 * @param[in]	source		   	String to search.
+		 * @param[in]	replaceWhat	   	Substring to find and replace
+		 * @param[in]	replaceWithWhat	Substring to replace with (the new sub-string)
+		 *
+		 * @return	An updated string with the substrings replaced.
+		 */
+		static const String replaceAll(const String& source, const String& replaceWhat, const String& replaceWithWhat);
+
+		/** @copydoc replaceAll(const String&, const String&, const String&) */
+		static const WString replaceAll(const WString& source, const WString& replaceWhat, const WString& replaceWithWhat);
+
+		/**
+		 * Compares two strings. Returns 0 if the two compare equal, <0 if the value of the left string is lower than of 
+		 * the right string, or >0 if the value of the left string is higher than the right string.
+		 *
+		 * @param[in]	lhs				Left string to compare.
+		 * @param[in]	rhs				Right string to compare.
+		 * @param[in]	caseSensitive	If true the comparison will consider uppercase and lowercase characters different.
+		 */
+		template <class T>
+		static int compare(const BasicString<T>& lhs, const BasicString<T>& rhs, bool caseSensitive = true)
+		{
+			if (caseSensitive)
+				return (int)lhs.compare(rhs);
+
+			int size = (int)std::min(lhs.size(), rhs.size());
+			for (int i = 0; i < size; i++)
+			{
+				if (toupper(lhs[i]) < toupper(rhs[i])) return -1;
+				if (toupper(lhs[i]) > toupper(rhs[i])) return 1;
+			}
+
+			return (lhs.size() < rhs.size() ? -1 : (lhs.size() == rhs.size() ? 0 : 1));
+		}
+
+		/** @copydoc StringFormat::format */
+		template<class T, class... Args>
+		static BasicString<T> format(const BasicString<T>& source, Args&& ...args)
+		{
+			return StringFormat::format(source.c_str(), std::forward<Args>(args)...);
+		}
+
+		/** @copydoc StringFormat::format */
+		template<class T, class... Args>
+		static BasicString<T> format(const T* source, Args&& ...args)
+		{
+			return StringFormat::format(source, std::forward<Args>(args)...);
+		}
+
+		/** Constant blank string, useful for returning by ref where local does not exist. */
+        static const String BLANK;
+
+		/**	Constant blank wide string, useful for returning by ref where local does not exist. */
+		static const WString WBLANK;
+
+	private:
+		template <class T>
+		static Vector<BasicString<T>> splitInternal(const BasicString<T>& str, const BasicString<T>& delims, unsigned int maxSplits)
+		{
+			Vector<BasicString<T>> ret;
+			// Pre-allocate some space for performance
+			ret.reserve(maxSplits ? maxSplits+1 : 10);    // 10 is guessed capacity for most case
+
+			unsigned int numSplits = 0;
+
+			// Use STL methods 
+			size_t start, pos;
+			start = 0;
+			do 
+			{
+				pos = str.find_first_of(delims, start);
+				if (pos == start)
+				{
+					// Do nothing
+					start = pos + 1;
+				}
+				else if (pos == BasicString<T>::npos || (maxSplits && numSplits == maxSplits))
+				{
+					// Copy the rest of the string
+					ret.push_back(str.substr(start));
+					break;
+				}
+				else
+				{
+					// Copy up to delimiter
+					ret.push_back(str.substr(start, pos - start));
+					start = pos + 1;
+				}
+				// parse up to next real data
+				start = str.find_first_not_of(delims, start);
+				++numSplits;
+
+			} while (pos != BasicString<T>::npos);
+
+			return ret;
+		}
+
+		template <class T>
+		static Vector<BasicString<T>> tokeniseInternal(const BasicString<T>& str, const BasicString<T>& singleDelims, 
+			const BasicString<T>& doubleDelims, unsigned int maxSplits)
+		{
+			Vector<BasicString<T>> ret;
+			// Pre-allocate some space for performance
+			ret.reserve(maxSplits ? maxSplits + 1 : 10);    // 10 is guessed capacity for most case
+
+			unsigned int numSplits = 0;
+			BasicString<T> delims = singleDelims + doubleDelims;
+
+			// Use STL methods 
+			size_t start, pos;
+			T curDoubleDelim = 0;
+			start = 0;
+			do 
+			{
+				if (curDoubleDelim != 0)
+				{
+					pos = str.find(curDoubleDelim, start);
+				}
+				else
+				{
+					pos = str.find_first_of(delims, start);
+				}
+
+				if (pos == start)
+				{
+					T curDelim = str.at(pos);
+					if (doubleDelims.find_first_of(curDelim) != BasicString<T>::npos)
+					{
+						curDoubleDelim = curDelim;
+					}
+					// Do nothing
+					start = pos + 1;
+				}
+				else if (pos == BasicString<T>::npos || (maxSplits && numSplits == maxSplits))
+				{
+					if (curDoubleDelim != 0)
+					{
+						//Missing closer. Warn or throw exception?
+					}
+					// Copy the rest of the string
+					ret.push_back( str.substr(start) );
+					break;
+				}
+				else
+				{
+					if (curDoubleDelim != 0)
+					{
+						curDoubleDelim = 0;
+					}
+
+					// Copy up to delimiter
+					ret.push_back( str.substr(start, pos - start) );
+					start = pos + 1;
+				}
+				if (curDoubleDelim == 0)
+				{
+					// parse up to next real data
+					start = str.find_first_not_of(singleDelims, start);
+				}
+
+				++numSplits;
+
+			} while (pos != BasicString<T>::npos);
+
+			return ret;
+		}
+
+		template <class T>
+		static bool startsWithInternal(const BasicString<T>& str, const BasicString<T>& pattern, bool lowerCase)
+		{
+			size_t thisLen = str.length();
+			size_t patternLen = pattern.length();
+			if (thisLen < patternLen || patternLen == 0)
+				return false;
+
+			BasicString<T> startOfThis = str.substr(0, patternLen);
+			if (lowerCase)
+				StringUtil::toLowerCase(startOfThis);
+
+			return (startOfThis == pattern);
+		}
+
+		template <class T>
+		static bool endsWithInternal(const BasicString<T>& str, const BasicString<T>& pattern, bool lowerCase)
+		{
+			size_t thisLen = str.length();
+			size_t patternLen = pattern.length();
+			if (thisLen < patternLen || patternLen == 0)
+				return false;
+
+			BasicString<T> endOfThis = str.substr(thisLen - patternLen, patternLen);
+			if (lowerCase)
+				StringUtil::toLowerCase(endOfThis);
+
+			return (endOfThis == pattern);
+		}
+
+		template <class T>
+		static bool matchInternal(const BasicString<T>& str, const BasicString<T>& pattern, bool caseSensitive)
+		{
+			BasicString<T> tmpStr = str;
+			BasicString<T> tmpPattern = pattern;
+			if (!caseSensitive)
+			{
+				StringUtil::toLowerCase(tmpStr);
+				StringUtil::toLowerCase(tmpPattern);
+			}
+
+			BasicString<T>::const_iterator strIt = tmpStr.begin();
+			BasicString<T>::const_iterator patIt = tmpPattern.begin();
+			BasicString<T>::const_iterator lastWildCardIt = tmpPattern.end();
+			while (strIt != tmpStr.end() && patIt != tmpPattern.end())
+			{
+				if (*patIt == '*')
+				{
+					lastWildCardIt = patIt;
+					// Skip over looking for next character
+					++patIt;
+					if (patIt == tmpPattern.end())
+					{
+						// Skip right to the end since * matches the entire rest of the string
+						strIt = tmpStr.end();
+					}
+					else
+					{
+						// scan until we find next pattern character
+						while(strIt != tmpStr.end() && *strIt != *patIt)
+							++strIt;
+					}
+				}
+				else
+				{
+					if (*patIt != *strIt)
+					{
+						if (lastWildCardIt != tmpPattern.end())
+						{
+							// The last wildcard can match this incorrect sequence
+							// rewind pattern to wildcard and keep searching
+							patIt = lastWildCardIt;
+							lastWildCardIt = tmpPattern.end();
+						}
+						else
+						{
+							// no wildwards left
+							return false;
+						}
+					}
+					else
+					{
+						++patIt;
+						++strIt;
+					}
+				}
+
+			}
+
+			// If we reached the end of both the pattern and the string, we succeeded
+			if (patIt == tmpPattern.end() && strIt == tmpStr.end())
+				return true;
+			else
+				return false;
+		}
+
+		template <class T>
+		static BasicString<T> replaceAllInternal(const BasicString<T>& source, 
+			const BasicString<T>& replaceWhat, const BasicString<T>& replaceWithWhat)
+		{
+			BasicString<T> result = source;
+			BasicString<T>::size_type pos = 0;
+			while(1)
+			{
+				pos = result.find(replaceWhat,pos);
+				if (pos == BasicString<T>::npos) break;
+				result.replace(pos,replaceWhat.size(), replaceWithWhat);
+				pos += replaceWithWhat.size();
+			}
+			return result;
+		}
+    };
+
+	/** Converts a narrow string to a wide string. */
+	BS_UTILITY_EXPORT WString toWString(const String& source);
+
+	/**	Converts a narrow string to a wide string. */
+	BS_UTILITY_EXPORT WString toWString(const char* source);
+
+	/** Converts a float to a string. */
+    BS_UTILITY_EXPORT WString toWString(float val, unsigned short precision = 6, 
+        unsigned short width = 0, char fill = ' ', 
+        std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/** Converts a double to a string. */
+	BS_UTILITY_EXPORT WString toWString(double val, unsigned short precision = 6, 
+		unsigned short width = 0, char fill = ' ', 
+		std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/** Converts a Radian to a string. */
+    BS_UTILITY_EXPORT WString toWString(Radian val, unsigned short precision = 6, 
+        unsigned short width = 0, char fill = ' ', 
+        std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/** Converts a Degree to a string. */
+    BS_UTILITY_EXPORT WString toWString(Degree val, unsigned short precision = 6, 
+        unsigned short width = 0, char fill = ' ', 
+        std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts an int to a string. */
+    BS_UTILITY_EXPORT WString toWString(int val, unsigned short width = 0, 
+        char fill = ' ', 
+        std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts an unsigned int to a string. */
+    BS_UTILITY_EXPORT WString toWString(unsigned int val, 
+        unsigned short width = 0, char fill = ' ', 
+        std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts an 64bit integer to a string. */
+	BS_UTILITY_EXPORT WString toWString(INT64 val, 
+		unsigned short width = 0, char fill = ' ', 
+		std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts an 64bit unsigned to a string. */
+	BS_UTILITY_EXPORT WString toWString(UINT64 val, 
+		unsigned short width = 0, char fill = ' ', 
+		std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts an narrow char unsigned to a string. */
+	BS_UTILITY_EXPORT WString toWString(char val,
+		unsigned short width = 0, char fill = ' ',
+		std::ios::fmtflags flags = std::ios::fmtflags(0));
+
+	/**	Converts an wide bit char unsigned to a string. */
+	BS_UTILITY_EXPORT WString toWString(wchar_t val,
+		unsigned short width = 0, char fill = ' ',
+		std::ios::fmtflags flags = std::ios::fmtflags(0));
+
+    /**
+     * Converts a boolean to a string.
+     *
+     * @param[in]	val  	Value to convert.
+     * @param[in]	yesNo	(optional) If set to true, result is "yes" or "no" instead of "true" or "false".
+     */
+    BS_UTILITY_EXPORT WString toWString(bool val, bool yesNo = false);
+
+    /**
+     * Converts a 2 dimensional vector to a string.
+     * 			
+	 * @note	Format is "x y".
+     */
+    BS_UTILITY_EXPORT WString toWString(const Vector2& val);
+
+    /**
+     * Converts a 2 dimensional integer vector to a string.
+     * 			
+	 * @note	Format is "x y".
+     */
+    BS_UTILITY_EXPORT WString toWString(const Vector2I& val);
+
+    /**
+     * Converts a 3 dimensional vector to a string.
+     * 			
+	 * @note	Format is "x y z".
+     */
+    BS_UTILITY_EXPORT WString toWString(const Vector3& val);
+
+    /**
+     * Converts a 4 dimensional vector to a string.
+     * 			
+	 * @note	Format is "x y z w".
+     */
+    BS_UTILITY_EXPORT WString toWString(const Vector4& val);
+
+    /**
+     * Converts a 3x3 matrix to a string.
+     * 			
+	 * @note	Format is "00 01 02 10 11 12 20 21 22".
+     */
+    BS_UTILITY_EXPORT WString toWString(const Matrix3& val);
+
+    /**
+     * Converts a 4x4 matrix to a string.
+     * 			
+	 * @note	Format is "00 01 02 03 10 11 12 13 20 21 22 23 30 31 32 33".
+     */
+    BS_UTILITY_EXPORT WString toWString(const Matrix4& val);
+
+    /**
+     * Converts a Quaternion to a string.
+     * 			
+	 * @note	Format is "w x y z".
+     */
+    BS_UTILITY_EXPORT WString toWString(const Quaternion& val);
+
+    /**
+     * Converts a color to a string.
+     * 			
+	 * @note	Format is "r g b a".
+     */
+    BS_UTILITY_EXPORT WString toWString(const Color& val);
+
+    /** Converts a vector of strings into a single string where the substrings are delimited by spaces. */
+    BS_UTILITY_EXPORT WString toWString(const Vector<BansheeEngine::WString>& val);
+
+	/** Converts a wide string to a narrow string. */
+	BS_UTILITY_EXPORT String toString(const WString& source);
+
+	/**	Converts a wide string to a narrow string. */
+	BS_UTILITY_EXPORT String toString(const wchar_t* source);
+
+	/**	Converts a float to a string. */
+    BS_UTILITY_EXPORT String toString(float val, unsigned short precision = 6, 
+        unsigned short width = 0, char fill = ' ', 
+        std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts a double to a string. */
+	BS_UTILITY_EXPORT String toString(double val, unsigned short precision = 6, 
+		unsigned short width = 0, char fill = ' ', 
+		std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts a Radian to a string. */
+    BS_UTILITY_EXPORT String toString(Radian val, unsigned short precision = 6, 
+        unsigned short width = 0, char fill = ' ', 
+        std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts a Degree to a string. */
+    BS_UTILITY_EXPORT String toString(Degree val, unsigned short precision = 6, 
+        unsigned short width = 0, char fill = ' ', 
+        std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts an int to a string. */
+    BS_UTILITY_EXPORT String toString(int val, unsigned short width = 0, 
+        char fill = ' ', 
+        std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts an unsigned int to a string. */
+    BS_UTILITY_EXPORT String toString(unsigned int val, 
+        unsigned short width = 0, char fill = ' ', 
+        std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts a 64bit int to a string. */
+	BS_UTILITY_EXPORT String toString(INT64 val, 
+		unsigned short width = 0, char fill = ' ', 
+		std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+	/**	Converts an 64bit unsigned int to a string. */
+	BS_UTILITY_EXPORT String toString(UINT64 val, 
+		unsigned short width = 0, char fill = ' ', 
+		std::ios::fmtflags flags = std::ios::fmtflags(0) );
+
+    /**
+     * Converts a boolean to a string.
+     *
+     * @param[in]	val  	true to value.
+     * @param[in]	yesNo	(optional) If set to true, result is "yes" or "no" instead of "true" or "false".
+     */
+    BS_UTILITY_EXPORT String toString(bool val, bool yesNo = false);
+
+    /**
+     * Converts a 2 dimensional vector to a string.
+     * 			
+	 * @note	Format is "x y".
+     */
+    BS_UTILITY_EXPORT String toString(const Vector2& val);
+
+    /**
+     * Converts a 2 dimensional integer vector to a string.
+     * 			
+	 * @note	Format is "x y".
+     */
+    BS_UTILITY_EXPORT String toString(const Vector2I& val);
+
+    /**
+     * Converts a 3 dimensional vector to a string.
+     * 			
+	 * @note	Format is "x y z".
+     */
+    BS_UTILITY_EXPORT String toString(const Vector3& val);
+
+    /**
+     * Converts a 4 dimensional vector to a string.
+     * 			
+	 * @note	Format is "x y z w".
+     */
+    BS_UTILITY_EXPORT String toString(const Vector4& val);
+
+    /**
+     * Converts a 3x3 matrix to a string.
+     * 			
+	 * @note	Format is "00 01 02 10 11 12 20 21 22".
+     */
+    BS_UTILITY_EXPORT String toString(const Matrix3& val);
+
+    /**
+     * Converts a 4x4 matrix to a string.
+     * 			
+	 * @note	Format is "00 01 02 03 10 11 12 13 20 21 22 23 30 31 32 33".
+     */
+    BS_UTILITY_EXPORT String toString(const Matrix4& val);
+
+    /**
+     * Converts a Quaternion to a string.
+     * 			
+	 * @note	Format is "w x y z".
+     */
+    BS_UTILITY_EXPORT String toString(const Quaternion& val);
+
+    /**
+     * Converts a color to a string.
+     * 			
+	 * @note	Format is "r g b a".
+     */
+    BS_UTILITY_EXPORT String toString(const Color& val);
+
+    /**
+     * Converts a vector of strings into a single string where the substrings are delimited by spaces.
+     */
+    BS_UTILITY_EXPORT String toString(const Vector<BansheeEngine::String>& val);
+
+    /**
+     * Converts a String to a float.
+     *
+     * @note	0.0f if the value could not be parsed, otherwise the numeric version of the string.
+     */
+    BS_UTILITY_EXPORT float parseFloat(const String& val, float defaultValue = 0);
+
+    /**
+     * Converts a String to a whole number.
+     *
+     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
+     */
+    BS_UTILITY_EXPORT INT32 parseINT32(const String& val, INT32 defaultValue = 0);
+
+    /**
+     * Converts a String to a whole number.
+     *
+     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
+     */
+    BS_UTILITY_EXPORT UINT32 parseUINT32(const String& val, UINT32 defaultValue = 0);
+
+    /**
+     * Converts a String to a whole number.
+     *
+     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
+     */
+    BS_UTILITY_EXPORT INT64 parseINT64(const String& val, INT64 defaultValue = 0);
+
+    /**
+     * Converts a String to a whole number.
+     *
+     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
+     */
+    BS_UTILITY_EXPORT UINT64 parseUINT64(const String& val, UINT64 defaultValue = 0);
+
+    /**
+     * Converts a String to a boolean.
+     *
+	 * @note	Returns true if case-insensitive match of the start of the string matches "true", "yes" or "1", 
+	 *			false otherwise.
+     */
+    BS_UTILITY_EXPORT bool parseBool(const String& val, bool defaultValue = 0);
+
+    /** Checks the String is a valid number value. */
+    BS_UTILITY_EXPORT bool isNumber(const String& val);
+
+    /**
+     * Converts a WString to a float.
+     *
+     * @note	0.0f if the value could not be parsed, otherwise the numeric version of the string.
+     */
+    BS_UTILITY_EXPORT float parseFloat(const WString& val, float defaultValue = 0);
+
+    /**
+     * Converts a WString to a whole number.
+     *
+     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
+     */
+    BS_UTILITY_EXPORT INT32 parseINT32(const WString& val, INT32 defaultValue = 0);
+
+    /**
+     * Converts a WString to a whole number.
+     *
+     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
+     */
+    BS_UTILITY_EXPORT UINT32 parseUINT32(const WString& val, UINT32 defaultValue = 0);
+
+    /**
+     * Converts a WString to a whole number.
+     *
+     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
+     */
+    BS_UTILITY_EXPORT INT64 parseINT64(const WString& val, INT64 defaultValue = 0);
+
+    /**
+     * Converts a WString to a whole number.
+     *
+     * @note	0 if the value could not be parsed, otherwise the numeric version of the string.
+     */
+    BS_UTILITY_EXPORT UINT64 parseUINT64(const WString& val, UINT64 defaultValue = 0);
+
+    /**
+     * Converts a WString to a boolean.
+     *
+	 * @note	Returns true if case-insensitive match of the start of the string
+	 *			matches "true", "yes" or "1", false otherwise.
+     */
+    BS_UTILITY_EXPORT bool parseBool(const WString& val, bool defaultValue = 0);
+
+    /**
+     * Checks the WString is a valid number value.
+     */
+    BS_UTILITY_EXPORT bool isNumber(const WString& val);
+
+	/** @name Internal 
+	 *  @{
+	 */
+
+	/** Helper method that throws an exception regarding a data overflow. */
+	void BS_UTILITY_EXPORT __string_throwDataOverflowException();
+
+	/** @} */
+	/** @cond SPECIALIZATIONS */
+
+	/**
+	 * RTTIPlainType specialization for String that allows strings be serialized as value types.
+	 * 			
+	 * @see		RTTIPlainType
+	 */
+	template<> struct RTTIPlainType<String>
+	{	
+		enum { id = 20 }; enum { hasDynamicSize = 1 };
+
+		static void toMemory(const 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 UINT32 fromMemory(String& data, char* memory)
+		{ 
+			UINT32 size;
+			memcpy(&size, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			UINT32 stringSize = size - sizeof(UINT32);
+			char* buffer = (char*)bs_alloc(stringSize + 1);
+			memcpy(buffer, memory, stringSize); 
+			buffer[stringSize] = '\0';
+			data = String(buffer);
+
+			bs_free(buffer);
+
+			return size;
+		}
+
+		static UINT32 getDynamicSize(const String& data)	
+		{ 
+			UINT64 dataSize = data.size() * sizeof(String::value_type) + sizeof(UINT32);
+
+#if BS_DEBUG_MODE
+			if(dataSize > std::numeric_limits<UINT32>::max())
+			{
+				__string_throwDataOverflowException();
+			}
+#endif
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
+	/**
+	 * RTTIPlainType specialization for WString that allows strings be serialized as value types.
+	 * 			
+	 * @see		RTTIPlainType
+	 */
+	template<> struct RTTIPlainType<WString>
+	{	
+		enum { id = TID_WString }; enum { hasDynamicSize = 1 };
+
+		static void toMemory(const WString& data, char* memory)
+		{ 
+			UINT32 size = getDynamicSize(data);
+
+			memcpy(memory, &size, sizeof(UINT32));
+			memory += sizeof(UINT32);
+			size -= sizeof(UINT32);
+			memcpy(memory, data.data(), size); 
+		}
+
+		static UINT32 fromMemory(WString& data, char* memory)
+		{ 
+			UINT32 size;
+			memcpy(&size, memory, sizeof(UINT32)); 
+			memory += sizeof(UINT32);
+
+			UINT32 stringSize = size - sizeof(UINT32);
+			WString::value_type* buffer = (WString::value_type*)bs_alloc(stringSize + sizeof(WString::value_type));
+			memcpy(buffer, memory, stringSize); 
+
+			UINT32 numChars =  stringSize / sizeof(WString::value_type);
+			buffer[numChars] = L'\0';
+
+			data = WString(buffer);
+
+			bs_free(buffer);
+
+			return size;
+		}
+
+		static UINT32 getDynamicSize(const WString& data)	
+		{ 
+			UINT64 dataSize = data.size() * sizeof(WString::value_type) + sizeof(UINT32);
+
+#if BS_DEBUG_MODE
+			if(dataSize > std::numeric_limits<UINT32>::max())
+			{
+				__string_throwDataOverflowException();
+			}
+#endif
+
+			return (UINT32)dataSize;
+		}	
+	}; 
+
+	/** @endcond */
+	/** @} */
+}
+
+/** @cond STDLIB */
+
+/** Hash value generator for String. */
+template<> 
+struct std::hash<BansheeEngine::String>
+{
+	size_t operator()(const BansheeEngine::String& string) const
+	{
+		size_t hash = 0;
+		for(size_t i = 0; i < string.size(); i++) 
+			hash = 65599 * hash + string[i];
+		return hash ^ (hash >> 16);
+	}
+};
+
+/**	Hash value generator for WString. */
+template<> 
+struct std::hash<BansheeEngine::WString>
+{
+	size_t operator()(const BansheeEngine::WString& string) const
+	{
+		size_t hash = 0;
+		for(size_t i = 0; i < string.size(); i++) 
+			hash = 65599 * hash + string[i];
+		return hash ^ (hash >> 16);
+	}
+};
+
+/** @endcond */

+ 13 - 6
Source/BansheeUtility/Include/BsStringFormat.h

@@ -2,8 +2,11 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 namespace BansheeEngine
 {
-	/** @cond INTERNAL */
-	/** @addtogroup String
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup String-Internal
 	 *  @{
 	 */
 
@@ -41,9 +44,13 @@ namespace BansheeEngine
 		 * represented like "{0}, {1}" in the source string, where the number represents the position of the parameter 
 		 * that will be used for replacing the identifier.
 		 *			
-		 * @note	You may use "\" to escape identifier brackets.
-		 * @note	Maximum identifier number is 19 (for a total of 20 unique identifiers. e.g. {20} won't be recognized as an identifier).
-		 * @note	Total number of parameters that can be referenced is 200.
+		 * @note	
+		 * You may use "\" to escape identifier brackets.
+		 * @note
+		 * Maximum identifier number is 19 (for a total of 20 unique identifiers. for example {20} won't be recognized as
+		 * an identifier).
+		 * @note	
+		 * Total number of parameters that can be referenced is 200.
 		 */
 		template<class T, class... Args>
 		static BasicString<T> format(const T* source, Args&& ...args)
@@ -277,5 +284,5 @@ namespace BansheeEngine
 	};
 
 	/** @} */
-	/** @endcond */
+	/** @} */
 }

+ 9 - 7
Source/BansheeUtility/Include/BsTestSuite.h

@@ -4,9 +4,13 @@
 
 #include "BsPrerequisitesUtil.h"
 
-/** @addtogroup Testing
- *  @{
- */
+
+
+namespace BansheeEngine
+{
+	/** @addtogroup Testing
+	 *  @{
+	 */
 
 /** Tests if condition is true, and reports unit test failure if it fails. */
 #define BS_TEST_ASSERT(expr) assertment((expr), "", __FILE__, __LINE__); 
@@ -14,8 +18,6 @@
 /** Tests if condition is true, and reports unit test failure with a message if it fails. */
 #define BS_TEST_ASSERT_MSG(expr, msg) assertment((expr), msg, __FILE__, __LINE__); 
 
-namespace BansheeEngine
-{
 	/**
 	 * Primary class for unit testing. Override and register unit tests in constructor then run the tests using the 
 	 * desired method of output.
@@ -86,9 +88,9 @@ namespace BansheeEngine
 		TestOutput* mOutput;
 		String mActiveTestName;
 	};
-}
 
 /** Registers a new unit test within an implementation of TestSuite. */
 #define BS_ADD_TEST(func) addTest(static_cast<Func>(&func), #func);
 
-/** @} */
+	/** @} */
+}

+ 110 - 110
Source/BansheeUtility/Include/BsTexAtlasGenerator.h

@@ -1,111 +1,111 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector2.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Image
-	 *  @{
-	 */
-
-	/**
-	 * Represents a single element used as in input to TexAtlasGenerator. Usually represents a single texture.
-	 * 			
-	 * @note	input is required to be filled in before passing it to TexAtlasGenerator.
-	 * @note	output will be filled in by TexAtlasGenerator after a call to TexAtlasGenerator::createAtlasLayout().
-	 */
-	struct TexAtlasElementDesc
-	{
-		struct
-		{
-			UINT32 width, height;
-		} input;
-		
-		struct
-		{
-			UINT32 x, y;
-			INT32 page;
-		} output;
-	};
-
-	/** A single page of the texture atlas. */
-	struct TexAtlasPageDesc
-	{
-		UINT32 width, height;
-	};
-
-	class TexAtlasNode;
-
-	/** Organizes a set of textures into a single larger texture (an atlas) by minimizing empty space. */
-	class BS_UTILITY_EXPORT TexAtlasGenerator
-	{
-	public:
-		/**
-		 * Constructs a new texture atlas generator with the provided parameters.
-		 *
-		 * @param[in]	square			(optional) Should the returned texture always be square. (width == height)
-		 * 								This option is only used if @p fixedSize parameter is set to false.
-		 * @param[in]	maxTexWidth 	(optional) Maximum width of the texture. 
-		 * @param[in]	maxTexHeight	(optional) Maximum height of the texture. 
-		 * @param[in]	fixedSize   	(optional) If this field is false, algorithm will try to reduce the size of the texture
-		 * 								if possible. If it is true, the algorithm will always produce textures of the specified
-		 * 								@p maxTexWidth, @p maxTexHeight size.
-		 */
-		TexAtlasGenerator(bool square = false, UINT32 maxTexWidth = 2048, UINT32 maxTexHeight = 2048, bool fixedSize = false);
-
-		/**
-		 * Creates an optimal texture layout by packing texture elements in order to end up with as little empty space 
-		 * as possible.
-		 *
-		 * @param[in]	elements	Elements to process. They need to have their input structures filled in,
-		 * 							and this method will fill output when it returns.
-		 * @return					One or more descriptors that determine the size of the final atlas textures. 
-		 *							Texture elements will reference these pages with their output.page parameter.
-		 *
-		 * @note	
-		 * Algorithm will split elements over multiple textures if they don't fit in a single texture (Determined by 
-		 * maximum texture size).
-		 */
-		Vector<TexAtlasPageDesc> createAtlasLayout(Vector<TexAtlasElementDesc>& elements) const;
-
-	private:
-		bool mSquare;
-		bool mFixedSize;
-		UINT32 mMaxTexWidth;
-		UINT32 mMaxTexHeight;
-
-		/**
-		 * Organize all of the provide elements and place them into minimum number of pages with the specified width and height.
-		 * 			
-		 * Caller must ensure @p elements array has the page indexes reset to -1 before calling, otherwise it will be assumed
-		 * those elements already have assigned pages.
-		 * 			
-		 * Using @p startPage parameter you may add an offset to the generated page indexes.
-		 *
-		 * @return	Number of pages generated.
-		 */
-		int generatePagesForSize(Vector<TexAtlasElementDesc>& elements, UINT32 width, UINT32 height, UINT32 startPage = 0) const;
-
-		/**
-		 * Finds the largest element without a page that fits within the provided node.
-		 *
-		 * @return	Array index of the found page, or -1 if all textures have a page.
-		 */
-		int addLargestTextureWithoutPageThatFits(Vector<TexAtlasElementDesc>& elements, TexAtlasNode& node) const;
-
-		/**
-		 * Scan all of the provided elements and find the largest one that still doesn't have a page assigned.
-		 * 			
-		 * @return	Array index of the found page, or -1 if all textures have a page.
-		 */
-		int findLargestTextureWithoutPage(const Vector<TexAtlasElementDesc>& elements) const;
-
-		/** Sorts all the texture elements so that larget elements come first. */
-		void sortBySize(Vector<TexAtlasElementDesc>& elements) const;
-	};
-
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector2.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Image
+	 *  @{
+	 */
+
+	/**
+	 * Represents a single element used as in input to TexAtlasGenerator. Usually represents a single texture.
+	 * 			
+	 * @note	input is required to be filled in before passing it to TexAtlasGenerator.
+	 * @note	output will be filled in by TexAtlasGenerator after a call to TexAtlasGenerator::createAtlasLayout().
+	 */
+	struct TexAtlasElementDesc
+	{
+		struct
+		{
+			UINT32 width, height;
+		} input;
+		
+		struct
+		{
+			UINT32 x, y;
+			INT32 page;
+		} output;
+	};
+
+	/** A single page of the texture atlas. */
+	struct TexAtlasPageDesc
+	{
+		UINT32 width, height;
+	};
+
+	class TexAtlasNode;
+
+	/** Organizes a set of textures into a single larger texture (an atlas) by minimizing empty space. */
+	class BS_UTILITY_EXPORT TexAtlasGenerator
+	{
+	public:
+		/**
+		 * Constructs a new texture atlas generator with the provided parameters.
+		 *
+		 * @param[in]	square			(optional) Should the returned texture always be square. (width == height)
+		 * 								This option is only used if @p fixedSize parameter is set to false.
+		 * @param[in]	maxTexWidth 	(optional) Maximum width of the texture. 
+		 * @param[in]	maxTexHeight	(optional) Maximum height of the texture. 
+		 * @param[in]	fixedSize   	(optional) If this field is false, algorithm will try to reduce the size of the texture
+		 * 								if possible. If it is true, the algorithm will always produce textures of the specified
+		 * 								@p maxTexWidth, @p maxTexHeight size.
+		 */
+		TexAtlasGenerator(bool square = false, UINT32 maxTexWidth = 2048, UINT32 maxTexHeight = 2048, bool fixedSize = false);
+
+		/**
+		 * Creates an optimal texture layout by packing texture elements in order to end up with as little empty space 
+		 * as possible.
+		 *
+		 * @param[in]	elements	Elements to process. They need to have their input structures filled in,
+		 * 							and this method will fill output when it returns.
+		 * @return					One or more descriptors that determine the size of the final atlas textures. 
+		 *							Texture elements will reference these pages with their output.page parameter.
+		 *
+		 * @note	
+		 * Algorithm will split elements over multiple textures if they don't fit in a single texture (Determined by 
+		 * maximum texture size).
+		 */
+		Vector<TexAtlasPageDesc> createAtlasLayout(Vector<TexAtlasElementDesc>& elements) const;
+
+	private:
+		bool mSquare;
+		bool mFixedSize;
+		UINT32 mMaxTexWidth;
+		UINT32 mMaxTexHeight;
+
+		/**
+		 * Organize all of the provide elements and place them into minimum number of pages with the specified width and height.
+		 * 			
+		 * Caller must ensure @p elements array has the page indexes reset to -1 before calling, otherwise it will be assumed
+		 * those elements already have assigned pages.
+		 * 			
+		 * Using @p startPage parameter you may add an offset to the generated page indexes.
+		 *
+		 * @return	Number of pages generated.
+		 */
+		int generatePagesForSize(Vector<TexAtlasElementDesc>& elements, UINT32 width, UINT32 height, UINT32 startPage = 0) const;
+
+		/**
+		 * Finds the largest element without a page that fits within the provided node.
+		 *
+		 * @return	Array index of the found page, or -1 if all textures have a page.
+		 */
+		int addLargestTextureWithoutPageThatFits(Vector<TexAtlasElementDesc>& elements, TexAtlasNode& node) const;
+
+		/**
+		 * Scan all of the provided elements and find the largest one that still doesn't have a page assigned.
+		 * 			
+		 * @return	Array index of the found page, or -1 if all textures have a page.
+		 */
+		int findLargestTextureWithoutPage(const Vector<TexAtlasElementDesc>& elements) const;
+
+		/** Sorts all the texture elements so that larget elements come first. */
+		void sortBySize(Vector<TexAtlasElementDesc>& elements) const;
+	};
+
+	/** @} */
 }

+ 23 - 4
Source/BansheeUtility/Include/BsThreadPool.h

@@ -28,7 +28,14 @@ namespace BansheeEngine
 		ThreadPool* mPool;
 	};
 
-	/** @cond INTERNAL */
+	/** @} */
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Threading-Internal
+	 *  @{
+	 */
 
 	/**	Wrapper around a thread that is used within ThreadPool. */
 	class BS_UTILITY_EXPORT PooledThread
@@ -127,7 +134,12 @@ namespace BansheeEngine
 		}
 	};
 
-	/** @endcond */
+	/** @} */
+	/** @} */
+
+	/** @addtogroup Threading
+	 *  @{
+	 */
 
 	/**
 	 * Class that maintains a pool of threads we can easily retrieve and use for any task. This saves on the cost of 
@@ -203,7 +215,14 @@ namespace BansheeEngine
 		BS_MUTEX(mMutex);
 	};
 
-	/** @cond INTERNAL */
+	/** @} */
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Threading-Internal
+	 *  @{
+	 */
 
 	/** Policy used for thread start & end used by the ThreadPool. */
 	class ThreadNoPolicy
@@ -240,6 +259,6 @@ namespace BansheeEngine
 		}
 	};
 
-	/** @endcond */
+	/** @} */
 	/** @} */
 }

+ 401 - 401
Source/BansheeUtility/Include/BsVector3.h

@@ -1,401 +1,401 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsRadian.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Math
-	 *  @{
-	 */
-
-	/** A three dimensional vector. */
-    class BS_UTILITY_EXPORT Vector3
-    {
-    public:
-		float x, y, z;
-
-    public:
-        Vector3()
-			:x(0.0f), y(0.0f), z(0.0f)
-        { }
-
-        Vector3(float x, float y, float z)
-            :x(x), y(y), z(z)
-        { }
-
-		explicit Vector3(const Vector4& vec);
-
-		/** Exchange the contents of this vector with another. */
-		void swap(Vector3& other)
-		{
-			std::swap(x, other.x);
-			std::swap(y, other.y);
-			std::swap(z, other.z);
-		}
-
-		float operator[] (UINT32 i) const
-        {
-            assert(i < 3);
-
-            return *(&x+i);
-        }
-
-		float& operator[] (UINT32 i)
-        {
-            assert(i < 3);
-
-            return *(&x+i);
-        }
-
-		/** Pointer accessor for direct copying. */
-		float* ptr()
-		{
-			return &x;
-		}
-
-		/** Pointer accessor for direct copying. */
-		const float* ptr() const
-		{
-			return &x;
-		}
-
-        Vector3& operator= (const Vector3& rhs)
-        {
-            x = rhs.x;
-            y = rhs.y;
-            z = rhs.z;
-
-            return *this;
-        }
-
-        Vector3& operator= (float rhs)
-        {
-            x = rhs;
-            y = rhs;
-            z = rhs;
-
-            return *this;
-        }
-
-        bool operator== (const Vector3& rhs) const
-        {
-            return (x == rhs.x && y == rhs.y && z == rhs.z);
-        }
-
-        bool operator!= (const Vector3& rhs) const
-        {
-            return (x != rhs.x || y != rhs.y || z != rhs.z);
-        }
-
-        Vector3 operator+ (const Vector3& rhs) const
-        {
-            return Vector3(x + rhs.x, y + rhs.y, z + rhs.z);
-        }
-
-        Vector3 operator- (const Vector3& rhs) const
-        {
-            return Vector3(x - rhs.x, y - rhs.y, z - rhs.z);
-        }
-
-        Vector3 operator* (float rhs) const
-        {
-            return Vector3(x * rhs, y * rhs, z * rhs);
-        }
-
-        Vector3 operator* (const Vector3& rhs) const
-        {
-            return Vector3(x * rhs.x, y * rhs.y, z * rhs.z);
-        }
-
-        Vector3 operator/ (float val) const
-        {
-            assert(val != 0.0);
-
-            float fInv = 1.0f / val;
-            return Vector3(x * fInv, y * fInv, z * fInv);
-        }
-
-        Vector3 operator/ (const Vector3& rhs) const
-        {
-            return Vector3(x / rhs.x, y / rhs.y, z / rhs.z);
-        }
-
-        const Vector3& operator+ () const
-        {
-            return *this;
-        }
-
-        Vector3 operator- () const
-        {
-            return Vector3(-x, -y, -z);
-        }
-
-        friend Vector3 operator* (float lhs, const Vector3& rhs)
-        {
-            return Vector3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
-        }
-
-        friend Vector3 operator/ (float lhs, const Vector3& rhs)
-        {
-            return Vector3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z);
-        }
-
-        friend Vector3 operator+ (const Vector3& lhs, float rhs)
-        {
-            return Vector3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs);
-        }
-
-        friend Vector3 operator+ (float lhs, const Vector3& rhs)
-        {
-            return Vector3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z);
-        }
-
-        friend Vector3 operator- (const Vector3& lhs, float rhs)
-        {
-            return Vector3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs);
-        }
-
-        friend Vector3 operator- (float lhs, const Vector3& rhs)
-        {
-            return Vector3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z);
-        }
-
-        Vector3& operator+= (const Vector3& rhs)
-        {
-            x += rhs.x;
-            y += rhs.y;
-            z += rhs.z;
-
-            return *this;
-        }
-
-        Vector3& operator+= (float rhs)
-        {
-            x += rhs;
-            y += rhs;
-            z += rhs;
-
-            return *this;
-        }
-
-        Vector3& operator-= (const Vector3& rhs)
-        {
-            x -= rhs.x;
-            y -= rhs.y;
-            z -= rhs.z;
-
-            return *this;
-        }
-
-        Vector3& operator-= (float rhs)
-        {
-            x -= rhs;
-            y -= rhs;
-            z -= rhs;
-
-            return *this;
-        }
-
-        Vector3& operator*= (float rhs)
-        {
-            x *= rhs;
-            y *= rhs;
-            z *= rhs;
-
-            return *this;
-        }
-
-        Vector3& operator*= (const Vector3& rhs)
-        {
-            x *= rhs.x;
-            y *= rhs.y;
-            z *= rhs.z;
-
-            return *this;
-        }
-
-        Vector3& operator/= (float rhs)
-        {
-            assert(rhs != 0.0f);
-
-            float inv = 1.0f / rhs;
-
-            x *= inv;
-            y *= inv;
-            z *= inv;
-
-            return *this;
-        }
-
-        Vector3& operator/= (const Vector3& rhs)
-        {
-            x /= rhs.x;
-            y /= rhs.y;
-            z /= rhs.z;
-
-            return *this;
-        }
-
-        /** Returns the length (magnitude) of the vector. */
-		inline float length() const;
-
-        /** Returns the square of the length(magnitude) of the vector. */
-        float squaredLength() const
-        {
-            return x * x + y * y + z * z;
-        }
-
-        /**	Returns the distance to another vector. */
-        float distance(const Vector3& rhs) const
-        {
-            return (*this - rhs).length();
-        }
-
-        /** Returns the square of the distance to another vector. */
-        float squaredDistance(const Vector3& rhs) const
-        {
-            return (*this - rhs).squaredLength();
-        }
-
-        /** Calculates the dot (scalar) product of this vector with another. */
-        float dot(const Vector3& vec) const
-        {
-            return x * vec.x + y * vec.y + z * vec.z;
-        }
-
-        /** Normalizes the vector. */
-		inline float normalize();
-
-        /** Calculates the cross-product of 2 vectors, i.e. the vector that lies perpendicular to them both. */
-        Vector3 cross(const Vector3& other) const
-        {
-            return Vector3(
-                y * other.z - z * other.y,
-                z * other.x - x * other.z,
-                x * other.y - y * other.x);
-        }
-
-        /** Sets this vector's components to the minimum of its own and the ones of the passed in vector. */
-        void floor(const Vector3& cmp)
-        {
-            if(cmp.x < x) x = cmp.x;
-            if(cmp.y < y) y = cmp.y;
-            if(cmp.z < z) z = cmp.z;
-        }
-
-        /** Sets this vector's components to the maximum of its own and the ones of the passed in vector. */
-        void ceil(const Vector3& cmp)
-        {
-            if(cmp.x > x) x = cmp.x;
-            if(cmp.y > y) y = cmp.y;
-            if(cmp.z > z) z = cmp.z;
-        }
-
-        /** Generates a vector perpendicular to this vector. */
-        Vector3 perpendicular() const
-        {
-            static const float squareZero = (float)(1e-06 * 1e-06);
-
-            Vector3 perp = this->cross(Vector3::UNIT_X);
-
-            if(perp.squaredLength() < squareZero)
-                perp = this->cross(Vector3::UNIT_Y);
-
-			perp.normalize();
-            return perp;
-        }
-
-		/** Gets the angle between 2 vectors. */
-		inline Radian angleBetween(const Vector3& dest) const;
-
-        /** Returns true if this vector is zero length. */
-        bool isZeroLength() const
-        {
-            float sqlen = (x * x) + (y * y) + (z * z);
-            return (sqlen < (1e-06 * 1e-06));
-        }
-
-        /** Calculates a reflection vector to the plane with the given normal. */
-        Vector3 reflect(const Vector3& normal) const
-        {
-            return Vector3(*this - (2 * this->dot(normal) * normal));
-        }
-
-		/** Calculates two vectors orthonormal to the current vector, and normalizes the current vector if not already. */
-		void orthogonalComplement(Vector3& a, Vector3& b)
-		{
-			if (fabs(x) > fabs(y))
-				a = Vector3(-z, 0, x);
-			else
-				a = Vector3(0, z, -y);
-
-			b = cross(a);
-
-			orthonormalize(*this, a, b);
-		}
-
-		/** Performs Gram-Schmidt orthonormalization. */
-		static void orthonormalize(Vector3& vec0, Vector3& vec1, Vector3& vec2)
-		{
-			vec0.normalize();
-
-			float dot0 = vec0.dot(vec1); 
-			vec1 -= dot0*vec0;
-			vec1.normalize();
-
-			float dot1 = vec1.dot(vec2);
-			dot0 = vec0.dot(vec2);
-			vec2 -= dot0*vec0 + dot1*vec1;
-			vec2.normalize();
-		}
-
-        /** Calculates the dot (scalar) product of two vectors. */
-		static float dot(const Vector3& a, const Vector3& b)
-		{
-			return a.x * b.x + a.y * b.y + a.z * b.z;
-		}
-
-		/** Normalizes the provided vector and returns a new normalized instance. */
-		static Vector3 normalize(const Vector3& val);
-
-		/** Calculates the cross-product of 2 vectors, i.e. the vector that lies perpendicular to them both. */
-		static Vector3 cross(const Vector3& a, const Vector3& b)
-        {
-            return Vector3(
-				a.y * b.z - a.z * b.y,
-				a.z * b.x - a.x * b.z,
-				a.x * b.y - a.y * b.x);
-        }
-
-		/** Checks are any of the vector components not a number. */
-		inline bool isNaN() const;
-
-		/** Returns the minimum of all the vector components as a new vector. */
-		static Vector3 min(const Vector3& a, const Vector3& b)
-		{
-			return Vector3(std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z));
-		}
-
-		/** Returns the maximum of all the vector components as a new vector. */
-		static Vector3 max(const Vector3& a, const Vector3& b)
-		{
-			return Vector3(std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z));
-		}
-
-        static const Vector3 ZERO;
-		static const Vector3 ONE;
-		static const Vector3 INF;
-        static const Vector3 UNIT_X;
-        static const Vector3 UNIT_Y;
-        static const Vector3 UNIT_Z;
-    };
-
-	/** @} */
-
-	/** @cond SPECIALIZATIONS */
-	BS_ALLOW_MEMCPY_SERIALIZATION(Vector3);
-	/** @endcond */
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsRadian.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Math
+	 *  @{
+	 */
+
+	/** A three dimensional vector. */
+    class BS_UTILITY_EXPORT Vector3
+    {
+    public:
+		float x, y, z;
+
+    public:
+        Vector3()
+			:x(0.0f), y(0.0f), z(0.0f)
+        { }
+
+        Vector3(float x, float y, float z)
+            :x(x), y(y), z(z)
+        { }
+
+		explicit Vector3(const Vector4& vec);
+
+		/** Exchange the contents of this vector with another. */
+		void swap(Vector3& other)
+		{
+			std::swap(x, other.x);
+			std::swap(y, other.y);
+			std::swap(z, other.z);
+		}
+
+		float operator[] (UINT32 i) const
+        {
+            assert(i < 3);
+
+            return *(&x+i);
+        }
+
+		float& operator[] (UINT32 i)
+        {
+            assert(i < 3);
+
+            return *(&x+i);
+        }
+
+		/** Pointer accessor for direct copying. */
+		float* ptr()
+		{
+			return &x;
+		}
+
+		/** Pointer accessor for direct copying. */
+		const float* ptr() const
+		{
+			return &x;
+		}
+
+        Vector3& operator= (const Vector3& rhs)
+        {
+            x = rhs.x;
+            y = rhs.y;
+            z = rhs.z;
+
+            return *this;
+        }
+
+        Vector3& operator= (float rhs)
+        {
+            x = rhs;
+            y = rhs;
+            z = rhs;
+
+            return *this;
+        }
+
+        bool operator== (const Vector3& rhs) const
+        {
+            return (x == rhs.x && y == rhs.y && z == rhs.z);
+        }
+
+        bool operator!= (const Vector3& rhs) const
+        {
+            return (x != rhs.x || y != rhs.y || z != rhs.z);
+        }
+
+        Vector3 operator+ (const Vector3& rhs) const
+        {
+            return Vector3(x + rhs.x, y + rhs.y, z + rhs.z);
+        }
+
+        Vector3 operator- (const Vector3& rhs) const
+        {
+            return Vector3(x - rhs.x, y - rhs.y, z - rhs.z);
+        }
+
+        Vector3 operator* (float rhs) const
+        {
+            return Vector3(x * rhs, y * rhs, z * rhs);
+        }
+
+        Vector3 operator* (const Vector3& rhs) const
+        {
+            return Vector3(x * rhs.x, y * rhs.y, z * rhs.z);
+        }
+
+        Vector3 operator/ (float val) const
+        {
+            assert(val != 0.0);
+
+            float fInv = 1.0f / val;
+            return Vector3(x * fInv, y * fInv, z * fInv);
+        }
+
+        Vector3 operator/ (const Vector3& rhs) const
+        {
+            return Vector3(x / rhs.x, y / rhs.y, z / rhs.z);
+        }
+
+        const Vector3& operator+ () const
+        {
+            return *this;
+        }
+
+        Vector3 operator- () const
+        {
+            return Vector3(-x, -y, -z);
+        }
+
+        friend Vector3 operator* (float lhs, const Vector3& rhs)
+        {
+            return Vector3(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
+        }
+
+        friend Vector3 operator/ (float lhs, const Vector3& rhs)
+        {
+            return Vector3(lhs / rhs.x, lhs / rhs.y, lhs / rhs.z);
+        }
+
+        friend Vector3 operator+ (const Vector3& lhs, float rhs)
+        {
+            return Vector3(lhs.x + rhs, lhs.y + rhs, lhs.z + rhs);
+        }
+
+        friend Vector3 operator+ (float lhs, const Vector3& rhs)
+        {
+            return Vector3(lhs + rhs.x, lhs + rhs.y, lhs + rhs.z);
+        }
+
+        friend Vector3 operator- (const Vector3& lhs, float rhs)
+        {
+            return Vector3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs);
+        }
+
+        friend Vector3 operator- (float lhs, const Vector3& rhs)
+        {
+            return Vector3(lhs - rhs.x, lhs - rhs.y, lhs - rhs.z);
+        }
+
+        Vector3& operator+= (const Vector3& rhs)
+        {
+            x += rhs.x;
+            y += rhs.y;
+            z += rhs.z;
+
+            return *this;
+        }
+
+        Vector3& operator+= (float rhs)
+        {
+            x += rhs;
+            y += rhs;
+            z += rhs;
+
+            return *this;
+        }
+
+        Vector3& operator-= (const Vector3& rhs)
+        {
+            x -= rhs.x;
+            y -= rhs.y;
+            z -= rhs.z;
+
+            return *this;
+        }
+
+        Vector3& operator-= (float rhs)
+        {
+            x -= rhs;
+            y -= rhs;
+            z -= rhs;
+
+            return *this;
+        }
+
+        Vector3& operator*= (float rhs)
+        {
+            x *= rhs;
+            y *= rhs;
+            z *= rhs;
+
+            return *this;
+        }
+
+        Vector3& operator*= (const Vector3& rhs)
+        {
+            x *= rhs.x;
+            y *= rhs.y;
+            z *= rhs.z;
+
+            return *this;
+        }
+
+        Vector3& operator/= (float rhs)
+        {
+            assert(rhs != 0.0f);
+
+            float inv = 1.0f / rhs;
+
+            x *= inv;
+            y *= inv;
+            z *= inv;
+
+            return *this;
+        }
+
+        Vector3& operator/= (const Vector3& rhs)
+        {
+            x /= rhs.x;
+            y /= rhs.y;
+            z /= rhs.z;
+
+            return *this;
+        }
+
+        /** Returns the length (magnitude) of the vector. */
+		inline float length() const;
+
+        /** Returns the square of the length(magnitude) of the vector. */
+        float squaredLength() const
+        {
+            return x * x + y * y + z * z;
+        }
+
+        /**	Returns the distance to another vector. */
+        float distance(const Vector3& rhs) const
+        {
+            return (*this - rhs).length();
+        }
+
+        /** Returns the square of the distance to another vector. */
+        float squaredDistance(const Vector3& rhs) const
+        {
+            return (*this - rhs).squaredLength();
+        }
+
+        /** Calculates the dot (scalar) product of this vector with another. */
+        float dot(const Vector3& vec) const
+        {
+            return x * vec.x + y * vec.y + z * vec.z;
+        }
+
+        /** Normalizes the vector. */
+		inline float normalize();
+
+        /** Calculates the cross-product of 2 vectors, that is, the vector that lies perpendicular to them both. */
+        Vector3 cross(const Vector3& other) const
+        {
+            return Vector3(
+                y * other.z - z * other.y,
+                z * other.x - x * other.z,
+                x * other.y - y * other.x);
+        }
+
+        /** Sets this vector's components to the minimum of its own and the ones of the passed in vector. */
+        void floor(const Vector3& cmp)
+        {
+            if(cmp.x < x) x = cmp.x;
+            if(cmp.y < y) y = cmp.y;
+            if(cmp.z < z) z = cmp.z;
+        }
+
+        /** Sets this vector's components to the maximum of its own and the ones of the passed in vector. */
+        void ceil(const Vector3& cmp)
+        {
+            if(cmp.x > x) x = cmp.x;
+            if(cmp.y > y) y = cmp.y;
+            if(cmp.z > z) z = cmp.z;
+        }
+
+        /** Generates a vector perpendicular to this vector. */
+        Vector3 perpendicular() const
+        {
+            static const float squareZero = (float)(1e-06 * 1e-06);
+
+            Vector3 perp = this->cross(Vector3::UNIT_X);
+
+            if(perp.squaredLength() < squareZero)
+                perp = this->cross(Vector3::UNIT_Y);
+
+			perp.normalize();
+            return perp;
+        }
+
+		/** Gets the angle between 2 vectors. */
+		inline Radian angleBetween(const Vector3& dest) const;
+
+        /** Returns true if this vector is zero length. */
+        bool isZeroLength() const
+        {
+            float sqlen = (x * x) + (y * y) + (z * z);
+            return (sqlen < (1e-06 * 1e-06));
+        }
+
+        /** Calculates a reflection vector to the plane with the given normal. */
+        Vector3 reflect(const Vector3& normal) const
+        {
+            return Vector3(*this - (2 * this->dot(normal) * normal));
+        }
+
+		/** Calculates two vectors orthonormal to the current vector, and normalizes the current vector if not already. */
+		void orthogonalComplement(Vector3& a, Vector3& b)
+		{
+			if (fabs(x) > fabs(y))
+				a = Vector3(-z, 0, x);
+			else
+				a = Vector3(0, z, -y);
+
+			b = cross(a);
+
+			orthonormalize(*this, a, b);
+		}
+
+		/** Performs Gram-Schmidt orthonormalization. */
+		static void orthonormalize(Vector3& vec0, Vector3& vec1, Vector3& vec2)
+		{
+			vec0.normalize();
+
+			float dot0 = vec0.dot(vec1); 
+			vec1 -= dot0*vec0;
+			vec1.normalize();
+
+			float dot1 = vec1.dot(vec2);
+			dot0 = vec0.dot(vec2);
+			vec2 -= dot0*vec0 + dot1*vec1;
+			vec2.normalize();
+		}
+
+        /** Calculates the dot (scalar) product of two vectors. */
+		static float dot(const Vector3& a, const Vector3& b)
+		{
+			return a.x * b.x + a.y * b.y + a.z * b.z;
+		}
+
+		/** Normalizes the provided vector and returns a new normalized instance. */
+		static Vector3 normalize(const Vector3& val);
+
+		/** Calculates the cross-product of 2 vectors, that is, the vector that lies perpendicular to them both. */
+		static Vector3 cross(const Vector3& a, const Vector3& b)
+        {
+            return Vector3(
+				a.y * b.z - a.z * b.y,
+				a.z * b.x - a.x * b.z,
+				a.x * b.y - a.y * b.x);
+        }
+
+		/** Checks are any of the vector components not a number. */
+		inline bool isNaN() const;
+
+		/** Returns the minimum of all the vector components as a new vector. */
+		static Vector3 min(const Vector3& a, const Vector3& b)
+		{
+			return Vector3(std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z));
+		}
+
+		/** Returns the maximum of all the vector components as a new vector. */
+		static Vector3 max(const Vector3& a, const Vector3& b)
+		{
+			return Vector3(std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z));
+		}
+
+        static const Vector3 ZERO;
+		static const Vector3 ONE;
+		static const Vector3 INF;
+        static const Vector3 UNIT_X;
+        static const Vector3 UNIT_Y;
+        static const Vector3 UNIT_Z;
+    };
+
+	/** @} */
+
+	/** @cond SPECIALIZATIONS */
+	BS_ALLOW_MEMCPY_SERIALIZATION(Vector3);
+	/** @endcond */
+}

+ 29 - 26
Source/BansheeUtility/Include/Win32/BsWin32PlatformUtility.h

@@ -1,27 +1,30 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-#include "BsPrerequisitesUtil.h"
-#include <windows.h>
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup Platform-Utility
-	 *  @{
-	 */
-
-	/** Provides access to various Windows specific utility functions. */
-	class BS_UTILITY_EXPORT Win32PlatformUtility
-	{
-	public:
-		/**
-		 * Creates a new bitmap usable by various Win32 methods from the provided pixel data. Caller must ensure to call 
-		 * DeleteObject() on the bitmap handle when finished.
-		 */
-		static HBITMAP createBitmap(const Color* pixels, UINT32 width, UINT32 height, bool premultiplyAlpha);
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+#include "BsPrerequisitesUtil.h"
+#include <windows.h>
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Platform-Utility-Internal
+	 *  @{
+	 */
+
+	/** Provides access to various Windows specific utility functions. */
+	class BS_UTILITY_EXPORT Win32PlatformUtility
+	{
+	public:
+		/**
+		 * Creates a new bitmap usable by various Win32 methods from the provided pixel data. Caller must ensure to call 
+		 * DeleteObject() on the bitmap handle when finished.
+		 */
+		static HBITMAP createBitmap(const Color* pixels, UINT32 width, UINT32 height, bool premultiplyAlpha);
+	};
+
+	/** @} */
+	/** @} */
 }

+ 141 - 138
Source/BansheeUtility/Include/Win32/BsWin32Window.h

@@ -1,139 +1,142 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-#include "BsVector2I.h"
-#include "windows.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup Platform-Utility
-	 *  @{
-	 */
-
-	/**	Descriptor used for creating a platform specific native window. */
-	struct BS_UTILITY_EXPORT WINDOW_DESC
-	{
-		WINDOW_DESC()
-			: module(nullptr), monitor(nullptr), parent(nullptr), external(nullptr), width(0), height(0), fullscreen(false)
-			, hidden(false), left(-1), top(-1), title(""), border(WindowBorder::Normal), outerDimensions(false)
-			, enableDoubleClick(true), toolWindow(false), creationParams(nullptr), alphaBlending(false), modal(false)
-			, wndProc(nullptr), backgroundPixels(nullptr), backgroundWidth(0), backgroundHeight(0)
-		{ }
-
-		HINSTANCE module; /**< Instance to the local module. */
-		HMONITOR monitor; /**< Handle ot the monitor onto which to display the window. */
-		HWND parent; /**< Optional handle to the parent window if this window is to be a child of an existing window. */
-		HWND external; /**< Optional external window handle if the window was created externally. */
-		void* creationParams; /**< Parameter that will be passed through the WM_CREATE message. */
-		UINT32 width; /**< Width of the window in pixels. */
-		UINT32 height; /**< Height of the window in pixels. */
-		bool fullscreen; /**< Should the window be opened in fullscreen mode. */
-		bool hidden; /**< Should the window be hidden initially. */
-		INT32 left; /**< Window origin on X axis in pixels. -1 == screen center. Relative to provided monitor. */
-		INT32 top; /**< Window origin on Y axis in pixels. -1 == screen center. Relative to provided monitor. */
-		String title; /**< Title of the window. */
-		WindowBorder border; /**< Type of border to create the window with. */
-		bool outerDimensions; /**< Do our dimensions include space for things like title-bar and border. */
-		bool enableDoubleClick; /**< Does window accept double-clicks. */
-		/** Tool windows have a different style than normal windows and can be created with no border or title bar. */
-		bool toolWindow; 
-		/**
-		 * Optional background image to apply to the window. This must be a buffer of size 
-		 * backgroundWidth * backgroundHeight. 
-		 */
-		Color* backgroundPixels;
-		UINT32 backgroundWidth; /** Width of the background image. Only relevant if backgroundPixels is not null. */
-		UINT32 backgroundHeight; /** Width of the background image. Only relevant if backgroundPixels is not null. */
-		/** If true the window will support transparency based on the alpha channel of the background image. */
-		bool alphaBlending; 
-		bool modal; /**< When a modal window is open all other windows will be locked until modal window is closed. */
-		WNDPROC wndProc; /**< Pointer to a function that handles windows message processing. */
-	};
-
-	/**	Represents a Windows native window. */
-	class BS_UTILITY_EXPORT Win32Window
-	{
-	public:
-		Win32Window(const WINDOW_DESC& desc);
-		~Win32Window();
-
-		/**	Returns position of the left-most border of the window, relative to the screen. */
-		INT32 getLeft() const;
-
-		/**	Returns position of the top-most border of the window, relative to the screen. */
-		INT32 getTop() const;
-
-		/**	Returns width of the window in pixels. */
-		UINT32 getWidth() const;
-
-		/**	Returns height of the window in pixels. */
-		UINT32 getHeight() const;
-
-		/**	Returns the native window handle. */
-		HWND getHWnd() const;
-
-        /**	Hide or show the window. */
-        void setHidden(bool hidden);
-
-		/**	Restores or minimizes the window. */
-		void setActive(bool state);
-
-		/**	Minimizes the window to the taskbar. */
-		void minimize();
-
-		/**	Maximizes the window over the entire current screen. */
-		void maximize();
-
-		/**	Restores the window to original position and size if it is minimized or maximized. */
-		void restore();
-
-        /**	Change the size of the window. */
-        void resize(UINT32 width, UINT32 height);
-
-        /**	Reposition the window. */
-		void move(INT32 left, INT32 top);
-
-		/**	Converts screen position into window local position. */
-		Vector2I screenToWindowPos(const Vector2I& screenPos) const;
-
-		/**	Converts window local position to screen position. */
-		Vector2I windowToScreenPos(const Vector2I& windowPos) const;
-
-		/**	Returns the window style flags used for creating it. */
-		DWORD getStyle() const;
-
-		/**	Returns the extended window style flags used for creating it. */
-		DWORD getStyleEx() const;
-
-		/** Called when window is moved or resized externally. */
-		void _windowMovedOrResized();
-
-		/** 
-		 * Enables all open windows. Enabled windows can receive mouse and keyboard input. This includes even windows 
-		 * disabled because there is a modal window on top of them.
-		 */
-		void static _enableAllWindows();
-
-		/**
-		 * Restores disabled state of all windows that were disabled due to modal windows being on top of them. Companion
-		 * method to _enableAllWindows() that can help restore original state after it is called. 
-		 */
-		void static _restoreModalWindows();
-
-	private:
-		friend class Win32WindowManager;
-
-		struct Pimpl;
-		Pimpl* m;
-
-		static Vector<Win32Window*> sAllWindows;
-		static Vector<Win32Window*> sModalWindowStack;
-		static Mutex sWindowsMutex;
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsVector2I.h"
+#include "windows.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Internal-Utility
+	 *  @{
+	 */
+
+	/** @addtogroup Platform-Utility-Internal
+	 *  @{
+	 */
+
+	/**	Descriptor used for creating a platform specific native window. */
+	struct BS_UTILITY_EXPORT WINDOW_DESC
+	{
+		WINDOW_DESC()
+			: module(nullptr), monitor(nullptr), parent(nullptr), external(nullptr), width(0), height(0), fullscreen(false)
+			, hidden(false), left(-1), top(-1), title(""), border(WindowBorder::Normal), outerDimensions(false)
+			, enableDoubleClick(true), toolWindow(false), creationParams(nullptr), alphaBlending(false), modal(false)
+			, wndProc(nullptr), backgroundPixels(nullptr), backgroundWidth(0), backgroundHeight(0)
+		{ }
+
+		HINSTANCE module; /**< Instance to the local module. */
+		HMONITOR monitor; /**< Handle ot the monitor onto which to display the window. */
+		HWND parent; /**< Optional handle to the parent window if this window is to be a child of an existing window. */
+		HWND external; /**< Optional external window handle if the window was created externally. */
+		void* creationParams; /**< Parameter that will be passed through the WM_CREATE message. */
+		UINT32 width; /**< Width of the window in pixels. */
+		UINT32 height; /**< Height of the window in pixels. */
+		bool fullscreen; /**< Should the window be opened in fullscreen mode. */
+		bool hidden; /**< Should the window be hidden initially. */
+		INT32 left; /**< Window origin on X axis in pixels. -1 == screen center. Relative to provided monitor. */
+		INT32 top; /**< Window origin on Y axis in pixels. -1 == screen center. Relative to provided monitor. */
+		String title; /**< Title of the window. */
+		WindowBorder border; /**< Type of border to create the window with. */
+		bool outerDimensions; /**< Do our dimensions include space for things like title-bar and border. */
+		bool enableDoubleClick; /**< Does window accept double-clicks. */
+		/** Tool windows have a different style than normal windows and can be created with no border or title bar. */
+		bool toolWindow; 
+		/**
+		 * Optional background image to apply to the window. This must be a buffer of size 
+		 * backgroundWidth * backgroundHeight. 
+		 */
+		Color* backgroundPixels;
+		UINT32 backgroundWidth; /** Width of the background image. Only relevant if backgroundPixels is not null. */
+		UINT32 backgroundHeight; /** Width of the background image. Only relevant if backgroundPixels is not null. */
+		/** If true the window will support transparency based on the alpha channel of the background image. */
+		bool alphaBlending; 
+		bool modal; /**< When a modal window is open all other windows will be locked until modal window is closed. */
+		WNDPROC wndProc; /**< Pointer to a function that handles windows message processing. */
+	};
+
+	/**	Represents a Windows native window. */
+	class BS_UTILITY_EXPORT Win32Window
+	{
+	public:
+		Win32Window(const WINDOW_DESC& desc);
+		~Win32Window();
+
+		/**	Returns position of the left-most border of the window, relative to the screen. */
+		INT32 getLeft() const;
+
+		/**	Returns position of the top-most border of the window, relative to the screen. */
+		INT32 getTop() const;
+
+		/**	Returns width of the window in pixels. */
+		UINT32 getWidth() const;
+
+		/**	Returns height of the window in pixels. */
+		UINT32 getHeight() const;
+
+		/**	Returns the native window handle. */
+		HWND getHWnd() const;
+
+        /**	Hide or show the window. */
+        void setHidden(bool hidden);
+
+		/**	Restores or minimizes the window. */
+		void setActive(bool state);
+
+		/**	Minimizes the window to the taskbar. */
+		void minimize();
+
+		/**	Maximizes the window over the entire current screen. */
+		void maximize();
+
+		/**	Restores the window to original position and size if it is minimized or maximized. */
+		void restore();
+
+        /**	Change the size of the window. */
+        void resize(UINT32 width, UINT32 height);
+
+        /**	Reposition the window. */
+		void move(INT32 left, INT32 top);
+
+		/**	Converts screen position into window local position. */
+		Vector2I screenToWindowPos(const Vector2I& screenPos) const;
+
+		/**	Converts window local position to screen position. */
+		Vector2I windowToScreenPos(const Vector2I& windowPos) const;
+
+		/**	Returns the window style flags used for creating it. */
+		DWORD getStyle() const;
+
+		/**	Returns the extended window style flags used for creating it. */
+		DWORD getStyleEx() const;
+
+		/** Called when window is moved or resized externally. */
+		void _windowMovedOrResized();
+
+		/** 
+		 * Enables all open windows. Enabled windows can receive mouse and keyboard input. This includes even windows 
+		 * disabled because there is a modal window on top of them.
+		 */
+		void static _enableAllWindows();
+
+		/**
+		 * Restores disabled state of all windows that were disabled due to modal windows being on top of them. Companion
+		 * method to _enableAllWindows() that can help restore original state after it is called. 
+		 */
+		void static _restoreModalWindows();
+
+	private:
+		friend class Win32WindowManager;
+
+		struct Pimpl;
+		Pimpl* m;
+
+		static Vector<Win32Window*> sAllWindows;
+		static Vector<Win32Window*> sModalWindowStack;
+		static Mutex sWindowsMutex;
+	};
+
+	/** @} */
+	/** @} */
 }