2
0
Эх сурвалжийг харах

Proper screen <-> window coordinate transformations for modal windows
Updated GUILayoutUtility so it can return coordinates relative to a specific GUIPanel

Marko Pintera 10 жил өмнө
parent
commit
97a70b6f03

+ 10 - 0
BansheeEditor/Include/BsModalWindow.h

@@ -14,6 +14,16 @@ namespace BansheeEngine
 		virtual void close();
 		virtual void close();
 		void setTitle(const HString& title);
 		void setTitle(const HString& title);
 
 
+		/**
+		 * Converts screen pointer coordinates into coordinates relative to the window contents GUI panel.
+		 */
+		Vector2I screenToWindowPos(const Vector2I& screenPos) const;
+
+		/**
+		 * Converts pointer coordinates relative to the window contents GUI panel into screen coordinates.
+		 */
+		Vector2I windowToScreenPos(const Vector2I& windowPos) const;
+
 	protected:
 	protected:
 		friend class EditorWindowManager;
 		friend class EditorWindowManager;
 
 

+ 24 - 0
BansheeEditor/Source/BsModalWindow.cpp

@@ -70,6 +70,30 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
+	Vector2I ModalWindow::screenToWindowPos(const Vector2I& screenPos) const
+	{
+		Vector2I renderWindowPos = getRenderWindow()->screenToWindowPos(screenPos);
+
+		Vector2I contentsPos = renderWindowPos;
+		Rect2I contentArea = getContentArea();
+
+		contentsPos.x -= contentArea.x;
+		contentsPos.y -= contentArea.y;
+
+		return contentsPos;
+	}
+
+	Vector2I ModalWindow::windowToScreenPos(const Vector2I& windowPos) const
+	{
+		Vector2I contentsPos = windowPos;
+		Rect2I contentArea = getContentArea();
+
+		contentsPos.x += contentArea.x;
+		contentsPos.y += contentArea.y;
+
+		return getRenderWindow()->windowToScreenPos(contentsPos);
+	}
+
 	void ModalWindow::update()
 	void ModalWindow::update()
 	{
 	{
 
 

+ 6 - 1
BansheeEngine/Include/BsGUILayoutUtility.h

@@ -21,12 +21,17 @@ namespace BansheeEngine
 		/**
 		/**
 		 * Calculates position and size of a GUI element in its current layout.
 		 * Calculates position and size of a GUI element in its current layout.
 		 * Returned position is relative to parent GUI panel.
 		 * Returned position is relative to parent GUI panel.
+		 *
+		 * @param	elem		Element to calculate bounds for.
+		 * @param	relativeTo	Parent panel of the provided element relative to which to return the
+		 *						bounds. If null the bounds relative to the first parent panel are returned.
+		 *						Behavior is undefined if provided panel is not a parent of the element.
 		 */
 		 */
 		// TODO - This method might fail if element is part of a more complex hierarchy
 		// TODO - This method might fail if element is part of a more complex hierarchy
 		// other than just GUILayouts and base elements (e.g. a tree view) because for a lot
 		// other than just GUILayouts and base elements (e.g. a tree view) because for a lot
 		// of such custom container elements like tree view don't have method for calculating 
 		// of such custom container elements like tree view don't have method for calculating 
 		// element bounds implemented
 		// element bounds implemented
-		static Rect2I calcBounds(const GUIElementBase* elem);
+		static Rect2I calcBounds(const GUIElementBase* elem, GUIPanel* relativeTo = nullptr);
 
 
 		/**
 		/**
 		 * @brief	Calculates the actual size of the layout taken up by all of its elements.
 		 * @brief	Calculates the actual size of the layout taken up by all of its elements.

+ 4 - 2
BansheeEngine/Source/BsGUILayoutUtility.cpp

@@ -5,6 +5,7 @@
 #include "BsGUIElementStyle.h"
 #include "BsGUIElementStyle.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 #include "BsViewport.h"
 #include "BsViewport.h"
+#include "BsGUIPanel.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -13,7 +14,7 @@ namespace BansheeEngine
 		return elem->_calculateLayoutSizeRange().optimal;
 		return elem->_calculateLayoutSizeRange().optimal;
 	}
 	}
 
 
-	Rect2I GUILayoutUtility::calcBounds(const GUIElementBase* elem)
+	Rect2I GUILayoutUtility::calcBounds(const GUIElementBase* elem, GUIPanel* relativeTo)
 	{
 	{
 		Rect2I parentArea;
 		Rect2I parentArea;
 
 
@@ -22,7 +23,8 @@ namespace BansheeEngine
 		{
 		{
 			parentArea = calcBounds(parent);
 			parentArea = calcBounds(parent);
 
 
-			if (parent->_getType() == GUIElementBase::Type::Panel)
+			// TODO - Implement this properly
+			if (parent->_getType() == GUIElementBase::Type::Panel && (relativeTo == nullptr || relativeTo == parent))
 			{
 			{
 				parentArea.x = 0;
 				parentArea.x = 0;
 				parentArea.y = 0;
 				parentArea.y = 0;

+ 7 - 3
MBansheeEngine/GUI/GUILayoutUtility.cs

@@ -15,10 +15,14 @@ namespace BansheeEngine
             return output;
             return output;
         }
         }
 
 
-        public static Rect2I CalculateBounds(GUIElement element)
+        public static Rect2I CalculateBounds(GUIElement element, GUIPanel relativeTo = null)
         {
         {
+            IntPtr relativeToNative = IntPtr.Zero;
+            if (relativeTo != null)
+                relativeToNative = relativeTo.GetCachedPtr();
+
             Rect2I output;
             Rect2I output;
-            Internal_CalculateBounds(element.GetCachedPtr(), out output);
+            Internal_CalculateBounds(element.GetCachedPtr(), relativeToNative, out output);
             return output;
             return output;
         }
         }
 
 
@@ -26,6 +30,6 @@ namespace BansheeEngine
         private static extern void Internal_CalculateOptimalSize(IntPtr element, out Vector2I output);
         private static extern void Internal_CalculateOptimalSize(IntPtr element, out Vector2I output);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CalculateBounds(IntPtr element, out Rect2I output);
+        private static extern void Internal_CalculateBounds(IntPtr element, IntPtr relativeTo, out Rect2I output);
     }
     }
 }
 }

+ 8 - 4
SBansheeEditor/Source/BsScriptModalWindow.cpp

@@ -171,14 +171,18 @@ namespace BansheeEngine
 
 
 	void ScriptModalWindow::internal_screenToWindowPos(ScriptModalWindow* thisPtr, Vector2I screenPos, Vector2I* windowPos)
 	void ScriptModalWindow::internal_screenToWindowPos(ScriptModalWindow* thisPtr, Vector2I screenPos, Vector2I* windowPos)
 	{
 	{
-		RenderWindowPtr parentRenderWindow = thisPtr->mModalWindow->getRenderWindow();
-		*windowPos = parentRenderWindow->screenToWindowPos(screenPos);
+		if (thisPtr->mModalWindow != nullptr)
+			*windowPos = thisPtr->mModalWindow->screenToWindowPos(screenPos);
+		else
+			*windowPos = screenPos;
 	}
 	}
 
 
 	void ScriptModalWindow::internal_windowToScreenPos(ScriptModalWindow* thisPtr, Vector2I windowPos, Vector2I* screenPos)
 	void ScriptModalWindow::internal_windowToScreenPos(ScriptModalWindow* thisPtr, Vector2I windowPos, Vector2I* screenPos)
 	{
 	{
-		RenderWindowPtr parentRenderWindow = thisPtr->mModalWindow->getRenderWindow();
-		*screenPos = parentRenderWindow->windowToScreenPos(windowPos);
+		if (thisPtr->mModalWindow != nullptr)
+			*screenPos = thisPtr->mModalWindow->windowToScreenPos(windowPos);
+		else
+			*screenPos = windowPos;
 	}
 	}
 
 
 	ManagedModalWindow::ManagedModalWindow(bool allowCloseButton, MonoObject* managedInstance)
 	ManagedModalWindow::ManagedModalWindow(bool allowCloseButton, MonoObject* managedInstance)

+ 1 - 1
SBansheeEngine/Include/BsScriptGUILayoutUtility.h

@@ -17,6 +17,6 @@ namespace BansheeEngine
 
 
 	private:
 	private:
 		static void internal_CalculateOptimalSize(ScriptGUIElementBaseTBase* guiElement, Vector2I* output);
 		static void internal_CalculateOptimalSize(ScriptGUIElementBaseTBase* guiElement, Vector2I* output);
-		static void internal_CalculateBounds(ScriptGUIElementBaseTBase* guiElement, Rect2I* output);
+		static void internal_CalculateBounds(ScriptGUIElementBaseTBase* guiElement, ScriptGUILayout* relativeTo, Rect2I* output);
 	};
 	};
 }
 }

+ 9 - 2
SBansheeEngine/Source/BsScriptGUILayoutUtility.cpp

@@ -5,6 +5,9 @@
 #include "BsMonoManager.h"
 #include "BsMonoManager.h"
 #include "BsMonoUtil.h"
 #include "BsMonoUtil.h"
 #include "BsScriptGUIElement.h"
 #include "BsScriptGUIElement.h"
+#include "BsGUIPanel.h"
+#include "BsGUIElementBase.h"
+#include "BsScriptGUILayout.h"
 #include "BsGUILayoutUtility.h"
 #include "BsGUILayoutUtility.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
@@ -24,8 +27,12 @@ namespace BansheeEngine
 		*output = GUILayoutUtility::calcOptimalSize(guiElement->getGUIElement());;
 		*output = GUILayoutUtility::calcOptimalSize(guiElement->getGUIElement());;
 	}
 	}
 
 
-	void ScriptGUILayoutUtility::internal_CalculateBounds(ScriptGUIElementBaseTBase* guiElement, Rect2I* output)
+	void ScriptGUILayoutUtility::internal_CalculateBounds(ScriptGUIElementBaseTBase* guiElement, ScriptGUILayout* relativeTo, Rect2I* output)
 	{
 	{
-		*output = GUILayoutUtility::calcBounds(guiElement->getGUIElement());
+		GUIPanel* relativeToPanel = nullptr;
+		if (relativeTo != nullptr)
+			relativeToPanel = static_cast<GUIPanel*>(relativeTo->getGUIElement());
+
+		*output = GUILayoutUtility::calcBounds(guiElement->getGUIElement(), relativeToPanel);
 	}
 	}
 }
 }

+ 0 - 3
TODO.txt

@@ -17,9 +17,6 @@ the same and the only variable will be the 4byte random number, which can someti
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 GUIArea refactor:
 GUIArea refactor:
 
 
-EditorWindow and ModalWindow need to initialize the C# "GUI" field.
- - Check if the default GUIPanel has proper size. EditorWindow should be fine, but modal window might need additional handling (I don't think it even has a default contents panel)
-
 ColorPicker 2D handle is broken because it uses window coordinates for positioning, but it needs coordinates relative to parent GUI panel
 ColorPicker 2D handle is broken because it uses window coordinates for positioning, but it needs coordinates relative to parent GUI panel
  - Will likely need a new method for that
  - Will likely need a new method for that
  - Extend GUILayoutUtility::calcBounds so it can returns bounds relative to specific GUIPanel
  - Extend GUILayoutUtility::calcBounds so it can returns bounds relative to specific GUIPanel