瀏覽代碼

WIP working on Clang compilation

BearishSun 9 年之前
父節點
當前提交
262ead5e28

+ 1 - 0
BansheeUtility/Include/BsMath.h

@@ -5,6 +5,7 @@
 #include "BsPrerequisitesUtil.h"
 #include "BsDegree.h"
 #include "BsRadian.h"
+#include "BsVector3.h"
 
 namespace BansheeEngine
 {

+ 1 - 1
BansheeUtility/Include/BsQuaternion.h

@@ -23,7 +23,7 @@ namespace BansheeEngine
 
     public:
         Quaternion(float w = 1.0f, float x = 0.0f, float y = 0.0f, float z = 0.0f)
-			:w(w), z(z), y(y), x(x)
+			:x(x), y(y), z(z), w(w)
 		{ }
 
         /** Construct a quaternion from a rotation matrix. */

+ 2 - 0
BansheeUtility/Include/BsRTTIManagedDataBlockField.h

@@ -76,6 +76,8 @@ namespace BansheeEngine
 		{
 			BS_EXCEPT(InternalErrorException, 
 				"Data block types don't support arrays.");
+
+			return 0;
 		}
 
 		/** @copydoc RTTIField::setArraySize */

+ 1 - 1
BansheeUtility/Include/BsRTTIPlainField.h

@@ -108,7 +108,7 @@ namespace BansheeEngine
 		 */
 		void initSingle(const String& name, UINT16 uniqueId, Any getter, Any setter, UINT64 flags)
 		{
-			int typeId = RTTIPlainType<DataType>::id; // Just making sure provided type has a type ID
+			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 " \

+ 2 - 9
BansheeUtility/Include/BsSphere.h

@@ -45,17 +45,10 @@ namespace BansheeEngine
 		void transform(const Matrix4& matrix);
 
 		/** Returns whether or not this sphere contains the provided point. */
-		bool contains(const Vector3& v) const
-		{
-            return ((v - mCenter).squaredLength() <= Math::sqr(mRadius));
-		}
+		inline bool contains(const Vector3& v) const;
 
 		/** Returns whether or not this sphere intersects another sphere. */
-		bool intersects(const Sphere& s) const
-		{
-            return (s.mCenter - mCenter).squaredLength() <=
-                Math::sqr(s.mRadius + mRadius);
-		}
+		bool intersects(const Sphere& s) const;
 
 		/** Returns whether or not this sphere intersects a box. */
 		bool intersects(const AABox& box) const;

+ 1 - 0
BansheeUtility/Include/BsTaskScheduler.h

@@ -11,6 +11,7 @@ namespace BansheeEngine
 	/** @addtogroup Threading
 	 *  @{
 	 */
+	class TaskScheduler;
 
 	/** Task priority. Tasks with higher priority will get executed sooner. */
 	enum class TaskPriority

+ 7 - 58
BansheeUtility/Include/BsVector3.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsPrerequisitesUtil.h"
-#include "BsMath.h"
+#include "BsRadian.h"
 
 namespace BansheeEngine
 {
@@ -240,10 +240,7 @@ namespace BansheeEngine
         }
 
         /** Returns the length (magnitude) of the vector. */
-        float length() const
-        {
-            return Math::sqrt(x * x + y * y + z * z);
-        }
+		inline float length() const;
 
         /** Returns the square of the length(magnitude) of the vector. */
         float squaredLength() const
@@ -270,21 +267,7 @@ namespace BansheeEngine
         }
 
         /** Normalizes the vector. */
-        float normalize()
-        {
-            float len = Math::sqrt(x * x + y * y + z * z);
-
-            // Will also work for zero-sized vectors, but will change nothing
-            if (len > 1e-08)
-            {
-                float invLen = 1.0f / len;
-                x *= invLen;
-                y *= invLen;
-                z *= invLen;
-            }
-
-            return len;
-        }
+		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
@@ -326,20 +309,7 @@ namespace BansheeEngine
         }
 
 		/** Gets the angle between 2 vectors. */
-		Radian angleBetween(const Vector3& dest) const
-		{
-			float lenProduct = length() * dest.length();
-
-			// Divide by zero check
-			if(lenProduct < 1e-6f)
-				lenProduct = 1e-6f;
-
-			float f = dot(dest) / lenProduct;
-
-			f = Math::clamp(f, -1.0f, 1.0f);
-			return Math::acos(f);
-
-		}
+		inline Radian angleBetween(const Vector3& dest) const;
 
         /** Returns true if this vector is zero length. */
         bool isZeroLength() const
@@ -389,25 +359,7 @@ namespace BansheeEngine
 		}
 
 		/** Normalizes the provided vector and returns a new normalized instance. */
-		static Vector3 normalize(const Vector3& val)
-		{
-			float len = Math::sqrt(val.x * val.x + val.y * val.y + val.z * val.z);
-
-			// Will also work for zero-sized vectors, but will change nothing
-			if (len > 1e-08)
-			{
-				float invLen = 1.0f / len;
-
-				Vector3 normalizedVec;
-				normalizedVec.x = val.x * invLen;
-				normalizedVec.y = val.y * invLen;
-				normalizedVec.z = val.z * invLen;
-
-				return normalizedVec;
-			}
-			else
-				return val;
-		}
+		static inline 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)
@@ -418,11 +370,8 @@ namespace BansheeEngine
 				a.x * b.y - a.y * b.x);
         }
 
-		/** Checks are any of the vector components NaN. */
-		bool isNaN() const
-		{
-			return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z);
-		}
+		/** 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)

+ 2 - 5
BansheeUtility/Include/BsVector4.h

@@ -268,11 +268,8 @@ namespace BansheeEngine
             return x * vec.x + y * vec.y + z * vec.z + w * vec.w;
         }
 
-		/** 	Checks are any of the vector components NaN. */
-		bool isNaN() const
-		{
-			return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z) || Math::isNaN(w);
-		}
+		/** Checks are any of the vector components NaN. */
+		inline bool isNaN() const;
 
         static const Vector4 ZERO;
     };

+ 635 - 625
BansheeUtility/Source/BsBinaryDiff.cpp

