Просмотр исходного кода

Updating collider scale when parent component's transform changes

BearishSun 9 лет назад
Родитель
Сommit
0830458eea
2 измененных файлов с 819 добавлено и 813 удалено
  1. 341 338
      Source/BansheeCore/Source/BsCCollider.cpp
  2. 478 475
      Source/MBansheeEngine/Physics/Collider.cs

+ 341 - 338
Source/BansheeCore/Source/BsCCollider.cpp

@@ -1,339 +1,342 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsCCollider.h"
-#include "BsSceneObject.h"
-#include "BsCRigidbody.h"
-#include "BsPhysics.h"
-#include "BsCColliderRTTI.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	CCollider::CCollider(const HSceneObject& parent)
-		: Component(parent)
-	{
-		setName("Collider");
-
-		mNotifyFlags = (TransformChangedFlags)(TCF_Parent | TCF_Transform);
-	}
-
-	void CCollider::setIsTrigger(bool value)
-	{
-		if (mIsTrigger == value)
-			return;
-
-		mIsTrigger = value;
-
-		if (mInternal != nullptr)
-		{
-			mInternal->setIsTrigger(value);
-
-			updateParentRigidbody();
-			updateTransform();
-		}
-	}
-
-	void CCollider::setMass(float mass)
-	{
-		if (mMass == mass)
-			return;
-
-		mMass = mass;
-
-		if (mInternal != nullptr)
-		{
-			mInternal->setMass(mass);
-
-			if (mParent != nullptr)
-				mParent->_updateMassDistribution();
-		}
-	}
-
-	void CCollider::setMaterial(const HPhysicsMaterial& material)
-	{
-		mMaterial = material;
-
-		if (mInternal != nullptr)
-			mInternal->setMaterial(material);
-	}
-
-	void CCollider::setContactOffset(float value)
-	{
-		mContactOffset = value;
-
-		if (mInternal != nullptr)
-			mInternal->setContactOffset(value);
-	}
-
-	void CCollider::setRestOffset(float value)
-	{
-		mRestOffset = value;
-
-		if (mInternal != nullptr)
-			mInternal->setRestOffset(value);
-	}
-
-	void CCollider::setLayer(UINT64 layer)
-	{
-		mLayer = layer;
-
-		if (mInternal != nullptr)
-			mInternal->setLayer(layer);
-	}
-
-	void CCollider::setCollisionReportMode(CollisionReportMode mode)
-	{
-		mCollisionReportMode = mode;
-
-		if (mInternal != nullptr)
-			updateCollisionReportMode();
-	}
-
-	void CCollider::onInitialized()
-	{
-
-	}
-
-	void CCollider::onDestroyed()
-	{
-		destroyInternal();
-	}
-
-	void CCollider::onDisabled()
-	{
-		destroyInternal();
-	}
-
-	void CCollider::onEnabled()
-	{
-		restoreInternal();
-	}
-
-	void CCollider::onTransformChanged(TransformChangedFlags flags)
-	{
-		if (!SO()->getActive())
-			return;
-
-		if ((flags & TCF_Parent) != 0)
-			updateParentRigidbody();
-
-		// Don't update the transform if it's due to Physics update since then we can guarantee it will remain at the same
-		// relative transform to its parent
-		if (gPhysics()._isUpdateInProgress())
-			return;
-
-		if ((flags & (TCF_Parent | TCF_Transform)) != 0)
-			updateTransform();
-	}
-
-	void CCollider::setRigidbody(const HRigidbody& rigidbody, bool internal)
-	{
-		if (rigidbody == mParent)
-			return;
-
-		if (mInternal != nullptr && !internal)
-		{
-			if (mParent != nullptr)
-				mParent->removeCollider(mThisHandle);
-
-			Rigidbody* rigidBodyPtr = nullptr;
-
-			if (rigidbody != nullptr)
-				rigidBodyPtr = rigidbody->_getInternal();
-
-			mInternal->setRigidbody(rigidBodyPtr);
-
-			if (rigidbody != nullptr)
-				rigidbody->addCollider(mThisHandle);
-		}
-
-		mParent = rigidbody;
-		updateCollisionReportMode();
-	}
-
-	bool CCollider::rayCast(const Ray& ray, PhysicsQueryHit& hit, float maxDist) const
-	{
-		if (mInternal == nullptr)
-			return false;
-
-		return mInternal->rayCast(ray, hit, maxDist);
-	}
-
-	bool CCollider::rayCast(const Vector3& origin, const Vector3& unitDir, PhysicsQueryHit& hit,
-		float maxDist) const
-	{
-		if (mInternal == nullptr)
-			return false;
-
-		return mInternal->rayCast(origin, unitDir, hit, maxDist);
-	}
-
-	void CCollider::restoreInternal()
-	{
-		if (mInternal == nullptr)
-		{
-			mInternal = createInternal();
-
-			mInternal->onCollisionBegin.connect(std::bind(&CCollider::triggerOnCollisionBegin, this, _1));
-			mInternal->onCollisionStay.connect(std::bind(&CCollider::triggerOnCollisionStay, this, _1));
-			mInternal->onCollisionEnd.connect(std::bind(&CCollider::triggerOnCollisionEnd, this, _1));
-		}
-
-		// Note: Merge into one call to avoid many virtual function calls
-		mInternal->setIsTrigger(mIsTrigger);
-		mInternal->setMass(mMass);
-		mInternal->setMaterial(mMaterial);
-		mInternal->setContactOffset(mContactOffset);
-		mInternal->setRestOffset(mRestOffset);
-		mInternal->setLayer(mLayer);
-
-		updateParentRigidbody();
-		updateTransform();
-		updateCollisionReportMode();
-	}
-
-	void CCollider::destroyInternal()
-	{
-		if (mParent != nullptr)
-			mParent->removeCollider(mThisHandle);
-
-		mParent = nullptr;
-
-		// This should release the last reference and destroy the internal collider
-		mInternal->_setOwner(PhysicsOwnerType::None, nullptr);
-		mInternal = nullptr;
-	}
-
-	void CCollider::updateParentRigidbody()
-	{
-		if (mIsTrigger)
-		{
-			setRigidbody(HRigidbody());
-			return;
-		}
-
-		HSceneObject currentSO = SO();
-		while (currentSO != nullptr)
-		{
-			HRigidbody parent = currentSO->getComponent<CRigidbody>();
-			if (parent != nullptr)
-			{
-				if(currentSO->getActive() && isValidParent(parent))
-					setRigidbody(parent);
-				else
-					setRigidbody(HRigidbody());
-
-				return;
-			}
-
-			currentSO = currentSO->getParent();
-		}
-
-		// Not found
-		setRigidbody(HRigidbody());
-	}
-
-	void CCollider::updateTransform()
-	{
-		if (mParent != nullptr)
-		{
-			Vector3 parentPos = mParent->SO()->getWorldPosition();
-			Quaternion parentRot = mParent->SO()->getWorldRotation();
-
-			Vector3 myPos = SO()->getWorldPosition();
-			Quaternion myRot = SO()->getWorldRotation();
-
-			Vector3 scale = mParent->SO()->getWorldScale();
-			Vector3 invScale = scale;
-			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 = parentRot.inverse();
-
-			Vector3 relativePos = invRotation.rotate(myPos - parentPos) *  invScale;
-			Quaternion relativeRot = invRotation * myRot;
-
-			relativePos = relativePos + myRot.rotate(mLocalPosition * scale);
-			relativeRot = relativeRot * mLocalRotation;
-
-			mInternal->setTransform(relativePos, relativeRot);
-			mParent->_updateMassDistribution();
-		}
-		else
-		{
-			Vector3 myScale = SO()->getWorldScale();
-			Quaternion myRot = SO()->getWorldRotation();
-			Vector3 myPos = SO()->getWorldPosition() + myRot.rotate(mLocalPosition * myScale);
-			myRot = myRot * mLocalRotation;
-
-			mInternal->setTransform(myPos, myRot);
-		}
-	}
-
-	void CCollider::updateCollisionReportMode()
-	{
-		CollisionReportMode mode = mCollisionReportMode;
-
-		if (mParent != nullptr)
-			mode = mParent->getCollisionReportMode();
-
-		mInternal->setCollisionReportMode(mode);
-	}
-
-	void CCollider::triggerOnCollisionBegin(const CollisionData& data)
-	{
-		// Const-cast and modify is okay because we're the only object receiving this event
-		CollisionData& hit = const_cast<CollisionData&>(data);
-		hit.collider[0] = mThisHandle;
-
-		if(hit.collidersRaw[1] != nullptr)
-		{
-			CCollider* other = (CCollider*)hit.collidersRaw[1]->_getOwner(PhysicsOwnerType::Component);
-			hit.collider[1] = other->getHandle();
-		}
-
-		onCollisionBegin(hit);
-	}
-
-	void CCollider::triggerOnCollisionStay(const CollisionData& data)
-	{
-		// Const-cast and modify is okay because we're the only object receiving this event
-		CollisionData& hit = const_cast<CollisionData&>(data);
-		hit.collider[0] = mThisHandle;
-
-		if (hit.collidersRaw[1] != nullptr)
-		{
-			CCollider* other = (CCollider*)hit.collidersRaw[1]->_getOwner(PhysicsOwnerType::Component);
-			hit.collider[1] = other->getHandle();
-		}
-
-		onCollisionStay(hit);
-	}
-
-	void CCollider::triggerOnCollisionEnd(const CollisionData& data)
-	{
-		// Const-cast and modify is okay because we're the only object receiving this event
-		CollisionData& hit = const_cast<CollisionData&>(data);
-		hit.collider[0] = mThisHandle;
-
-		if (hit.collidersRaw[1] != nullptr)
-		{
-			CCollider* other = (CCollider*)hit.collidersRaw[1]->_getOwner(PhysicsOwnerType::Component);
-			hit.collider[1] = other->getHandle();
-		}
-
-		onCollisionEnd(hit);
-	}
-
-	RTTITypeBase* CCollider::getRTTIStatic()
-	{
-		return CColliderRTTI::instance();
-	}
-
-	RTTITypeBase* CCollider::getRTTI() const
-	{
-		return CCollider::getRTTIStatic();
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsCCollider.h"
+#include "BsSceneObject.h"
+#include "BsCRigidbody.h"
+#include "BsPhysics.h"
+#include "BsCColliderRTTI.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	CCollider::CCollider(const HSceneObject& parent)
+		: Component(parent)
+	{
+		setName("Collider");
+
+		mNotifyFlags = (TransformChangedFlags)(TCF_Parent | TCF_Transform);
+	}
+
+	void CCollider::setIsTrigger(bool value)
+	{
+		if (mIsTrigger == value)
+			return;
+
+		mIsTrigger = value;
+
+		if (mInternal != nullptr)
+		{
+			mInternal->setIsTrigger(value);
+
+			updateParentRigidbody();
+			updateTransform();
+		}
+	}
+
+	void CCollider::setMass(float mass)
+	{
+		if (mMass == mass)
+			return;
+
+		mMass = mass;
+
+		if (mInternal != nullptr)
+		{
+			mInternal->setMass(mass);
+
+			if (mParent != nullptr)
+				mParent->_updateMassDistribution();
+		}
+	}
+
+	void CCollider::setMaterial(const HPhysicsMaterial& material)
+	{
+		mMaterial = material;
+
+		if (mInternal != nullptr)
+			mInternal->setMaterial(material);
+	}
+
+	void CCollider::setContactOffset(float value)
+	{
+		mContactOffset = value;
+
+		if (mInternal != nullptr)
+			mInternal->setContactOffset(value);
+	}
+
+	void CCollider::setRestOffset(float value)
+	{
+		mRestOffset = value;
+
+		if (mInternal != nullptr)
+			mInternal->setRestOffset(value);
+	}
+
+	void CCollider::setLayer(UINT64 layer)
+	{
+		mLayer = layer;
+
+		if (mInternal != nullptr)
+			mInternal->setLayer(layer);
+	}
+
+	void CCollider::setCollisionReportMode(CollisionReportMode mode)
+	{
+		mCollisionReportMode = mode;
+
+		if (mInternal != nullptr)
+			updateCollisionReportMode();
+	}
+
+	void CCollider::onInitialized()
+	{
+
+	}
+
+	void CCollider::onDestroyed()
+	{
+		destroyInternal();
+	}
+
+	void CCollider::onDisabled()
+	{
+		destroyInternal();
+	}
+
+	void CCollider::onEnabled()
+	{
+		restoreInternal();
+	}
+
+	void CCollider::onTransformChanged(TransformChangedFlags flags)
+	{
+		if (!SO()->getActive())
+			return;
+
+		if ((flags & TCF_Parent) != 0)
+			updateParentRigidbody();
+
+		// Don't update the transform if it's due to Physics update since then we can guarantee it will remain at the same
+		// relative transform to its parent
+		if (gPhysics()._isUpdateInProgress())
+			return;
+
+		if ((flags & (TCF_Parent | TCF_Transform)) != 0)
+			updateTransform();
+	}
+
+	void CCollider::setRigidbody(const HRigidbody& rigidbody, bool internal)
+	{
+		if (rigidbody == mParent)
+			return;
+
+		if (mInternal != nullptr && !internal)
+		{
+			if (mParent != nullptr)
+				mParent->removeCollider(mThisHandle);
+
+			Rigidbody* rigidBodyPtr = nullptr;
+
+			if (rigidbody != nullptr)
+				rigidBodyPtr = rigidbody->_getInternal();
+
+			mInternal->setRigidbody(rigidBodyPtr);
+
+			if (rigidbody != nullptr)
+				rigidbody->addCollider(mThisHandle);
+		}
+
+		mParent = rigidbody;
+		updateCollisionReportMode();
+	}
+
+	bool CCollider::rayCast(const Ray& ray, PhysicsQueryHit& hit, float maxDist) const
+	{
+		if (mInternal == nullptr)
+			return false;
+
+		return mInternal->rayCast(ray, hit, maxDist);
+	}
+
+	bool CCollider::rayCast(const Vector3& origin, const Vector3& unitDir, PhysicsQueryHit& hit,
+		float maxDist) const
+	{
+		if (mInternal == nullptr)
+			return false;
+
+		return mInternal->rayCast(origin, unitDir, hit, maxDist);
+	}
+
+	void CCollider::restoreInternal()
+	{
+		if (mInternal == nullptr)
+		{
+			mInternal = createInternal();
+
+			mInternal->onCollisionBegin.connect(std::bind(&CCollider::triggerOnCollisionBegin, this, _1));
+			mInternal->onCollisionStay.connect(std::bind(&CCollider::triggerOnCollisionStay, this, _1));
+			mInternal->onCollisionEnd.connect(std::bind(&CCollider::triggerOnCollisionEnd, this, _1));
+		}
+
+		// Note: Merge into one call to avoid many virtual function calls
+		mInternal->setIsTrigger(mIsTrigger);
+		mInternal->setMass(mMass);
+		mInternal->setMaterial(mMaterial);
+		mInternal->setContactOffset(mContactOffset);
+		mInternal->setRestOffset(mRestOffset);
+		mInternal->setLayer(mLayer);
+
+		updateParentRigidbody();
+		updateTransform();
+		updateCollisionReportMode();
+	}
+
+	void CCollider::destroyInternal()
+	{
+		if (mParent != nullptr)
+			mParent->removeCollider(mThisHandle);
+
+		mParent = nullptr;
+
+		// This should release the last reference and destroy the internal collider
+		mInternal->_setOwner(PhysicsOwnerType::None, nullptr);
+		mInternal = nullptr;
+	}
+
+	void CCollider::updateParentRigidbody()
+	{
+		if (mIsTrigger)
+		{
+			setRigidbody(HRigidbody());
+			return;
+		}
+
+		HSceneObject currentSO = SO();
+		while (currentSO != nullptr)
+		{
+			HRigidbody parent = currentSO->getComponent<CRigidbody>();
+			if (parent != nullptr)
+			{
+				if(currentSO->getActive() && isValidParent(parent))
+					setRigidbody(parent);
+				else
+					setRigidbody(HRigidbody());
+
+				return;
+			}
+
+			currentSO = currentSO->getParent();
+		}
+
+		// Not found
+		setRigidbody(HRigidbody());
+	}
+
+	void CCollider::updateTransform()
+	{
+		Vector3 myScale = SO()->getWorldScale();
+
+		if (mParent != nullptr)
+		{
+			Vector3 parentPos = mParent->SO()->getWorldPosition();
+			Quaternion parentRot = mParent->SO()->getWorldRotation();
+
+			Vector3 myPos = SO()->getWorldPosition();
+			Quaternion myRot = SO()->getWorldRotation();
+
+			Vector3 scale = mParent->SO()->getWorldScale();
+			Vector3 invScale = scale;
+			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 = parentRot.inverse();
+
+			Vector3 relativePos = invRotation.rotate(myPos - parentPos) *  invScale;
+			Quaternion relativeRot = invRotation * myRot;
+
+			relativePos = relativePos + myRot.rotate(mLocalPosition * scale);
+			relativeRot = relativeRot * mLocalRotation;
+
+			mInternal->setTransform(relativePos, relativeRot);
+			mParent->_updateMassDistribution();
+		}
+		else
+		{
+			Quaternion myRot = SO()->getWorldRotation();
+			Vector3 myPos = SO()->getWorldPosition() + myRot.rotate(mLocalPosition * myScale);
+			myRot = myRot * mLocalRotation;
+
+			mInternal->setTransform(myPos, myRot);
+		}
+
+		mInternal->setScale(myScale);
+	}
+
+	void CCollider::updateCollisionReportMode()
+	{
+		CollisionReportMode mode = mCollisionReportMode;
+
+		if (mParent != nullptr)
+			mode = mParent->getCollisionReportMode();
+
+		mInternal->setCollisionReportMode(mode);
+	}
+
+	void CCollider::triggerOnCollisionBegin(const CollisionData& data)
+	{
+		// Const-cast and modify is okay because we're the only object receiving this event
+		CollisionData& hit = const_cast<CollisionData&>(data);
+		hit.collider[0] = mThisHandle;
+
+		if(hit.collidersRaw[1] != nullptr)
+		{
+			CCollider* other = (CCollider*)hit.collidersRaw[1]->_getOwner(PhysicsOwnerType::Component);
+			hit.collider[1] = other->getHandle();
+		}
+
+		onCollisionBegin(hit);
+	}
+
+	void CCollider::triggerOnCollisionStay(const CollisionData& data)
+	{
+		// Const-cast and modify is okay because we're the only object receiving this event
+		CollisionData& hit = const_cast<CollisionData&>(data);
+		hit.collider[0] = mThisHandle;
+
+		if (hit.collidersRaw[1] != nullptr)
+		{
+			CCollider* other = (CCollider*)hit.collidersRaw[1]->_getOwner(PhysicsOwnerType::Component);
+			hit.collider[1] = other->getHandle();
+		}
+
+		onCollisionStay(hit);
+	}
+
+	void CCollider::triggerOnCollisionEnd(const CollisionData& data)
+	{
+		// Const-cast and modify is okay because we're the only object receiving this event
+		CollisionData& hit = const_cast<CollisionData&>(data);
+		hit.collider[0] = mThisHandle;
+
+		if (hit.collidersRaw[1] != nullptr)
+		{
+			CCollider* other = (CCollider*)hit.collidersRaw[1]->_getOwner(PhysicsOwnerType::Component);
+			hit.collider[1] = other->getHandle();
+		}
+
+		onCollisionEnd(hit);
+	}
+
+	RTTITypeBase* CCollider::getRTTIStatic()
+	{
+		return CColliderRTTI::instance();
+	}
+
+	RTTITypeBase* CCollider::getRTTI() const
+	{
+		return CCollider::getRTTIStatic();
+	}
 }
 }

