Jelajahi Sumber

A couple of fixes that handle opening of drop down windows and menus at proper location

Marko Pintera 10 tahun lalu
induk
melakukan
23ac844b5d

+ 1 - 0
BansheeEditor/Include/BsDropDownWindow.h

@@ -74,6 +74,7 @@ namespace BansheeEngine
 		HSceneObject mSceneObject;
 		HSceneObject mSceneObject;
 		HGUIWidget mGUI;
 		HGUIWidget mGUI;
 
 
+		GUIDropDownHitBox* mHitBox;
 		GUIPanel* mRootPanel;
 		GUIPanel* mRootPanel;
 		Vector2I mPosition;
 		Vector2I mPosition;
 		UINT32 mWidth;
 		UINT32 mWidth;

+ 15 - 14
BansheeEditor/Source/BsDropDownWindow.cpp

@@ -14,7 +14,7 @@ namespace BansheeEngine
 	DropDownWindow::DropDownWindow(const RenderWindowPtr& parent, Viewport* target, 
 	DropDownWindow::DropDownWindow(const RenderWindowPtr& parent, Viewport* target, 
 		const Vector2I& position, UINT32 width, UINT32 height)
 		const Vector2I& position, UINT32 width, UINT32 height)
 		:mRootPanel(nullptr), mPosition(position), mWidth(width), mHeight(height), 
 		:mRootPanel(nullptr), mPosition(position), mWidth(width), mHeight(height), 
-		mRenderWindow(parent)
+		mRenderWindow(parent), mHitBox(nullptr)
 	{
 	{
 		mSceneObject = SceneObject::create("EditorWindow");
 		mSceneObject = SceneObject::create("EditorWindow");
 
 
@@ -25,6 +25,18 @@ namespace BansheeEngine
 
 
 		mRootPanel = mGUI->getPanel()->addNewElement<GUIPanel>();
 		mRootPanel = mGUI->getPanel()->addNewElement<GUIPanel>();
 		
 		
+		GUIPanel* hitBoxPanel = mRootPanel->addNewElement<GUIPanel>(std::numeric_limits<INT16>::min());
+
+		mHitBox = GUIDropDownHitBox::create(false);
+		mHitBox->onFocusLost.connect(std::bind(&DropDownWindow::dropDownFocusLost, this));
+		mHitBox->setFocus(true);
+		hitBoxPanel->addElement(mHitBox);
+
+		GUIPanel* captureHitBoxPanel = mGUI->getPanel()->addNewElement<GUIPanel>(std::numeric_limits<INT16>::max());
+		GUIDropDownHitBox* captureHitBox = GUIDropDownHitBox::create(true);
+		captureHitBox->setBounds(Rect2I(0, 0, target->getWidth(), target->getHeight()));
+		captureHitBoxPanel->addElement(captureHitBox);
+
 		setSize(width, height);
 		setSize(width, height);
 
 
 		GUIPanel* backgroundPanel = mRootPanel->addNewElement<GUIPanel>(500);
 		GUIPanel* backgroundPanel = mRootPanel->addNewElement<GUIPanel>(500);
@@ -40,19 +52,6 @@ namespace BansheeEngine
 		mContents->setPosition(1, 1);
 		mContents->setPosition(1, 1);
 		mContents->setWidth(width - 2);
 		mContents->setWidth(width - 2);
 		mContents->setHeight(height - 2);
 		mContents->setHeight(height - 2);
-
-
-		GUIPanel* hitBoxPanel = mRootPanel->addNewElement<GUIPanel>(std::numeric_limits<INT16>::min());
-
-		GUIDropDownHitBox* hitBox = GUIDropDownHitBox::create(false);
-		hitBox->onFocusLost.connect(std::bind(&DropDownWindow::dropDownFocusLost, this));
-		hitBox->setFocus(true);
-		hitBoxPanel->addElement(hitBox);
-
-		GUIPanel* captureHitBoxPanel = mGUI->getPanel()->addNewElement<GUIPanel>(std::numeric_limits<INT16>::max());
-
-		GUIDropDownHitBox* captureHitBox = GUIDropDownHitBox::create(true);
-		captureHitBoxPanel->addElement(captureHitBox);
 	}
 	}
 
 
 	DropDownWindow::~DropDownWindow()
 	DropDownWindow::~DropDownWindow()