@@ -1,628 +1,638 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsBinaryDiff.h"
-#include "BsSerializedObject.h"
-#include "BsBinarySerializer.h"
-#include "BsBinaryCloner.h"
-#include "BsRTTIType.h"
-
-namespace BansheeEngine
-{
-	SPtr<SerializedObject> IDiff::generateDiff(const SPtr<SerializedObject>& orgObj,
-		const SPtr<SerializedObject>& newObj)
-	{
-		ObjectMap objectMap;
-		return generateDiff(orgObj, newObj, objectMap);
-	}
-
-	SPtr<SerializedInstance> IDiff::generateDiff(RTTITypeBase* rtti, UINT32 fieldType, const SPtr<SerializedInstance>& orgData,
-		const SPtr<SerializedInstance>& newData, ObjectMap& objectMap)
-	{
-		SPtr<SerializedInstance> modification;
-		switch (fieldType)
-		{
-		case SerializableFT_ReflectablePtr:
-		case SerializableFT_Reflectable:
-		{
-			SPtr<SerializedObject> orgObjData = std::static_pointer_cast<SerializedObject>(orgData);
-			SPtr<SerializedObject> newObjData = std::static_pointer_cast<SerializedObject>(newData);
-
-			auto iterFind = objectMap.find(newObjData);
-			if (iterFind != objectMap.end())
-				modification = iterFind->second;
-			else
-			{
-				RTTITypeBase* childRtti = nullptr;
-				if (orgObjData->getRootTypeId() == newObjData->getRootTypeId())
-					childRtti = IReflectable::_getRTTIfromTypeId(newObjData->getRootTypeId());
-
-				SPtr<SerializedObject> objectDiff;
-				if (childRtti != nullptr)
-				{
-					IDiff& handler = childRtti->getDiffHandler();
-					objectDiff = handler.generateDiff(orgObjData, newObjData, objectMap);
-				}
-
-				if (objectDiff != nullptr)
-					objectMap[newObjData] = objectDiff;
-
-				modification = objectDiff;
-			}
-		}
-			break;
-		case SerializableFT_Plain:
-		case SerializableFT_DataBlock:
-		{
-			SPtr<SerializedField> orgFieldData = std::static_pointer_cast<SerializedField>(orgData);
-			SPtr<SerializedField> newFieldData = std::static_pointer_cast<SerializedField>(newData);
-
-			bool isModified = orgFieldData->size != newFieldData->size;
-			if (!isModified)
-				isModified = memcmp(orgFieldData->value, newFieldData->value, newFieldData->size) != 0;
-
-			if (isModified)
-				modification = newFieldData->clone();
-		}
-			break;
-		}
-
-		return modification;
-	}
-
-	void IDiff::applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff)
-	{
-		Vector<DiffCommand> commands;
-
-		DiffObjectMap objectMap;
-		applyDiff(object, diff, objectMap, commands);
-
-		IReflectable* destObject = nullptr;
-		Stack<IReflectable*> objectStack;
-
-		for (auto& command : commands)
-		{
-			bool isArray = (command.type & Diff_ArrayFlag) != 0;
-			DiffCommandType type = (DiffCommandType)(command.type & 0xF);
-
-			switch (type)
-			{
-			case Diff_ArraySize:
-				command.field->setArraySize(destObject, command.arraySize);
-				break;
-			case Diff_ObjectStart:
-			{
-				destObject = command.object.get();
-				objectStack.push(destObject);
-
-				RTTITypeBase* curRtti = destObject->getRTTI();
-				while (curRtti != nullptr)
-				{
-					curRtti->onDeserializationStarted(destObject);
-					curRtti = curRtti->getBaseClass();
-				}
-			}
-				break;
-			case Diff_ObjectEnd:
-			{
-				Stack<RTTITypeBase*> rttiTypes;
-				RTTITypeBase* curRtti = destObject->getRTTI();
-				while (curRtti != nullptr)
-				{
-					rttiTypes.push(curRtti);
-					curRtti = curRtti->getBaseClass();
-				}
-
-				while (!rttiTypes.empty())
-				{
-					rttiTypes.top()->onDeserializationEnded(destObject);
-					rttiTypes.pop();
-				}
-
-				objectStack.pop();
-
-				if (!objectStack.empty())
-					destObject = objectStack.top();
-				else
-					destObject = nullptr;
-			}
-				break;
-			}
-
-			if (isArray)
-			{
-				switch (type)
-				{
-				case Diff_ReflectablePtr:
-				{
-					RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(command.field);
-					field->setArrayValue(destObject, command.arrayIdx, command.object);
-				}
-					break;
-				case Diff_Reflectable:
-				{
-					RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(command.field);
-					field->setArrayValue(destObject, command.arrayIdx, *command.object);
-				}
-					break;
-				case Diff_Plain:
-				{
-					RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(command.field);
-					field->arrayElemFromBuffer(destObject, command.arrayIdx, command.value);
-				}
-					break;
-				}
-			}
-			else
-			{
-				switch (type)
-				{
-				case Diff_ReflectablePtr:
-				{
-					RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(command.field);
-					field->setValue(destObject, command.object);
-				}
-					break;
-				case Diff_Reflectable:
-				{
-					RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(command.field);
-					field->setValue(destObject, *command.object);
-				}
-					break;
-				case Diff_Plain:
-				{
-					RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(command.field);
-					field->fromBuffer(destObject, command.value);
-				}
-					break;
-				case Diff_DataBlock:
-				{
-					RTTIManagedDataBlockFieldBase* field = static_cast<RTTIManagedDataBlockFieldBase*>(command.field);
-					UINT8* dataCopy = field->allocate(destObject, command.size);
-					memcpy(dataCopy, command.value, command.size);
-
-					ManagedDataBlock value(dataCopy, command.size); // Not managed because I assume the owner class will decide whether to delete the data or keep it
-					field->setValue(destObject, value);
-				}
-					break;
-				}
-			}
-		}
-	}
-
-	void IDiff::applyDiff(RTTITypeBase* rtti, const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, 
-		DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands)
-	{
-		IDiff& diffHandler = rtti->getDiffHandler();
-		diffHandler.applyDiff(object, diff, objectMap, diffCommands);
-	}
-
-	SPtr<SerializedObject> BinaryDiff::generateDiff(const SPtr<SerializedObject>& orgObj, 
-		const SPtr<SerializedObject>& newObj, ObjectMap& objectMap)
-	{
-		SPtr<SerializedObject> output;
-		for (auto& subObject : newObj->subObjects)
-		{
-			RTTITypeBase* rtti = IReflectable::_getRTTIfromTypeId(subObject.typeId);
-			if (rtti == nullptr)
-				continue;
-
-			SerializedSubObject* orgSubObject = nullptr;
-			for (auto& curSubObject : orgObj->subObjects)
-			{
-				if (curSubObject.typeId == subObject.typeId)
-				{
-					orgSubObject = &curSubObject;
-					break;
-				}
-			}
-			
-			SerializedSubObject* diffSubObject = nullptr;
-			for (auto& newEntry : subObject.entries)
-			{
-				RTTIField* genericField = rtti->findField(newEntry.first);
-				if (genericField == nullptr)
-					continue;
-
-				SPtr<SerializedInstance> newEntryData = newEntry.second.serialized;
-				SPtr<SerializedInstance> orgEntryData;
-
-				if (orgSubObject != nullptr)
-				{
-					auto orgEntryFind = orgSubObject->entries.find(newEntry.first);
-					if (orgEntryFind != orgSubObject->entries.end())
-						orgEntryData = orgEntryFind->second.serialized;
-				}
-
-				SPtr<SerializedInstance> modification;
-				bool hasModification = false;
-				if (genericField->isArray())
-				{
-					SPtr<SerializedArray> orgArrayData = std::static_pointer_cast<SerializedArray>(orgEntryData);
-					SPtr<SerializedArray> newArrayData = std::static_pointer_cast<SerializedArray>(newEntryData);
-
-					SPtr<SerializedArray> serializedArray;
-
-					if (newEntryData != nullptr && orgEntryData != nullptr)
-					{
-						for (auto& arrayEntryPair : newArrayData->entries)
-						{
-							SPtr<SerializedInstance> arrayModification;
-
-							auto iterFind = orgArrayData->entries.find(arrayEntryPair.first);
-							if (iterFind == orgArrayData->entries.end())
-								arrayModification = arrayEntryPair.second.serialized->clone();
-							else
-							{
-								arrayModification = IDiff::generateDiff(rtti, genericField->mType, iterFind->second.serialized,
-									arrayEntryPair.second.serialized, objectMap);
-							}
-
-							if (arrayModification != nullptr)
-							{
-								if (serializedArray == nullptr)
-								{
-									serializedArray = bs_shared_ptr_new<SerializedArray>();
-									serializedArray->numElements = newArrayData->numElements;
-								}
-
-								SerializedArrayEntry arrayEntry;
-								arrayEntry.index = arrayEntryPair.first;
-								arrayEntry.serialized = arrayModification;
-								serializedArray->entries[arrayEntryPair.first] = arrayEntry;
-							}
-						}
-					}
-					else if (newEntryData == nullptr)
-					{
-						serializedArray = bs_shared_ptr_new<SerializedArray>();
-					}
-					else if (orgEntryData == nullptr)
-					{
-						serializedArray = std::static_pointer_cast<SerializedArray>(newArrayData->clone());
-					}
-
-					modification = serializedArray;
-					hasModification = modification != nullptr;
-				}
-				else
-				{
-					if (newEntryData != nullptr && orgEntryData != nullptr)
-					{
-						modification = IDiff::generateDiff(rtti, genericField->mType, orgEntryData, newEntryData, objectMap);
-						hasModification = modification != nullptr;
-					}
-					else if (newEntryData == nullptr)
-					{
-						switch (genericField->mType)
-						{
-						case SerializableFT_Plain:
-						case SerializableFT_DataBlock:
-							modification = bs_shared_ptr_new<SerializedField>();
-							break;
-						}
-
-						hasModification = true;
-					}
-					else if (orgEntryData == nullptr)
-					{
-						modification = newEntryData->clone();
-						hasModification = modification != nullptr;
-					}
-				}
-
-				if (hasModification)
-				{
-					if (output == nullptr)
-						output = bs_shared_ptr_new<SerializedObject>();
-
-					if (diffSubObject == nullptr)
-					{
-						output->subObjects.push_back(SerializedSubObject());
-						diffSubObject = &output->subObjects.back();
-						diffSubObject->typeId = rtti->getRTTIId();
-					}
-
-					SerializedEntry modificationEntry;
-					modificationEntry.fieldId = genericField->mUniqueId;
-					modificationEntry.serialized = modification;
-					diffSubObject->entries[genericField->mUniqueId] = modificationEntry;
-				}
-			}
-		}
-
-		return output;
-	}
-
-	void BinaryDiff::applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff,
-		DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands)
-	{
-		if (object == nullptr || diff == nullptr || object->getTypeId() != diff->getRootTypeId())
-			return;
-
-		DiffCommand objStartCommand;
-		objStartCommand.field = nullptr;
-		objStartCommand.type = Diff_ObjectStart;
-		objStartCommand.object = object;
-
-		diffCommands.push_back(objStartCommand);
-
-		Stack<RTTITypeBase*> rttiTypes;
-		for (auto& subObject : diff->subObjects)
-		{
-			for (auto& diffEntry : subObject.entries)
-			{
-				RTTITypeBase* rtti = IReflectable::_getRTTIfromTypeId(subObject.typeId);
-				if (rtti == nullptr)
-					continue;
-
-				if (!object->isDerivedFrom(rtti))
-					continue;
-
-				rtti->onSerializationStarted(object.get());
-				rttiTypes.push(rtti);
-
-				RTTIField* genericField = rtti->findField(diffEntry.first);
-				if (genericField == nullptr)
-					continue;
-
-				SPtr<SerializedInstance> diffData = diffEntry.second.serialized;
-
-				if (genericField->isArray())
-				{
-					SPtr<SerializedArray> diffArray = std::static_pointer_cast<SerializedArray>(diffData);
-
-					UINT32 numArrayElements = (UINT32)diffArray->numElements;
-
-					DiffCommand arraySizeCommand;
-					arraySizeCommand.field = genericField;
-					arraySizeCommand.type = Diff_ArraySize | Diff_ArrayFlag;
-					arraySizeCommand.arraySize = numArrayElements;
-
-					diffCommands.push_back(arraySizeCommand);
-
-					switch (genericField->mType)
-					{
-					case SerializableFT_ReflectablePtr:
-					{
-						RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
-
-						UINT32 orgArraySize = genericField->getArraySize(object.get());
-						for (auto& arrayElem : diffArray->entries)
-						{
-							SPtr<SerializedObject> arrayElemData = std::static_pointer_cast<SerializedObject>(arrayElem.second.serialized);
-
-							DiffCommand command;
-							command.field = genericField;
-							command.type = Diff_ReflectablePtr | Diff_ArrayFlag;
-							command.arrayIdx = arrayElem.first;
-
-							if (arrayElemData == nullptr)
-							{
-								command.object = nullptr;
-								diffCommands.push_back(command);
-							}
-							else
-							{
-								bool needsNewObject = arrayElem.first >= orgArraySize;
-
-								if (!needsNewObject)
-								{
-									SPtr<IReflectable> childObj = field->getArrayValue(object.get(), arrayElem.first);
-									if (childObj != nullptr)
-									{
-										IDiff::applyDiff(childObj->getRTTI(), childObj, arrayElemData, objectMap, diffCommands);
-										command.object = childObj;
-									}
-									else
-										needsNewObject = true;
-								}
-
-								if (needsNewObject)
-								{
-									RTTITypeBase* childRtti = IReflectable::_getRTTIfromTypeId(arrayElemData->getRootTypeId());
-									if (childRtti != nullptr)
-									{
-										auto findObj = objectMap.find(arrayElemData);
-										if (findObj == objectMap.end())
-										{
-											SPtr<IReflectable> newObject = childRtti->newRTTIObject();
-											findObj = objectMap.insert(std::make_pair(arrayElemData, newObject)).first;
-										}
-
-										IDiff::applyDiff(childRtti, findObj->second, arrayElemData, objectMap, diffCommands);
-										command.object = findObj->second;
-										diffCommands.push_back(command);
-									}
-									else
-									{
-										command.object = nullptr;
-										diffCommands.push_back(command);
-									}
-								}
-							}
-						}
-					}
-						break;
-					case SerializableFT_Reflectable:
-					{
-						RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
-
-						UINT32 orgArraySize = genericField->getArraySize(object.get());
-
-						Vector<SPtr<IReflectable>> newArrayElements(numArrayElements);
-						UINT32 minArrayLength = std::min(orgArraySize, numArrayElements);
-						for (UINT32 i = 0; i < minArrayLength; i++)
-						{
-							IReflectable& childObj = field->getArrayValue(object.get(), i);
-							newArrayElements[i] = BinaryCloner::clone(&childObj, true);
-						}
-
-						for (auto& arrayElem : diffArray->entries)
-						{
-							SPtr<SerializedObject> arrayElemData = std::static_pointer_cast<SerializedObject>(arrayElem.second.serialized);
-
-							if (arrayElem.first < orgArraySize)
-							{
-								SPtr<IReflectable> childObj = newArrayElements[arrayElem.first];
-								IDiff::applyDiff(childObj->getRTTI(), childObj, arrayElemData, objectMap, diffCommands);
-							}
-							else
-							{
-								RTTITypeBase* childRtti = IReflectable::_getRTTIfromTypeId(arrayElemData->getRootTypeId());
-								if (childRtti != nullptr)
-								{
-									SPtr<IReflectable> newObject = childRtti->newRTTIObject();
-									IDiff::applyDiff(childRtti, newObject, arrayElemData, objectMap, diffCommands);
-
-									newArrayElements[arrayElem.first] = newObject;
-								}
-							}
-						}
-
-						for (UINT32 i = 0; i < numArrayElements; i++)
-						{
-							DiffCommand command;
-							command.field = genericField;
-							command.type = Diff_Reflectable | Diff_ArrayFlag;
-							command.arrayIdx = i;
-							command.object = newArrayElements[i];
-
-							diffCommands.push_back(command);
-						}
-					}
-						break;
-					case SerializableFT_Plain:
-					{
-						for (auto& arrayElem : diffArray->entries)
-						{
-							SPtr<SerializedField> fieldData = std::static_pointer_cast<SerializedField>(arrayElem.second.serialized);
-							if (fieldData != nullptr)
-							{
-								DiffCommand command;
-								command.field = genericField;
-								command.type = Diff_Plain | Diff_ArrayFlag;
-								command.value = fieldData->value;
-								command.size = fieldData->size;
-								command.arrayIdx = arrayElem.first;
-
-								diffCommands.push_back(command);
-							}
-						}
-					}
-						break;
-					}
-				}
-				else
-				{
-					switch (genericField->mType)
-					{
-					case SerializableFT_ReflectablePtr:
-					{
-						RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
-						SPtr<SerializedObject> fieldObjectData = std::static_pointer_cast<SerializedObject>(diffData);
-
-						DiffCommand command;
-						command.field = genericField;
-						command.type = Diff_ReflectablePtr;
-
-						if (fieldObjectData == nullptr)
-							command.object = nullptr;
-						else
-						{
-							SPtr<IReflectable> childObj = field->getValue(object.get());
-							if (childObj == nullptr)
-							{
-								RTTITypeBase* childRtti = IReflectable::_getRTTIfromTypeId(fieldObjectData->getRootTypeId());
-								if (childRtti != nullptr)
-								{
-									auto findObj = objectMap.find(fieldObjectData);
-									if (findObj == objectMap.end())
-									{
-										SPtr<IReflectable> newObject = childRtti->newRTTIObject();
-										findObj = objectMap.insert(std::make_pair(fieldObjectData, newObject)).first;
-									}
-
-									IDiff::applyDiff(childRtti, findObj->second, fieldObjectData, objectMap, diffCommands);
-									command.object = findObj->second;
-								}
-								else
-								{
-									command.object = nullptr;
-								}
-							}
-							else
-							{
-								IDiff::applyDiff(childObj->getRTTI(), childObj, fieldObjectData, objectMap, diffCommands);
-								command.object = childObj;
-							}
-						}
-
-						diffCommands.push_back(command);
-					}
-						break;
-					case SerializableFT_Reflectable:
-					{
-						RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
-						SPtr<SerializedObject> fieldObjectData = std::static_pointer_cast<SerializedObject>(diffData);
-
-						IReflectable& childObj = field->getValue(object.get());
-						std::shared_ptr<IReflectable> clonedObj = BinaryCloner::clone(&childObj, true);
-
-						IDiff::applyDiff(clonedObj->getRTTI(), clonedObj, fieldObjectData, objectMap, diffCommands);
-
-						DiffCommand command;
-						command.field = genericField;
-						command.type = Diff_Reflectable;
-						command.object = clonedObj;
-
-						diffCommands.push_back(command);
-					}
-						break;
-					case SerializableFT_Plain:
-					{
-						SPtr<SerializedField> diffFieldData = std::static_pointer_cast<SerializedField>(diffData);
-
-						if (diffFieldData->size > 0)
-						{
-							DiffCommand command;
-							command.field = genericField;
-							command.type = Diff_Plain;
-							command.value = diffFieldData->value;
-							command.size = diffFieldData->size;
-
-							diffCommands.push_back(command);
-						}
-					}
-						break;
-					case SerializableFT_DataBlock:
-					{
-						SPtr<SerializedField> diffFieldData = std::static_pointer_cast<SerializedField>(diffData);
-
-						DiffCommand command;
-						command.field = genericField;
-						command.type = Diff_DataBlock;
-						command.value = diffFieldData->value;
-						command.size = diffFieldData->size;
-
-						diffCommands.push_back(command);
-					}
-						break;
-					}
-				}
-			}
-		}
-
-		DiffCommand objEndCommand;
-		objEndCommand.field = nullptr;
-		objEndCommand.type = Diff_ObjectEnd;
-		objEndCommand.object = object;
-
-		diffCommands.push_back(objEndCommand);
-
-		while (!rttiTypes.empty())
-		{
-			rttiTypes.top()->onSerializationEnded(object.get());
-			rttiTypes.pop();
-		}
-	}
+#include "BsBinaryDiff.h"
+#include "BsSerializedObject.h"
+#include "BsBinarySerializer.h"
+#include "BsBinaryCloner.h"
+#include "BsRTTIType.h"
+
+namespace BansheeEngine
+{
+	SPtr<SerializedObject> IDiff::generateDiff(const SPtr<SerializedObject>& orgObj,
+		const SPtr<SerializedObject>& newObj)
+	{
+		ObjectMap objectMap;
+		return generateDiff(orgObj, newObj, objectMap);
+	}
+
+	SPtr<SerializedInstance> IDiff::generateDiff(RTTITypeBase* rtti, UINT32 fieldType, const SPtr<SerializedInstance>& orgData,
+		const SPtr<SerializedInstance>& newData, ObjectMap& objectMap)
+	{
+		SPtr<SerializedInstance> modification;
+		switch (fieldType)
+		{
+		case SerializableFT_ReflectablePtr:
+		case SerializableFT_Reflectable:
+		{
+			SPtr<SerializedObject> orgObjData = std::static_pointer_cast<SerializedObject>(orgData);
+			SPtr<SerializedObject> newObjData = std::static_pointer_cast<SerializedObject>(newData);
+
+			auto iterFind = objectMap.find(newObjData);
+			if (iterFind != objectMap.end())
+				modification = iterFind->second;
+			else
+			{
+				RTTITypeBase* childRtti = nullptr;
+				if (orgObjData->getRootTypeId() == newObjData->getRootTypeId())
+					childRtti = IReflectable::_getRTTIfromTypeId(newObjData->getRootTypeId());
+
+				SPtr<SerializedObject> objectDiff;
+				if (childRtti != nullptr)
+				{
+					IDiff& handler = childRtti->getDiffHandler();
+					objectDiff = handler.generateDiff(orgObjData, newObjData, objectMap);
+				}
+
+				if (objectDiff != nullptr)
+					objectMap[newObjData] = objectDiff;
+
+				modification = objectDiff;
+			}
+		}
+			break;
+		case SerializableFT_Plain:
+		case SerializableFT_DataBlock:
+		{
+			SPtr<SerializedField> orgFieldData = std::static_pointer_cast<SerializedField>(orgData);
+			SPtr<SerializedField> newFieldData = std::static_pointer_cast<SerializedField>(newData);
+
+			bool isModified = orgFieldData->size != newFieldData->size;
+			if (!isModified)
+				isModified = memcmp(orgFieldData->value, newFieldData->value, newFieldData->size) != 0;
+
+			if (isModified)
+				modification = newFieldData->clone();
+		}
+			break;
+		}
+
+		return modification;
+	}
+
+	void IDiff::applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff)
+	{
+		Vector<DiffCommand> commands;
+
+		DiffObjectMap objectMap;
+		applyDiff(object, diff, objectMap, commands);
+
+		IReflectable* destObject = nullptr;
+		Stack<IReflectable*> objectStack;
+
+		for (auto& command : commands)
+		{
+			bool isArray = (command.type & Diff_ArrayFlag) != 0;
+			DiffCommandType type = (DiffCommandType)(command.type & 0xF);
+
+			switch (type)
+			{
+			case Diff_ArraySize:
+				command.field->setArraySize(destObject, command.arraySize);
+				break;
+			case Diff_ObjectStart:
+			{
+				destObject = command.object.get();
+				objectStack.push(destObject);
+
+				RTTITypeBase* curRtti = destObject->getRTTI();
+				while (curRtti != nullptr)
+				{
+					curRtti->onDeserializationStarted(destObject);
+					curRtti = curRtti->getBaseClass();
+				}
+			}
+				break;
+			case Diff_ObjectEnd:
+			{
+				Stack<RTTITypeBase*> rttiTypes;
+				RTTITypeBase* curRtti = destObject->getRTTI();
+				while (curRtti != nullptr)
+				{
+					rttiTypes.push(curRtti);
+					curRtti = curRtti->getBaseClass();
+				}
+
+				while (!rttiTypes.empty())
+				{
+					rttiTypes.top()->onDeserializationEnded(destObject);
+					rttiTypes.pop();
+				}
+
+				objectStack.pop();
+
+				if (!objectStack.empty())
+					destObject = objectStack.top();
+				else
+					destObject = nullptr;
+			}
+				break;
+			default:
+				break;
+			}
+
+			if (isArray)
+			{
+				switch (type)
+				{
+				case Diff_ReflectablePtr:
+				{
+					RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(command.field);
+					field->setArrayValue(destObject, command.arrayIdx, command.object);
+				}
+					break;
+				case Diff_Reflectable:
+				{
+					RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(command.field);
+					field->setArrayValue(destObject, command.arrayIdx, *command.object);
+				}
+					break;
+				case Diff_Plain:
+				{
+					RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(command.field);
+					field->arrayElemFromBuffer(destObject, command.arrayIdx, command.value);
+				}
+					break;
+				default:
+					break;
+				}
+			}
+			else
+			{
+				switch (type)
+				{
+				case Diff_ReflectablePtr:
+				{
+					RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(command.field);
+					field->setValue(destObject, command.object);
+				}
+					break;
+				case Diff_Reflectable:
+				{
+					RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(command.field);
+					field->setValue(destObject, *command.object);
+				}
+					break;
+				case Diff_Plain:
+				{
+					RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(command.field);
+					field->fromBuffer(destObject, command.value);
+				}
+					break;
+				case Diff_DataBlock:
+				{
+					RTTIManagedDataBlockFieldBase* field = static_cast<RTTIManagedDataBlockFieldBase*>(command.field);
+					UINT8* dataCopy = field->allocate(destObject, command.size);
+					memcpy(dataCopy, command.value, command.size);
+
+					ManagedDataBlock value(dataCopy, command.size); // Not managed because I assume the owner class will decide whether to delete the data or keep it
+					field->setValue(destObject, value);
+				}
+					break;
+				default:
+					break;
+				}
+			}
+		}
+	}
+
+	void IDiff::applyDiff(RTTITypeBase* rtti, const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, 
+		DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands)
+	{
+		IDiff& diffHandler = rtti->getDiffHandler();
+		diffHandler.applyDiff(object, diff, objectMap, diffCommands);
+	}
+
+	SPtr<SerializedObject> BinaryDiff::generateDiff(const SPtr<SerializedObject>& orgObj, 
+		const SPtr<SerializedObject>& newObj, ObjectMap& objectMap)
+	{
+		SPtr<SerializedObject> output;
+		for (auto& subObject : newObj->subObjects)
+		{
+			RTTITypeBase* rtti = IReflectable::_getRTTIfromTypeId(subObject.typeId);
+			if (rtti == nullptr)
+				continue;
+
+			SerializedSubObject* orgSubObject = nullptr;
+			for (auto& curSubObject : orgObj->subObjects)
+			{
+				if (curSubObject.typeId == subObject.typeId)
+				{
+					orgSubObject = &curSubObject;
+					break;
+				}
+			}
+			
+			SerializedSubObject* diffSubObject = nullptr;
+			for (auto& newEntry : subObject.entries)
+			{
+				RTTIField* genericField = rtti->findField(newEntry.first);
+				if (genericField == nullptr)
+					continue;
+
+				SPtr<SerializedInstance> newEntryData = newEntry.second.serialized;
+				SPtr<SerializedInstance> orgEntryData;
+
+				if (orgSubObject != nullptr)
+				{
+					auto orgEntryFind = orgSubObject->entries.find(newEntry.first);
+					if (orgEntryFind != orgSubObject->entries.end())
+						orgEntryData = orgEntryFind->second.serialized;
+				}
+
+				SPtr<SerializedInstance> modification;
+				bool hasModification = false;
+				if (genericField->isArray())
+				{
+					SPtr<SerializedArray> orgArrayData = std::static_pointer_cast<SerializedArray>(orgEntryData);
+					SPtr<SerializedArray> newArrayData = std::static_pointer_cast<SerializedArray>(newEntryData);
+
+					SPtr<SerializedArray> serializedArray;
+
+					if (newEntryData != nullptr && orgEntryData != nullptr)
+					{
+						for (auto& arrayEntryPair : newArrayData->entries)
+						{
+							SPtr<SerializedInstance> arrayModification;
+
+							auto iterFind = orgArrayData->entries.find(arrayEntryPair.first);
+							if (iterFind == orgArrayData->entries.end())
+								arrayModification = arrayEntryPair.second.serialized->clone();
+							else
+							{
+								arrayModification = IDiff::generateDiff(rtti, genericField->mType, iterFind->second.serialized,
+									arrayEntryPair.second.serialized, objectMap);
+							}
+
+							if (arrayModification != nullptr)
+							{
+								if (serializedArray == nullptr)
+								{
+									serializedArray = bs_shared_ptr_new<SerializedArray>();
+									serializedArray->numElements = newArrayData->numElements;
+								}
+
+								SerializedArrayEntry arrayEntry;
+								arrayEntry.index = arrayEntryPair.first;
+								arrayEntry.serialized = arrayModification;
+								serializedArray->entries[arrayEntryPair.first] = arrayEntry;
+							}
+						}
+					}
+					else if (newEntryData == nullptr)
+					{
+						serializedArray = bs_shared_ptr_new<SerializedArray>();
+					}
+					else if (orgEntryData == nullptr)
+					{
+						serializedArray = std::static_pointer_cast<SerializedArray>(newArrayData->clone());
+					}
+
+					modification = serializedArray;
+					hasModification = modification != nullptr;
+				}
+				else
+				{
+					if (newEntryData != nullptr && orgEntryData != nullptr)
+					{
+						modification = IDiff::generateDiff(rtti, genericField->mType, orgEntryData, newEntryData, objectMap);
+						hasModification = modification != nullptr;
+					}
+					else if (newEntryData == nullptr)
+					{
+						switch (genericField->mType)
+						{
+						case SerializableFT_Plain:
+						case SerializableFT_DataBlock:
+							modification = bs_shared_ptr_new<SerializedField>();
+							break;
+						default:
+							break;
+						}
+
+						hasModification = true;
+					}
+					else if (orgEntryData == nullptr)
+					{
+						modification = newEntryData->clone();
+						hasModification = modification != nullptr;
+					}
+				}
+
+				if (hasModification)
+				{
+					if (output == nullptr)
+						output = bs_shared_ptr_new<SerializedObject>();
+
+					if (diffSubObject == nullptr)
+					{
+						output->subObjects.push_back(SerializedSubObject());
+						diffSubObject = &output->subObjects.back();
+						diffSubObject->typeId = rtti->getRTTIId();
+					}
+
+					SerializedEntry modificationEntry;
+					modificationEntry.fieldId = genericField->mUniqueId;
+					modificationEntry.serialized = modification;
+					diffSubObject->entries[genericField->mUniqueId] = modificationEntry;
+				}
+			}
+		}
+
+		return output;
+	}
+
+	void BinaryDiff::applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff,
+		DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands)
+	{
+		if (object == nullptr || diff == nullptr || object->getTypeId() != diff->getRootTypeId())
+			return;
+
+		DiffCommand objStartCommand;
+		objStartCommand.field = nullptr;
+		objStartCommand.type = Diff_ObjectStart;
+		objStartCommand.object = object;
+
+		diffCommands.push_back(objStartCommand);
+
+		Stack<RTTITypeBase*> rttiTypes;
+		for (auto& subObject : diff->subObjects)
+		{
+			for (auto& diffEntry : subObject.entries)
+			{
+				RTTITypeBase* rtti = IReflectable::_getRTTIfromTypeId(subObject.typeId);
+				if (rtti == nullptr)
+					continue;
+
+				if (!object->isDerivedFrom(rtti))
+					continue;
+
+				rtti->onSerializationStarted(object.get());
+				rttiTypes.push(rtti);
+
+				RTTIField* genericField = rtti->findField(diffEntry.first);
+				if (genericField == nullptr)
+					continue;
+
+				SPtr<SerializedInstance> diffData = diffEntry.second.serialized;
+
+				if (genericField->isArray())
+				{
+					SPtr<SerializedArray> diffArray = std::static_pointer_cast<SerializedArray>(diffData);
+
+					UINT32 numArrayElements = (UINT32)diffArray->numElements;
+
+					DiffCommand arraySizeCommand;
+					arraySizeCommand.field = genericField;
+					arraySizeCommand.type = Diff_ArraySize | Diff_ArrayFlag;
+					arraySizeCommand.arraySize = numArrayElements;
+
+					diffCommands.push_back(arraySizeCommand);
+
+					switch (genericField->mType)
+					{
+					case SerializableFT_ReflectablePtr:
+					{
+						RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
+
+						UINT32 orgArraySize = genericField->getArraySize(object.get());
+						for (auto& arrayElem : diffArray->entries)
+						{
+							SPtr<SerializedObject> arrayElemData = std::static_pointer_cast<SerializedObject>(arrayElem.second.serialized);
+
+							DiffCommand command;
+							command.field = genericField;
+							command.type = Diff_ReflectablePtr | Diff_ArrayFlag;
+							command.arrayIdx = arrayElem.first;
+
+							if (arrayElemData == nullptr)
+							{
+								command.object = nullptr;
+								diffCommands.push_back(command);
+							}
+							else
+							{
+								bool needsNewObject = arrayElem.first >= orgArraySize;
+
+								if (!needsNewObject)
+								{
+									SPtr<IReflectable> childObj = field->getArrayValue(object.get(), arrayElem.first);
+									if (childObj != nullptr)
+									{
+										IDiff::applyDiff(childObj->getRTTI(), childObj, arrayElemData, objectMap, diffCommands);
+										command.object = childObj;
+									}
+									else
+										needsNewObject = true;
+								}
+
+								if (needsNewObject)
+								{
+									RTTITypeBase* childRtti = IReflectable::_getRTTIfromTypeId(arrayElemData->getRootTypeId());
+									if (childRtti != nullptr)
+									{
+										auto findObj = objectMap.find(arrayElemData);
+										if (findObj == objectMap.end())
+										{
+											SPtr<IReflectable> newObject = childRtti->newRTTIObject();
+											findObj = objectMap.insert(std::make_pair(arrayElemData, newObject)).first;
+										}
+
+										IDiff::applyDiff(childRtti, findObj->second, arrayElemData, objectMap, diffCommands);
+										command.object = findObj->second;
+										diffCommands.push_back(command);
+									}
+									else
+									{
+										command.object = nullptr;
+										diffCommands.push_back(command);
+									}
+								}
+							}
+						}
+					}
+						break;
+					case SerializableFT_Reflectable:
+					{
+						RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
+
+						UINT32 orgArraySize = genericField->getArraySize(object.get());
+
+						Vector<SPtr<IReflectable>> newArrayElements(numArrayElements);
+						UINT32 minArrayLength = std::min(orgArraySize, numArrayElements);
+						for (UINT32 i = 0; i < minArrayLength; i++)
+						{
+							IReflectable& childObj = field->getArrayValue(object.get(), i);
+							newArrayElements[i] = BinaryCloner::clone(&childObj, true);
+						}
+
+						for (auto& arrayElem : diffArray->entries)
+						{
+							SPtr<SerializedObject> arrayElemData = std::static_pointer_cast<SerializedObject>(arrayElem.second.serialized);
+
+							if (arrayElem.first < orgArraySize)
+							{
+								SPtr<IReflectable> childObj = newArrayElements[arrayElem.first];
+								IDiff::applyDiff(childObj->getRTTI(), childObj, arrayElemData, objectMap, diffCommands);
+							}
+							else
+							{
+								RTTITypeBase* childRtti = IReflectable::_getRTTIfromTypeId(arrayElemData->getRootTypeId());
+								if (childRtti != nullptr)
+								{
+									SPtr<IReflectable> newObject = childRtti->newRTTIObject();
+									IDiff::applyDiff(childRtti, newObject, arrayElemData, objectMap, diffCommands);
+
+									newArrayElements[arrayElem.first] = newObject;
+								}
+							}
+						}
+
+						for (UINT32 i = 0; i < numArrayElements; i++)
+						{
+							DiffCommand command;
+							command.field = genericField;
+							command.type = Diff_Reflectable | Diff_ArrayFlag;
+							command.arrayIdx = i;
+							command.object = newArrayElements[i];
+
+							diffCommands.push_back(command);
+						}
+					}
+						break;
+					case SerializableFT_Plain:
+					{
+						for (auto& arrayElem : diffArray->entries)
+						{
+							SPtr<SerializedField> fieldData = std::static_pointer_cast<SerializedField>(arrayElem.second.serialized);
+							if (fieldData != nullptr)
+							{
+								DiffCommand command;
+								command.field = genericField;
+								command.type = Diff_Plain | Diff_ArrayFlag;
+								command.value = fieldData->value;
+								command.size = fieldData->size;
+								command.arrayIdx = arrayElem.first;
+
+								diffCommands.push_back(command);
+							}
+						}
+					}
+						break;
+					default:
+						break;
+					}
+				}
+				else
+				{
+					switch (genericField->mType)
+					{
+					case SerializableFT_ReflectablePtr:
+					{
+						RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
+						SPtr<SerializedObject> fieldObjectData = std::static_pointer_cast<SerializedObject>(diffData);
+
+						DiffCommand command;
+						command.field = genericField;
+						command.type = Diff_ReflectablePtr;
+
+						if (fieldObjectData == nullptr)
+							command.object = nullptr;
+						else
+						{
+							SPtr<IReflectable> childObj = field->getValue(object.get());
+							if (childObj == nullptr)
+							{
+								RTTITypeBase* childRtti = IReflectable::_getRTTIfromTypeId(fieldObjectData->getRootTypeId());
+								if (childRtti != nullptr)
+								{
+									auto findObj = objectMap.find(fieldObjectData);
+									if (findObj == objectMap.end())
+									{
+										SPtr<IReflectable> newObject = childRtti->newRTTIObject();
+										findObj = objectMap.insert(std::make_pair(fieldObjectData, newObject)).first;
+									}
+
+									IDiff::applyDiff(childRtti, findObj->second, fieldObjectData, objectMap, diffCommands);
+									command.object = findObj->second;
+								}
+								else
+								{
+									command.object = nullptr;
+								}
+							}
+							else
+							{
+								IDiff::applyDiff(childObj->getRTTI(), childObj, fieldObjectData, objectMap, diffCommands);
+								command.object = childObj;
+							}
+						}
+
+						diffCommands.push_back(command);
+					}
+						break;
+					case SerializableFT_Reflectable:
+					{
+						RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
+						SPtr<SerializedObject> fieldObjectData = std::static_pointer_cast<SerializedObject>(diffData);
+
+						IReflectable& childObj = field->getValue(object.get());
+						std::shared_ptr<IReflectable> clonedObj = BinaryCloner::clone(&childObj, true);
+
+						IDiff::applyDiff(clonedObj->getRTTI(), clonedObj, fieldObjectData, objectMap, diffCommands);
+
+						DiffCommand command;
+						command.field = genericField;
+						command.type = Diff_Reflectable;
+						command.object = clonedObj;
+
+						diffCommands.push_back(command);
+					}
+						break;
+					case SerializableFT_Plain:
+					{
+						SPtr<SerializedField> diffFieldData = std::static_pointer_cast<SerializedField>(diffData);
+
+						if (diffFieldData->size > 0)
+						{
+							DiffCommand command;
+							command.field = genericField;
+							command.type = Diff_Plain;
+							command.value = diffFieldData->value;
+							command.size = diffFieldData->size;
+
+							diffCommands.push_back(command);
+						}
+					}
+						break;
+					case SerializableFT_DataBlock:
+					{
+						SPtr<SerializedField> diffFieldData = std::static_pointer_cast<SerializedField>(diffData);
+
+						DiffCommand command;
+						command.field = genericField;
+						command.type = Diff_DataBlock;
+						command.value = diffFieldData->value;
+						command.size = diffFieldData->size;
+
+						diffCommands.push_back(command);
+					}
+						break;
+					}
+				}
+			}
+		}
+
+		DiffCommand objEndCommand;
+		objEndCommand.field = nullptr;
+		objEndCommand.type = Diff_ObjectEnd;
+		objEndCommand.object = object;
+
+		diffCommands.push_back(objEndCommand);
+
+		while (!rttiTypes.empty())
+		{
+			rttiTypes.top()->onSerializationEnded(object.get());
+			rttiTypes.pop();
+		}
+	}
 }