+ 478 - 475
Source/MBansheeEngine/Physics/Collider.cs

@@ -1,475 +1,478 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Collider represents physics geometry that can be in multiple states:
-    ///  - Default: Static geometry that physics objects can collide with.
-    ///  - Trigger: Static geometry that can't be collided with but will report touch events.
-    ///  - Dynamic: Dynamic geometry that is a part of a Rigidbody.A set of colliders defines the shape of the parent 
-    ///             rigidbody.
-    /// </summary>
-    public abstract class Collider : Component
-    {
-        internal NativeCollider native;
-        protected Rigidbody parent;
-
-        [SerializeField]
-        internal SerializableData serializableData = new SerializableData();
-
-        /// <summary>
-        /// Triggered when some object starts interacting with the collider. Only triggered if proper collision report mode
-        /// is turned on.
-        /// </summary>
-        public event Action<CollisionData> OnCollisionBegin;
-
-        /// <summary>
-        /// Triggered for every frame that an object remains interacting with a collider. Only triggered if proper collision
-        /// report mode is turned on.
-        /// </summary>
-        public event Action<CollisionData> OnCollisionStay;
-
-        /// <summary>
-        /// Triggered when some object stops interacting with the collider. Only triggered if proper collision report mode
-        /// is turned on.
-        /// </summary>
-        public event Action<CollisionData> OnCollisionEnd;
-
-        /// <summary>
-        /// Determines how the collider used. A trigger will not be used for collisions (i.e. objects will pass through it),
-        /// but collision events will still be reported.
-        /// </summary>
-        public bool IsTrigger
-        {
-            get { return serializableData.isTrigger; }
-            set
-            {
-                if (serializableData.isTrigger == value)
-                    return;
-
-                serializableData.isTrigger = value;
-
-                if (native != null)
-                {
-                    native.IsTrigger = value;
-                    UpdateParentRigidbody();
-                    UpdateTransform();
-                }
-            }
-        }
-
-        /// <summary>
-        /// Determines mass of the collider. Only relevant if the collider is part of a rigidbody. Ultimately this will 
-        /// determine the total mass, center of mass and inertia tensors of the parent rigidbody(if they're being calculated
-        /// automatically).
-        /// </summary>
-        public float Mass
-        {
-            get { return serializableData.mass; }
-            set
-            {
-                if (serializableData.mass == value)
-                    return;
-
-                serializableData.mass = value;
-
-                if (native != null)
-                {
-                    native.Mass = value;
-
-                    if (parent != null)
-                        parent.UpdateMassDistribution();
-                }
-            }
-        }
-
-        /// <summary>
-        /// Physics material that determines how objects hitting the collider behave.
-        /// </summary>
-        public PhysicsMaterial Material
-        {
-            get { return serializableData.material; }
-            set
-            {
-                serializableData.material = value;
-
-                if (native != null)
-                    native.Material = value;
-            }
-        }
-
-        /// <summary>
-        /// Determines how far apart do two shapes need to be away from each other before the physics runtime starts 
-        /// generating repelling impulse for them.This distance will be the sum of contact offsets of the two interacting
-        /// objects.If objects are moving fast you can increase this value to start generating the impulse earlier and 
-        /// potentially prevent the objects from interpenetrating. This value is in meters.
-        /// </summary>
-        public float ContactOffset
-        {
-            get { return serializableData.contactOffset; }
-            set
-            {
-                serializableData.contactOffset = value;
-
-                if (native != null)
-                    native.ContactOffset = value;
-            }
-        }
-
-        /// <summary>
-        /// Determines at what distance should two objects resting on one another come to an equilibrium. The value used in the
-        /// runtime will be the sum of rest offsets for both interacting objects. This value is in meters.
-        /// </summary>
-        public float RestOffset
-        {
-            get { return serializableData.restOffset; }
-            set
-            {
-                serializableData.restOffset = value;
-
-                if (native != null)
-                    native.RestOffset = value;
-            }
-        }
-
-        /// <summary>
-        /// Determines with which objects will the collider collide. Objects that are allowed to collide with this
-        /// object must have the same bits set in their own layers.
-        /// </summary>
-        public ulong Layer
-        {
-            get { return serializableData.layer; }
-            set
-            {
-                serializableData.layer = value;
-
-                if (native != null)
-                    native.Layer = value;
-            }
-        }
-
-        /// <summary>
-        /// Determines which (if any) collision events are reported.
-        /// </summary>
-        public CollisionReportMode CollisionReportMode
-        {
-            get { return serializableData.collisionReportMode; }
-            set
-            {
-                serializableData.collisionReportMode = value;
-
-                if (native != null)
-                    UpdateCollisionReportMode();
-            }
-        }
-
-        /// <summary>
-        /// Checks does the ray hit this collider. 
-        /// </summary>
-        /// <param name="ray">Ray to check.</param>
-        /// <param name="hit">Information about the hit. Valid only if the method returns true.</param>
-        /// <param name="maxDist">Maximum distance from the ray origin to search for hits.</param>
-        /// <returns>True if the ray has hit the collider.</returns>
-        public bool Raycast(Ray ray, out PhysicsQueryHit hit, float maxDist)
-        {
-            return Raycast(ray.origin, ray.direction, out hit, maxDist);
-        }
-
-        /// <summary>
-        /// Checks does the ray hit this collider. 
-        /// </summary>
-        /// <param name="origin">Origin of the ray to check.</param>
-        /// <param name="unitDir">Unit direction of the ray to check.</param>
-        /// <param name="hit">Information about the hit. Valid only if the method returns true.</param>
-        /// <param name="maxDist">Maximum distance from the ray origin to search for hits.</param>
-        /// <returns>True if the ray has hit the collider.</returns>
-        public bool Raycast(Vector3 origin, Vector3 unitDir, out PhysicsQueryHit hit, float maxDist = float.MaxValue)
-        {
-            hit = new PhysicsQueryHit();
-
-            if (native == null)
-                return false;
-
-            ScriptPhysicsQueryHit scriptHit;
-            bool wasHit = native.Raycast(origin, unitDir, out scriptHit, maxDist);
-
-            hit.collider = scriptHit.collider.Component;
-            hit.distance = scriptHit.distance;
-            hit.normal = scriptHit.normal;
-            hit.point = scriptHit.point;
-            hit.triangleIdx = scriptHit.triangleIdx;
-            hit.uv = scriptHit.uv;
-
-            return wasHit;
-        }
-
-        /// <summary>
-        /// Creates an internal instance of the collider. Should be overriden by specific collider implementations.
-        /// </summary>
-        /// <returns>An instance of a specific internal collider implementation. </returns>
-        internal abstract NativeCollider CreateCollider();
-
-        /// <summary>
-        /// Changes the rigidbody parent of the collider. Meant to be called from the Rigidbody itself. 
-        /// </summary>
-        /// <param name="rigidbody">New rigidbody to assign as the parent to the collider.</param>
-        /// <param name="isInternal">If true the rigidbody will just be changed internally, but parent rigidbody will not be
-        ///                          notified.</param>
-        internal void SetRigidbody(Rigidbody rigidbody, bool isInternal = false)
-	    {
-		    if (rigidbody == parent)
-			    return;
-
-		    if (native != null && !isInternal)
-		    {
-			    if (parent != null)
-                    parent.RemoveCollider(this);
-
-			    NativeRigidbody nativeRigidbody = null;
-
-			    if (rigidbody != null)
-                    nativeRigidbody = rigidbody.native;
-
-		        native.Rigidbody = nativeRigidbody;;
-
-			    if (rigidbody != null)
-				    rigidbody.AddCollider(this);
-		    }
-
-		    parent = rigidbody;
-		    UpdateCollisionReportMode();
-	    }
-
-        /// <summary>
-        /// Triggered when the internal collider begins touching another object.
-        /// </summary>
-        /// <param name="data">Data about the collision.</param>
-        internal void DoOnCollisionBegin(CollisionData data)
-        {
-            if (OnCollisionBegin != null)
-                OnCollisionBegin(data);
-        }
-
-        /// <summary>
-        /// Triggered when the internal collider ends touching another object.
-        /// </summary>
-        /// <param name="data">Data about the collision.</param>
-        internal void DoOnCollisionStay(CollisionData data)
-        {
-            if (OnCollisionStay != null)
-                OnCollisionStay(data);
-        }
-
-        /// <summary>
-        /// Triggered when the internal collider ends touching another object.
-        /// </summary>
-        /// <param name="data">Data about the collision.</param>
-        internal void DoOnCollisionEnd(CollisionData data)
-        {
-            if (OnCollisionEnd != null)
-                OnCollisionEnd(data);
-        }
-
-        /// <summary>
-        /// Checks is the provided rigidbody a valid parent for this collider.
-        /// 
-        /// This is required because certain colliders are limited in how they can be used.
-        /// </summary>
-        /// <param name="parent">Rigidbody that is the potential parent.</param>
-        /// <returns>True if collider can be a part of the rigidbody.</returns>
-        protected internal virtual bool IsValidParent(Rigidbody parent)
-        {
-            return true;
-        }
-
-        /// <summary>
-        /// Searches the parent scene object hierarchy to find a parent Rigidbody component.
-        /// </summary>
-        protected void UpdateParentRigidbody()
-        {
-            if (serializableData.isTrigger)
-            {
-                SetRigidbody(null);
-                return;
-            }
-
-            SceneObject currentSO = SceneObject;
-            while (currentSO != null)
-            {
-                Rigidbody parent = currentSO.GetComponent<Rigidbody>();
-                if (parent != null)
-                {
-                    if (currentSO.Active && IsValidParent(parent))
-                        SetRigidbody(parent);
-                    else
-                        SetRigidbody(null);
-
-                    return;
-                }
-
-                currentSO = currentSO.Parent;
-            }
-
-            // Not found
-            SetRigidbody(null);
-        }
-
-        /// <summary>
-        /// Updates the transform of the internal Collider representation from the transform of the component's scene object.
-        /// </summary>
-        protected void UpdateTransform()
-        {
-            if (parent != null)
-            {
-                Vector3 parentPos = parent.SceneObject.Position;
-                Quaternion parentRot = parent.SceneObject.Rotation;
-
-                Vector3 myPos = SceneObject.Position;
-                Quaternion myRot = SceneObject.Rotation;
-
-                Vector3 scale = parent.SceneObject.Scale;
-                Vector3 invScale = scale;
-                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 = parentRot.Inverse;
-
-                Vector3 relativePos = invRotation.Rotate(myPos - parentPos) * invScale;
-                Quaternion relativeRot = invRotation * myRot;
-
-                relativePos = relativePos + myRot.Rotate(serializableData.localPosition * scale);
-                relativeRot = relativeRot * serializableData.localRotation;
-
-                native.Position = relativePos;
-                native.Rotation = relativeRot;
-
-                parent.UpdateMassDistribution();
-            }
-            else
-            {
-                Vector3 myScale = SceneObject.Scale;
-                Quaternion myRot = SceneObject.Rotation;
-                Vector3 myPos = SceneObject.Position + myRot.Rotate(serializableData.localPosition * myScale);
-                myRot = myRot * serializableData.localRotation;
-
-                native.Position = myPos;
-                native.Rotation = myRot;
-            }
-        }
-
-        /// <summary>
-        /// Applies the collision report mode to the internal collider depending on the current state.
-        /// </summary>
-        internal void UpdateCollisionReportMode()
-        {
-            CollisionReportMode mode = serializableData.collisionReportMode;
-
-            if (parent != null)
-                mode = parent.CollisionReportMode;
-
-            native.CollisionReportMode = mode;
-        }
-
-        private void OnInitialize()
-        {
-            NotifyFlags = TransformChangedFlags.Transform | TransformChangedFlags.Parent;
-        }
-
-        private void OnReset()
-        {
-            RestoreNative();
-        }
-
-        private void OnEnable()
-        {
-            if (native == null)
-                RestoreNative();
-        }
-
-        private void OnDisable()
-        {
-            DestroyNative();
-        }
-
-        private void OnDestroy()
-        {
-            DestroyNative();
-        }
-
-        private void OnTransformChanged(TransformChangedFlags flags)
-        {
-            if (!SceneObject.Active)
-                return;
-
-            if ((flags & TransformChangedFlags.Parent) != 0)
-                UpdateParentRigidbody();
-
-            // Don't update the transform if it's due to Physics update since then we can guarantee it will remain at the same
-            // relative transform to its parent
-            if (Physics.IsUpdateInProgress)
-                return;
-
-            if ((flags & (TransformChangedFlags.Parent | TransformChangedFlags.Transform)) != 0)
-                UpdateTransform();
-        }
-
-        /// <summary>
-        /// Destroys the internal collider representation.
-        /// </summary>
-        private void DestroyNative()
-        {
-            if (parent != null)
-                parent.RemoveCollider(this);
-
-            parent = null;
-
-            if (native != null)
-            {
-                native.Destroy();
-                native = null;
-            }
-        }
-
-        /// <summary>
-        /// Creates the internal representation of the Collider and restores the values saved by the Component.
-        /// </summary>
-        private void RestoreNative()
-        {
-            native = CreateCollider();
-
-            native.Component = this;
-            native.Position = serializableData.localPosition;
-            native.Rotation = serializableData.localRotation;
-            native.IsTrigger = serializableData.isTrigger;
-            native.Mass = serializableData.mass;
-            native.Material = serializableData.material;
-            native.ContactOffset = serializableData.contactOffset;
-            native.RestOffset = serializableData.restOffset;
-            native.Layer = serializableData.layer;
-
-            UpdateParentRigidbody();
-            UpdateTransform();
-            UpdateCollisionReportMode();
-        }
-
-        /// <summary>
-        /// Holds all data the collider component needs to persist through serialization.
-        /// </summary>
-        [SerializeObject]
-        internal class SerializableData
-        {
-            public Vector3 localPosition;
-            public Quaternion localRotation;
-            public bool isTrigger;
-            public float mass = 1.0f;
-            public PhysicsMaterial material;
-            public float contactOffset;
-            public float restOffset;
-            public ulong layer = 1;
-            public CollisionReportMode collisionReportMode = CollisionReportMode.None;
-        }
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Collider represents physics geometry that can be in multiple states:
+    ///  - Default: Static geometry that physics objects can collide with.
+    ///  - Trigger: Static geometry that can't be collided with but will report touch events.
+    ///  - Dynamic: Dynamic geometry that is a part of a Rigidbody.A set of colliders defines the shape of the parent 
+    ///             rigidbody.
+    /// </summary>
+    public abstract class Collider : Component
+    {
+        internal NativeCollider native;
+        protected Rigidbody parent;
+
+        [SerializeField]
+        internal SerializableData serializableData = new SerializableData();
+
+        /// <summary>
+        /// Triggered when some object starts interacting with the collider. Only triggered if proper collision report mode
+        /// is turned on.
+        /// </summary>
+        public event Action<CollisionData> OnCollisionBegin;
+
+        /// <summary>
+        /// Triggered for every frame that an object remains interacting with a collider. Only triggered if proper collision
+        /// report mode is turned on.
+        /// </summary>
+        public event Action<CollisionData> OnCollisionStay;
+
+        /// <summary>
+        /// Triggered when some object stops interacting with the collider. Only triggered if proper collision report mode
+        /// is turned on.
+        /// </summary>
+        public event Action<CollisionData> OnCollisionEnd;
+
+        /// <summary>
+        /// Determines how the collider used. A trigger will not be used for collisions (i.e. objects will pass through it),
+        /// but collision events will still be reported.
+        /// </summary>
+        public bool IsTrigger
+        {
+            get { return serializableData.isTrigger; }
+            set
+            {
+                if (serializableData.isTrigger == value)
+                    return;
+
+                serializableData.isTrigger = value;
+
+                if (native != null)
+                {
+                    native.IsTrigger = value;
+                    UpdateParentRigidbody();
+                    UpdateTransform();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Determines mass of the collider. Only relevant if the collider is part of a rigidbody. Ultimately this will 
+        /// determine the total mass, center of mass and inertia tensors of the parent rigidbody(if they're being calculated
+        /// automatically).
+        /// </summary>
+        public float Mass
+        {
+            get { return serializableData.mass; }
+            set
+            {
+                if (serializableData.mass == value)
+                    return;
+
+                serializableData.mass = value;
+
+                if (native != null)
+                {
+                    native.Mass = value;
+
+                    if (parent != null)
+                        parent.UpdateMassDistribution();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Physics material that determines how objects hitting the collider behave.
+        /// </summary>
+        public PhysicsMaterial Material
+        {
+            get { return serializableData.material; }
+            set
+            {
+                serializableData.material = value;
+
+                if (native != null)
+                    native.Material = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines how far apart do two shapes need to be away from each other before the physics runtime starts 
+        /// generating repelling impulse for them.This distance will be the sum of contact offsets of the two interacting
+        /// objects.If objects are moving fast you can increase this value to start generating the impulse earlier and 
+        /// potentially prevent the objects from interpenetrating. This value is in meters.
+        /// </summary>
+        public float ContactOffset
+        {
+            get { return serializableData.contactOffset; }
+            set
+            {
+                serializableData.contactOffset = value;
+
+                if (native != null)
+                    native.ContactOffset = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines at what distance should two objects resting on one another come to an equilibrium. The value used in the
+        /// runtime will be the sum of rest offsets for both interacting objects. This value is in meters.
+        /// </summary>
+        public float RestOffset
+        {
+            get { return serializableData.restOffset; }
+            set
+            {
+                serializableData.restOffset = value;
+
+                if (native != null)
+                    native.RestOffset = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines with which objects will the collider collide. Objects that are allowed to collide with this
+        /// object must have the same bits set in their own layers.
+        /// </summary>
+        public ulong Layer
+        {
+            get { return serializableData.layer; }
+            set
+            {
+                serializableData.layer = value;
+
+                if (native != null)
+                    native.Layer = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines which (if any) collision events are reported.
+        /// </summary>
+        public CollisionReportMode CollisionReportMode
+        {
+            get { return serializableData.collisionReportMode; }
+            set
+            {
+                serializableData.collisionReportMode = value;
+
+                if (native != null)
+                    UpdateCollisionReportMode();
+            }
+        }
+
+        /// <summary>
+        /// Checks does the ray hit this collider. 
+        /// </summary>
+        /// <param name="ray">Ray to check.</param>
+        /// <param name="hit">Information about the hit. Valid only if the method returns true.</param>
+        /// <param name="maxDist">Maximum distance from the ray origin to search for hits.</param>
+        /// <returns>True if the ray has hit the collider.</returns>
+        public bool Raycast(Ray ray, out PhysicsQueryHit hit, float maxDist)
+        {
+            return Raycast(ray.origin, ray.direction, out hit, maxDist);
+        }
+
+        /// <summary>
+        /// Checks does the ray hit this collider. 
+        /// </summary>
+        /// <param name="origin">Origin of the ray to check.</param>
+        /// <param name="unitDir">Unit direction of the ray to check.</param>
+        /// <param name="hit">Information about the hit. Valid only if the method returns true.</param>
+        /// <param name="maxDist">Maximum distance from the ray origin to search for hits.</param>
+        /// <returns>True if the ray has hit the collider.</returns>
+        public bool Raycast(Vector3 origin, Vector3 unitDir, out PhysicsQueryHit hit, float maxDist = float.MaxValue)
+        {
+            hit = new PhysicsQueryHit();
+
+            if (native == null)
+                return false;
+
+            ScriptPhysicsQueryHit scriptHit;
+            bool wasHit = native.Raycast(origin, unitDir, out scriptHit, maxDist);
+
+            hit.collider = scriptHit.collider.Component;
+            hit.distance = scriptHit.distance;
+            hit.normal = scriptHit.normal;
+            hit.point = scriptHit.point;
+            hit.triangleIdx = scriptHit.triangleIdx;
+            hit.uv = scriptHit.uv;
+
+            return wasHit;
+        }
+
+        /// <summary>
+        /// Creates an internal instance of the collider. Should be overriden by specific collider implementations.
+        /// </summary>
+        /// <returns>An instance of a specific internal collider implementation. </returns>
+        internal abstract NativeCollider CreateCollider();
+
+        /// <summary>
+        /// Changes the rigidbody parent of the collider. Meant to be called from the Rigidbody itself. 
+        /// </summary>
+        /// <param name="rigidbody">New rigidbody to assign as the parent to the collider.</param>
+        /// <param name="isInternal">If true the rigidbody will just be changed internally, but parent rigidbody will not be
+        ///                          notified.</param>
+        internal void SetRigidbody(Rigidbody rigidbody, bool isInternal = false)
+	    {
+		    if (rigidbody == parent)
+			    return;
+
+		    if (native != null && !isInternal)
+		    {
+			    if (parent != null)
+                    parent.RemoveCollider(this);
+
+			    NativeRigidbody nativeRigidbody = null;
+
+			    if (rigidbody != null)
+                    nativeRigidbody = rigidbody.native;
+
+		        native.Rigidbody = nativeRigidbody;;
+
+			    if (rigidbody != null)
+				    rigidbody.AddCollider(this);
+		    }
+
+		    parent = rigidbody;
+		    UpdateCollisionReportMode();
+	    }
+
+        /// <summary>
+        /// Triggered when the internal collider begins touching another object.
+        /// </summary>
+        /// <param name="data">Data about the collision.</param>
+        internal void DoOnCollisionBegin(CollisionData data)
+        {
+            if (OnCollisionBegin != null)
+                OnCollisionBegin(data);
+        }
+
+        /// <summary>
+        /// Triggered when the internal collider ends touching another object.
+        /// </summary>
+        /// <param name="data">Data about the collision.</param>
+        internal void DoOnCollisionStay(CollisionData data)
+        {
+            if (OnCollisionStay != null)
+                OnCollisionStay(data);
+        }
+
+        /// <summary>
+        /// Triggered when the internal collider ends touching another object.
+        /// </summary>
+        /// <param name="data">Data about the collision.</param>
+        internal void DoOnCollisionEnd(CollisionData data)
+        {
+            if (OnCollisionEnd != null)
+                OnCollisionEnd(data);
+        }
+
+        /// <summary>
+        /// Checks is the provided rigidbody a valid parent for this collider.
+        /// 
+        /// This is required because certain colliders are limited in how they can be used.
+        /// </summary>
+        /// <param name="parent">Rigidbody that is the potential parent.</param>
+        /// <returns>True if collider can be a part of the rigidbody.</returns>
+        protected internal virtual bool IsValidParent(Rigidbody parent)
+        {
+            return true;
+        }
+
+        /// <summary>
+        /// Searches the parent scene object hierarchy to find a parent Rigidbody component.
+        /// </summary>
+        protected void UpdateParentRigidbody()
+        {
+            if (serializableData.isTrigger)
+            {
+                SetRigidbody(null);
+                return;
+            }
+
+            SceneObject currentSO = SceneObject;
+            while (currentSO != null)
+            {
+                Rigidbody parent = currentSO.GetComponent<Rigidbody>();
+                if (parent != null)
+                {
+                    if (currentSO.Active && IsValidParent(parent))
+                        SetRigidbody(parent);
+                    else
+                        SetRigidbody(null);
+
+                    return;
+                }
+
+                currentSO = currentSO.Parent;
+            }
+
+            // Not found
+            SetRigidbody(null);
+        }
+
+        /// <summary>
+        /// Updates the transform of the internal Collider representation from the transform of the component's scene object.
+        /// </summary>
+        protected void UpdateTransform()
+        {
+            Vector3 myScale = SceneObject.Scale;
+
+            if (parent != null)
+            {
+                Vector3 parentPos = parent.SceneObject.Position;
+                Quaternion parentRot = parent.SceneObject.Rotation;
+
+                Vector3 myPos = SceneObject.Position;
+                Quaternion myRot = SceneObject.Rotation;
+
+                Vector3 scale = parent.SceneObject.Scale;
+                Vector3 invScale = scale;
+                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 = parentRot.Inverse;
+
+                Vector3 relativePos = invRotation.Rotate(myPos - parentPos) * invScale;
+                Quaternion relativeRot = invRotation * myRot;
+
+                relativePos = relativePos + myRot.Rotate(serializableData.localPosition * scale);
+                relativeRot = relativeRot * serializableData.localRotation;
+
+                native.Position = relativePos;
+                native.Rotation = relativeRot;
+
+                parent.UpdateMassDistribution();
+            }
+            else
+            {
+                Quaternion myRot = SceneObject.Rotation;
+                Vector3 myPos = SceneObject.Position + myRot.Rotate(serializableData.localPosition * myScale);
+                myRot = myRot * serializableData.localRotation;
+
+                native.Position = myPos;
+                native.Rotation = myRot;
+            }
+
+            native.Scale = myScale;
+        }
+
+        /// <summary>
+        /// Applies the collision report mode to the internal collider depending on the current state.
+        /// </summary>
+        internal void UpdateCollisionReportMode()
+        {
+            CollisionReportMode mode = serializableData.collisionReportMode;
+
+            if (parent != null)
+                mode = parent.CollisionReportMode;
+
+            native.CollisionReportMode = mode;
+        }
+
+        private void OnInitialize()
+        {
+            NotifyFlags = TransformChangedFlags.Transform | TransformChangedFlags.Parent;
+        }
+
+        private void OnReset()
+        {
+            RestoreNative();
+        }
+
+        private void OnEnable()
+        {
+            if (native == null)
+                RestoreNative();
+        }
+
+        private void OnDisable()
+        {
+            DestroyNative();
+        }
+
+        private void OnDestroy()
+        {
+            DestroyNative();
+        }
+
+        private void OnTransformChanged(TransformChangedFlags flags)
+        {
+            if (!SceneObject.Active)
+                return;
+
+            if ((flags & TransformChangedFlags.Parent) != 0)
+                UpdateParentRigidbody();
+
+            // Don't update the transform if it's due to Physics update since then we can guarantee it will remain at the same
+            // relative transform to its parent
+            if (Physics.IsUpdateInProgress)
+                return;
+
+            if ((flags & (TransformChangedFlags.Parent | TransformChangedFlags.Transform)) != 0)
+                UpdateTransform();
+        }
+
+        /// <summary>
+        /// Destroys the internal collider representation.
+        /// </summary>
+        private void DestroyNative()
+        {
+            if (parent != null)
+                parent.RemoveCollider(this);
+
+            parent = null;
+
+            if (native != null)
+            {
+                native.Destroy();
+                native = null;
+            }
+        }
+
+        /// <summary>
+        /// Creates the internal representation of the Collider and restores the values saved by the Component.
+        /// </summary>
+        private void RestoreNative()
+        {
+            native = CreateCollider();
+
+            native.Component = this;
+            native.Position = serializableData.localPosition;
+            native.Rotation = serializableData.localRotation;
+            native.IsTrigger = serializableData.isTrigger;
+            native.Mass = serializableData.mass;
+            native.Material = serializableData.material;
+            native.ContactOffset = serializableData.contactOffset;
+            native.RestOffset = serializableData.restOffset;
+            native.Layer = serializableData.layer;
+
+            UpdateParentRigidbody();
+            UpdateTransform();
+            UpdateCollisionReportMode();
+        }
+
+        /// <summary>
+        /// Holds all data the collider component needs to persist through serialization.
+        /// </summary>
+        [SerializeObject]
+        internal class SerializableData
+        {
+            public Vector3 localPosition;
+            public Quaternion localRotation;
+            public bool isTrigger;
+            public float mass = 1.0f;
+            public PhysicsMaterial material;
+            public float contactOffset;
+            public float restOffset;
+            public ulong layer = 1;
+            public CollisionReportMode collisionReportMode = CollisionReportMode.None;
+        }
+    }
+}