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

GUILayout refactor so child layouts properly respect their elements min and max sizes
Some other fixes for ModalWindow and ColorPicker

Marko Pintera 10 лет назад
Родитель
Сommit
bdc149073b
33 измененных файлов с 310 добавлено и 221 удалено
  1. 5 0
      BansheeCore/Include/BsRenderWindow.h
  2. 11 0
      BansheeCore/Source/BsRenderWindow.cpp
  3. 1 0
      BansheeEditor/Include/BsEditorWindowManager.h
  4. 5 0
      BansheeEditor/Source/BsEditorWindowManager.cpp
  5. 3 1
      BansheeEditor/Source/BsModalWindow.cpp
  6. 1 0
      BansheeEngine/BansheeEngine.vcxproj
  7. 3 0
      BansheeEngine/BansheeEngine.vcxproj.filters
  8. 8 0
      BansheeEngine/Include/BsEnums.h
  9. 0 8
      BansheeEngine/Include/BsGUIArea.h
  10. 2 2
      BansheeEngine/Include/BsGUIElement.h
  11. 4 4
      BansheeEngine/Include/BsGUIElementBase.h
  12. 8 4
      BansheeEngine/Include/BsGUILayout.h
  13. 3 3
      BansheeEngine/Include/BsGUILayoutExplicit.h
  14. 18 0
      BansheeEngine/Include/BsGUILayoutOptions.h
  15. 3 3
      BansheeEngine/Include/BsGUILayoutX.h
  16. 3 3
      BansheeEngine/Include/BsGUILayoutY.h
  17. 2 2
      BansheeEngine/Include/BsGUIScrollArea.h
  18. 4 4
      BansheeEngine/Include/BsGUISpace.h
  19. 3 39
      BansheeEngine/Source/BsGUIElement.cpp
  20. 1 1
      BansheeEngine/Source/BsGUIElementBase.cpp
  21. 2 4
      BansheeEngine/Source/BsGUILayout.cpp
  22. 3 3
      BansheeEngine/Source/BsGUILayoutExplicit.cpp
  23. 53 0
      BansheeEngine/Source/BsGUILayoutOptions.cpp
  24. 7 7
      BansheeEngine/Source/BsGUILayoutUtility.cpp
  25. 44 57
      BansheeEngine/Source/BsGUILayoutX.cpp
  26. 44 57
      BansheeEngine/Source/BsGUILayoutY.cpp
  27. 8 8
      BansheeEngine/Source/BsGUIScrollArea.cpp
  28. 24 0
      BansheeEngine/Source/BsGUISpace.cpp
  29. 26 7
      MBansheeEditor/ColorPicker.cs
  30. 1 0
      MBansheeEditor/EditorApplication.cs
  31. 4 4
      SBansheeEngine/Source/BsScriptInput.cpp
  32. 1 0
      SBansheeEngine/Source/BsScriptTexture2D.cpp
  33. 5 0
      TODO.txt

+ 5 - 0
BansheeCore/Include/BsRenderWindow.h

@@ -348,6 +348,11 @@ namespace BansheeEngine
 
 
 		RenderWindow(const RENDER_WINDOW_DESC& desc);
 		RenderWindow(const RENDER_WINDOW_DESC& desc);
 
 
+		/**
+		 * @brief	Returns render window properties that may be edited.
+		 */
+		RenderWindowProperties& getMutableProperties();
+
 		/**
 		/**
 		 * @brief	Updates internal properties using the provided data. Data must have been retrieved from
 		 * @brief	Updates internal properties using the provided data. Data must have been retrieved from
 		 *			"getSyncData" method of the core version of this object.
 		 *			"getSyncData" method of the core version of this object.

+ 11 - 0
BansheeCore/Source/BsRenderWindow.cpp

@@ -141,6 +141,8 @@ namespace BansheeEngine
 			renderWindow->resize(width, height);
 			renderWindow->resize(width, height);
 		};
 		};
 
 
+		getMutableProperties().mWidth = width;
+		getMutableProperties().mHeight = height;
 		accessor.queueCommand(std::bind(resizeFunc, getCore(), width, height));
 		accessor.queueCommand(std::bind(resizeFunc, getCore(), width, height));
 	}
 	}
 
 
@@ -152,6 +154,8 @@ namespace BansheeEngine
 			renderWindow->move(left, top);
 			renderWindow->move(left, top);
 		};
 		};
 
 
+		getMutableProperties().mLeft = left;
+		getMutableProperties().mTop = top;
 		accessor.queueCommand(std::bind(moveFunc, getCore(), left, top));
 		accessor.queueCommand(std::bind(moveFunc, getCore(), left, top));
 	}
 	}
 
 
@@ -163,6 +167,7 @@ namespace BansheeEngine
 			renderWindow->setHidden(true);
 			renderWindow->setHidden(true);
 		};
 		};
 
 
+		getMutableProperties().mHidden = true;
 		accessor.queueCommand(std::bind(hideFunc, getCore()));
 		accessor.queueCommand(std::bind(hideFunc, getCore()));
 	}
 	}
 
 
@@ -174,6 +179,7 @@ namespace BansheeEngine
 			renderWindow->setHidden(false);
 			renderWindow->setHidden(false);
 		};
 		};
 
 
+		getMutableProperties().mHidden = false;
 		accessor.queueCommand(std::bind(showFunc, getCore()));
 		accessor.queueCommand(std::bind(showFunc, getCore()));
 	}
 	}
 
 
@@ -260,6 +266,11 @@ namespace BansheeEngine
 		return RenderWindowManager::instance().create(desc, parentWindow);
 		return RenderWindowManager::instance().create(desc, parentWindow);
 	}
 	}
 
 
+	RenderWindowProperties& RenderWindow::getMutableProperties()
+	{
+		return const_cast<RenderWindowProperties&>(getProperties());
+	}
+
 	CoreSyncData RenderWindow::syncToCore(FrameAlloc* allocator)
 	CoreSyncData RenderWindow::syncToCore(FrameAlloc* allocator)
 	{
 	{
 		UINT32 size = sizeof(RenderWindowProperties);
 		UINT32 size = sizeof(RenderWindowProperties);

+ 1 - 0
BansheeEditor/Include/BsEditorWindowManager.h

@@ -14,6 +14,7 @@ namespace BansheeEngine
 
 
 		MainEditorWindow* createMain(const RenderWindowPtr& parentRenderWindow);
 		MainEditorWindow* createMain(const RenderWindowPtr& parentRenderWindow);
 		EditorWindow* create();
 		EditorWindow* create();
+		void registerWindow(EditorWindowBase* window);
 		void destroy(EditorWindowBase* window);
 		void destroy(EditorWindowBase* window);
 
 
 		MainEditorWindow* getMainWindow() const { return mMainWindow; }
 		MainEditorWindow* getMainWindow() const { return mMainWindow; }

+ 5 - 0
BansheeEditor/Source/BsEditorWindowManager.cpp

@@ -41,6 +41,11 @@ namespace BansheeEngine
 		return newWindow;
 		return newWindow;
 	}
 	}
 
 
+	void EditorWindowManager::registerWindow(EditorWindowBase* window)
+	{
+		mEditorWindows.push_back(window);
+	}
+
 	void EditorWindowManager::destroy(EditorWindowBase* window)
 	void EditorWindowManager::destroy(EditorWindowBase* window)
 	{
 	{
 		auto iterFind = std::find(begin(mEditorWindows), end(mEditorWindows), window);
 		auto iterFind = std::find(begin(mEditorWindows), end(mEditorWindows), window);

+ 3 - 1
BansheeEditor/Source/BsModalWindow.cpp

@@ -15,6 +15,8 @@ namespace BansheeEngine
 		:EditorWindowBase(true), mTitleBarArea(nullptr), mTitleBarBgArea(nullptr), 
 		:EditorWindowBase(true), mTitleBarArea(nullptr), mTitleBarBgArea(nullptr), 
 		mCloseButton(nullptr), mTitleBarBg(nullptr), mTitle(nullptr)
 		mCloseButton(nullptr), mTitleBarBg(nullptr), mTitle(nullptr)
 	{
 	{
+		EditorWindowManager::instance().registerWindow(this);
+
 		mTitleBarBgArea = GUIArea::createStretchedXY(*mGUI, 1, 1, 1, 1, std::numeric_limits<UINT16>::max() - 1);
 		mTitleBarBgArea = GUIArea::createStretchedXY(*mGUI, 1, 1, 1, 1, std::numeric_limits<UINT16>::max() - 1);
 		mTitleBarArea = GUIArea::createStretchedXY(*mGUI, 1, 1, 1, 1, 0);
 		mTitleBarArea = GUIArea::createStretchedXY(*mGUI, 1, 1, 1, 1, 0);
 
 
@@ -59,7 +61,7 @@ namespace BansheeEngine
 
 
 	void ModalWindow::close()
 	void ModalWindow::close()
 	{
 	{
-		bs_delete(this);
+		EditorWindowManager::instance().destroy(this);
 	}
 	}
 
 
 	void ModalWindow::setTitle(const HString& title)
 	void ModalWindow::setTitle(const HString& title)

+ 1 - 0
BansheeEngine/BansheeEngine.vcxproj

@@ -239,6 +239,7 @@
     <ClCompile Include="Source\BsGUILayoutUtility.cpp" />
     <ClCompile Include="Source\BsGUILayoutUtility.cpp" />
     <ClCompile Include="Source\BsGUIProgressBar.cpp" />
     <ClCompile Include="Source\BsGUIProgressBar.cpp" />
     <ClCompile Include="Source\BsGUISlider.cpp" />
     <ClCompile Include="Source\BsGUISlider.cpp" />
+    <ClCompile Include="Source\BsGUISpace.cpp" />
     <ClCompile Include="Source\BsInputConfiguration.cpp" />
     <ClCompile Include="Source\BsInputConfiguration.cpp" />
     <ClCompile Include="Source\BsRenderableController.cpp" />
     <ClCompile Include="Source\BsRenderableController.cpp" />
     <ClCompile Include="Source\BsRenderableHandler.cpp" />
     <ClCompile Include="Source\BsRenderableHandler.cpp" />

+ 3 - 0
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -505,5 +505,8 @@
     <ClCompile Include="Source\BsGUILayoutExplicit.cpp">
     <ClCompile Include="Source\BsGUILayoutExplicit.cpp">
       <Filter>Source Files\GUI</Filter>
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsGUISpace.cpp">
+      <Filter>Source Files\GUI</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 8 - 0
BansheeEngine/Include/BsEnums.h

@@ -30,4 +30,12 @@ namespace BansheeEngine
 	{
 	{
 		RenType_LitTextured
 		RenType_LitTextured
 	};
 	};
+
+	/**
+	 * @brief	Type of layout that a GUIArea can initially be created with.
+	 */
+	enum class GUILayoutType
+	{
+		LayoutX, LayoutY, LayoutExplicit
+	};
 }
 }