@@ -97,6 +96,8 @@ namespace BansheeEngine
 		mRootPanel->setWidth(width);
 		mRootPanel->setWidth(width);
 		mRootPanel->setHeight(height);
 		mRootPanel->setHeight(height);
 
 
+		mHitBox->setBounds(Rect2I(placementBounds.x, placementBounds.y, width, height));
+
 		mWidth = width;
 		mWidth = width;
 		mHeight = height;
 		mHeight = height;
 	}
 	}

+ 4 - 3
BansheeEngine/Source/BsDropDownAreaPlacement.cpp

@@ -1,4 +1,5 @@
 #include "BsDropDownAreaPlacement.h"
 #include "BsDropDownAreaPlacement.h"
+#include "BsDebug.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -93,7 +94,7 @@ namespace BansheeEngine
 		if (height <= availableDownwardHeight)
 		if (height <= availableDownwardHeight)
 		{
 		{
 			output.y = potentialBottomStart;
 			output.y = potentialBottomStart;
-			output.height = availableDownwardHeight;
+			output.height = height;
 			vertDir = VertDir::Down;
 			vertDir = VertDir::Down;
 		}
 		}
 		else
 		else
@@ -101,13 +102,13 @@ namespace BansheeEngine
 			if (availableDownwardHeight >= availableUpwardHeight)
 			if (availableDownwardHeight >= availableUpwardHeight)
 			{
 			{
 				output.y = potentialBottomStart;
 				output.y = potentialBottomStart;
-				output.height = availableDownwardHeight;
+				output.height = std::min(height, availableDownwardHeight);;
 				vertDir = VertDir::Down;
 				vertDir = VertDir::Down;
 			}
 			}
 			else
 			else
 			{
 			{
 				output.y = potentialTopStart - (INT32)std::min(height, availableUpwardHeight);
 				output.y = potentialTopStart - (INT32)std::min(height, availableUpwardHeight);
-				output.height = availableUpwardHeight;
+				output.height = std::min(height, availableUpwardHeight);
 				vertDir = VertDir::Up;
 				vertDir = VertDir::Up;
 			}
 			}
 		}
 		}

+ 10 - 5
BansheeEngine/Source/BsGUIDropDownMenu.cpp

@@ -14,6 +14,7 @@
 #include "BsSceneObject.h"
 #include "BsSceneObject.h"
 #include "BsGUIDropDownHitBox.h"
 #include "BsGUIDropDownHitBox.h"
 #include "BsGUIDropDownContent.h"
 #include "BsGUIDropDownContent.h"
+#include "BsDebug.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 
@@ -173,8 +174,6 @@ namespace BansheeEngine
 		mContentPanel->setHeight(height);
 		mContentPanel->setHeight(height);
 		mContentPanel->setDepthRange(100 - depthOffset * 2 - 1);
 		mContentPanel->setDepthRange(100 - depthOffset * 2 - 1);
 
 
-		mContentLayout = mContentPanel->addNewElement<GUILayoutY>();
-
 		// Background frame
 		// Background frame
 		mBackgroundPanel = mOwner->getPanel()->addNewElement<GUIPanel>();
 		mBackgroundPanel = mOwner->getPanel()->addNewElement<GUIPanel>();
 		mBackgroundPanel->setWidth(width);
 		mBackgroundPanel->setWidth(width);
