Browse Source

Properly calculate bounds for managed Renderable components
Fixing an issue with scale handle where it would incorrectly scale previously scaled object

BearishSun 10 years ago
parent
commit
7184765d9d

+ 10 - 0
BansheeCore/Include/BsComponent.h

@@ -2,6 +2,7 @@
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
 #include "BsGameObject.h"
 #include "BsGameObject.h"
+#include "BsBounds.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -29,6 +30,15 @@ namespace BansheeEngine
 		 */
 		 */
 		virtual void update() { }
 		virtual void update() { }
 
 
+		/**
+		 * @brief	Calculates bounds of the visible contents represented by this component (e.g. a mesh for Renderable).
+		 * 
+		 * @param	bounds	Bounds of the contents in world space coordinates.
+		 * 					
+		 * @returns	True if the component has bounds with non-zero volume, otherwise false.
+		 */
+		virtual bool calculateBounds(Bounds& bounds);
+
 		/**
 		/**
 		 * @brief	Checks if this and the provided component represent the same type.
 		 * @brief	Checks if this and the provided component represent the same type.
 		 * 			
 		 * 			

+ 8 - 0
BansheeCore/Source/BsComponent.cpp

@@ -20,6 +20,14 @@ namespace BansheeEngine
 		return getRTTI()->getRTTIId() == other.getRTTI()->getRTTIId();
 		return getRTTI()->getRTTIId() == other.getRTTI()->getRTTIId();
 	}
 	}
 
 
+	bool Component::calculateBounds(Bounds& bounds)
+	{
+		Vector3 position = SO()->getWorldPosition();
+
+		bounds = Bounds(AABox(position, position), Sphere(position, 0.0f));
+		return false;
+	}
+
 	void Component::destroy(bool immediate)
 	void Component::destroy(bool immediate)
 	{
 	{
 		SO()->destroyComponent(this, immediate);
 		SO()->destroyComponent(this, immediate);

+ 22 - 6
BansheeEditor/Source/BsEditorUtility.cpp

@@ -41,14 +41,30 @@ namespace BansheeEngine
 
 
 	bool EditorUtility::calculateMeshBounds(const HSceneObject& object, AABox& bounds)
 	bool EditorUtility::calculateMeshBounds(const HSceneObject& object, AABox& bounds)
 	{
 	{
-		if (object->hasComponent<CRenderable>())
-		{
-			HRenderable renderable = object->getComponent<CRenderable>();
-			bounds = renderable->getBounds().getBox();
+		bounds = AABox(Vector3::ZERO, Vector3::ZERO);
 
 
-			return true;
+		bool foundOne = false;
+		const Vector<HComponent>& components = object->getComponents();
+		for (auto& component : components)
+		{
+			Bounds curBounds;
+			if (component->calculateBounds(curBounds))
+			{
+				if (!foundOne)
+				{
+					bounds = curBounds.getBox();
+					foundOne = true;
+				}
+				else
+					bounds.merge(curBounds.getBox());
+			}
+			else
+			{
+				if (!foundOne)
+					bounds = curBounds.getBox();
+			}
 		}
 		}
 
 
-		return false;
+		return foundOne;
 	}
 	}
 }
 }

+ 5 - 0
BansheeEngine/Include/BsCRenderable.h

@@ -55,6 +55,11 @@ namespace BansheeEngine
 		 */
 		 */
 		Bounds getBounds() const;
 		Bounds getBounds() const;
 
 