+ 0 - 8
BansheeEngine/Include/BsGUIArea.h

@@ -5,14 +5,6 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	/**
-	 * @brief	Type of layout that a GUIArea can initially be created with
-	 */
-	enum class GUILayoutType
-	{
-		LayoutX, LayoutY, LayoutExplicit
-	};
-
 	/**
 	/**
 	 * @brief	GUIArea represents a freely positionable GUI panel with a GUILayout child.
 	 * @brief	GUIArea represents a freely positionable GUI panel with a GUILayout child.
 	 *			This is one of the top GUI elements (aside from GUIWidget) and all layouts
 	 *			This is one of the top GUI elements (aside from GUIWidget) and all layouts

+ 2 - 2
BansheeEngine/Include/BsGUIElement.h

@@ -363,9 +363,9 @@ namespace BansheeEngine
 		virtual bool _hasCustomCursor(const Vector2I position, CursorType& type) const { return false; }
 		virtual bool _hasCustomCursor(const Vector2I position, CursorType& type) const { return false; }
 
 
 		/**
 		/**
-		 * @copydoc	GUIElementBase::_calculateOptimalLayoutSize
+		 * @copydoc	GUIElementBase::_calculateLayoutSizeRange
 		 */
 		 */
-		virtual Vector2I _calculateOptimalLayoutSize() const;
+		virtual LayoutSizeRange _calculateLayoutSizeRange() const;
 
 
 		/**
 		/**
 		 * @brief	Checks if the GUI element accepts a drag and drop operation of the specified type.
 		 * @brief	Checks if the GUI element accepts a drag and drop operation of the specified type.

+ 4 - 4
BansheeEngine/Include/BsGUIElementBase.h

@@ -121,9 +121,9 @@ namespace BansheeEngine
 		 * @param	height			Available height for the layout elements.
 		 * @param	height			Available height for the layout elements.
 		 * @param	elementAreas	Array to hold output areas. Must be the same size as the number of child elements.
 		 * @param	elementAreas	Array to hold output areas. Must be the same size as the number of child elements.
 		 * @param	numElements		Size of the element areas array.
 		 * @param	numElements		Size of the element areas array.
-		 * @param	optimalSizes	Optimal sizes used by the elements. Array must be same size as elements array.
+		 * @param	optimalSizes	Ranges of possible sizes used for the elements. Array must be same size as elements array.
 		 */
 		 */
-		virtual void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<Vector2I>& optimalSizes) const;
+		virtual void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<LayoutSizeRange>& sizeRanges) const;
 
 
 		/**
 		/**
 		 * @brief	Sets a new parent for this element.
 		 * @brief	Sets a new parent for this element.
@@ -154,11 +154,11 @@ namespace BansheeEngine
 		virtual Vector2I _getOptimalSize() const = 0;
 		virtual Vector2I _getOptimalSize() const = 0;
 
 
 		/**
 		/**
-		 * @brief	Returns element optimal size constrained by its layout options.
+		 * @brief	Returns element size range constrained by its layout options.
 		 *
 		 *
 		 * @note	Internal method.
 		 * @note	Internal method.
 		 */
 		 */
-		virtual Vector2I _calculateOptimalLayoutSize() const = 0;
+		virtual LayoutSizeRange _calculateLayoutSizeRange() const = 0;
 
 
 		/**
 		/**
 		 * @brief	Returns element padding that determines how far apart to space out this element
 		 * @brief	Returns element padding that determines how far apart to space out this element

+ 8 - 4
BansheeEngine/Include/BsGUILayout.h

@@ -101,10 +101,15 @@ namespace BansheeEngine
 		 */
 		 */
 		void removeChildAt(UINT32 idx);
 		void removeChildAt(UINT32 idx);
 
 
+		/**
+		 * @brief	Returns a size range that was cached during the last "_updateOptimalLayoutSizes" call.
+		 */
+		LayoutSizeRange _getCachedSizeRange() const { return mSizeRange; }
+
 		/**
 		/**
 		 * @copydoc	GUIElementBase::_getOptimalSize
 		 * @copydoc	GUIElementBase::_getOptimalSize
 		 */
 		 */
-		Vector2I _getOptimalSize() const { return Vector2I(mOptimalWidth, mOptimalHeight); }
+		Vector2I _getOptimalSize() const { return mSizeRange.optimal; }
 
 
 		/**
 		/**
 		 * @copydoc	GUIElementBase::_getPadding
 		 * @copydoc	GUIElementBase::_getPadding
@@ -154,9 +159,8 @@ namespace BansheeEngine
 	protected:
 	protected:
 		GUIArea* mParentGUIArea;
 		GUIArea* mParentGUIArea;
 
 
-		Vector<Vector2I> mOptimalSizes;
-		UINT32 mOptimalWidth;
-		UINT32 mOptimalHeight;
+		Vector<LayoutSizeRange> mChildSizeRanges;
+		LayoutSizeRange mSizeRange;
 
 
 		UINT32 mActualWidth;
 		UINT32 mActualWidth;
 		UINT32 mActualHeight;
 		UINT32 mActualHeight;

+ 3 - 3
BansheeEngine/Include/BsGUILayoutExplicit.h

@@ -22,14 +22,14 @@ namespace BansheeEngine
 		void _updateOptimalLayoutSizes();
 		void _updateOptimalLayoutSizes();
 
 
 		/**
 		/**
-		 * @copydoc	GUIElementBase::_calculateOptimalLayoutSize
+		 * @copydoc	GUIElementBase::_calculateLayoutSizeRange
 		 */
 		 */
-		virtual Vector2I _calculateOptimalLayoutSize() const;
+		virtual LayoutSizeRange _calculateLayoutSizeRange() const;
 
 
 		/**
 		/**
 		 * @copydoc	GUILayout::_getElementAreas
 		 * @copydoc	GUILayout::_getElementAreas
 		 */
 		 */
-		void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<Vector2I>& optimalSizes) const;
+		void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<LayoutSizeRange>& sizeRanges) const;
 
 
 		/**
 		/**
 		 * @copydoc	GUILayout::_calcActualSize
 		 * @copydoc	GUILayout::_calcActualSize

+ 18 - 0
BansheeEngine/Include/BsGUILayoutOptions.h

@@ -1,9 +1,20 @@
 #pragma once
 #pragma once
 
 
 #include "BsPrerequisites.h"
 #include "BsPrerequisites.h"
+#include "BsVector2I.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	/**
+	 * @brief	Contains valid size range for a GUI element in a GUI layout
+	 */
+	struct BS_EXPORT LayoutSizeRange
+	{
+		Vector2I optimal;
+		Vector2I min;
+		Vector2I max;
+	};
+
 	/**
 	/**
 	 * @brief	Options that control how an element is positioned and sized in a GUI layout.
 	 * @brief	Options that control how an element is positioned and sized in a GUI layout.
 	 */
 	 */
@@ -27,6 +38,13 @@ namespace BansheeEngine
 		 */
 		 */
 		void updateWithStyle(const GUIElementStyle* style);
 		void updateWithStyle(const GUIElementStyle* style);
 
 
+		/**
+		 * @brief	Calculates size range for a GUI element using this layout.
+		 *
+		 * @param	optimal	Preferred size of the GUI element.
+		 */
+		LayoutSizeRange calculateSizeRange(const Vector2I& optimal) const;
+
 		UINT32 width, height;
 		UINT32 width, height;
 		UINT32 minWidth, maxWidth, minHeight, maxHeight;
 		UINT32 minWidth, maxWidth, minHeight, maxHeight;
 		bool fixedWidth, fixedHeight;
 		bool fixedWidth, fixedHeight;

+ 3 - 3
BansheeEngine/Include/BsGUILayoutX.h

@@ -22,14 +22,14 @@ namespace BansheeEngine
 		void _updateOptimalLayoutSizes();
 		void _updateOptimalLayoutSizes();
 
 
 		/**
 		/**
-		 * @copydoc	GUIElementBase::_calculateOptimalLayoutSize
+		 * @copydoc	GUIElementBase::_calculateLayoutSizeRange
 		 */
 		 */
