Sfoglia il codice sorgente

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

BearishSun 10 anni fa
parent
commit
7184765d9d

+ 10 - 0
BansheeCore/Include/BsComponent.h

@@ -2,6 +2,7 @@
 
 #include "BsCorePrerequisites.h"
 #include "BsGameObject.h"
+#include "BsBounds.h"
 
 namespace BansheeEngine
 {
@@ -29,6 +30,15 @@ namespace BansheeEngine
 		 */
 		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.
 		 * 			

+ 8 - 0
BansheeCore/Source/BsComponent.cpp

@@ -20,6 +20,14 @@ namespace BansheeEngine
 		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)
 	{
 		SO()->destroyComponent(this, immediate);

+ 22 - 6
BansheeEditor/Source/BsEditorUtility.cpp

@@ -41,14 +41,30 @@ namespace BansheeEngine
 
 	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;
 
+		/**
+		 * @copydoc	Component::calculateBounds
+		 */
+		bool calculateBounds(Bounds& bounds) override;
+
 		/**
 		 * @brief	Returns the internal renderable that is used for
 		 *			majority of operations by this component.

+ 7 - 0
BansheeEngine/Source/BsCRenderable.cpp

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

+ 0 - 2
MBansheeEditor/Library/LibraryWindow.cs

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

+ 0 - 5
MBansheeEditor/Scene/DefaultHandleManager.cs

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

+ 16 - 0
MBansheeEngine/Component.cs

@@ -21,6 +21,22 @@ namespace BansheeEngine
             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)]
         internal static extern Component Internal_AddComponent(SceneObject parent, Type type);
 

+ 6 - 0
MBansheeEngine/Math/AABox.cs

@@ -63,5 +63,11 @@ namespace BansheeEngine
             _minimum = min;
             _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();
         }
 
+        /// <inheritdoc/>
+        internal protected override bool CalculateBounds(out AABox box, out Sphere sphere)
+        {
+            Bounds bounds = Bounds;
+
+            box = bounds.Box;
+            sphere = bounds.Sphere;
+
+            return true;
+        }
+
         /// <summary>
         /// Holds all data the renderable component needs to persist through serialization.
         /// </summary>

+ 8 - 2
SBansheeEngine/Include/BsManagedComponent.h

@@ -110,6 +110,7 @@ namespace BansheeEngine
 		OnDestroyedThunkDef mOnDestroyThunk;
 		OnDestroyedThunkDef mOnDisabledThunk;
 		OnDestroyedThunkDef mOnEnabledThunk;
+		MonoMethod* mCalculateBoundsMethod;
 
 		/************************************************************************/
 		/* 							COMPONENT OVERRIDES                    		*/
@@ -150,12 +151,17 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	Component::update
 		 */
-		virtual void update() override;
+		void update() override;
 
 		/**
 		 * @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		                     		*/

+ 29 - 2
SBansheeEngine/Source/BsManagedComponent.cpp

@@ -14,13 +14,14 @@ namespace BansheeEngine
 {
 	ManagedComponent::ManagedComponent()
 		: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)
 		: Component(parent), mManagedInstance(nullptr), mRuntimeType(runtimeType), mUpdateThunk(nullptr), 
 		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);
 		::MonoClass* monoClass = mono_type_get_class(monoType);
@@ -87,6 +88,7 @@ namespace BansheeEngine
 			mOnDestroyThunk = nullptr;
 			mOnEnabledThunk = nullptr;
 			mOnDisabledThunk = nullptr;
+			mCalculateBoundsMethod = nullptr;
 		}
 
 		return backupData;
@@ -164,6 +166,8 @@ namespace BansheeEngine
 			MonoMethod* onEnableMethod = managedClass->getMethod("OnEnable", 0);
 			if (onEnableMethod != nullptr)
 				mOnEnabledThunk = (OnInitializedThunkDef)onEnableMethod->getThunk();
+
+			mCalculateBoundsMethod = managedClass->getMethod("CalculateBounds", 2);
 		}
 	}
 
@@ -180,6 +184,29 @@ namespace BansheeEngine
 		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()
 	{
 		assert(mManagedInstance != nullptr);

+ 1 - 1
SBansheeEngine/Source/BsScriptSceneObject.cpp

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