@@ -186,6 +185,7 @@ namespace BansheeEngine
 		mBackgroundFrame = GUITexture::create(GUIImageScaleMode::StretchToFit, mOwner->mBackgroundStyle);
 		mBackgroundFrame = GUITexture::create(GUIImageScaleMode::StretchToFit, mOwner->mBackgroundStyle);
 		backgroundLayout->addElement(mBackgroundFrame);
 		backgroundLayout->addElement(mBackgroundFrame);
 
 
+		mContentLayout = mContentPanel->addNewElement<GUILayoutY>();
 		mContentLayout->addElement(mContent); // Note: It's important this is added to the layout before we 
 		mContentLayout->addElement(mContent); // Note: It's important this is added to the layout before we 
 		// use it for size calculations, in order for its skin to be assigned
 		// use it for size calculations, in order for its skin to be assigned
 
 
@@ -203,13 +203,18 @@ namespace BansheeEngine
 
 
 		mOpenedUpward = vertDir == DropDownAreaPlacement::VertDir::Up;
 		mOpenedUpward = vertDir == DropDownAreaPlacement::VertDir::Up;
 
 
+		UINT32 actualY = placementBounds.y;
+		if (mOpenedUpward)
+			y = placementBounds.y + placementBounds.height;
+		else
+			y = placementBounds.y;
+
 		x = placementBounds.x;
 		x = placementBounds.x;
-		y = placementBounds.y;
 		width = placementBounds.width;
 		width = placementBounds.width;
 		height = placementBounds.height;
 		height = placementBounds.height;
 
 
-		mContentPanel->setPosition(x, y);
-		mBackgroundPanel->setPosition(x, y);
+		mContentPanel->setPosition(x, actualY);
+		mBackgroundPanel->setPosition(x, actualY);
 
 
 		updateGUIElements();
 		updateGUIElements();
 
 

+ 17 - 2
BansheeUtility/Include/BsMath.h

@@ -91,15 +91,30 @@ namespace BansheeEngine
 		}
 		}
 
 
         /**
         /**
-         * @brief	Compare 2 floats, using tolerance for inaccuracies.
+         * @brief	Compare two floats, using tolerance for inaccuracies.
          */
          */
         static bool approxEquals(float a, float b, float tolerance = std::numeric_limits<float>::epsilon());
         static bool approxEquals(float a, float b, float tolerance = std::numeric_limits<float>::epsilon());
 
 
         /**
         /**
-         * @brief	Compare 2 doubles, using tolerance for inaccuracies.
+         * @brief	Compare two doubles, using tolerance for inaccuracies.
          */
          */
 		static bool approxEquals(double a, double b, double tolerance = std::numeric_limits<double>::epsilon());
 		static bool approxEquals(double a, double b, double tolerance = std::numeric_limits<double>::epsilon());
 
 
+		/**
+         * @brief	Compare two 2D vectors, using tolerance for inaccuracies.
+         */
+		static bool approxEquals(const Vector2& a, const Vector2& b, float tolerance = std::numeric_limits<float>::epsilon());
+
+		/**
+         * @brief	Compare two 3D vectors, using tolerance for inaccuracies.
+         */
+		static bool approxEquals(const Vector3& a, const Vector3& b, float tolerance = std::numeric_limits<float>::epsilon());
+
+		/**
+         * @brief	Compare two 4D vectors, using tolerance for inaccuracies.
+         */
+		static bool approxEquals(const Vector4& a, const Vector4& b, float tolerance = std::numeric_limits<float>::epsilon());
+
         /**
         /**
          * @brief	Calculates the tangent space vector for a given set of positions / texture coords.
          * @brief	Calculates the tangent space vector for a given set of positions / texture coords.
          */
          */

+ 12 - 0
BansheeUtility/Include/BsVector3.h

@@ -441,6 +441,18 @@ namespace BansheeEngine
 				return val;
 				return val;
 		}
 		}
 
 