-		virtual Vector2I _calculateOptimalLayoutSize() const;
+		virtual LayoutSizeRange _calculateLayoutSizeRange() const;
 
 
 		/**
 		/**
 		 * @copydoc	GUILayout::_getElementAreas
 		 * @copydoc	GUILayout::_getElementAreas
 		 */
 		 */
-		void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<Vector2I>& optimalSizes) const;
+		void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<LayoutSizeRange>& sizeRanges) const;
 
 
 		/**
 		/**
 		 * @copydoc	GUILayout::_calcActualSize
 		 * @copydoc	GUILayout::_calcActualSize

+ 3 - 3
BansheeEngine/Include/BsGUILayoutY.h

@@ -22,14 +22,14 @@ namespace BansheeEngine
 		void _updateOptimalLayoutSizes();
 		void _updateOptimalLayoutSizes();
 
 
 		/**
 		/**
-		 * @copydoc	GUIElementBase::_calculateOptimalLayoutSize
+		 * @copydoc	GUIElementBase::_calculateLayoutSizeRange
 		 */
 		 */
-		virtual Vector2I _calculateOptimalLayoutSize() const;
+		virtual LayoutSizeRange _calculateLayoutSizeRange() const;
 
 
 		/**
 		/**
 		 * @copydoc	GUILayout::_getElementAreas
 		 * @copydoc	GUILayout::_getElementAreas
 		 */
 		 */
-		void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<Vector2I>& optimalSizes) const;
+		void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<LayoutSizeRange>& sizeRanges) const;
 
 
 		/**
 		/**
 		 * @copydoc	GUILayout::_calcActualSize
 		 * @copydoc	GUILayout::_calcActualSize

+ 2 - 2
BansheeEngine/Include/BsGUIScrollArea.h

@@ -173,7 +173,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc	GUIElementContainer::_getElementAreas
 		 * @copydoc	GUIElementContainer::_getElementAreas
 		 */
 		 */
-		void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<Vector2I>& optimalSizes) const;
+		void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<LayoutSizeRange>& sizeRanges) const;
 
 
 		/**
 		/**
 		 * @copydoc	GUIElementContainer::_getElementAreas
 		 * @copydoc	GUIElementContainer::_getElementAreas
@@ -181,7 +181,7 @@ namespace BansheeEngine
 		 * @note	Also calculates some scroll area specific values.
 		 * @note	Also calculates some scroll area specific values.
 		 */
 		 */
 		void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, 
 		void _getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, 
-			const Vector<Vector2I>& optimalSizes, Vector2I& visibleSize, Vector2I& contentSize) const;
+			const Vector<LayoutSizeRange>& sizeRanges, Vector2I& visibleSize, Vector2I& contentSize) const;
 
 
 		ScrollBarType mVertBarType;
 		ScrollBarType mVertBarType;
 		ScrollBarType mHorzBarType;
 		ScrollBarType mHorzBarType;

+ 4 - 4
BansheeEngine/Include/BsGUISpace.h

@@ -39,9 +39,9 @@ namespace BansheeEngine
 		virtual Vector2I _getOptimalSize() const { return Vector2I(getSize(), getSize()); }
 		virtual Vector2I _getOptimalSize() const { return Vector2I(getSize(), getSize()); }
 
 
 		/**
 		/**
-		 * @copydoc	GUIElementBase::_calculateOptimalLayoutSize
+		 * @copydoc	GUIElementBase::_calculateLayoutSizeRange
 		 */
 		 */
-		virtual Vector2I _calculateOptimalLayoutSize() const { return _getOptimalSize(); }
+		virtual LayoutSizeRange _calculateLayoutSizeRange() const;
 
 
 		/**
 		/**
 		 * @copydoc	GUIElementBase::_isContentDirty
 		 * @copydoc	GUIElementBase::_isContentDirty
@@ -96,9 +96,9 @@ namespace BansheeEngine
 		virtual Vector2I _getOptimalSize() const { return Vector2I(0, 0); }
 		virtual Vector2I _getOptimalSize() const { return Vector2I(0, 0); }
 
 
 		/**
 		/**
-		 * @copydoc	GUIElementBase::_calculateOptimalLayoutSize
+		 * @copydoc	GUIElementBase::_calculateLayoutSizeRange
 		 */
 		 */