+ 12 - 0
BansheeUtility/Source/BsSphere.cpp

@@ -4,6 +4,7 @@
 #include "BsRay.h"
 #include "BsPlane.h"
 #include "BsAABox.h"
+#include "BsMath.h"
 
 namespace BansheeEngine
 {
@@ -33,6 +34,17 @@ namespace BansheeEngine
 		mRadius = mCenter.distance(edge);
 	}
 
+	bool Sphere::contains(const Vector3& v) const
+	{
+		return ((v - mCenter).squaredLength() <= Math::sqr(mRadius));
+	}
+
+	bool Sphere::intersects(const Sphere& s) const
+	{
+		return (s.mCenter - mCenter).squaredLength() <=
+			Math::sqr(s.mRadius + mRadius);
+	}
+
 	std::pair<bool, float> Sphere::intersects(const Ray& ray, bool discardInside) const
 	{
 		const Vector3& raydir = ray.getDirection();

+ 3 - 4
BansheeUtility/Source/BsTaskScheduler.cpp

@@ -7,8 +7,8 @@ namespace BansheeEngine
 {
 	Task::Task(const PrivatelyConstruct& dummy, const String& name, std::function<void()> taskWorker, 
 		TaskPriority priority, TaskPtr dependency)
-		:mName(name), mState(0), mPriority(priority), mTaskId(0), 
-		mTaskDependency(dependency), mTaskWorker(taskWorker), mParent(nullptr)
+		:mName(name), mPriority(priority), mTaskId(0), mTaskWorker(taskWorker), mTaskDependency(dependency),
+		mParent(nullptr)
 	{
 
 	}
@@ -39,8 +39,7 @@ namespace BansheeEngine
 	}
 
 	TaskScheduler::TaskScheduler()
-		:mMaxActiveTasks(0), mNumActiveTasks(0), mNextTaskId(0), mShutdown(false),
-		mTaskQueue(&TaskScheduler::taskCompare)
+		:mTaskQueue(&TaskScheduler::taskCompare), mNumActiveTasks(0), mMaxActiveTasks(0), mNextTaskId(0), mShutdown(false)
 	{
 		mMaxActiveTasks = BS_THREAD_HARDWARE_CONCURRENCY;
 

+ 1 - 1
BansheeUtility/Source/BsTestOutput.cpp

@@ -7,6 +7,6 @@ namespace BansheeEngine
 {
 	void ExceptionTestOutput::outputFail(const String& desc, const String& function, const String& file, long line)
 	{
-		throw UnitTestException(desc, function, file.c_str(), line);
+		BS_EXCEPT(UnitTestException, desc);
 	}
 }

+ 4 - 4
BansheeUtility/Source/BsThreadPool.cpp

@@ -16,11 +16,11 @@
 namespace BansheeEngine
 {
 	HThread::HThread()
-		:mPool(nullptr), mThreadId(0)
+		:mThreadId(0), mPool(nullptr)
 	{ }
 
 	HThread::HThread(ThreadPool* pool, UINT32 threadId)
-		:mPool(pool), mThreadId(threadId)
+		:mThreadId(threadId), mPool(pool)
 	{ }
 
 	void HThread::blockUntilComplete()
@@ -53,8 +53,8 @@ namespace BansheeEngine
 	}
 
 	PooledThread::PooledThread(const String& name)
-		:mName(name), mIdle(true), mThreadStarted(false),
-		mThreadReady(false), mIdleTime(0), mId(0)
+		:mName(name), mId(0), mIdle(true), mThreadStarted(false),
+		mThreadReady(false), mIdleTime(0)
 	{ }
 
 	PooledThread::~PooledThread()

+ 0 - 1
BansheeUtility/Source/BsVector2.cpp

@@ -1,7 +1,6 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsVector2.h"
-#include "BsMath.h"
 
 namespace BansheeEngine
 {

+ 61 - 1
BansheeUtility/Source/BsVector3.cpp

@@ -1,8 +1,8 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsVector3.h"
-#include "BsMath.h"
 #include "BsVector4.h"
+#include "BsMath.h"
 
 namespace BansheeEngine
 {
@@ -12,6 +12,66 @@ namespace BansheeEngine
 
 	}
 
+	float Vector3::length() const
+	{
+		return Math::sqrt(x * x + y * y + z * z);
+	}
+
+	float Vector3::normalize()
+	{
+		float len = Math::sqrt(x * x + y * y + z * z);
+
+		// Will also work for zero-sized vectors, but will change nothing
+		if (len > 1e-08)
+		{
+			float invLen = 1.0f / len;
+			x *= invLen;
+			y *= invLen;
+			z *= invLen;
+		}
+
+		return len;
+	}
+
+	Radian Vector3::angleBetween(const Vector3& dest) const
+	{
+		float lenProduct = length() * dest.length();
+
+		// Divide by zero check
+		if (lenProduct < 1e-6f)
+			lenProduct = 1e-6f;
+
+		float f = dot(dest) / lenProduct;
+
+		f = Math::clamp(f, -1.0f, 1.0f);
+		return Math::acos(f);
+	}
+
+	Vector3 Vector3::normalize(const Vector3& val)
+	{
+		float len = Math::sqrt(val.x * val.x + val.y * val.y + val.z * val.z);
+
+		// Will also work for zero-sized vectors, but will change nothing
+		if (len > 1e-08)
+		{
+			float invLen = 1.0f / len;
+
+			Vector3 normalizedVec;
+			normalizedVec.x = val.x * invLen;
+			normalizedVec.y = val.y * invLen;
+			normalizedVec.z = val.z * invLen;
+
+			return normalizedVec;
+		}
+		else
+			return val;
+	}
+
+	bool Vector3::isNaN() const
+	{
+		return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z);
+	}
+
     const Vector3 Vector3::ZERO(0, 0, 0);
 	const Vector3 Vector3::ONE(1, 1, 1);
 	const Vector3 Vector3::INF =

+ 6 - 1
BansheeUtility/Source/BsVector4.cpp

@@ -5,5 +5,10 @@
 
 namespace BansheeEngine
 {
-    const Vector4 Vector4::ZERO( 0, 0, 0, 0 );
+    const Vector4 Vector4::ZERO(0, 0, 0, 0);
+
+	bool Vector4::isNaN() const
+	{
+		return Math::isNaN(x) || Math::isNaN(y) || Math::isNaN(z) || Math::isNaN(w);
+	}
 }