+		/**
+		 * @brief	Calculates the cross-product of 2 vectors, i.e. the vector that
+		 *			lies perpendicular to them both.
+         */
+		static Vector3 cross(const Vector3& a, const Vector3& b)
+        {
+            return Vector3(
+				a.y * b.z - a.z * b.y,
+				a.z * b.x - a.x * b.z,
+				a.x * b.y - a.y * b.x);
+        }
+
 		/**
 		/**
 		 * @brief	Checks are any of the vector components NaN.
 		 * @brief	Checks are any of the vector components NaN.
 		 */
 		 */

+ 24 - 0
BansheeUtility/Source/BsMath.cpp

@@ -285,6 +285,30 @@ namespace BansheeEngine
 			return false;
 			return false;
 	}
 	}
 
 
+	bool Math::approxEquals(const Vector2& a, const Vector2& b, float tolerance)
+	{
+		if (fabs(b.x - a.x) <= tolerance || fabs(b.y - a.y) <= tolerance)
+			return true;
+		else
+			return false;
+	}
+
+	bool Math::approxEquals(const Vector3& a, const Vector3& b, float tolerance)
+	{
+		if (fabs(b.x - a.x) <= tolerance || fabs(b.y - a.y) <= tolerance || fabs(b.z - a.z) <= tolerance)
+			return true;
+		else
+			return false;
+	}
+
+	bool Math::approxEquals(const Vector4& a, const Vector4& b, float tolerance)
+	{
+		if (fabs(b.x - a.x) <= tolerance || fabs(b.y - a.y) <= tolerance || fabs(b.z - a.z) <= tolerance || fabs(b.w - a.w) <= tolerance)
+			return true;
+		else
+			return false;
+	}
+
 	Vector3 Math::calculateTriTangent(const Vector3& position1, const Vector3& position2, 
 	Vector3 Math::calculateTriTangent(const Vector3& position1, const Vector3& position2, 
 		const Vector3& position3, float u1, float v1, float u2, float v2, float u3, float v3)
 		const Vector3& position3, float u1, float v1, float u2, float v2, float u3, float v3)
 	{
 	{

+ 1 - 1
MBansheeEditor/ProjectWindow.cs

@@ -506,7 +506,7 @@ namespace BansheeEditor
         private void OpenOptionsWindow()
         private void OpenOptionsWindow()
         {
         {
             Vector2I openPosition;
             Vector2I openPosition;
-            Rect2I buttonBounds = optionsButton.Bounds;
+            Rect2I buttonBounds = GUILayoutUtility.CalculateBounds(optionsButton, GUI);
 
 
             openPosition.x = buttonBounds.x + buttonBounds.width / 2;
             openPosition.x = buttonBounds.x + buttonBounds.width / 2;
             openPosition.y = buttonBounds.y + buttonBounds.height / 2;
             openPosition.y = buttonBounds.y + buttonBounds.height / 2;

+ 11 - 3
SBansheeEditor/Source/BsScriptDropDownWindow.cpp

@@ -54,20 +54,28 @@ namespace BansheeEngine
 		ManagedDropDownWindow* dropDownWindow = nullptr;
 		ManagedDropDownWindow* dropDownWindow = nullptr;
 		if (parentWindow != nullptr)
 		if (parentWindow != nullptr)
 		{
 		{
-			EditorWidgetContainer* parentContainer = parentWindow->getEditorWidget()->_getParent();
+			EditorWidgetBase* editorWidget = parentWindow->getEditorWidget();
+			EditorWidgetContainer* parentContainer = editorWidget->_getParent();
 			if (parentContainer != nullptr)
 			if (parentContainer != nullptr)
 			{
 			{
 				RenderWindowPtr parentRenderWindow = parentContainer->getParentWindow()->getRenderWindow();
 				RenderWindowPtr parentRenderWindow = parentContainer->getParentWindow()->getRenderWindow();
 				Viewport* parentTarget = parentContainer->getParentWidget().getTarget();
 				Viewport* parentTarget = parentContainer->getParentWidget().getTarget();
 
 
+				position.x += editorWidget->getX();
+				position.y += editorWidget->getY();
+
 				dropDownWindow = DropDownWindowManager::instance().open<ManagedDropDownWindow>(
 				dropDownWindow = DropDownWindowManager::instance().open<ManagedDropDownWindow>(
 					parentRenderWindow, parentTarget, position, instance, width, height);
 					parentRenderWindow, parentTarget, position, instance, width, height);
 			}
 			}
 		}
 		}
 
 
 		ScriptDropDownWindow* nativeInstance = new (bs_alloc<ScriptDropDownWindow>()) ScriptDropDownWindow(dropDownWindow);
 		ScriptDropDownWindow* nativeInstance = new (bs_alloc<ScriptDropDownWindow>()) ScriptDropDownWindow(dropDownWindow);
-		dropDownWindow->initialize(nativeInstance);
-		dropDownWindow->triggerOnInitialize();
+
+		if (dropDownWindow != nullptr)
+		{
+			dropDownWindow->initialize(nativeInstance);
+			dropDownWindow->triggerOnInitialize();
+		}
 	}
 	}
 
 
 	void ScriptDropDownWindow::internal_Close(ScriptDropDownWindow* thisPtr)
 	void ScriptDropDownWindow::internal_Close(ScriptDropDownWindow* thisPtr)

+ 12 - 6
TODO.txt

@@ -25,16 +25,22 @@ GUIResourceField doesn't distinguish between tex2d, tex3d and texcube.
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 Project window
 Project window
 
 
-FBXImporter:
- - It should use DefaultMeshData
- - It should use and apply MeshImportOptions
+Opening drop down when it doesn't fit vertically opens it at the wrong position
+Crash when opening and closing the context menu many times, trying to delete a GUILayout that has already been deleted
+ - This might happen when parent layout or panel goes out of scope. It will get destroyed but it will not mark any of its children as destroyed
+ - And I can't just call Destroy in finalizer since it accesses its children which might have been finalized already
+ - When a window is closed(editor, modal or drop down, do I call destroy on its child layout?)
+
+Other:
+ - Double click doesn't seem to work
+ - Elements in the options drop down don't have proper style and are ugly in general
+ - List view doesn't look right
+
 
 
 Test context menu
 Test context menu
 Test drop down window
 Test drop down window
 
 
- - Need to know when a focus was lost from the main area
-  - GUIElement::OnFocusChanged
-   - THis is only partially finished. I haven't hooked up the callback to GUIElement from ScriptGUIElement
+When clicking on drop down window it will interact with GUI elements beneath it
 
 
 Simple tasks:
 Simple tasks:
  - Hook up windows drag and drop support
  - Hook up windows drag and drop support

+ 3 - 6
TODOExperimentation.txt

@@ -1,12 +1,9 @@
 -------------------------
 -------------------------
 FBX
 FBX
- - Unity stores mesh attributes per-index and then performs splitting as needed. See code in ImportMeshUtility
-  - This means I probably want to delay creating MeshData - which is also okay since I determine bone weights at a later stage anyway
+ - DefaultMeshData is defined in BansheeEngine but FBXImporter only includes Banshee Core
  - Transform tangent/bitangent and encode them into a 4-vector value
  - Transform tangent/bitangent and encode them into a 4-vector value
- - Transform between FBX trans/rot/scale and engine trans/rot/scale
- - Neater mesh parsing
- - Calculate normals from smoothing groups
-  - Control this via an import option? Since in same cases normals are provided.
+ - It should use DefaultMeshData
+ - It should use and apply MeshImportOptions
  - Import skeleton
  - Import skeleton
   - Unity just maps nodes referenced by FbxSkin clusters to bones, it do no separate parsing
   - Unity just maps nodes referenced by FbxSkin clusters to bones, it do no separate parsing
  - Import keyframes
  - Import keyframes