Explorar o código

Fixed an issue where collider sometimes wasn't attached to a rigidbody if they were both initialized on the same frame
Properly apply SO active state after deserialization

BearishSun %!s(int64=9) %!d(string=hai) anos
pai
achega
f9dbcd6b8b

+ 2 - 2
Source/BansheeCore/Include/BsSceneObject.h

@@ -484,8 +484,8 @@ namespace BansheeEngine
 		 */
 		 */
 		void removeChild(const HSceneObject& object);
 		void removeChild(const HSceneObject& object);
 
 
-		/** Changes the object active in hierarchy state. */
-		void setActiveHierarchy(bool active);
+		/** Changes the object active in hierarchy state, and triggers necessary events. */
+		void setActiveHierarchy(bool active, bool triggerEvents = true);
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								Component	                     		*/
 		/* 								Component	                     		*/

+ 6 - 0
Source/BansheeCore/Include/BsSceneObjectRTTI.h

@@ -139,6 +139,12 @@ namespace BansheeEngine
 			{
 			{
 				GameObjectManager::instance().endDeserialization();
 				GameObjectManager::instance().endDeserialization();
 
 
+				bool parentActive = true;
+				if (so->getParent() != nullptr)
+					parentActive = so->getParent()->getActive();
+
+				so->setActiveHierarchy(parentActive, false);
+
 				if ((so->mFlags & SOF_DontInstantiate) == 0)
 				if ((so->mFlags & SOF_DontInstantiate) == 0)
 					so->_instantiate();
 					so->_instantiate();
 			}
 			}

+ 6 - 6
Source/BansheeCore/Source/BsCRigidbody.cpp

@@ -280,15 +280,15 @@ namespace BansheeEngine
 					if (!entry->isValidParent(mThisHandle))
 					if (!entry->isValidParent(mThisHandle))
 						continue;
 						continue;
 
 
+					Collider* collider = entry->_getInternal();
+					if (collider == nullptr)
+						continue;
+
 					entry->setRigidbody(mThisHandle, true);
 					entry->setRigidbody(mThisHandle, true);
 					mChildren.push_back(entry);
 					mChildren.push_back(entry);
 
 
-					Collider* collider = entry->_getInternal();
-					if (collider != nullptr)
-					{
-						collider->setRigidbody(mInternal.get());
-						mInternal->addCollider(collider->_getInternal());
-					}
+					collider->setRigidbody(mInternal.get());
+					mInternal->addCollider(collider->_getInternal());
 				}
 				}
 			}
 			}
 
 

+ 778 - 775
Source/BansheeCore/Source/BsSceneObject.cpp