-		virtual Vector2I _calculateOptimalLayoutSize() const { return _getOptimalSize(); }
+		virtual LayoutSizeRange _calculateLayoutSizeRange() const;
 
 
 		/**
 		/**
 		 * @copydoc	GUIElementBase::_isContentDirty
 		 * @copydoc	GUIElementBase::_isContentDirty

+ 3 - 39
BansheeEngine/Source/BsGUIElement.cpp

@@ -160,49 +160,13 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	Vector2I GUIElement::_calculateOptimalLayoutSize() const
+	LayoutSizeRange GUIElement::_calculateLayoutSizeRange() const
 	{
 	{
 		if (mIsDisabled)
 		if (mIsDisabled)
-			return Vector2I(0, 0);
+			return LayoutSizeRange();
 
 
 		const GUILayoutOptions& layoutOptions = _getLayoutOptions();
 		const GUILayoutOptions& layoutOptions = _getLayoutOptions();
-
-		UINT32 optimalWidth = 0;
-		UINT32 optimalHeight = 0;
-
-		Vector2I optimalSize;
-		if (!layoutOptions.fixedWidth || !layoutOptions.fixedHeight)
-			optimalSize = _getOptimalSize();
-
-		if (layoutOptions.fixedHeight)
-		{
-			optimalHeight = layoutOptions.height;
-		}
-		else
-		{
-			optimalHeight = optimalSize.y;
-
-			if (layoutOptions.minHeight > 0)
-				optimalHeight = std::max(layoutOptions.minHeight, optimalHeight);
-
-			if (layoutOptions.maxHeight > 0)
-				optimalHeight = std::min(layoutOptions.maxHeight, optimalHeight);
-		}
-
-		if (layoutOptions.fixedWidth)
-			optimalWidth = layoutOptions.width;
-		else
-		{
-			optimalWidth = optimalSize.x;
-
-			if (layoutOptions.minWidth > 0)
-				optimalWidth = std::max(layoutOptions.minWidth, optimalWidth);
-
-			if (layoutOptions.maxWidth > 0)
-				optimalWidth = std::min(layoutOptions.maxWidth, optimalWidth);
-		}
-
-		return Vector2I(optimalWidth, optimalHeight);
+		return layoutOptions.calculateSizeRange(_getOptimalSize());
 	}
 	}
 
 
 	Rect2I GUIElement::_getCachedBounds() const
 	Rect2I GUIElement::_getCachedBounds() const

+ 1 - 1
BansheeEngine/Source/BsGUIElementBase.cpp

@@ -153,7 +153,7 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	void GUIElementBase::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<Vector2I>& optimalSizes) const
+	void GUIElementBase::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<LayoutSizeRange>& sizeRanges) const
 	{
 	{
 		assert(mChildren.size() == 0);
 		assert(mChildren.size() == 0);
 	}
 	}

+ 2 - 4
BansheeEngine/Source/BsGUILayout.cpp

@@ -8,15 +8,13 @@
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	GUILayout::GUILayout(GUIArea* parentArea)
 	GUILayout::GUILayout(GUIArea* parentArea)
-		:mOptimalWidth(0), mOptimalHeight(0), mActualWidth(0), 
-		mActualHeight(0), mParentGUIArea(parentArea)
+		:mParentGUIArea(parentArea)
 	{
 	{
 
 
 	}
 	}
 
 
 	GUILayout::GUILayout()
 	GUILayout::GUILayout()
-		:mOptimalWidth(0), mOptimalHeight(0), mActualWidth(0),
-		mActualHeight(0), mParentGUIArea(nullptr)
+		:mParentGUIArea(nullptr)
 	{
 	{
 
 
 	}
 	}

+ 3 - 3
BansheeEngine/Source/BsGUILayoutExplicit.cpp

@@ -10,9 +10,9 @@ namespace BansheeEngine
 		:GUILayout(parentArea)
 		:GUILayout(parentArea)
 	{ }
 	{ }
 
 
-	Vector2I GUILayoutExplicit::_calculateOptimalLayoutSize() const
+	LayoutSizeRange GUILayoutExplicit::_calculateLayoutSizeRange() const
 	{
 	{
-		return Vector2I(0, 0);
+		return LayoutSizeRange();
 	}
 	}
 
 
 	void GUILayoutExplicit::_updateOptimalLayoutSizes()
 	void GUILayoutExplicit::_updateOptimalLayoutSizes()
@@ -20,7 +20,7 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	void GUILayoutExplicit::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<Vector2I>& optimalSizes) const
+	void GUILayoutExplicit::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<LayoutSizeRange>& sizeRanges) const
 	{
 	{
 		assert(mChildren.size() == numElements);
 		assert(mChildren.size() == numElements);
 
 

+ 53 - 0
BansheeEngine/Source/BsGUILayoutOptions.cpp

@@ -71,4 +71,57 @@ namespace BansheeEngine
 	{
 	{
 
 
 	}
 	}
+
+	LayoutSizeRange GUILayoutOptions::calculateSizeRange(const Vector2I& optimal) const
+	{
+		LayoutSizeRange sizeRange;
+
+		if (fixedHeight)
+		{
+			sizeRange.optimal.y = height;
+			sizeRange.min.y = height;
+			sizeRange.max.y = height;
+		}
+		else
+		{
+			sizeRange.optimal.y = optimal.y;
+
+			if (minHeight > 0)
+			{
+				sizeRange.optimal.y = std::max((INT32)minHeight, sizeRange.optimal.y);
+				sizeRange.min.y = minHeight;
+			}
+
+			if (maxHeight > 0)
+			{
+				sizeRange.optimal.y = std::min((INT32)maxHeight, sizeRange.optimal.y);
+				sizeRange.max.y = maxHeight;
+			}
+		}
+
+		if (fixedWidth)
+		{
+			sizeRange.optimal.x = width;
+			sizeRange.min.x = width;
+			sizeRange.max.x = width;
+		}
+		else
+		{
+			sizeRange.optimal.x = optimal.x;
+
+			if (minWidth > 0)
+			{
+				sizeRange.optimal.x = std::max((INT32)minWidth, sizeRange.optimal.x);
+				sizeRange.min.x = minWidth;
+			}
+
+			if (maxWidth > 0)
+			{
+				sizeRange.optimal.x = std::min((INT32)maxWidth, sizeRange.optimal.x);
+				sizeRange.max.x = maxWidth;
+			}
+		}
+
+		return sizeRange;
+	}
 }
 }

+ 7 - 7
BansheeEngine/Source/BsGUILayoutUtility.cpp

@@ -9,7 +9,7 @@ namespace BansheeEngine
 {
 {
 	Vector2I GUILayoutUtility::calcOptimalSize(const GUIElementBase* elem)
 	Vector2I GUILayoutUtility::calcOptimalSize(const GUIElementBase* elem)
 	{
 	{
-		return elem->_calculateOptimalLayoutSize();
+		return elem->_calculateLayoutSizeRange().optimal;
 	}
 	}
 
 
 	Rect2I GUILayoutUtility::calcBounds(const GUIElementBase* elem)
 	Rect2I GUILayoutUtility::calcBounds(const GUIElementBase* elem)
@@ -36,7 +36,7 @@ namespace BansheeEngine
 		UINT32 numElements = (UINT32)parent->_getNumChildren();
 		UINT32 numElements = (UINT32)parent->_getNumChildren();
 		UINT32 myIndex = 0;
 		UINT32 myIndex = 0;
 
 
-		Vector<Vector2I> optimalSizes;
+		Vector<LayoutSizeRange> sizeRanges;
 		for (UINT32 i = 0; i < numElements; i++)
 		for (UINT32 i = 0; i < numElements; i++)
 		{
 		{
 			GUIElementBase* child = parent->_getChild(i);
 			GUIElementBase* child = parent->_getChild(i);
@@ -44,7 +44,7 @@ namespace BansheeEngine
 			if (child == elem)
 			if (child == elem)
 				myIndex = i;
 				myIndex = i;
 
 
-			optimalSizes.push_back(calcOptimalSize(child));
+			sizeRanges.push_back(child->_calculateLayoutSizeRange());
 		}
 		}
 
 
 		Rect2I* elementAreas = nullptr;
 		Rect2I* elementAreas = nullptr;
@@ -52,7 +52,7 @@ namespace BansheeEngine
 		if (numElements > 0)
 		if (numElements > 0)
 			elementAreas = stackConstructN<Rect2I>(numElements);
 			elementAreas = stackConstructN<Rect2I>(numElements);
 
 
-		parent->_getElementAreas(parentArea.x, parentArea.y, parentArea.width, parentArea.height, elementAreas, numElements, optimalSizes);
+		parent->_getElementAreas(parentArea.x, parentArea.y, parentArea.width, parentArea.height, elementAreas, numElements, sizeRanges);
 		Rect2I myArea = elementAreas[myIndex];
 		Rect2I myArea = elementAreas[myIndex];
 
 
 		if (elementAreas != nullptr)
 		if (elementAreas != nullptr)
@@ -65,11 +65,11 @@ namespace BansheeEngine
 	{
 	{
 		UINT32 numElements = (UINT32)layout->_getNumChildren();
 		UINT32 numElements = (UINT32)layout->_getNumChildren();
 
 
-		Vector<Vector2I> optimalSizes;
+		Vector<LayoutSizeRange> sizeRanges;
 		for (UINT32 i = 0; i < numElements; i++)
 		for (UINT32 i = 0; i < numElements; i++)
 		{
 		{
 			GUIElementBase* child = layout->_getChild(i);
 			GUIElementBase* child = layout->_getChild(i);
-			optimalSizes.push_back(GUILayoutUtility::calcOptimalSize(child));
+			sizeRanges.push_back(child->_calculateLayoutSizeRange());
 		}
 		}
 
 
 		Rect2I* elementAreas = nullptr;
 		Rect2I* elementAreas = nullptr;
@@ -77,7 +77,7 @@ namespace BansheeEngine
 		if (numElements > 0)
 		if (numElements > 0)
 			elementAreas = stackConstructN<Rect2I>(numElements);
 			elementAreas = stackConstructN<Rect2I>(numElements);
 
 
-		layout->_getElementAreas(0, 0, width, height, elementAreas, numElements, optimalSizes);
+		layout->_getElementAreas(0, 0, width, height, elementAreas, numElements, sizeRanges);
 		Rect2I* actualAreas = elementAreas; // We re-use the same array
 		Rect2I* actualAreas = elementAreas; // We re-use the same array
 
 
 		for (UINT32 i = 0; i < numElements; i++)
 		for (UINT32 i = 0; i < numElements; i++)

+ 44 - 57
BansheeEngine/Source/BsGUILayoutX.cpp

@@ -10,29 +10,33 @@ namespace BansheeEngine
 		:GUILayout(parentArea)
 		:GUILayout(parentArea)
 	{ }
 	{ }
 
 
-	Vector2I GUILayoutX::_calculateOptimalLayoutSize() const
+	LayoutSizeRange GUILayoutX::_calculateLayoutSizeRange() const
 	{
 	{
-		if (mIsDisabled)
-			return Vector2I(0, 0);
+		LayoutSizeRange layoutSizeRange;
 
 
-		UINT32 optimalWidth = 0;
-		UINT32 optimalHeight = 0;
+		if (mIsDisabled)
+			return layoutSizeRange;
 
 
 		for (auto& child : mChildren)
 		for (auto& child : mChildren)
 		{
 		{
-			Vector2I optimalSize = child->_calculateOptimalLayoutSize();
+			LayoutSizeRange sizeRange = child->_calculateLayoutSizeRange();
 
 
 			if (child->_getType() == GUIElementBase::Type::FixedSpace)
 			if (child->_getType() == GUIElementBase::Type::FixedSpace)
-				optimalSize.y = 0;
+				sizeRange.optimal.y = sizeRange.min.y = sizeRange.max.y = 0;
 
 
 			UINT32 paddingX = child->_getPadding().left + child->_getPadding().right;
 			UINT32 paddingX = child->_getPadding().left + child->_getPadding().right;
 			UINT32 paddingY = child->_getPadding().top + child->_getPadding().bottom;
 			UINT32 paddingY = child->_getPadding().top + child->_getPadding().bottom;
 
 
-			optimalWidth += optimalSize.x + paddingX;
-			optimalHeight = std::max((UINT32)optimalSize.y, optimalHeight + paddingY);
+			layoutSizeRange.optimal.x += sizeRange.optimal.x + paddingX;
+			layoutSizeRange.min.x += sizeRange.min.x + paddingX;
+			layoutSizeRange.max.x += sizeRange.max.x + paddingX;
+
+			layoutSizeRange.optimal.y = std::max((UINT32)sizeRange.optimal.y, layoutSizeRange.optimal.y + paddingY);
+			layoutSizeRange.min.y = std::max((UINT32)sizeRange.min.y, layoutSizeRange.min.y + paddingY);
+			layoutSizeRange.max.y = std::max((UINT32)sizeRange.max.y, layoutSizeRange.max.y + paddingY);
 		}
 		}
 
 
-		return Vector2I(optimalWidth, optimalHeight);
+		return layoutSizeRange;
 	}
 	}
 
 
 	void GUILayoutX::_updateOptimalLayoutSizes()
 	void GUILayoutX::_updateOptimalLayoutSizes()
@@ -40,52 +44,54 @@ namespace BansheeEngine
 		// Update all children first, otherwise we can't determine our own optimal size
 		// Update all children first, otherwise we can't determine our own optimal size
 		GUIElementBase::_updateOptimalLayoutSizes();
 		GUIElementBase::_updateOptimalLayoutSizes();
 
 
-		if(mChildren.size() != mOptimalSizes.size())
-			mOptimalSizes.resize(mChildren.size());
+		if(mChildren.size() != mChildSizeRanges.size())
+			mChildSizeRanges.resize(mChildren.size());
 
 
-		mOptimalWidth = 0;
-		mOptimalHeight = 0;
+		mSizeRange = LayoutSizeRange();
 
 
 		UINT32 childIdx = 0;
 		UINT32 childIdx = 0;
 		for(auto& child : mChildren)
 		for(auto& child : mChildren)
 		{
 		{
-			UINT32 optimalWidth = 0;
-			UINT32 optimalHeight = 0;
+			LayoutSizeRange& childSizeRange = mChildSizeRanges[childIdx];
 
 
 			if (child->_getType() == GUIElementBase::Type::FixedSpace)
 			if (child->_getType() == GUIElementBase::Type::FixedSpace)
 			{
 			{
 				GUIFixedSpace* fixedSpace = static_cast<GUIFixedSpace*>(child);
 				GUIFixedSpace* fixedSpace = static_cast<GUIFixedSpace*>(child);
-				optimalWidth = fixedSpace->_calculateOptimalLayoutSize().x;
+
+				childSizeRange = fixedSpace->_calculateLayoutSizeRange();
+				childSizeRange.optimal.y = 0;
+				childSizeRange.min.y = 0;
+				childSizeRange.max.y = 0;
 			}
 			}
 			else if (child->_getType() == GUIElementBase::Type::Element)
 			else if (child->_getType() == GUIElementBase::Type::Element)
 			{
 			{
 				GUIElement* element = static_cast<GUIElement*>(child);
 				GUIElement* element = static_cast<GUIElement*>(child);
 				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 
 
-				Vector2I optimalSize = child->_calculateOptimalLayoutSize();
-				optimalWidth = optimalSize.x;
-				optimalHeight = optimalSize.y;
+				childSizeRange = child->_calculateLayoutSizeRange();
 			}
 			}
 			else if(child->_getType() == GUIElementBase::Type::Layout)
 			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
 			{
-				optimalWidth = child->_getOptimalSize().x;
-				optimalHeight = child->_getOptimalSize().y;
+				GUILayout* layout = static_cast<GUILayout*>(child);
+				childSizeRange = layout->_getCachedSizeRange();
 			}
 			}
 
 
 			UINT32 paddingX = child->_getPadding().left + child->_getPadding().right;
 			UINT32 paddingX = child->_getPadding().left + child->_getPadding().right;
 			UINT32 paddingY = child->_getPadding().top + child->_getPadding().bottom;
 			UINT32 paddingY = child->_getPadding().top + child->_getPadding().bottom;
 
 
-			mOptimalSizes[childIdx].x = optimalWidth;
-			mOptimalWidth += optimalWidth + paddingX;
+			mSizeRange.optimal.x += childSizeRange.optimal.x + paddingX;
+			mSizeRange.min.x += childSizeRange.min.x + paddingX;
+			mSizeRange.max.x += childSizeRange.max.x + paddingX;
 
 
-			mOptimalSizes[childIdx].y = optimalHeight;
-			mOptimalHeight = std::max(mOptimalHeight, optimalHeight + paddingY);
+			mSizeRange.optimal.y = std::max((UINT32)mSizeRange.optimal.y, childSizeRange.optimal.y + paddingY);
+			mSizeRange.min.y = std::max((UINT32)mSizeRange.min.y, childSizeRange.min.y + paddingY);
+			mSizeRange.max.y = std::max((UINT32)mSizeRange.max.y, childSizeRange.max.y + paddingY);
 
 
 			childIdx++;
 			childIdx++;
 		}
 		}
 	}
 	}
 
 
-	void GUILayoutX::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<Vector2I>& optimalSizes) const
+	void GUILayoutX::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<LayoutSizeRange>& sizeRanges) const
 	{
 	{
 		assert(mChildren.size() == numElements);
 		assert(mChildren.size() == numElements);
 
 
@@ -110,7 +116,7 @@ namespace BansheeEngine
 		UINT32 childIdx = 0;
 		UINT32 childIdx = 0;
 		for (auto& child : mChildren)
 		for (auto& child : mChildren)
 		{
 		{
-			elementAreas[childIdx].width = optimalSizes[childIdx].x;
+			elementAreas[childIdx].width = sizeRanges[childIdx].optimal.x;
 
 
 			if (child->_getType() == GUIElementBase::Type::FixedSpace)
 			if (child->_getType() == GUIElementBase::Type::FixedSpace)
 			{
 			{
@@ -227,19 +233,18 @@ namespace BansheeEngine
 					UINT32 elementWidth = (UINT32)std::max(0, (INT32)elementAreas[childIdx].width - (INT32)extraWidth);
 					UINT32 elementWidth = (UINT32)std::max(0, (INT32)elementAreas[childIdx].width - (INT32)extraWidth);
 
 
 					// Clamp if needed
 					// Clamp if needed
-					if (child->_getType() == GUIElementBase::Type::Element)
+					if (child->_getType() == GUIElementBase::Type::Element || child->_getType() == GUIElementBase::Type::Layout)
 					{
 					{
-						GUIElement* element = static_cast<GUIElement*>(child);
-						const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
+						const LayoutSizeRange& childSizeRange = sizeRanges[childIdx];
 
 
 						if (elementWidth == 0)
 						if (elementWidth == 0)
 						{
 						{
 							processedElements[childIdx] = true;
 							processedElements[childIdx] = true;
 							numNonClampedElements--;
 							numNonClampedElements--;
 						}
 						}
-						else if (layoutOptions.minWidth > 0 && elementWidth < layoutOptions.minWidth)
+						else if (childSizeRange.min.x > 0 && (INT32)elementWidth < childSizeRange.min.x)
 						{
 						{
-							elementWidth = layoutOptions.minWidth;
+							elementWidth = childSizeRange.min.x;
 
 
 							processedElements[childIdx] = true;
 							processedElements[childIdx] = true;
 							numNonClampedElements--;
 							numNonClampedElements--;
@@ -249,18 +254,6 @@ namespace BansheeEngine
 						elementAreas[childIdx].width = elementWidth;
 						elementAreas[childIdx].width = elementWidth;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraWidth);
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraWidth);
 					}
 					}
-					else if (child->_getType() == GUIElementBase::Type::Layout)
-					{
-						if (elementWidth == 0)
-						{
-							processedElements[childIdx] = true;
-							numNonClampedElements--;
-						}
-
-						extraWidth = elementAreas[childIdx].width - elementWidth;
-						elementAreas[childIdx].width = elementWidth;
-						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraWidth);
-					}
 					else if (child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					else if (child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					{
 					{
 						elementAreas[childIdx].width = 0;
 						elementAreas[childIdx].width = 0;
@@ -297,19 +290,18 @@ namespace BansheeEngine
 					UINT32 elementWidth = elementAreas[childIdx].width + extraWidth;
 					UINT32 elementWidth = elementAreas[childIdx].width + extraWidth;
 
 
 					// Clamp if needed
 					// Clamp if needed
-					if (child->_getType() == GUIElementBase::Type::Element)
+					if (child->_getType() == GUIElementBase::Type::Element || child->_getType() == GUIElementBase::Type::Layout)
 					{
 					{
-						GUIElement* element = static_cast<GUIElement*>(child);
-						const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
+						const LayoutSizeRange& childSizeRange = sizeRanges[childIdx];
 
 
 						if (elementWidth == 0)
 						if (elementWidth == 0)
 						{
 						{
 							processedElements[childIdx] = true;
 							processedElements[childIdx] = true;
 							numNonClampedElements--;
 							numNonClampedElements--;
 						}
 						}
-						else if (layoutOptions.maxWidth > 0 && elementWidth > layoutOptions.maxWidth)
+						else if (childSizeRange.max.x > 0 && (INT32)elementWidth > childSizeRange.max.x)
 						{
 						{
-							elementWidth = layoutOptions.maxWidth;
+							elementWidth = childSizeRange.max.x;
 
 
 							processedElements[childIdx] = true;
 							processedElements[childIdx] = true;
 							numNonClampedElements--;
 							numNonClampedElements--;
@@ -319,11 +311,6 @@ namespace BansheeEngine
 						elementAreas[childIdx].width = elementWidth;
 						elementAreas[childIdx].width = elementWidth;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraWidth);
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraWidth);
 					}
 					}
-					else if (child->_getType() == GUIElementBase::Type::Layout)
-					{
-						elementAreas[childIdx].width = elementWidth;
-						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraWidth);
-					}
 					else if (child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					else if (child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					{
 					{
 						processedElements[childIdx] = true;
 						processedElements[childIdx] = true;
@@ -349,7 +336,7 @@ namespace BansheeEngine
 				GUIElement* element = static_cast<GUIElement*>(child);
 				GUIElement* element = static_cast<GUIElement*>(child);
 				element->setWidth(elemWidth);
 				element->setWidth(elemWidth);
 
 
-				UINT32 elemHeight = optimalSizes[childIdx].y;
+				UINT32 elemHeight = (UINT32)sizeRanges[childIdx].optimal.y;
 				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 				if (!layoutOptions.fixedHeight)
 				if (!layoutOptions.fixedHeight)
 				{
 				{
@@ -398,7 +385,7 @@ namespace BansheeEngine
 		if (numElements > 0)
 		if (numElements > 0)
 			elementAreas = stackConstructN<Rect2I>(numElements);
 			elementAreas = stackConstructN<Rect2I>(numElements);
 
 
-		_getElementAreas(x, y,width, height, elementAreas, numElements, mOptimalSizes);
+		_getElementAreas(x, y,width, height, elementAreas, numElements, mChildSizeRanges);
 
 
 		// Now that we have all the areas, actually assign them
 		// Now that we have all the areas, actually assign them
 		UINT32 childIdx = 0;
 		UINT32 childIdx = 0;

+ 44 - 57
BansheeEngine/Source/BsGUILayoutY.cpp

@@ -10,29 +10,33 @@ namespace BansheeEngine
 		:GUILayout(parentArea)
 		:GUILayout(parentArea)
 	{ }
 	{ }
 
 
-	Vector2I GUILayoutY::_calculateOptimalLayoutSize() const
+	LayoutSizeRange GUILayoutY::_calculateLayoutSizeRange() const
 	{
 	{
-		if (mIsDisabled)
-			return Vector2I(0, 0);
+		LayoutSizeRange layoutSizeRange;
 
 
-		UINT32 optimalWidth = 0;
-		UINT32 optimalHeight = 0;
+		if (mIsDisabled)
+			return layoutSizeRange;
 
 
 		for (auto& child : mChildren)
 		for (auto& child : mChildren)
 		{
 		{
-			Vector2I optimalSize = child->_calculateOptimalLayoutSize();
+			LayoutSizeRange sizeRange = child->_calculateLayoutSizeRange();
 			
 			
 			if (child->_getType() == GUIElementBase::Type::FixedSpace)
 			if (child->_getType() == GUIElementBase::Type::FixedSpace)
-				optimalSize.x = 0;
+				sizeRange.optimal.x = sizeRange.min.x = sizeRange.max.x = 0;
 
 
 			UINT32 paddingX = child->_getPadding().left + child->_getPadding().right;
 			UINT32 paddingX = child->_getPadding().left + child->_getPadding().right;
 			UINT32 paddingY = child->_getPadding().top + child->_getPadding().bottom;
 			UINT32 paddingY = child->_getPadding().top + child->_getPadding().bottom;
 
 
-			optimalHeight += optimalSize.y + paddingY;
-			optimalWidth = std::max((UINT32)optimalSize.x, optimalWidth + paddingX);
+			layoutSizeRange.optimal.y += sizeRange.optimal.y + paddingY;
+			layoutSizeRange.min.y += sizeRange.min.y + paddingY;
+			layoutSizeRange.max.y += sizeRange.max.y + paddingY;
+
+			layoutSizeRange.optimal.x = std::max((UINT32)sizeRange.optimal.x, layoutSizeRange.optimal.x + paddingX);
+			layoutSizeRange.min.x = std::max((UINT32)sizeRange.min.x, layoutSizeRange.min.x + paddingX);
+			layoutSizeRange.max.x = std::max((UINT32)sizeRange.max.x, layoutSizeRange.max.x + paddingX);
 		}
 		}
 
 
-		return Vector2I(optimalWidth, optimalHeight);
+		return layoutSizeRange;
 	}
 	}
 
 
 	void GUILayoutY::_updateOptimalLayoutSizes()
 	void GUILayoutY::_updateOptimalLayoutSizes()
@@ -40,53 +44,55 @@ namespace BansheeEngine
 		// Update all children first, otherwise we can't determine our own optimal size
 		// Update all children first, otherwise we can't determine our own optimal size
 		GUIElementBase::_updateOptimalLayoutSizes();
 		GUIElementBase::_updateOptimalLayoutSizes();
 
 
-		if(mChildren.size() != mOptimalSizes.size())
-			mOptimalSizes.resize(mChildren.size());
+		if(mChildren.size() != mChildSizeRanges.size())
+			mChildSizeRanges.resize(mChildren.size());
 
 
-		mOptimalWidth = 0;
-		mOptimalHeight = 0;
+		mSizeRange = LayoutSizeRange();
 
 
 		UINT32 childIdx = 0;
 		UINT32 childIdx = 0;
 		for(auto& child : mChildren)
 		for(auto& child : mChildren)
 		{
 		{
-			UINT32 optimalWidth = 0;
-			UINT32 optimalHeight = 0;
+			LayoutSizeRange& childSizeRange = mChildSizeRanges[childIdx];
 
 
 			if(child->_getType() == GUIElementBase::Type::FixedSpace)
 			if(child->_getType() == GUIElementBase::Type::FixedSpace)
 			{
 			{
 				GUIFixedSpace* fixedSpace = static_cast<GUIFixedSpace*>(child);
 				GUIFixedSpace* fixedSpace = static_cast<GUIFixedSpace*>(child);
-				optimalHeight = fixedSpace->_calculateOptimalLayoutSize().y;
+
+				childSizeRange = fixedSpace->_calculateLayoutSizeRange();
+				childSizeRange.optimal.x = 0;
+				childSizeRange.min.x = 0;
+				childSizeRange.max.x = 0;
 			}
 			}
 			else if(child->_getType() == GUIElementBase::Type::Element)
 			else if(child->_getType() == GUIElementBase::Type::Element)
 			{
 			{
 				GUIElement* element = static_cast<GUIElement*>(child);
 				GUIElement* element = static_cast<GUIElement*>(child);
 				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 
 
-				Vector2I optimalSize = child->_calculateOptimalLayoutSize();
-				optimalWidth = optimalSize.x;
-				optimalHeight = optimalSize.y;
+				childSizeRange = child->_calculateLayoutSizeRange();
 			}
 			}
 			else if(child->_getType() == GUIElementBase::Type::Layout)
 			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
 			{
 				GUILayout* layout = static_cast<GUILayout*>(child);
 				GUILayout* layout = static_cast<GUILayout*>(child);
-				optimalWidth = layout->_getOptimalSize().x;
-				optimalHeight = layout->_getOptimalSize().y;
+				childSizeRange = layout->_getCachedSizeRange();
 			}
 			}
 
 
 			UINT32 paddingX = child->_getPadding().left + child->_getPadding().right;
 			UINT32 paddingX = child->_getPadding().left + child->_getPadding().right;
 			UINT32 paddingY = child->_getPadding().top + child->_getPadding().bottom;
 			UINT32 paddingY = child->_getPadding().top + child->_getPadding().bottom;
 
 
-			mOptimalSizes[childIdx].y = optimalHeight;
-			mOptimalHeight += optimalHeight + paddingY;
+			mSizeRange.optimal.y += childSizeRange.optimal.y + paddingY;
+			mSizeRange.min.y += childSizeRange.min.y + paddingY;
+			mSizeRange.max.y += childSizeRange.max.y + paddingY;
 
 
-			mOptimalSizes[childIdx].x = optimalWidth;
-			mOptimalWidth = std::max(mOptimalWidth, optimalWidth + paddingX);
+			mSizeRange.optimal.x = std::max((UINT32)mSizeRange.optimal.x, childSizeRange.optimal.x + paddingX);
+			mSizeRange.min.x = std::max((UINT32)mSizeRange.min.x, childSizeRange.min.x + paddingX);
+			mSizeRange.max.x = std::max((UINT32)mSizeRange.max.x, childSizeRange.max.x + paddingX);
 
 
 			childIdx++;
 			childIdx++;
 		}
 		}
 	}
 	}
 
 
-	void GUILayoutY::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<Vector2I>& optimalSizes) const
+	void GUILayoutY::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, 
+		const Vector<LayoutSizeRange>& sizeRanges) const
 	{
 	{
 		assert(mChildren.size() == numElements);
 		assert(mChildren.size() == numElements);
 
 
@@ -111,7 +117,7 @@ namespace BansheeEngine
 		UINT32 childIdx = 0;
 		UINT32 childIdx = 0;
 		for (auto& child : mChildren)
 		for (auto& child : mChildren)
 		{
 		{
-			elementAreas[childIdx].height = optimalSizes[childIdx].y;
+			elementAreas[childIdx].height = sizeRanges[childIdx].optimal.y;
 
 
 			if (child->_getType() == GUIElementBase::Type::FixedSpace)
 			if (child->_getType() == GUIElementBase::Type::FixedSpace)
 			{
 			{
@@ -228,19 +234,18 @@ namespace BansheeEngine
 					UINT32 elementHeight = (UINT32)std::max(0, (INT32)elementAreas[childIdx].height - (INT32)extraHeight);
 					UINT32 elementHeight = (UINT32)std::max(0, (INT32)elementAreas[childIdx].height - (INT32)extraHeight);
 
 
 					// Clamp if needed
 					// Clamp if needed
-					if (child->_getType() == GUIElementBase::Type::Element)
+					if (child->_getType() == GUIElementBase::Type::Element || child->_getType() == GUIElementBase::Type::Layout)
 					{
 					{
-						GUIElement* element = static_cast<GUIElement*>(child);
-						const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
+						const LayoutSizeRange& childSizeRange = sizeRanges[childIdx];
 
 
 						if (elementHeight == 0)
 						if (elementHeight == 0)
 						{
 						{
 							processedElements[childIdx] = true;
 							processedElements[childIdx] = true;
 							numNonClampedElements--;
 							numNonClampedElements--;
 						}
 						}
-						else if (layoutOptions.minHeight > 0 && elementHeight < layoutOptions.minHeight)
+						else if (childSizeRange.min.y > 0 && (INT32)elementHeight < childSizeRange.min.y)
 						{
 						{
-							elementHeight = layoutOptions.minHeight;
+							elementHeight = childSizeRange.min.y;
 
 
 							processedElements[childIdx] = true;
 							processedElements[childIdx] = true;
 							numNonClampedElements--;
 							numNonClampedElements--;
@@ -250,18 +255,6 @@ namespace BansheeEngine
 						elementAreas[childIdx].height = elementHeight;
 						elementAreas[childIdx].height = elementHeight;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraHeight);
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraHeight);
 					}
 					}
-					else if (child->_getType() == GUIElementBase::Type::Layout)
-					{
-						if (elementHeight == 0)
-						{
-							processedElements[childIdx] = true;
-							numNonClampedElements--;
-						}
-
-						extraHeight = elementAreas[childIdx].height - elementHeight;
-						elementAreas[childIdx].height = elementHeight;
-						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraHeight);
-					}
 					else if (child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					else if (child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					{
 					{
 						elementAreas[childIdx].height = 0;
 						elementAreas[childIdx].height = 0;
@@ -298,19 +291,18 @@ namespace BansheeEngine
 					UINT32 elementHeight = elementAreas[childIdx].height + extraHeight;
 					UINT32 elementHeight = elementAreas[childIdx].height + extraHeight;
 
 
 					// Clamp if needed
 					// Clamp if needed
-					if (child->_getType() == GUIElementBase::Type::Element)
+					if (child->_getType() == GUIElementBase::Type::Element || child->_getType() == GUIElementBase::Type::Layout)
 					{
 					{
-						GUIElement* element = static_cast<GUIElement*>(child);
-						const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
+						const LayoutSizeRange& childSizeRange = sizeRanges[childIdx];
 
 
 						if (elementHeight == 0)
 						if (elementHeight == 0)
 						{
 						{
 							processedElements[childIdx] = true;
 							processedElements[childIdx] = true;
 							numNonClampedElements--;
 							numNonClampedElements--;
 						}
 						}
-						else if (layoutOptions.maxHeight > 0 && elementHeight > layoutOptions.maxHeight)
+						else if (childSizeRange.max.y > 0 && (INT32)elementHeight > childSizeRange.max.y)
 						{
 						{
-							elementHeight = layoutOptions.maxHeight;
+							elementHeight = childSizeRange.max.y;
 
 
 							processedElements[childIdx] = true;
 							processedElements[childIdx] = true;
 							numNonClampedElements--;
 							numNonClampedElements--;
@@ -320,11 +312,6 @@ namespace BansheeEngine
 						elementAreas[childIdx].height = elementHeight;
 						elementAreas[childIdx].height = elementHeight;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraHeight);
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraHeight);
 					}
 					}
-					else if (child->_getType() == GUIElementBase::Type::Layout)
-					{
-						elementAreas[childIdx].height = elementHeight;
-						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraHeight);
-					}
 					else if (child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					else if (child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					{
 					{
 						processedElements[childIdx] = true;
 						processedElements[childIdx] = true;
@@ -354,7 +341,7 @@ namespace BansheeEngine
 			if (child->_getType() == GUIElementBase::Type::Element)
 			if (child->_getType() == GUIElementBase::Type::Element)
 			{
 			{
 				GUIElement* element = static_cast<GUIElement*>(child);
 				GUIElement* element = static_cast<GUIElement*>(child);
-				UINT32 elemWidth = optimalSizes[childIdx].x;
+				UINT32 elemWidth = (UINT32)sizeRanges[childIdx].optimal.x;
 				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 				if (!layoutOptions.fixedWidth)
 				if (!layoutOptions.fixedWidth)
 				{
 				{
@@ -395,7 +382,7 @@ namespace BansheeEngine
 		if (numElements > 0)
 		if (numElements > 0)
 			elementAreas = stackConstructN<Rect2I>(numElements);
 			elementAreas = stackConstructN<Rect2I>(numElements);
 
 
-		_getElementAreas(x, y, width, height, elementAreas, numElements, mOptimalSizes);
+		_getElementAreas(x, y, width, height, elementAreas, numElements, mChildSizeRanges);
 
 
 		// Now that we have all the areas, actually assign them
 		// Now that we have all the areas, actually assign them
 		UINT32 childIdx = 0;
 		UINT32 childIdx = 0;

+ 8 - 8
BansheeEngine/Source/BsGUIScrollArea.cpp

@@ -51,14 +51,14 @@ namespace BansheeEngine
 		mClippedBounds = bounds;
 		mClippedBounds = bounds;
 	}
 	}
 
 
-	void GUIScrollArea::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<Vector2I>& optimalSizes) const
+	void GUIScrollArea::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, const Vector<LayoutSizeRange>& sizeRanges) const
 	{
 	{
 		Vector2I visibleSize, contentSize;
 		Vector2I visibleSize, contentSize;
-		_getElementAreas(x, y, width, height, elementAreas, numElements, optimalSizes, visibleSize, contentSize);
+		_getElementAreas(x, y, width, height, elementAreas, numElements, sizeRanges, visibleSize, contentSize);
 	}
 	}
 
 
 	void GUIScrollArea::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, 
 	void GUIScrollArea::_getElementAreas(INT32 x, INT32 y, UINT32 width, UINT32 height, Rect2I* elementAreas, UINT32 numElements, 
-		const Vector<Vector2I>& optimalSizes, Vector2I& visibleSize, Vector2I& contentSize) const
+		const Vector<LayoutSizeRange>& sizeRanges, Vector2I& visibleSize, Vector2I& contentSize) const
 	{
 	{
 		assert(mChildren.size() == numElements && numElements == 3);
 		assert(mChildren.size() == numElements && numElements == 3);
 
 
@@ -86,11 +86,11 @@ namespace BansheeEngine
 		//// technically provides "infinite" space
 		//// technically provides "infinite" space
 		UINT32 optimalContentWidth = width;
 		UINT32 optimalContentWidth = width;
 		if (mHorzBarType != ScrollBarType::NeverShow)
 		if (mHorzBarType != ScrollBarType::NeverShow)
-			optimalContentWidth = optimalSizes[layoutIdx].x;
+			optimalContentWidth = sizeRanges[layoutIdx].optimal.x;
 
 
 		UINT32 optimalContentHeight = height;
 		UINT32 optimalContentHeight = height;
 		if (mVertBarType != ScrollBarType::NeverShow)
 		if (mVertBarType != ScrollBarType::NeverShow)
-			optimalContentHeight = optimalSizes[layoutIdx].y;
+			optimalContentHeight = sizeRanges[layoutIdx].optimal.y;
 
 
 		UINT32 layoutWidth = std::max(optimalContentWidth, width);
 		UINT32 layoutWidth = std::max(optimalContentWidth, width);
 		UINT32 layoutHeight = std::max(optimalContentHeight, height);
 		UINT32 layoutHeight = std::max(optimalContentHeight, height);
@@ -195,14 +195,14 @@ namespace BansheeEngine
 		if (numElements > 0)
 		if (numElements > 0)
 			elementAreas = stackConstructN<Rect2I>(numElements);
 			elementAreas = stackConstructN<Rect2I>(numElements);
 
 
-		Vector<Vector2I> optimalSizes;
+		Vector<LayoutSizeRange> sizeRanges;
 		UINT32 layoutIdx = 0;
 		UINT32 layoutIdx = 0;
 		UINT32 horzScrollIdx = 0;
 		UINT32 horzScrollIdx = 0;
 		UINT32 vertScrollIdx = 0;
 		UINT32 vertScrollIdx = 0;
 		for (UINT32 i = 0; i < numElements; i++)
 		for (UINT32 i = 0; i < numElements; i++)
 		{
 		{
 			GUIElementBase* child = _getChild(i);
 			GUIElementBase* child = _getChild(i);
-			optimalSizes.push_back(GUILayoutUtility::calcOptimalSize(child));
+			sizeRanges.push_back(child->_calculateLayoutSizeRange());
 
 
 			if (child == mContentLayout)
 			if (child == mContentLayout)
 				layoutIdx = i;
 				layoutIdx = i;
@@ -214,7 +214,7 @@ namespace BansheeEngine
 				vertScrollIdx = i;
 				vertScrollIdx = i;
 		}
 		}
 
 
-		_getElementAreas(x, y, width, height, elementAreas, numElements, optimalSizes, mVisibleSize, mContentSize);
+		_getElementAreas(x, y, width, height, elementAreas, numElements, sizeRanges, mVisibleSize, mContentSize);
 
 
 		Rect2I& layoutBounds = elementAreas[layoutIdx];
 		Rect2I& layoutBounds = elementAreas[layoutIdx];
 		Rect2I& horzScrollBounds = elementAreas[horzScrollIdx];
 		Rect2I& horzScrollBounds = elementAreas[horzScrollIdx];

+ 24 - 0
BansheeEngine/Source/BsGUISpace.cpp

@@ -0,0 +1,24 @@
+#include "BsGUISpace.h"
+
+namespace BansheeEngine
+{
+	LayoutSizeRange GUIFixedSpace::_calculateLayoutSizeRange() const
+	{ 
+		LayoutSizeRange range;
+		range.optimal = _getOptimalSize();
+		range.min = range.optimal;
+		range.max = range.optimal;
+
+		return range;
+	}
+
+	LayoutSizeRange GUIFlexibleSpace::_calculateLayoutSizeRange() const
+	{
+		LayoutSizeRange range;
+		range.optimal = _getOptimalSize();
+		range.min = range.optimal;
+		range.max = range.optimal;
+
+		return range;
+	}
+}

+ 26 - 7
MBansheeEditor/ColorPicker.cs

@@ -86,8 +86,8 @@ namespace BansheeEditor
             : base(false)
             : base(false)
         {
         {
             Title = "Color Picker";
             Title = "Color Picker";
-            Width = 250;
-            Height = 75;
+            Width = 400;
+            Height = 800;
         }
         }
 
 
         private void OnInitialize()
         private void OnInitialize()
@@ -98,14 +98,16 @@ namespace BansheeEditor
             guiSliderRHorzTex = new GUITexture(null);
             guiSliderRHorzTex = new GUITexture(null);
             guiSliderGHorzTex = new GUITexture(null);
             guiSliderGHorzTex = new GUITexture(null);
             guiSliderBHorzTex = new GUITexture(null);
             guiSliderBHorzTex = new GUITexture(null);
+            guiSliderAHorzTex = new GUITexture(null);
 
 
             guiColorBoxBtn = new GUIButton(colorBoxMode.ToString());
             guiColorBoxBtn = new GUIButton(colorBoxMode.ToString());
             guiColorModeBtn = new GUIButton(sliderMode.ToString());
             guiColorModeBtn = new GUIButton(sliderMode.ToString());
 
 
-            guiSliderVert = new GUISliderV();
-            guiSliderRHorz = new GUISliderH();
-            guiSliderGHorz = new GUISliderH();
-            guiSliderBHorz = new GUISliderH();
+            guiSliderVert = new GUISliderV(EditorStyles.ColorSliderVert);
+            guiSliderRHorz = new GUISliderH(EditorStyles.ColorSliderHorz);
+            guiSliderGHorz = new GUISliderH(EditorStyles.ColorSliderHorz);
+            guiSliderBHorz = new GUISliderH(EditorStyles.ColorSliderHorz);
+            guiSliderAHorz = new GUISliderH(EditorStyles.ColorSliderHorz);
             guiSlider2DHandle = new GUITexture(null);
             guiSlider2DHandle = new GUITexture(null);
 
 
             guiLabelR = new GUILabel("R");
             guiLabelR = new GUILabel("R");
@@ -157,6 +159,8 @@ namespace BansheeEditor
             h2.AddFlexibleSpace();
             h2.AddFlexibleSpace();
             h2.AddElement(guiInputR);
             h2.AddElement(guiInputR);
 
 
+            v0.AddSpace(15);
+
             GUILayout h3 = v0.AddLayoutX();
             GUILayout h3 = v0.AddLayoutX();
             h3.AddElement(guiLabelG);
             h3.AddElement(guiLabelG);
             h3.AddFlexibleSpace();
             h3.AddFlexibleSpace();
@@ -164,6 +168,8 @@ namespace BansheeEditor
             h3.AddFlexibleSpace();
             h3.AddFlexibleSpace();
             h3.AddElement(guiInputG);
             h3.AddElement(guiInputG);
 
 
+            v0.AddSpace(15);
+
             GUILayout h4 = v0.AddLayoutX();
             GUILayout h4 = v0.AddLayoutX();
             h4.AddElement(guiLabelB);
             h4.AddElement(guiLabelB);
             h4.AddFlexibleSpace();
             h4.AddFlexibleSpace();
@@ -171,11 +177,21 @@ namespace BansheeEditor
             h4.AddFlexibleSpace();
             h4.AddFlexibleSpace();
             h4.AddElement(guiInputB);
             h4.AddElement(guiInputB);
 
 
+            v0.AddSpace(15);
+
+            GUILayout h5 = v0.AddLayoutX();
+            h5.AddElement(guiLabelA);
+            h5.AddFlexibleSpace();
+            h5.AddElement(guiSliderAHorzTex);
+            h5.AddFlexibleSpace();
+            h5.AddElement(guiInputA);
+
             GUIArea overlay = GUI.AddArea(0, 0, Width, Height, -1, GUILayoutType.Explicit);
             GUIArea overlay = GUI.AddArea(0, 0, Width, Height, -1, GUILayoutType.Explicit);
             overlay.layout.AddElement(guiSliderVert);
             overlay.layout.AddElement(guiSliderVert);
             overlay.layout.AddElement(guiSliderRHorz);
             overlay.layout.AddElement(guiSliderRHorz);
             overlay.layout.AddElement(guiSliderGHorz);
             overlay.layout.AddElement(guiSliderGHorz);
             overlay.layout.AddElement(guiSliderBHorz);
             overlay.layout.AddElement(guiSliderBHorz);
+            overlay.layout.AddElement(guiSliderAHorz);
             overlay.layout.AddElement(guiSlider2DHandle);
             overlay.layout.AddElement(guiSlider2DHandle);
 
 
             colorBox = new ColorSlider2D(guiSlider2DTex, guiSlider2DHandle, ColorBoxWidth, ColorBoxHeight);
             colorBox = new ColorSlider2D(guiSlider2DTex, guiSlider2DHandle, ColorBoxWidth, ColorBoxHeight);
@@ -198,13 +214,16 @@ namespace BansheeEditor
             Color startA = new Color(0, 0, 0, 1);
             Color startA = new Color(0, 0, 0, 1);
             Color stepA = new Color(1, 1, 1, 0);
             Color stepA = new Color(1, 1, 1, 0);
             sliderA.UpdateTexture(startA, stepA, false);
             sliderA.UpdateTexture(startA, stepA, false);
+            guiInputA.SetRange(0, 255);
         }
         }
 
 
-        private void EditorUpdate()
+        private void OnEditorUpdate()
         {
         {
             Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition);
             Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition);
 
 
             colorBox.UpdateInput(windowPos);
             colorBox.UpdateInput(windowPos);
+
+            Debug.Log(Width + " - " + Height + " - " + GUI.childAreas[0].mCachedPtr);
         }
         }
 
 
         private static void FillArea(int width, int height, Color[] colors, Color start, Color rightGradient, Color downGradient)
         private static void FillArea(int width, int height, Color[] colors, Color start, Color rightGradient, Color downGradient)

+ 1 - 0
MBansheeEditor/EditorApplication.cs

@@ -96,6 +96,7 @@ namespace BansheeEditor
             gizmoDbgObject.AddComponent<DbgGizmoComponent>();
             gizmoDbgObject.AddComponent<DbgGizmoComponent>();
 
 
             //ProgressBar.Show("Test", 0.5f);
             //ProgressBar.Show("Test", 0.5f);
+            ColorPicker.Show();
 
 
             // DEBUG ONLY END
             // DEBUG ONLY END
         }
         }

+ 4 - 4
SBansheeEngine/Source/BsScriptInput.cpp

@@ -44,10 +44,10 @@ namespace BansheeEngine
 		OnButtonPressedThunk = (OnButtonEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerButtonDown", "ButtonCode,int")->getThunk();
 		OnButtonPressedThunk = (OnButtonEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerButtonDown", "ButtonCode,int")->getThunk();
 		OnButtonReleasedThunk = (OnButtonEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerButtonUp", "ButtonCode,int")->getThunk();
 		OnButtonReleasedThunk = (OnButtonEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerButtonUp", "ButtonCode,int")->getThunk();
 		OnCharInputThunk = (OnCharInputEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerCharInput", "int")->getThunk();
 		OnCharInputThunk = (OnCharInputEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerCharInput", "int")->getThunk();
-		OnPointerPressedThunk = (OnPointerEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerPointerPressed", "Vector2I,Vector2I,PointerEventButton,bool,bool,bool,single")->getThunk();
-		OnPointerReleasedThunk = (OnPointerEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerPointerReleased", "Vector2I,Vector2I,PointerEventButton,bool,bool,bool,single")->getThunk();
-		OnPointerMovedThunk = (OnPointerEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerPointerMove", "Vector2I,Vector2I,PointerEventButton,bool,bool,bool,single")->getThunk();
-		OnPointerDoubleClickThunk = (OnPointerEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerPointerDoubleClick", "Vector2I,Vector2I,PointerEventButton,bool,bool,bool,single")->getThunk();
+		OnPointerPressedThunk = (OnPointerEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerPointerPressed", "Vector2I,Vector2I,PointerButton,bool,bool,bool,single")->getThunk();
+		OnPointerReleasedThunk = (OnPointerEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerPointerReleased", "Vector2I,Vector2I,PointerButton,bool,bool,bool,single")->getThunk();
+		OnPointerMovedThunk = (OnPointerEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerPointerMove", "Vector2I,Vector2I,PointerButton,bool,bool,bool,single")->getThunk();
+		OnPointerDoubleClickThunk = (OnPointerEventThunkDef)metaData.scriptClass->getMethodExact("Internal_TriggerPointerDoubleClick", "Vector2I,Vector2I,PointerButton,bool,bool,bool,single")->getThunk();
 	}
 	}
 
 
 	void ScriptInput::startUp()
 	void ScriptInput::startUp()

+ 1 - 0
SBansheeEngine/Source/BsScriptTexture2D.cpp

@@ -94,6 +94,7 @@ namespace BansheeEngine
 		const TextureProperties& props = texture->getProperties();
 		const TextureProperties& props = texture->getProperties();
 
 
 		PixelDataPtr pixelData = bs_shared_ptr<PixelData>(props.getWidth(), props.getHeight(), props.getDepth(), props.getFormat());
 		PixelDataPtr pixelData = bs_shared_ptr<PixelData>(props.getWidth(), props.getHeight(), props.getDepth(), props.getFormat());
+		pixelData->allocateInternalBuffer();
 		pixelData->setColors(colorsRaw, numElements);
 		pixelData->setColors(colorsRaw, numElements);
 
 
 		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);
 		UINT32 subresourceIdx = texture->getProperties().mapToSubresourceIdx(0, mipLevel);

+ 5 - 0
TODO.txt

@@ -10,6 +10,11 @@ Possibly set up automatic refresh in debug mode after initialization? As an ad-h
 C#:
 C#:
 Dialog.Show(title, text, btn1 text, btn1 callback, btn2 text, btn2 callback, btn3 text, btn3 callback)
 Dialog.Show(title, text, btn1 text, btn1 callback, btn2 text, btn2 callback, btn3 text, btn3 callback)
 
 
+ColorPicker
+ - Add OK button
+ - GUI elements are all cut off and I cannot see the sliders
+ - Input range limit on int fields seems broken. As I enter larger values they seem to overflow to other fields?
+
 Got a crash on shutdown that was caused by locking a mutex in an Event destructor. Event was Platform::onMouseCaptureChanged. 
 Got a crash on shutdown that was caused by locking a mutex in an Event destructor. Event was Platform::onMouseCaptureChanged. 
 Issue happened when I closed the app via the X button (if that's relevant). It doesn't seem to happen always.
 Issue happened when I closed the app via the X button (if that's relevant). It doesn't seem to happen always.