+		/**
+		 * @copydoc	Component::calculateBounds
+		 */
+		bool calculateBounds(Bounds& bounds) override;
+
 		/**
 		/**
 		 * @brief	Returns the internal renderable that is used for
 		 * @brief	Returns the internal renderable that is used for
 		 *			majority of operations by this component.
 		 *			majority of operations by this component.

+ 7 - 0
BansheeEngine/Source/BsCRenderable.cpp

@@ -35,6 +35,13 @@ namespace BansheeEngine
 		return mInternal->getBounds();
 		return mInternal->getBounds();
 	}
 	}
 
 
+	bool CRenderable::calculateBounds(Bounds& bounds)
+	{
+		bounds = getBounds();
+
+		return true;
+	}
+
 	void CRenderable::updateTransform() const
 	void CRenderable::updateTransform() const
 	{
 	{
 		UINT32 curHash = SO()->getTransformHash();
 		UINT32 curHash = SO()->getTransformHash();

+ 0 - 2
MBansheeEditor/Library/LibraryWindow.cs

@@ -1058,8 +1058,6 @@ namespace BansheeEditor
         /// </summary>
         /// </summary>
         internal void RenameSelection()
         internal void RenameSelection()
         {
         {
-            Debug.Log("Rename " + selectionPaths.Count);
-
             if (selectionPaths.Count == 0)
             if (selectionPaths.Count == 0)
                 return;
                 return;
 
 

+ 0 - 5
MBansheeEditor/Scene/DefaultHandleManager.cs

@@ -41,7 +41,6 @@ namespace BansheeEditor
         private bool isDragged;
         private bool isDragged;
         private Vector3 initialHandlePosition;
         private Vector3 initialHandlePosition;
         private Quaternion initialHandleRotation;
         private Quaternion initialHandleRotation;
-        private Vector3 initialHandleScale;
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
         protected internal override void PreInput()
         protected internal override void PreInput()
@@ -107,9 +106,6 @@ namespace BansheeEditor
                 activeHandle.Position = position;
                 activeHandle.Position = position;
                 activeHandle.Rotation = rotation;
                 activeHandle.Rotation = rotation;
 
 
-                if (!isDragged)
-                    initialHandleScale = selectedSceneObjects[0].Scale;
-
                 activeHandle.PreInput();
                 activeHandle.PreInput();
             }
             }
         }
         }
@@ -186,7 +182,6 @@ namespace BansheeEditor
                             // Make sure we transform relative to the handle position
                             // Make sure we transform relative to the handle position
                             SceneObject temporarySO = new SceneObject("Temp");
                             SceneObject temporarySO = new SceneObject("Temp");
                             temporarySO.Position = activeHandle.Position;
                             temporarySO.Position = activeHandle.Position;
-                            temporarySO.LocalScale = initialHandleScale;
 
 
                             SceneObject[] originalParents = new SceneObject[activeSelection.Length];
                             SceneObject[] originalParents = new SceneObject[activeSelection.Length];
                             for (int i = 0; i < activeSelection.Length; i++)
                             for (int i = 0; i < activeSelection.Length; i++)

+ 16 - 0
MBansheeEngine/Component.cs

@@ -21,6 +21,22 @@ namespace BansheeEngine
             get { return Internal_GetSceneObject(mCachedPtr); }
             get { return Internal_GetSceneObject(mCachedPtr); }
         }
         }
 
 
+        /// <summary>
+        /// Calculates bounds of the visible content for this component.
+        /// </summary>
+        /// <param name="box">Bounds in world space represented as an axis aligned bounding box.</param>
+        /// <param name="sphere">Bounds in world space represented as a sphere.</param>
+        /// <returns>True if the bounds have non-zero volume, false otherwise.</returns>
+        internal protected virtual bool CalculateBounds(out AABox box, out Sphere sphere)
+        {
+            Vector3 pos = SceneObject.Position;
+
+            box = new AABox(pos, pos);
+            sphere = new Sphere(pos, 0.0f);
+
+            return false;
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         internal static extern Component Internal_AddComponent(SceneObject parent, Type type);
         internal static extern Component Internal_AddComponent(SceneObject parent, Type type);
 
 

+ 6 - 0
MBansheeEngine/Math/AABox.cs

@@ -63,5 +63,11 @@ namespace BansheeEngine
             _minimum = min;
             _minimum = min;
             _maximum = max;
             _maximum = max;
         }
         }
+
+        /// <inheritdoc/>
+        public override string ToString()
+        {
+            return "Min: " + _minimum + ". Max: " + _maximum;
+        }
 	};
 	};
 }
 }

+ 11 - 0
MBansheeEngine/Renderable.cs

@@ -137,6 +137,17 @@ namespace BansheeEngine
             _native.OnDestroy();
             _native.OnDestroy();
         }
         }
 
 
+        /// <inheritdoc/>
+        internal protected override bool CalculateBounds(out AABox box, out Sphere sphere)
+        {
+            Bounds bounds = Bounds;
+
+            box = bounds.Box;
+            sphere = bounds.Sphere;
+
+            return true;
+        }
+
         /// <summary>
         /// <summary>
         /// Holds all data the renderable component needs to persist through serialization.
         /// Holds all data the renderable component needs to persist through serialization.
         /// </summary>
         /// </summary>

+ 8 - 2
SBansheeEngine/Include/BsManagedComponent.h

@@ -110,6 +110,7 @@ namespace BansheeEngine
 		OnDestroyedThunkDef mOnDestroyThunk;
 		OnDestroyedThunkDef mOnDestroyThunk;
 		OnDestroyedThunkDef mOnDisabledThunk;
 		OnDestroyedThunkDef mOnDisabledThunk;
 		OnDestroyedThunkDef mOnEnabledThunk;
 		OnDestroyedThunkDef mOnEnabledThunk;
+		MonoMethod* mCalculateBoundsMethod;
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 							COMPONENT OVERRIDES                    		*/
 		/* 							COMPONENT OVERRIDES                    		*/
@@ -150,12 +151,17 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc	Component::update
 		 * @copydoc	Component::update
 		 */
 		 */
-		virtual void update() override;
+		void update() override;
 
 
 		/**
 		/**
 		 * @copydoc	Component::typeEquals
 		 * @copydoc	Component::typeEquals
 		 */
 		 */
-		virtual bool typeEquals(const Component& other) override;
+		bool typeEquals(const Component& other) override;
+
+		/**
+		 * @copydoc	Component::calculateBounds
+		 */
+		bool calculateBounds(Bounds& bounds) override;
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/* 								RTTI		                     		*/

+ 29 - 2
SBansheeEngine/Source/BsManagedComponent.cpp