@@ -1,776 +1,779 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsSceneObject.h"
-#include "BsComponent.h"
-#include "BsCoreSceneManager.h"
-#include "BsException.h"
-#include "BsDebug.h"
-#include "BsSceneObjectRTTI.h"
-#include "BsMemorySerializer.h"
-#include "BsGameObjectManager.h"
-#include "BsPrefabUtility.h"
-#include "BsMatrix3.h"
-#include "BsCoreApplication.h"
-
-namespace BansheeEngine
-{
-	SceneObject::SceneObject(const String& name, UINT32 flags)
-		:GameObject(), mPosition(Vector3::ZERO), mRotation(Quaternion::IDENTITY), mScale(Vector3::ONE),
-		mWorldPosition(Vector3::ZERO), mWorldRotation(Quaternion::IDENTITY), mWorldScale(Vector3::ONE),
-		mCachedLocalTfrm(Matrix4::IDENTITY), mDirtyFlags(0xFFFFFFFF), mCachedWorldTfrm(Matrix4::IDENTITY), 
-		mActiveSelf(true), mActiveHierarchy(true), mDirtyHash(0), mFlags(flags), mPrefabHash(0)
-	{
-		setName(name);
-	}
-
-	SceneObject::~SceneObject()
-	{
-		if(!mThisHandle.isDestroyed())
-		{
-			LOGWRN("Object is being deleted without being destroyed first?");
-			destroyInternal(mThisHandle, true);
-		}
-	}
-
-	HSceneObject SceneObject::create(const String& name, UINT32 flags)
-	{
-		HSceneObject newObject = createInternal(name, flags);
-
-		if (newObject->isInstantiated())
-			gCoreSceneManager().registerNewSO(newObject);
-
-		return newObject;
-	}
-
-	HSceneObject SceneObject::createInternal(const String& name, UINT32 flags)
-	{
-		SPtr<SceneObject> sceneObjectPtr = SPtr<SceneObject>(new (bs_alloc<SceneObject>()) SceneObject(name, flags),
-			&bs_delete<SceneObject>, StdAlloc<SceneObject>());
-		
-		HSceneObject sceneObject = GameObjectManager::instance().registerObject(sceneObjectPtr);
-		sceneObject->mThisHandle = sceneObject;
-
-		return sceneObject;
-	}
-
-	HSceneObject SceneObject::createInternal(const SPtr<SceneObject>& soPtr, UINT64 originalId)
-	{
-		HSceneObject sceneObject = GameObjectManager::instance().registerObject(soPtr, originalId);
-		sceneObject->mThisHandle = sceneObject;
-
-		return sceneObject;
-	}
-
-	void SceneObject::destroy(bool immediate)
-	{
-		// Parent is our owner, so when his reference to us is removed, delete might be called.
-		// So make sure this is the last thing we do.
-		if(mParent != nullptr)
-		{
-			if(!mParent.isDestroyed())
-				mParent->removeChild(mThisHandle);
-
-			mParent = nullptr;
-		}
-
-		destroyInternal(mThisHandle, immediate);
-	}
-
-	void SceneObject::destroyInternal(GameObjectHandleBase& handle, bool immediate)
-	{
-		if (immediate)
-		{
-			for (auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
-				(*iter)->destroyInternal(*iter, true);
-
-			mChildren.clear();
-
-			for (auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
-			{
-				HComponent component = *iter;
-				component->_setIsDestroyed();
-
-				if (isInstantiated())
-				{
-					if (getActive())
-						component->onDisabled();
-
-					component->onDestroyed();
-				}
-
-				component->destroyInternal(*iter, true);
-			}
-
-			mComponents.clear();
-
-			GameObjectManager::instance().unregisterObject(handle);
-		}
-		else
-			GameObjectManager::instance().queueForDestroy(handle);
-	}
-
-	void SceneObject::_setInstanceData(GameObjectInstanceDataPtr& other)
-	{
-		GameObject::_setInstanceData(other);
-
-		// Instance data changed, so make sure to refresh the handles to reflect that
-		mThisHandle._setHandleData(mThisHandle.getInternalPtr());
-	}
-
-	String SceneObject::getPrefabLink() const
-	{
-		const SceneObject* curObj = this;
-
-		while (curObj != nullptr)
-		{
-			if (!curObj->mPrefabLinkUUID.empty())
-				return curObj->mPrefabLinkUUID;
-
-			if (curObj->mParent != nullptr)
-				curObj = curObj->mParent.get();
-			else
-				curObj = nullptr;
-		}
-
-		return "";
-	}
-
-	HSceneObject SceneObject::getPrefabParent() const
-	{
-		HSceneObject curObj = mThisHandle;
-
-		while (curObj != nullptr)
-		{
-			if (!curObj->mPrefabLinkUUID.empty())
-				return curObj;
-
-			if (curObj->mParent != nullptr)
-				curObj = curObj->mParent;
-			else
-				curObj = nullptr;
-		}
-
-		return curObj;
-	}
-
-	void SceneObject::breakPrefabLink()
-	{
-		SceneObject* rootObj = this;
-
-		while (rootObj != nullptr)
-		{
-			if (!rootObj->mPrefabLinkUUID.empty())
-				break;
-
-			if (rootObj->mParent != nullptr)
-				rootObj = rootObj->mParent.get();
-			else
-				rootObj = nullptr;
-		}
-
-		if (rootObj != nullptr)
-		{
-			rootObj->mPrefabLinkUUID = "";
-			rootObj->mPrefabDiff = nullptr;
-			PrefabUtility::clearPrefabIds(rootObj->getHandle());
-		}
-	}
-
-	bool SceneObject::hasFlag(UINT32 flag) const
-	{
-		return (mFlags & flag) != 0;
-	}
-
-	void SceneObject::setFlags(UINT32 flags)
-	{
-		mFlags |= flags;
-
-		for (auto& child : mChildren)
-			child->setFlags(flags);
-	}
-
-	void SceneObject::unsetFlags(UINT32 flags)
-	{
-		mFlags &= ~flags;
-
-		for (auto& child : mChildren)
-			child->unsetFlags(flags);
-	}
-
-	void SceneObject::_instantiate()
-	{
-		std::function<void(SceneObject*)> instantiateRecursive = [&](SceneObject* obj)
-		{
-			obj->mFlags &= ~SOF_DontInstantiate;
-
-			if (obj->mParent == nullptr)
-				gCoreSceneManager().registerNewSO(obj->mThisHandle);
-
-			for (auto& component : obj->mComponents)
-				component->instantiate();
-
-			for (auto& child : obj->mChildren)
-				instantiateRecursive(child.get());
-		};
-
-		std::function<void(SceneObject*)> triggerEventsRecursive = [&](SceneObject* obj)
-		{
-			for (auto& component : obj->mComponents)
-			{
-				component->onInitialized();
-
-				if (obj->getActive())
-					component->onEnabled();
-			}
-
-			for (auto& child : obj->mChildren)
-				triggerEventsRecursive(child.get());
-		};
-
-		instantiateRecursive(this);
-		triggerEventsRecursive(this);
-	}
-
-	/************************************************************************/
-	/* 								Transform	                     		*/
-	/************************************************************************/
-
-	void SceneObject::setPosition(const Vector3& position)
-	{
-		mPosition = position;
-		notifyTransformChanged(TCF_Transform);
-	}
-
-	void SceneObject::setRotation(const Quaternion& rotation)
-	{
-		mRotation = rotation;
-		notifyTransformChanged(TCF_Transform);
-	}
-
-	void SceneObject::setScale(const Vector3& scale)
-	{
-		mScale = scale;
-		notifyTransformChanged(TCF_Transform);
-	}
-
-	void SceneObject::setWorldPosition(const Vector3& position)
-	{
-		if (mParent != nullptr)
-		{
-			Vector3 invScale = mParent->getWorldScale();
-			if (invScale.x != 0) invScale.x = 1.0f / invScale.x;
-			if (invScale.y != 0) invScale.y = 1.0f / invScale.y;
-			if (invScale.z != 0) invScale.z = 1.0f / invScale.z;
-
-			Quaternion invRotation = mParent->getWorldRotation().inverse();
-
-			mPosition = invRotation.rotate(position - mParent->getWorldPosition()) *  invScale;
-		}
-		else
-			mPosition = position;
-
-		notifyTransformChanged(TCF_Transform);
-	}
-
-	void SceneObject::setWorldRotation(const Quaternion& rotation)
-	{
-		if (mParent != nullptr)
-		{
-			Quaternion invRotation = mParent->getWorldRotation().inverse();
-
-			mRotation = invRotation * rotation;
-		}
-		else
-			mRotation = rotation;
-
-		notifyTransformChanged(TCF_Transform);
-	}
-
-	void SceneObject::setWorldScale(const Vector3& scale)
-	{
-		if (mParent != nullptr)
-		{
-			Matrix3 rotScale;
-			mParent->getWorldTfrm().extract3x3Matrix(rotScale);
-			rotScale.inverse();
-
-			Matrix3 scaleMat = Matrix3(Quaternion::IDENTITY, scale);
-			scaleMat = rotScale * scaleMat;
-
-			Quaternion rotation;
-			Vector3 localScale;
-			scaleMat.decomposition(rotation, localScale);
-
-			mScale = localScale;
-		}
-		else
-			mScale = scale;
-
-		notifyTransformChanged(TCF_Transform);
-	}
-
-	const Vector3& SceneObject::getWorldPosition() const
-	{ 
-		if (!isCachedWorldTfrmUpToDate())
-			updateWorldTfrm();
-
-		return mWorldPosition; 
-	}
-
-	const Quaternion& SceneObject::getWorldRotation() const 
-	{ 
-		if (!isCachedWorldTfrmUpToDate())
-			updateWorldTfrm();
-
-		return mWorldRotation; 
-	}
-
-	const Vector3& SceneObject::getWorldScale() const 
-	{ 
-		if (!isCachedWorldTfrmUpToDate())
-			updateWorldTfrm();
-
-		return mWorldScale; 
-	}
-
-	void SceneObject::lookAt(const Vector3& location, const Vector3& up)
-	{
-		Vector3 forward = location - getWorldPosition();
-		
-		Quaternion rotation = getWorldRotation();
-		rotation.lookRotation(forward, up);
-		setWorldRotation(rotation);
-	}
-
-	const Matrix4& SceneObject::getWorldTfrm() const
-	{
-		if (!isCachedWorldTfrmUpToDate())
-			updateWorldTfrm();
-
-		return mCachedWorldTfrm;
-	}
-
-	Matrix4 SceneObject::getInvWorldTfrm() const
-	{
-		if (!isCachedWorldTfrmUpToDate())
-			updateWorldTfrm();
-
-		Matrix4 worldToLocal = Matrix4::inverseTRS(mWorldPosition, mWorldRotation, mWorldScale);
-		return worldToLocal;
-	}
-
-	const Matrix4& SceneObject::getLocalTfrm() const
-	{
-		if (!isCachedLocalTfrmUpToDate())
-			updateLocalTfrm();
-
-		return mCachedLocalTfrm;
-	}
-
-	void SceneObject::move(const Vector3& vec)
-	{
-		setPosition(mPosition + vec);
-	}
-
-	void SceneObject::moveRelative(const Vector3& vec)
-	{
-		// Transform the axes of the relative vector by camera's local axes
-		Vector3 trans = mRotation.rotate(vec);
-
-		setPosition(mPosition + trans);
-	}
-
-	void SceneObject::rotate(const Vector3& axis, const Radian& angle)
-	{
-		Quaternion q;
-		q.fromAxisAngle(axis, angle);
-		rotate(q);
-	}
-
-	void SceneObject::rotate(const Quaternion& q)
-	{
-		// Note the order of the mult, i.e. q comes after
-
-		// Normalize the quat to avoid cumulative problems with precision
-		Quaternion qnorm = q;
-		qnorm.normalize();
-		setRotation(qnorm * mRotation);
-	}
-
-	void SceneObject::roll(const Radian& angle)
-	{
-		// Rotate around local Z axis
-		Vector3 zAxis = mRotation.rotate(Vector3::UNIT_Z);
-		rotate(zAxis, angle);
-	}
-
-	void SceneObject::yaw(const Radian& angle)
-	{
-		Vector3 yAxis = mRotation.rotate(Vector3::UNIT_Y);
-		rotate(yAxis, angle);
-	}
-
-	void SceneObject::pitch(const Radian& angle)
-	{
-		// Rotate around local X axis
-		Vector3 xAxis = mRotation.rotate(Vector3::UNIT_X);
-		rotate(xAxis, angle);
-	}
-
-	void SceneObject::setForward(const Vector3& forwardDir)
-	{
-		Quaternion currentRotation = getWorldRotation();
-		currentRotation.lookRotation(forwardDir);
-		setWorldRotation(currentRotation);
-	}
-
-	void SceneObject::updateTransformsIfDirty()
-	{
-		if (!isCachedLocalTfrmUpToDate())
-			updateLocalTfrm();
-
-		if (!isCachedWorldTfrmUpToDate())
-			updateWorldTfrm();
-	}
-
-	void SceneObject::notifyTransformChanged(TransformChangedFlags flags) const
-	{
-		mDirtyFlags |= DirtyFlags::LocalTfrmDirty | DirtyFlags::WorldTfrmDirty;
-		mDirtyHash++;
-
-		for(auto& entry : mComponents)
-		{
-			if (entry->supportsNotify(flags))
-				entry->onTransformChanged(flags);
-		}
-
-		for (auto& entry : mChildren)
-			entry->notifyTransformChanged(flags);
-	}
-
-	void SceneObject::updateWorldTfrm() const
-	{
-		if(mParent != nullptr)
-		{
-			// Update orientation
-			const Quaternion& parentOrientation = mParent->getWorldRotation();
-			mWorldRotation = parentOrientation * mRotation;
-
-			// Update scale
-			const Vector3& parentScale = mParent->getWorldScale();
-			// Scale own position by parent scale, just combine
-			// as equivalent axes, no shearing
-			mWorldScale = parentScale * mScale;
-
-			// Change position vector based on parent's orientation & scale
-			mWorldPosition = parentOrientation.rotate(parentScale * mPosition);
-
-			// Add altered position vector to parents
-			mWorldPosition += mParent->getWorldPosition();
-
-			mCachedWorldTfrm.setTRS(mWorldPosition, mWorldRotation, mWorldScale);
-		}
-		else
-		{
-			mWorldRotation = mRotation;
-			mWorldPosition = mPosition;
-			mWorldScale = mScale;
-
-			mCachedWorldTfrm = getLocalTfrm();
-		}
-
-		mDirtyFlags &= ~DirtyFlags::WorldTfrmDirty;
-	}
-
-	void SceneObject::updateLocalTfrm() const
-	{
-		mCachedLocalTfrm.setTRS(mPosition, mRotation, mScale);
-
-		mDirtyFlags &= ~DirtyFlags::LocalTfrmDirty;
-	}
-
-	/************************************************************************/
-	/* 								Hierarchy	                     		*/
-	/************************************************************************/
-
-	void SceneObject::setParent(const HSceneObject& parent, bool keepWorldTransform)
-	{
-		if (parent.isDestroyed())
-			return;
-
-#if BS_EDITOR_BUILD
-		String originalPrefab = getPrefabLink();
-#endif
-
-		_setParent(parent, keepWorldTransform);
-
-#if BS_EDITOR_BUILD
-		if (gCoreApplication().isEditor())
-		{
-			String newPrefab = getPrefabLink();
-			if (originalPrefab != newPrefab)
-				PrefabUtility::clearPrefabIds(mThisHandle);
-		}
-#endif
-	}
-
-	void SceneObject::_setParent(const HSceneObject& parent, bool keepWorldTransform)
-	{
-		if (mThisHandle == parent)
-			return;
-
-		if (mParent == nullptr || mParent != parent)
-		{
-			Vector3 worldPos;
-			Quaternion worldRot;
-			Vector3 worldScale;
-
-			if (keepWorldTransform)
-			{
-				// Make sure the object keeps its world coordinates
-				worldPos = getWorldPosition();
-				worldRot = getWorldRotation();
-				worldScale = getWorldScale();
-			}
-
-			if (mParent != nullptr)
-				mParent->removeChild(mThisHandle);
-
-			if (parent != nullptr)
-				parent->addChild(mThisHandle);
-
-			mParent = parent;
-
-			if (keepWorldTransform)
-			{
-				setWorldPosition(worldPos);
-				setWorldRotation(worldRot);
-				setWorldScale(worldScale);
-			}
-
-			notifyTransformChanged((TransformChangedFlags)(TCF_Parent | TCF_Transform));
-		}
-	}
-
-	HSceneObject SceneObject::getChild(UINT32 idx) const
-	{
-		if(idx < 0 || idx >= mChildren.size())
-		{
-			BS_EXCEPT(InternalErrorException, "Child index out of range.");
-		}
-
-		return mChildren[idx];
-	}
-
-	int SceneObject::indexOfChild(const HSceneObject& child) const
-	{
-		for(int i = 0; i < (int)mChildren.size(); i++)
-		{
-			if(mChildren[i] == child)
-				return i;
-		}
-
-		return -1;
-	}
-
-	void SceneObject::addChild(const HSceneObject& object)
-	{
-		mChildren.push_back(object); 
-
-		object->setFlags(mFlags);
-	}
-
-	void SceneObject::removeChild(const HSceneObject& object)
-	{
-		auto result = find(mChildren.begin(), mChildren.end(), object);
-
-		if(result != mChildren.end())
-			mChildren.erase(result);
-		else
-		{
-			BS_EXCEPT(InternalErrorException, 
-				"Trying to remove a child but it's not a child of the transform.");
-		}
-	}
-
-	HSceneObject SceneObject::findChild(const String& name, bool recursive)
-	{
-		for (auto& child : mChildren)
-		{
-			if (child->getName() == name)
-				return child;
-		}
-
-		if (recursive)
-		{
-			for (auto& child : mChildren)
-			{
-				HSceneObject foundObject = child->findChild(name, true);
-				if (foundObject != nullptr)
-					return foundObject;
-			}
-		}
-
-		return HSceneObject();
-	}
-
-	Vector<HSceneObject> SceneObject::findChildren(const String& name, bool recursive)
-	{
-		std::function<void(const HSceneObject&, Vector<HSceneObject>&)> findChildrenInternal = 
-			[&](const HSceneObject& so, Vector<HSceneObject>& output)
-		{
-			for (auto& child : so->mChildren)
-			{
-				if (child->getName() == name)
-					output.push_back(child);
-			}
-
-			if (recursive)
-			{
-				for (auto& child : so->mChildren)
-					findChildrenInternal(child, output);
-			}
-		};
-
-		Vector<HSceneObject> output;
-		findChildrenInternal(mThisHandle, output);
-
-		return output;
-	}
-
-	void SceneObject::setActive(bool active)
-	{
-		mActiveSelf = active;
-		setActiveHierarchy(active);
-	}
-
-	void SceneObject::setActiveHierarchy(bool active) 
-	{ 
-		bool activeHierarchy = active && mActiveSelf;
-
-		if (mActiveHierarchy != activeHierarchy)
-		{
-			mActiveHierarchy = activeHierarchy;
-
-			if (activeHierarchy)
-			{
-				for (auto& component : mComponents)
-					component->onEnabled();
-			}
-			else
-			{
-				for (auto& component : mComponents)
-					component->onDisabled();
-			}
-		}
-		
-		for (auto child : mChildren)
-		{
-			child->setActiveHierarchy(mActiveHierarchy);
-		}
-	}
-
-	bool SceneObject::getActive(bool self)
-	{
-		if (self)
-			return mActiveSelf;
-		else
-			return mActiveHierarchy;
-	}
-
-	HSceneObject SceneObject::clone(bool instantiate)
-	{
-		if (!instantiate)
-			setFlags(SOF_DontInstantiate);
-
-		UINT32 bufferSize = 0;
-
-		MemorySerializer serializer;
-		UINT8* buffer = serializer.encode(this, bufferSize, (void*(*)(UINT32))&bs_alloc);
-
-		GameObjectManager::instance().setDeserializationMode(GODM_UseNewIds | GODM_RestoreExternal);
-		std::shared_ptr<SceneObject> cloneObj = std::static_pointer_cast<SceneObject>(serializer.decode(buffer, bufferSize));
-		bs_free(buffer);
-
-		if (!instantiate)
-			unsetFlags(SOF_DontInstantiate);
-
-		return cloneObj->mThisHandle;
-	}
-
-	HComponent SceneObject::getComponent(RTTITypeBase* type) const
-	{
-		for(auto& entry : mComponents)
-		{
-			if(entry->getRTTI()->isDerivedFrom(type))
-				return entry;
-		}
-
-		return HComponent();
-	}
-
-	void SceneObject::destroyComponent(const HComponent component, bool immediate)
-	{
-		if(component == nullptr)
-		{
-			LOGDBG("Trying to remove a null component");
-			return;
-		}
-
-		auto iter = std::find(mComponents.begin(), mComponents.end(), component);
-
-		if(iter != mComponents.end())
-		{
-			(*iter)->_setIsDestroyed();
-
-			if (isInstantiated())
-			{
-				if (getActive())
-					component->onDisabled();
-
-				(*iter)->onDestroyed();
-			}
-			
-			(*iter)->destroyInternal(*iter, immediate);
-			mComponents.erase(iter);
-		}
-		else
-			LOGDBG("Trying to remove a component that doesn't exist on this SceneObject.");
-	}
-
-	void SceneObject::destroyComponent(Component* component, bool immediate)
-	{
-		auto iterFind = std::find_if(mComponents.begin(), mComponents.end(), 
-			[component](const HComponent& x) 
-		{ 
-			if(x.isDestroyed())
-				return false;
-
-			return x._getHandleData()->mPtr->object.get() == component; }
-		);
-
-		if(iterFind != mComponents.end())
-		{
-			destroyComponent(*iterFind, immediate);
-		}
-	}
-
-	void SceneObject::addComponentInternal(const std::shared_ptr<Component> component)
-	{
-		GameObjectHandle<Component> newComponent = GameObjectManager::instance().getObject(component->getInstanceId());
-		newComponent->mParent = mThisHandle;
-		newComponent->mThisHandle = newComponent;
-
-		mComponents.push_back(newComponent);
-	}
-
-	RTTITypeBase* SceneObject::getRTTIStatic()
-	{
-		return SceneObjectRTTI::instance();
-	}
-
-	RTTITypeBase* SceneObject::getRTTI() const
-	{
-		return SceneObject::getRTTIStatic();
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsSceneObject.h"
+#include "BsComponent.h"
+#include "BsCoreSceneManager.h"
+#include "BsException.h"
+#include "BsDebug.h"
+#include "BsSceneObjectRTTI.h"
+#include "BsMemorySerializer.h"
+#include "BsGameObjectManager.h"
+#include "BsPrefabUtility.h"
+#include "BsMatrix3.h"
+#include "BsCoreApplication.h"
+
+namespace BansheeEngine
+{
+	SceneObject::SceneObject(const String& name, UINT32 flags)
+		:GameObject(), mPosition(Vector3::ZERO), mRotation(Quaternion::IDENTITY), mScale(Vector3::ONE),
+		mWorldPosition(Vector3::ZERO), mWorldRotation(Quaternion::IDENTITY), mWorldScale(Vector3::ONE),
+		mCachedLocalTfrm(Matrix4::IDENTITY), mDirtyFlags(0xFFFFFFFF), mCachedWorldTfrm(Matrix4::IDENTITY), 
+		mActiveSelf(true), mActiveHierarchy(true), mDirtyHash(0), mFlags(flags), mPrefabHash(0)
+	{
+		setName(name);
+	}
+
+	SceneObject::~SceneObject()
+	{
+		if(!mThisHandle.isDestroyed())
+		{
+			LOGWRN("Object is being deleted without being destroyed first?");
+			destroyInternal(mThisHandle, true);
+		}
+	}
+
+	HSceneObject SceneObject::create(const String& name, UINT32 flags)
+	{
+		HSceneObject newObject = createInternal(name, flags);
+
+		if (newObject->isInstantiated())
+			gCoreSceneManager().registerNewSO(newObject);
+
+		return newObject;
+	}
+
+	HSceneObject SceneObject::createInternal(const String& name, UINT32 flags)
+	{
+		SPtr<SceneObject> sceneObjectPtr = SPtr<SceneObject>(new (bs_alloc<SceneObject>()) SceneObject(name, flags),
+			&bs_delete<SceneObject>, StdAlloc<SceneObject>());
+		
+		HSceneObject sceneObject = GameObjectManager::instance().registerObject(sceneObjectPtr);
+		sceneObject->mThisHandle = sceneObject;
+
+		return sceneObject;
+	}
+
+	HSceneObject SceneObject::createInternal(const SPtr<SceneObject>& soPtr, UINT64 originalId)
+	{
+		HSceneObject sceneObject = GameObjectManager::instance().registerObject(soPtr, originalId);
+		sceneObject->mThisHandle = sceneObject;
+
+		return sceneObject;
+	}
+
+	void SceneObject::destroy(bool immediate)
+	{
+		// Parent is our owner, so when his reference to us is removed, delete might be called.
+		// So make sure this is the last thing we do.
+		if(mParent != nullptr)
+		{
+			if(!mParent.isDestroyed())
+				mParent->removeChild(mThisHandle);
+
+			mParent = nullptr;
+		}
+
+		destroyInternal(mThisHandle, immediate);
+	}
+
+	void SceneObject::destroyInternal(GameObjectHandleBase& handle, bool immediate)
+	{
+		if (immediate)
+		{
+			for (auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
+				(*iter)->destroyInternal(*iter, true);
+
+			mChildren.clear();
+
+			for (auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
+			{
+				HComponent component = *iter;
+				component->_setIsDestroyed();
+
+				if (isInstantiated())
+				{
+					if (getActive())
+						component->onDisabled();
+
+					component->onDestroyed();
+				}
+
+				component->destroyInternal(*iter, true);
+			}
+
+			mComponents.clear();
+
+			GameObjectManager::instance().unregisterObject(handle);
+		}
+		else
+			GameObjectManager::instance().queueForDestroy(handle);
+	}
+
+	void SceneObject::_setInstanceData(GameObjectInstanceDataPtr& other)
+	{
+		GameObject::_setInstanceData(other);
+
+		// Instance data changed, so make sure to refresh the handles to reflect that
+		mThisHandle._setHandleData(mThisHandle.getInternalPtr());
+	}
+
+	String SceneObject::getPrefabLink() const
+	{
+		const SceneObject* curObj = this;
+
+		while (curObj != nullptr)
+		{
+			if (!curObj->mPrefabLinkUUID.empty())
+				return curObj->mPrefabLinkUUID;
+
+			if (curObj->mParent != nullptr)
+				curObj = curObj->mParent.get();
+			else
+				curObj = nullptr;
+		}
+
+		return "";
+	}
+
+	HSceneObject SceneObject::getPrefabParent() const
+	{
+		HSceneObject curObj = mThisHandle;
+
+		while (curObj != nullptr)
+		{
+			if (!curObj->mPrefabLinkUUID.empty())
+				return curObj;
+
+			if (curObj->mParent != nullptr)
+				curObj = curObj->mParent;
+			else
+				curObj = nullptr;
+		}
+
+		return curObj;
+	}
+
+	void SceneObject::breakPrefabLink()
+	{
+		SceneObject* rootObj = this;
+
+		while (rootObj != nullptr)
+		{
+			if (!rootObj->mPrefabLinkUUID.empty())
+				break;
+
+			if (rootObj->mParent != nullptr)
+				rootObj = rootObj->mParent.get();
+			else
+				rootObj = nullptr;
+		}
+
+		if (rootObj != nullptr)
+		{
+			rootObj->mPrefabLinkUUID = "";
+			rootObj->mPrefabDiff = nullptr;
+			PrefabUtility::clearPrefabIds(rootObj->getHandle());
+		}
+	}
+
+	bool SceneObject::hasFlag(UINT32 flag) const
+	{
+		return (mFlags & flag) != 0;
+	}
+
+	void SceneObject::setFlags(UINT32 flags)
+	{
+		mFlags |= flags;
+
+		for (auto& child : mChildren)
+			child->setFlags(flags);
+	}
+
+	void SceneObject::unsetFlags(UINT32 flags)
+	{
+		mFlags &= ~flags;
+
+		for (auto& child : mChildren)
+			child->unsetFlags(flags);
+	}
+
+	void SceneObject::_instantiate()
+	{
+		std::function<void(SceneObject*)> instantiateRecursive = [&](SceneObject* obj)
+		{
+			obj->mFlags &= ~SOF_DontInstantiate;
+
+			if (obj->mParent == nullptr)
+				gCoreSceneManager().registerNewSO(obj->mThisHandle);
+
+			for (auto& component : obj->mComponents)
+				component->instantiate();
+
+			for (auto& child : obj->mChildren)
+				instantiateRecursive(child.get());
+		};
+
+		std::function<void(SceneObject*)> triggerEventsRecursive = [&](SceneObject* obj)
+		{
+			for (auto& component : obj->mComponents)
+			{
+				component->onInitialized();
+
+				if (obj->getActive())
+					component->onEnabled();
+			}
+
+			for (auto& child : obj->mChildren)
+				triggerEventsRecursive(child.get());
+		};
+
+		instantiateRecursive(this);
+		triggerEventsRecursive(this);
+	}
+
+	/************************************************************************/
+	/* 								Transform	                     		*/
+	/************************************************************************/
+
+	void SceneObject::setPosition(const Vector3& position)
+	{
+		mPosition = position;
+		notifyTransformChanged(TCF_Transform);
+	}
+
+	void SceneObject::setRotation(const Quaternion& rotation)
+	{
+		mRotation = rotation;
+		notifyTransformChanged(TCF_Transform);
+	}
+
+	void SceneObject::setScale(const Vector3& scale)
+	{
+		mScale = scale;
+		notifyTransformChanged(TCF_Transform);
+	}
+
+	void SceneObject::setWorldPosition(const Vector3& position)
+	{
+		if (mParent != nullptr)
+		{
+			Vector3 invScale = mParent->getWorldScale();
+			if (invScale.x != 0) invScale.x = 1.0f / invScale.x;
+			if (invScale.y != 0) invScale.y = 1.0f / invScale.y;
+			if (invScale.z != 0) invScale.z = 1.0f / invScale.z;
+
+			Quaternion invRotation = mParent->getWorldRotation().inverse();
+
+			mPosition = invRotation.rotate(position - mParent->getWorldPosition()) *  invScale;
+		}
+		else
+			mPosition = position;
+
+		notifyTransformChanged(TCF_Transform);
+	}
+
+	void SceneObject::setWorldRotation(const Quaternion& rotation)
+	{
+		if (mParent != nullptr)
+		{
+			Quaternion invRotation = mParent->getWorldRotation().inverse();
+
+			mRotation = invRotation * rotation;
+		}
+		else
+			mRotation = rotation;
+
+		notifyTransformChanged(TCF_Transform);
+	}
+
+	void SceneObject::setWorldScale(const Vector3& scale)
+	{
+		if (mParent != nullptr)
+		{
+			Matrix3 rotScale;
+			mParent->getWorldTfrm().extract3x3Matrix(rotScale);
+			rotScale.inverse();
+
+			Matrix3 scaleMat = Matrix3(Quaternion::IDENTITY, scale);
+			scaleMat = rotScale * scaleMat;
+
+			Quaternion rotation;
+			Vector3 localScale;
+			scaleMat.decomposition(rotation, localScale);
+
+			mScale = localScale;
+		}
+		else
+			mScale = scale;
+
+		notifyTransformChanged(TCF_Transform);
+	}
+
+	const Vector3& SceneObject::getWorldPosition() const
+	{ 
+		if (!isCachedWorldTfrmUpToDate())
+			updateWorldTfrm();
+
+		return mWorldPosition; 
+	}
+
+	const Quaternion& SceneObject::getWorldRotation() const 
+	{ 
+		if (!isCachedWorldTfrmUpToDate())
+			updateWorldTfrm();
+
+		return mWorldRotation; 
+	}
+
+	const Vector3& SceneObject::getWorldScale() const 
+	{ 
+		if (!isCachedWorldTfrmUpToDate())
+			updateWorldTfrm();
+
+		return mWorldScale; 
+	}
+
+	void SceneObject::lookAt(const Vector3& location, const Vector3& up)
+	{
+		Vector3 forward = location - getWorldPosition();
+		
+		Quaternion rotation = getWorldRotation();
+		rotation.lookRotation(forward, up);
+		setWorldRotation(rotation);
+	}
+
+	const Matrix4& SceneObject::getWorldTfrm() const
+	{
+		if (!isCachedWorldTfrmUpToDate())
+			updateWorldTfrm();
+
+		return mCachedWorldTfrm;
+	}
+
+	Matrix4 SceneObject::getInvWorldTfrm() const
+	{
+		if (!isCachedWorldTfrmUpToDate())
+			updateWorldTfrm();
+
+		Matrix4 worldToLocal = Matrix4::inverseTRS(mWorldPosition, mWorldRotation, mWorldScale);
+		return worldToLocal;
+	}
+
+	const Matrix4& SceneObject::getLocalTfrm() const
+	{
+		if (!isCachedLocalTfrmUpToDate())
+			updateLocalTfrm();
+
+		return mCachedLocalTfrm;
+	}
+
+	void SceneObject::move(const Vector3& vec)
+	{
+		setPosition(mPosition + vec);
+	}
+
+	void SceneObject::moveRelative(const Vector3& vec)
+	{
+		// Transform the axes of the relative vector by camera's local axes
+		Vector3 trans = mRotation.rotate(vec);
+
+		setPosition(mPosition + trans);
+	}
+
+	void SceneObject::rotate(const Vector3& axis, const Radian& angle)
+	{
+		Quaternion q;
+		q.fromAxisAngle(axis, angle);
+		rotate(q);
+	}
+
+	void SceneObject::rotate(const Quaternion& q)
+	{
+		// Note the order of the mult, i.e. q comes after
+
+		// Normalize the quat to avoid cumulative problems with precision
+		Quaternion qnorm = q;
+		qnorm.normalize();
+		setRotation(qnorm * mRotation);
+	}
+
+	void SceneObject::roll(const Radian& angle)
+	{
+		// Rotate around local Z axis
+		Vector3 zAxis = mRotation.rotate(Vector3::UNIT_Z);
+		rotate(zAxis, angle);
+	}
+
+	void SceneObject::yaw(const Radian& angle)
+	{
+		Vector3 yAxis = mRotation.rotate(Vector3::UNIT_Y);
+		rotate(yAxis, angle);
+	}
+
+	void SceneObject::pitch(const Radian& angle)
+	{
+		// Rotate around local X axis
+		Vector3 xAxis = mRotation.rotate(Vector3::UNIT_X);
+		rotate(xAxis, angle);
+	}
+
+	void SceneObject::setForward(const Vector3& forwardDir)
+	{
+		Quaternion currentRotation = getWorldRotation();
+		currentRotation.lookRotation(forwardDir);
+		setWorldRotation(currentRotation);
+	}
+
+	void SceneObject::updateTransformsIfDirty()
+	{
+		if (!isCachedLocalTfrmUpToDate())
+			updateLocalTfrm();
+
+		if (!isCachedWorldTfrmUpToDate())
+			updateWorldTfrm();
+	}
+
+	void SceneObject::notifyTransformChanged(TransformChangedFlags flags) const
+	{
+		mDirtyFlags |= DirtyFlags::LocalTfrmDirty | DirtyFlags::WorldTfrmDirty;
+		mDirtyHash++;
+
+		for(auto& entry : mComponents)
+		{
+			if (entry->supportsNotify(flags))
+				entry->onTransformChanged(flags);
+		}
+
+		for (auto& entry : mChildren)
+			entry->notifyTransformChanged(flags);
+	}
+
+	void SceneObject::updateWorldTfrm() const
+	{
+		if(mParent != nullptr)
+		{
+			// Update orientation
+			const Quaternion& parentOrientation = mParent->getWorldRotation();
+			mWorldRotation = parentOrientation * mRotation;
+
+			// Update scale
+			const Vector3& parentScale = mParent->getWorldScale();
+			// Scale own position by parent scale, just combine
+			// as equivalent axes, no shearing
+			mWorldScale = parentScale * mScale;
+
+			// Change position vector based on parent's orientation & scale
+			mWorldPosition = parentOrientation.rotate(parentScale * mPosition);
+
+			// Add altered position vector to parents
+			mWorldPosition += mParent->getWorldPosition();
+
+			mCachedWorldTfrm.setTRS(mWorldPosition, mWorldRotation, mWorldScale);
+		}
+		else
+		{
+			mWorldRotation = mRotation;
+			mWorldPosition = mPosition;
+			mWorldScale = mScale;
+
+			mCachedWorldTfrm = getLocalTfrm();
+		}
+
+		mDirtyFlags &= ~DirtyFlags::WorldTfrmDirty;
+	}
+
+	void SceneObject::updateLocalTfrm() const
+	{
+		mCachedLocalTfrm.setTRS(mPosition, mRotation, mScale);
+
+		mDirtyFlags &= ~DirtyFlags::LocalTfrmDirty;
+	}
+
+	/************************************************************************/
+	/* 								Hierarchy	                     		*/
+	/************************************************************************/
+
+	void SceneObject::setParent(const HSceneObject& parent, bool keepWorldTransform)
+	{
+		if (parent.isDestroyed())
+			return;
+
+#if BS_EDITOR_BUILD
+		String originalPrefab = getPrefabLink();
+#endif
+
+		_setParent(parent, keepWorldTransform);
+
+#if BS_EDITOR_BUILD
+		if (gCoreApplication().isEditor())
+		{
+			String newPrefab = getPrefabLink();
+			if (originalPrefab != newPrefab)
+				PrefabUtility::clearPrefabIds(mThisHandle);
+		}
+#endif
+	}
+
+	void SceneObject::_setParent(const HSceneObject& parent, bool keepWorldTransform)
+	{
+		if (mThisHandle == parent)
+			return;
+
+		if (mParent == nullptr || mParent != parent)
+		{
+			Vector3 worldPos;
+			Quaternion worldRot;
+			Vector3 worldScale;
+
+			if (keepWorldTransform)
+			{
+				// Make sure the object keeps its world coordinates
+				worldPos = getWorldPosition();
+				worldRot = getWorldRotation();
+				worldScale = getWorldScale();
+			}
+
+			if (mParent != nullptr)
+				mParent->removeChild(mThisHandle);
+
+			if (parent != nullptr)
+				parent->addChild(mThisHandle);
+
+			mParent = parent;
+
+			if (keepWorldTransform)
+			{
+				setWorldPosition(worldPos);
+				setWorldRotation(worldRot);
+				setWorldScale(worldScale);
+			}
+
+			notifyTransformChanged((TransformChangedFlags)(TCF_Parent | TCF_Transform));
+		}
+	}
+
+	HSceneObject SceneObject::getChild(UINT32 idx) const
+	{
+		if(idx < 0 || idx >= mChildren.size())
+		{
+			BS_EXCEPT(InternalErrorException, "Child index out of range.");
+		}
+
+		return mChildren[idx];
+	}
+
+	int SceneObject::indexOfChild(const HSceneObject& child) const
+	{
+		for(int i = 0; i < (int)mChildren.size(); i++)
+		{
+			if(mChildren[i] == child)
+				return i;
+		}
+
+		return -1;
+	}
+
+	void SceneObject::addChild(const HSceneObject& object)
+	{
+		mChildren.push_back(object); 
+
+		object->setFlags(mFlags);
+	}
+
+	void SceneObject::removeChild(const HSceneObject& object)
+	{
+		auto result = find(mChildren.begin(), mChildren.end(), object);
+
+		if(result != mChildren.end())
+			mChildren.erase(result);
+		else
+		{
+			BS_EXCEPT(InternalErrorException, 
+				"Trying to remove a child but it's not a child of the transform.");
+		}
+	}
+
+	HSceneObject SceneObject::findChild(const String& name, bool recursive)
+	{
+		for (auto& child : mChildren)
+		{
+			if (child->getName() == name)
+				return child;
+		}
+
+		if (recursive)
+		{
+			for (auto& child : mChildren)
+			{
+				HSceneObject foundObject = child->findChild(name, true);
+				if (foundObject != nullptr)
+					return foundObject;
+			}
+		}
+
+		return HSceneObject();
+	}
+
+	Vector<HSceneObject> SceneObject::findChildren(const String& name, bool recursive)
+	{
+		std::function<void(const HSceneObject&, Vector<HSceneObject>&)> findChildrenInternal = 
+			[&](const HSceneObject& so, Vector<HSceneObject>& output)
+		{
+			for (auto& child : so->mChildren)
+			{
+				if (child->getName() == name)
+					output.push_back(child);
+			}
+
+			if (recursive)
+			{
+				for (auto& child : so->mChildren)
+					findChildrenInternal(child, output);
+			}
+		};
+
+		Vector<HSceneObject> output;
+		findChildrenInternal(mThisHandle, output);
+
+		return output;
+	}
+
+	void SceneObject::setActive(bool active)
+	{
+		mActiveSelf = active;
+		setActiveHierarchy(active);
+	}
+
+	void SceneObject::setActiveHierarchy(bool active, bool triggerEvents) 
+	{ 
+		bool activeHierarchy = active && mActiveSelf;
+
+		if (mActiveHierarchy != activeHierarchy)
+		{
+			mActiveHierarchy = activeHierarchy;
+
+			if (triggerEvents)
+			{
+				if (activeHierarchy)
+				{
+					for (auto& component : mComponents)
+						component->onEnabled();
+				}
+				else
+				{
+					for (auto& component : mComponents)
+						component->onDisabled();
+				}
+			}
+		}
+		
+		for (auto child : mChildren)
+		{
+			child->setActiveHierarchy(mActiveHierarchy, triggerEvents);
+		}
+	}
+
+	bool SceneObject::getActive(bool self)
+	{
+		if (self)
+			return mActiveSelf;
+		else
+			return mActiveHierarchy;
+	}
+
+	HSceneObject SceneObject::clone(bool instantiate)
+	{
+		if (!instantiate)
+			setFlags(SOF_DontInstantiate);
+
+		UINT32 bufferSize = 0;
+
+		MemorySerializer serializer;
+		UINT8* buffer = serializer.encode(this, bufferSize, (void*(*)(UINT32))&bs_alloc);
+
+		GameObjectManager::instance().setDeserializationMode(GODM_UseNewIds | GODM_RestoreExternal);
+		std::shared_ptr<SceneObject> cloneObj = std::static_pointer_cast<SceneObject>(serializer.decode(buffer, bufferSize));
+		bs_free(buffer);
+
+		if (!instantiate)
+			unsetFlags(SOF_DontInstantiate);
+
+		return cloneObj->mThisHandle;
+	}
+
+	HComponent SceneObject::getComponent(RTTITypeBase* type) const
+	{
+		for(auto& entry : mComponents)
+		{
+			if(entry->getRTTI()->isDerivedFrom(type))
+				return entry;
+		}
+
+		return HComponent();
+	}
+
+	void SceneObject::destroyComponent(const HComponent component, bool immediate)
+	{
+		if(component == nullptr)
+		{
+			LOGDBG("Trying to remove a null component");
+			return;
+		}
+
+		auto iter = std::find(mComponents.begin(), mComponents.end(), component);
+
+		if(iter != mComponents.end())
+		{
+			(*iter)->_setIsDestroyed();
+
+			if (isInstantiated())
+			{
+				if (getActive())
+					component->onDisabled();
+
+				(*iter)->onDestroyed();
+			}
+			
+			(*iter)->destroyInternal(*iter, immediate);
+			mComponents.erase(iter);
+		}
+		else
+			LOGDBG("Trying to remove a component that doesn't exist on this SceneObject.");
+	}
+
+	void SceneObject::destroyComponent(Component* component, bool immediate)
+	{
+		auto iterFind = std::find_if(mComponents.begin(), mComponents.end(), 
+			[component](const HComponent& x) 
+		{ 
+			if(x.isDestroyed())
+				return false;
+
+			return x._getHandleData()->mPtr->object.get() == component; }
+		);
+
+		if(iterFind != mComponents.end())
+		{
+			destroyComponent(*iterFind, immediate);
+		}
+	}
+
+	void SceneObject::addComponentInternal(const std::shared_ptr<Component> component)
+	{
+		GameObjectHandle<Component> newComponent = GameObjectManager::instance().getObject(component->getInstanceId());
+		newComponent->mParent = mThisHandle;
+		newComponent->mThisHandle = newComponent;
+
+		mComponents.push_back(newComponent);
+	}
+
+	RTTITypeBase* SceneObject::getRTTIStatic()
+	{
+		return SceneObjectRTTI::instance();
+	}
+
+	RTTITypeBase* SceneObject::getRTTI() const
+	{
+		return SceneObject::getRTTIStatic();
+	}
 }
 }

+ 1 - 0
Source/BansheeEditor/Source/BsGUISceneTreeView.cpp

@@ -164,6 +164,7 @@ namespace BansheeEngine
 					newChild->mName = currentSOChild->getName();
 					newChild->mName = currentSOChild->getName();
 					newChild->mSortedIdx = (UINT32)newChildren.size();
 					newChild->mSortedIdx = (UINT32)newChildren.size();
 					newChild->mIsVisible = element->mIsVisible && element->mIsExpanded;
 					newChild->mIsVisible = element->mIsVisible && element->mIsExpanded;
+					newChild->mIsDisabled = !currentSOChild->getActive();
 					newChild->mTint = isInternal ? Color::Red : (isPrefabInstance ? PREFAB_TINT : Color::White);
 					newChild->mTint = isInternal ? Color::Red : (isPrefabInstance ? PREFAB_TINT : Color::White);
 					newChild->mIsPrefabInstance = isPrefabInstance;
 					newChild->mIsPrefabInstance = isPrefabInstance;
 
 

+ 2 - 2
Source/MBansheeEditor/Library/LibraryGUIContent.cs

@@ -227,14 +227,14 @@ namespace BansheeEditor
                     case ProjectViewType.Grid64:
                     case ProjectViewType.Grid64:
                         tileSize = 64;
                         tileSize = 64;
                         elemWidth = tileSize;
                         elemWidth = tileSize;
-                        elemHeight = tileSize + 32;
+                        elemHeight = tileSize + 36;
                         horzElementSpacing = 10;
                         horzElementSpacing = 10;
                         vertElemSpacing = 12;
                         vertElemSpacing = 12;
                         break;
                         break;
                     case ProjectViewType.Grid48:
                     case ProjectViewType.Grid48:
                         tileSize = 48;
                         tileSize = 48;
                         elemWidth = tileSize;
                         elemWidth = tileSize;
-                        elemHeight = tileSize + 32;
+                        elemHeight = tileSize + 36;
                         horzElementSpacing = 8;
                         horzElementSpacing = 8;
                         vertElemSpacing = 10;
                         vertElemSpacing = 10;
                         break;
                         break;

+ 4 - 3
Source/MBansheeEngine/Physics/Rigidbody.cs

@@ -582,10 +582,11 @@ namespace BansheeEngine
                         if (!entry.IsValidParent(this))
                         if (!entry.IsValidParent(this))
                             continue;
                             continue;
 
 
-                        entry.SetRigidbody(this, true);
+                        if (entry.native == null)
+                            continue; 
 
 
-                        if(entry.native != null)
-                            entry.native.Rigidbody = native;
+                        entry.SetRigidbody(this, true);
+                        entry.native.Rigidbody = native;
 
 
                         children.Add(entry);
                         children.Add(entry);
                         native.AddCollider(entry);
                         native.AddCollider(entry);