@@ -14,13 +14,14 @@ namespace BansheeEngine
 {
 {
 	ManagedComponent::ManagedComponent()
 	ManagedComponent::ManagedComponent()
 		:mManagedInstance(nullptr), mUpdateThunk(nullptr), mOnDestroyThunk(nullptr), mOnInitializedThunk(nullptr), 
 		:mManagedInstance(nullptr), mUpdateThunk(nullptr), mOnDestroyThunk(nullptr), mOnInitializedThunk(nullptr), 
-		mOnResetThunk(nullptr), mMissingType(false), mRequiresReset(true), mOnEnabledThunk(nullptr), mOnDisabledThunk(nullptr)
+		mOnResetThunk(nullptr), mMissingType(false), mRequiresReset(true), mOnEnabledThunk(nullptr), mOnDisabledThunk(nullptr),
+		mCalculateBoundsMethod(nullptr)
 	{ }
 	{ }
 
 
 	ManagedComponent::ManagedComponent(const HSceneObject& parent, MonoReflectionType* runtimeType)
 	ManagedComponent::ManagedComponent(const HSceneObject& parent, MonoReflectionType* runtimeType)
 		: Component(parent), mManagedInstance(nullptr), mRuntimeType(runtimeType), mUpdateThunk(nullptr), 
 		: Component(parent), mManagedInstance(nullptr), mRuntimeType(runtimeType), mUpdateThunk(nullptr), 
 		mOnDestroyThunk(nullptr), mOnInitializedThunk(nullptr), mOnResetThunk(nullptr), mMissingType(false),
 		mOnDestroyThunk(nullptr), mOnInitializedThunk(nullptr), mOnResetThunk(nullptr), mMissingType(false),
-		mRequiresReset(true), mOnEnabledThunk(nullptr), mOnDisabledThunk(nullptr)
+		mRequiresReset(true), mOnEnabledThunk(nullptr), mOnDisabledThunk(nullptr), mCalculateBoundsMethod(nullptr)
 	{
 	{
 		MonoType* monoType = mono_reflection_type_get_type(mRuntimeType);
 		MonoType* monoType = mono_reflection_type_get_type(mRuntimeType);
 		::MonoClass* monoClass = mono_type_get_class(monoType);
 		::MonoClass* monoClass = mono_type_get_class(monoType);
@@ -87,6 +88,7 @@ namespace BansheeEngine
 			mOnDestroyThunk = nullptr;
 			mOnDestroyThunk = nullptr;
 			mOnEnabledThunk = nullptr;
 			mOnEnabledThunk = nullptr;
 			mOnDisabledThunk = nullptr;
 			mOnDisabledThunk = nullptr;
+			mCalculateBoundsMethod = nullptr;
 		}
 		}
 
 
 		return backupData;
 		return backupData;
@@ -164,6 +166,8 @@ namespace BansheeEngine
 			MonoMethod* onEnableMethod = managedClass->getMethod("OnEnable", 0);
 			MonoMethod* onEnableMethod = managedClass->getMethod("OnEnable", 0);
 			if (onEnableMethod != nullptr)
 			if (onEnableMethod != nullptr)
 				mOnEnabledThunk = (OnInitializedThunkDef)onEnableMethod->getThunk();
 				mOnEnabledThunk = (OnInitializedThunkDef)onEnableMethod->getThunk();
+
+			mCalculateBoundsMethod = managedClass->getMethod("CalculateBounds", 2);
 		}
 		}
 	}
 	}
 
 
@@ -180,6 +184,29 @@ namespace BansheeEngine
 		return false;
 		return false;
 	}
 	}
 
 
+	bool ManagedComponent::calculateBounds(Bounds& bounds)
+	{
+		if (mManagedInstance != nullptr && mCalculateBoundsMethod != nullptr)
+		{
+			AABox box;
+			Sphere sphere;
+
+			void* params[2];
+			params[0] = &box;
+			params[1] = &sphere;
+
+			MonoObject* areBoundsValidObj = mCalculateBoundsMethod->invokeVirtual(mManagedInstance, params);
+
+			bool areBoundsValid;
+			areBoundsValid = *(bool*)mono_object_unbox(areBoundsValidObj);
+
+			bounds = Bounds(box, sphere);
+			return areBoundsValid;
+		}
+
+		return Component::calculateBounds(bounds);
+	}
+
 	void ManagedComponent::update()
 	void ManagedComponent::update()
 	{
 	{
 		assert(mManagedInstance != nullptr);
 		assert(mManagedInstance != nullptr);

+ 1 - 1
SBansheeEngine/Source/BsScriptSceneObject.cpp

@@ -238,7 +238,7 @@ namespace BansheeEngine
 	void ScriptSceneObject::internal_getLocalScale(ScriptSceneObject* nativeInstance, Vector3* value)
 	void ScriptSceneObject::internal_getLocalScale(ScriptSceneObject* nativeInstance, Vector3* value)
 	{
 	{
 		if (!checkIfDestroyed(nativeInstance))
 		if (!checkIfDestroyed(nativeInstance))
-			*value = nativeInstance->mSceneObject->getWorldScale();
+			*value = nativeInstance->mSceneObject->getScale();
 		else
 		else
 			*value = Vector3();
 			*value = Vector3();
 	}
 	}