浏览代码

Improved performance by simpler and faster GUI element material management

BearishSun 10 年之前
父节点
当前提交
d8241a1166
共有 36 个文件被更改,包括 849 次插入1154 次删除
  1. 5 5
      BansheeEditor/Include/BsGUIColor.h
  2. 3 3
      BansheeEditor/Source/BsGUIColor.cpp
  3. 0 3
      BansheeEngine/BansheeEngine.vcxproj
  4. 0 9
      BansheeEngine/BansheeEngine.vcxproj.filters
  5. 3 4
      BansheeEngine/Include/BsBuiltinResources.h
  6. 5 5
      BansheeEngine/Include/BsGUIButtonBase.h
  7. 2 1
      BansheeEngine/Include/BsGUIElement.h
  8. 0 1
      BansheeEngine/Include/BsGUIElementBase.h
  9. 5 5
      BansheeEngine/Include/BsGUIElementContainer.h
  10. 5 5
      BansheeEngine/Include/BsGUIInputBox.h
  11. 5 5
      BansheeEngine/Include/BsGUILabel.h
  12. 34 11
      BansheeEngine/Include/BsGUIManager.h
  13. 0 18
      BansheeEngine/Include/BsGUIMaterialInfo.h
  14. 0 109
      BansheeEngine/Include/BsGUIMaterialManager.h
  15. 5 5
      BansheeEngine/Include/BsGUIScrollBar.h
  16. 175 175
      BansheeEngine/Include/BsGUISliderHandle.h
  17. 5 5
      BansheeEngine/Include/BsGUITexture.h
  18. 6 6
      BansheeEngine/Include/BsGUIViewport.h
  19. 1 0
      BansheeEngine/Include/BsPrerequisites.h
  20. 66 11
      BansheeEngine/Include/BsSprite.h
  21. 1 0
      BansheeEngine/Include/BsTextSprite.h
  22. 1 5
      BansheeEngine/Source/BsApplication.cpp
  23. 6 25
      BansheeEngine/Source/BsBuiltinResources.cpp
  24. 4 4
      BansheeEngine/Source/BsGUIButtonBase.cpp
  25. 1 1
      BansheeEngine/Source/BsGUIElementContainer.cpp
  26. 2 2
      BansheeEngine/Source/BsGUIInputBox.cpp
  27. 2 2
      BansheeEngine/Source/BsGUILabel.cpp
  28. 65 47
      BansheeEngine/Source/BsGUIManager.cpp
  29. 0 193
      BansheeEngine/Source/BsGUIMaterialManager.cpp
  30. 2 2
      BansheeEngine/Source/BsGUIScrollBar.cpp
  31. 400 400
      BansheeEngine/Source/BsGUISliderHandle.cpp
  32. 2 2
      BansheeEngine/Source/BsGUITexture.cpp
  33. 1 1
      BansheeEngine/Source/BsGUIViewport.cpp
  34. 5 42
      BansheeEngine/Source/BsImageSprite.cpp
  35. 27 3
      BansheeEngine/Source/BsSprite.cpp
  36. 5 39
      BansheeEngine/Source/BsTextSprite.cpp

+ 5 - 5
BansheeEditor/Include/BsGUIColor.h

@@ -60,22 +60,22 @@ namespace BansheeEngine
 		virtual ~GUIColor();
 		virtual ~GUIColor();
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumRenderElements()
+		 * @copydoc GUIElement::_getNumRenderElements()
 		 */
 		 */
 		virtual UINT32 _getNumRenderElements() const override;
 		virtual UINT32 _getNumRenderElements() const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getMaterial()
+		 * @copydoc GUIElement::_getMaterial()
 		 */
 		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
+		virtual const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumQuads()
+		 * @copydoc GUIElement::_getNumQuads()
 		 */
 		 */
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::fillBuffer()
+		 * @copydoc GUIElement::_fillBuffer()
 		 */
 		 */
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;

+ 3 - 3
BansheeEditor/Source/BsGUIColor.cpp

@@ -63,14 +63,14 @@ namespace BansheeEngine
 		return numElements;
 		return numElements;
 	}
 	}
 
 
-	const GUIMaterialInfo& GUIColor::_getMaterial(UINT32 renderElementIdx) const
+	const SpriteMaterialInfo& GUIColor::_getMaterial(UINT32 renderElementIdx) const
 	{
 	{
 		UINT32 alphaSpriteIdx = mColorSprite->getNumRenderElements();
 		UINT32 alphaSpriteIdx = mColorSprite->getNumRenderElements();
 
 
 		if(renderElementIdx >= alphaSpriteIdx)
 		if(renderElementIdx >= alphaSpriteIdx)
-			return mAlphaSprite->getMaterial(alphaSpriteIdx - renderElementIdx);
+			return mAlphaSprite->getMaterialInfo(alphaSpriteIdx - renderElementIdx);
 		else
 		else
-			return mColorSprite->getMaterial(renderElementIdx);
+			return mColorSprite->getMaterialInfo(renderElementIdx);
 	}
 	}
 
 
 	UINT32 GUIColor::_getNumQuads(UINT32 renderElementIdx) const
 	UINT32 GUIColor::_getNumQuads(UINT32 renderElementIdx) const

+ 0 - 3
BansheeEngine/BansheeEngine.vcxproj

@@ -342,7 +342,6 @@
     <ClInclude Include="Include\BsGUIElementBase.h" />
     <ClInclude Include="Include\BsGUIElementBase.h" />
     <ClInclude Include="Include\BsGUIInputTool.h" />
     <ClInclude Include="Include\BsGUIInputTool.h" />
     <ClInclude Include="Include\BsGUIInputBox.h" />
     <ClInclude Include="Include\BsGUIInputBox.h" />
-    <ClInclude Include="Include\BsGUIMaterialInfo.h" />
     <ClInclude Include="Include\BsGUIOptions.h" />
     <ClInclude Include="Include\BsGUIOptions.h" />
     <ClInclude Include="Include\BsGUIRenderTexture.h" />
     <ClInclude Include="Include\BsGUIRenderTexture.h" />
     <ClInclude Include="Include\BsGUITextInputEvent.h" />
     <ClInclude Include="Include\BsGUITextInputEvent.h" />
@@ -369,7 +368,6 @@
     <ClInclude Include="Include\BsGUIElementStyle.h" />
     <ClInclude Include="Include\BsGUIElementStyle.h" />
     <ClInclude Include="Include\BsGUILabel.h" />
     <ClInclude Include="Include\BsGUILabel.h" />
     <ClInclude Include="Include\BsGUIManager.h" />
     <ClInclude Include="Include\BsGUIManager.h" />
-    <ClInclude Include="Include\BsGUIMaterialManager.h" />
     <ClInclude Include="Include\BsGUIMouseEvent.h" />
     <ClInclude Include="Include\BsGUIMouseEvent.h" />
     <ClInclude Include="Include\BsGUISkin.h" />
     <ClInclude Include="Include\BsGUISkin.h" />
     <ClInclude Include="Include\BsCGUIWidget.h" />
     <ClInclude Include="Include\BsCGUIWidget.h" />
@@ -426,7 +424,6 @@
     <ClCompile Include="Source\BsGUILayout.cpp" />
     <ClCompile Include="Source\BsGUILayout.cpp" />
     <ClCompile Include="Source\BsGUILayoutY.cpp" />
     <ClCompile Include="Source\BsGUILayoutY.cpp" />
     <ClCompile Include="Source\BsGUIManager.cpp" />
     <ClCompile Include="Source\BsGUIManager.cpp" />
-    <ClCompile Include="Source\BsGUIMaterialManager.cpp" />
     <ClCompile Include="Source\BsGUIMouseEvent.cpp" />
     <ClCompile Include="Source\BsGUIMouseEvent.cpp" />
     <ClCompile Include="Source\BsGUIScrollBar.cpp" />
     <ClCompile Include="Source\BsGUIScrollBar.cpp" />
     <ClCompile Include="Source\BsGUISliderHandle.cpp" />
     <ClCompile Include="Source\BsGUISliderHandle.cpp" />

+ 0 - 9
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -56,9 +56,6 @@
     <ClInclude Include="Include\BsGUIManager.h">
     <ClInclude Include="Include\BsGUIManager.h">
       <Filter>Header Files\GUI</Filter>
       <Filter>Header Files\GUI</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="Include\BsGUIMaterialManager.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsGUISkin.h">
     <ClInclude Include="Include\BsGUISkin.h">
       <Filter>Header Files\GUI</Filter>
       <Filter>Header Files\GUI</Filter>
     </ClInclude>
     </ClInclude>
@@ -176,9 +173,6 @@
     <ClInclude Include="Include\BsGUIRenderTexture.h">
     <ClInclude Include="Include\BsGUIRenderTexture.h">
       <Filter>Header Files\GUI</Filter>
       <Filter>Header Files\GUI</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="Include\BsGUIMaterialInfo.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsScriptManager.h">
     <ClInclude Include="Include\BsScriptManager.h">
       <Filter>Header Files\Script</Filter>
       <Filter>Header Files\Script</Filter>
     </ClInclude>
     </ClInclude>
@@ -382,9 +376,6 @@
     <ClCompile Include="Source\BsGUIManager.cpp">
     <ClCompile Include="Source\BsGUIManager.cpp">
       <Filter>Source Files\GUI</Filter>
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="Source\BsGUIMaterialManager.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
     <ClCompile Include="Source\BsGUISkin.cpp">
     <ClCompile Include="Source\BsGUISkin.cpp">
       <Filter>Source Files\GUI</Filter>
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
     </ClCompile>

+ 3 - 4
BansheeEngine/Include/BsBuiltinResources.h

@@ -4,7 +4,6 @@
 #include "BsGUISkin.h"
 #include "BsGUISkin.h"
 #include "BsModule.h"
 #include "BsModule.h"
 #include "BsVector2I.h"
 #include "BsVector2I.h"
-#include "BsGUIMaterialInfo.h"
 #include "BsApplication.h"
 #include "BsApplication.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
@@ -114,17 +113,17 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @brief	Creates material used for textual sprite rendering (e.g. text in GUI).
 		 * @brief	Creates material used for textual sprite rendering (e.g. text in GUI).
 		 */
 		 */
-		GUIMaterialInfo createSpriteTextMaterial() const;
+		HMaterial createSpriteTextMaterial() const;
 
 
 		/**
 		/**
 		 * @brief	Creates material used for image sprite rendering (e.g. images in GUI).
 		 * @brief	Creates material used for image sprite rendering (e.g. images in GUI).
 		 */
 		 */
-		GUIMaterialInfo createSpriteImageMaterial() const;
+		HMaterial createSpriteImageMaterial() const;
 
 
 		/**
 		/**
 		* @brief	Creates material used for non-transparent image sprite rendering (e.g. images in GUI).
 		* @brief	Creates material used for non-transparent image sprite rendering (e.g. images in GUI).
 		*/
 		*/
-		GUIMaterialInfo createSpriteNonAlphaImageMaterial() const;
+		HMaterial createSpriteNonAlphaImageMaterial() const;
 
 
 		/**
 		/**
 		 * @brief	Retrieves one of the builtin meshes.
 		 * @brief	Retrieves one of the builtin meshes.

+ 5 - 5
BansheeEngine/Include/BsGUIButtonBase.h

@@ -73,22 +73,22 @@ namespace BansheeEngine
 		virtual ~GUIButtonBase();
 		virtual ~GUIButtonBase();
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumRenderElements
+		 * @copydoc GUIElement::_getNumRenderElements
 		 */
 		 */
 		virtual UINT32 _getNumRenderElements() const override;
 		virtual UINT32 _getNumRenderElements() const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getMaterial
+		 * @copydoc GUIElement::_getMaterial
 		 */
 		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
+		virtual const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumQuads
+		 * @copydoc GUIElement::_getNumQuads
 		 */
 		 */
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::fillBuffer
+		 * @copydoc GUIElement::_fillBuffer
 		 */
 		 */
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;

+ 2 - 1
BansheeEngine/Include/BsGUIElement.h

@@ -5,6 +5,7 @@
 #include "BsGUIOptions.h"
 #include "BsGUIOptions.h"
 #include "BsRect2I.h"
 #include "BsRect2I.h"
 #include "BsVector2I.h"
 #include "BsVector2I.h"
+#include "BsColor.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -102,7 +103,7 @@ namespace BansheeEngine
 		 *
 		 *
 		 * @note	Internal method.
 		 * @note	Internal method.
 		 */
 		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const = 0;
+		virtual const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx) const = 0;
 
 
 		/**
 		/**
 		 * @brief	Returns the number of quads that the specified render element will use. You will need this
 		 * @brief	Returns the number of quads that the specified render element will use. You will need this

+ 0 - 1
BansheeEngine/Include/BsGUIElementBase.h

@@ -1,7 +1,6 @@
 #pragma once
 #pragma once
 
 
 #include "BsPrerequisites.h"
 #include "BsPrerequisites.h"
-#include "BsGUIMaterialInfo.h"
 #include "BsGUIDimensions.h"
 #include "BsGUIDimensions.h"
 #include "BsGUILayoutData.h"
 #include "BsGUILayoutData.h"
 #include "BsRect2I.h"
 #include "BsRect2I.h"

+ 5 - 5
BansheeEngine/Include/BsGUIElementContainer.h

@@ -16,22 +16,22 @@ namespace BansheeEngine
 		virtual ~GUIElementContainer();
 		virtual ~GUIElementContainer();
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumRenderElements
+		 * @copydoc GUIElement::_getNumRenderElements
 		 */
 		 */
 		virtual UINT32 _getNumRenderElements() const override;
 		virtual UINT32 _getNumRenderElements() const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getMaterial
+		 * @copydoc GUIElement::_getMaterial
 		 */
 		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
+		virtual const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumQuads
+		 * @copydoc GUIElement::_getNumQuads
 		 */
 		 */
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::fillBuffer
+		 * @copydoc GUIElement::_fillBuffer
 		 */
 		 */
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;

+ 5 - 5
BansheeEngine/Include/BsGUIInputBox.h

@@ -105,22 +105,22 @@ namespace BansheeEngine
 		virtual ~GUIInputBox();
 		virtual ~GUIInputBox();
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumRenderElements()
+		 * @copydoc GUIElement::_getNumRenderElements()
 		 */
 		 */
 		virtual UINT32 _getNumRenderElements() const override;
 		virtual UINT32 _getNumRenderElements() const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getMaterial()
+		 * @copydoc GUIElement::_getMaterial()
 		 */
 		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
+		virtual const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumQuads()
+		 * @copydoc GUIElement::_getNumQuads()
 		 */
 		 */
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::fillBuffer()
+		 * @copydoc GUIElement::_fillBuffer()
 		 */
 		 */
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;

+ 5 - 5
BansheeEngine/Include/BsGUILabel.h

@@ -80,22 +80,22 @@ namespace BansheeEngine
 		~GUILabel();
 		~GUILabel();
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumRenderElements
+		 * @copydoc GUIElement::_getNumRenderElements
 		 */
 		 */
 		virtual UINT32 _getNumRenderElements() const override;
 		virtual UINT32 _getNumRenderElements() const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getMaterial
+		 * @copydoc GUIElement::_getMaterial
 		 */
 		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
+		virtual const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumQuads
+		 * @copydoc GUIElement::_getNumQuads
 		 */
 		 */
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::fillBuffer
+		 * @copydoc GUIElement::_fillBuffer
 		 */
 		 */
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;

+ 34 - 11
BansheeEngine/Include/BsGUIManager.h

@@ -5,11 +5,12 @@
 #include "BsGUITextInputEvent.h"
 #include "BsGUITextInputEvent.h"
 #include "BsGUICommandEvent.h"
 #include "BsGUICommandEvent.h"
 #include "BsGUIVirtualButtonEvent.h"
 #include "BsGUIVirtualButtonEvent.h"
-#include "BsGUIMaterialInfo.h"
+#include "BsSprite.h"
 #include "BsModule.h"
 #include "BsModule.h"
 #include "BsColor.h"
 #include "BsColor.h"
-#include "BsInput.h"
+#include "BsMatrix4.h"
 #include "BsEvent.h"
 #include "BsEvent.h"
+#include "BsMaterialParam.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -52,7 +53,7 @@ namespace BansheeEngine
 			{ }
 			{ }
 
 
 			Vector<TransientMeshPtr> cachedMeshes;
 			Vector<TransientMeshPtr> cachedMeshes;
-			Vector<GUIMaterialInfo> cachedMaterials;
+			Vector<SpriteMaterialInfo> cachedMaterials;
 			Vector<CGUIWidget*> cachedWidgetsPerMesh;
 			Vector<CGUIWidget*> cachedWidgetsPerMesh;
 			Vector<CGUIWidget*> widgets;
 			Vector<CGUIWidget*> widgets;
 			bool isDirty;
 			bool isDirty;
@@ -64,7 +65,9 @@ namespace BansheeEngine
 		struct GUICoreRenderData
 		struct GUICoreRenderData
 		{
 		{
 			SPtr<TransientMeshCore> mesh;
 			SPtr<TransientMeshCore> mesh;
-			SPtr<MaterialCore> material;
+			SPtr<TextureCore> texture;
+			SpriteMaterial materialType;
+			Color tint;
 			Matrix4 worldTransform;
 			Matrix4 worldTransform;
 		};
 		};
 
 
@@ -458,22 +461,35 @@ namespace BansheeEngine
 	{
 	{
 		friend class GUIManager;
 		friend class GUIManager;
 
 
-		/**
-		 * @brief	Contains mesh & material data for a group of GUI elements.
-		 */
-		struct RenderData
+		/** Material reference and parameter handles for a specific material type. */
+		struct MaterialInfo
 		{
 		{
-			SPtr<TransientMeshCore> mesh;
+			MaterialInfo() { }
+			MaterialInfo(const SPtr<MaterialCore>& material);
+
 			SPtr<MaterialCore> material;
 			SPtr<MaterialCore> material;
-			Matrix4 worldTransform;
 
 
 			MaterialParamMat4Core worldTransformParam;
 			MaterialParamMat4Core worldTransformParam;
 			MaterialParamFloatCore invViewportWidthParam;
 			MaterialParamFloatCore invViewportWidthParam;
 			MaterialParamFloatCore invViewportHeightParam;
 			MaterialParamFloatCore invViewportHeightParam;
+			MaterialParamColorCore tintParam;
+			MaterialParamTextureCore textureParam;
+			MaterialParamSampStateCore samplerParam;
 		};
 		};
+
 	public:
 	public:
 		~GUIManagerCore();
 		~GUIManagerCore();
 
 
+		/**
+		 * Initializes the object. Must be called right after construction.
+		 *
+		 * @param[in]	textMat			Material used for drawing text sprites.
+		 * @param[in]	imageMat		Material used for drawing non-transparent image sprites.
+		 * @param[in]	imageAlphaMat	Material used for drawing transparent image sprites.
+		 */
+		void initialize(const SPtr<MaterialCore>& textMat, const SPtr<MaterialCore>& imageMat,
+			const SPtr<MaterialCore>& imageAlphaMat);
+
 	private:
 	private:
 		/**
 		/**
 		 * @brief	Updates the internal data that determines what will be rendered on the next
 		 * @brief	Updates the internal data that determines what will be rendered on the next
@@ -488,7 +504,14 @@ namespace BansheeEngine
 		 */
 		 */
 		void render(const SPtr<CameraCore>& camera);
 		void render(const SPtr<CameraCore>& camera);
 
 
-		UnorderedMap<SPtr<CameraCore>, Vector<RenderData>> mPerCameraData;
+		UnorderedMap<SPtr<CameraCore>, Vector<GUIManager::GUICoreRenderData>> mPerCameraData;
+
+		// Immutable
+		MaterialInfo mTextMaterialInfo;
+		MaterialInfo mImageMaterialInfo;
+		MaterialInfo mImageAlphaMaterialInfo;
+
+		SPtr<SamplerStateCore> mSamplerState;
 	};
 	};
 
 
 	/**
 	/**

+ 0 - 18
BansheeEngine/Include/BsGUIMaterialInfo.h

@@ -1,18 +0,0 @@
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsMaterialParam.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Container for data about a GUI element material.
-	 */
-	struct GUIMaterialInfo
-	{
-		HMaterial material;
-		MaterialParamSampState mainTexSampler;
-		MaterialParamTexture mainTexture;
-		MaterialParamVec4 tint;
-	};
-}

+ 0 - 109
BansheeEngine/Include/BsGUIMaterialManager.h

@@ -1,109 +0,0 @@
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsGUIMaterialInfo.h"
-#include "BsModule.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Manages the materials used by the GUI system. Ensures that the GUI system doesn't
-	 * 			create an unnecessarily large amount of equivalent materials.
-	 */
-	class BS_EXPORT GUIMaterialManager : public Module<GUIMaterialManager>
-	{
-	public:
-		GUIMaterialManager();
-
-		/**
-		 * @brief	Creates a new material, or returns a reference to an existing one based on
-		 * 			the provided primary texture, tint and group id.
-		 * 			
-		 *			Returned material can be used for text rendering.
-		 *			
-		 *			Make sure to release all materials with a call to "releaseMaterial()".
-		 *
-		 *  @note	Group ID allows you to force the system to return different materials even if texture and tint could
-		 *			otherwise be shared. Sometimes you need this if you know other material properties (like world transform)
-		 *			won't be shared.
-		 */
-		const GUIMaterialInfo& requestTextMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
-
-		/**
-		 * @brief	Creates a new material, or returns a reference to an existing one based on
-		 * 			the provided primary texture, tint and group id.
-		 * 			
-		 *			Returned material can be used for normal image rendering.
-		 *			
-		 *			Make sure to release all materials with a call to "releaseMaterial()".
-		 *
-		 *  @note	Group ID allows you to force the system to return different materials even if texture and tint could
-		 *			otherwise be shared. Sometimes you need this if you know other material properties (like world transform)
-		 *			won't be shared.
-		 */
-		const GUIMaterialInfo& requestImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
-
-		/**
-		 * @brief	Creates a new material, or returns a reference to an existing one based on
-		 * 			the provided primary texture, tint and group id.
-		 * 			
-		 *			Returned material can be used for non-transparent image rendering.
-		 *			
-		 *			Make sure to release all materials with a call to "releaseMaterial()".
-		 *
-		 * @note	Group ID allows you to force the system to return different materials even if texture and tint could
-		 *			otherwise be shared. Sometimes you need this if you know other material properties (like world transform)
-		 *			won't be shared.
-		 */
-		const GUIMaterialInfo& requestNonAlphaImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
-
-		/**
-		 * @brief	Releases the held reference to the material. This allows us to fully unload a material
-		 * 			and their textures when they are no longer being used.
-		 */
-		void releaseMaterial(const GUIMaterialInfo& material) const;
-
-		/**
-		 * @brief	Attempts to find an existing text material with the specified color and tint. Returns null
-		 *			if one cannot be found.
-		 */
-		const GUIMaterialInfo* findExistingTextMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
-
-		/**
-		 * @brief	Attempts to find an existing image material with the specified color and tint. Returns null
-		 *			if one cannot be found.
-		 */
-		const GUIMaterialInfo* findExistingImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
-
-		/**
-		 * @brief	Attempts to find an existing non-transparent image material with the specified color and tint.
-		 *			Returns null if one cannot be found.
-		 */
-		const GUIMaterialInfo* findExistingNonAlphaImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
-
-		/**
-		 * @brief	Releases all internal materials, whether they are used or not.
-		 */
-		void clearMaterials();
-	private:
-		/**
-		 * @brief	Contains data about a GUI material and its usage count.
-		 */
-		struct GUIMaterial
-		{
-			GUIMaterial()
-				:refCount(0)
-			{ }
-
-			UINT64 groupId;
-			GUIMaterialInfo handle;
-			UINT32 refCount;
-		};
-
-		SamplerStatePtr mGUISamplerState;
-
-		mutable Vector<GUIMaterial> mTextMaterials;
-		mutable Vector<GUIMaterial> mImageMaterials;
-		mutable Vector<GUIMaterial> mNonAlphaImageMaterials;
-	};
-}

+ 5 - 5
BansheeEngine/Include/BsGUIScrollBar.h

@@ -79,22 +79,22 @@ namespace BansheeEngine
 		virtual ~GUIScrollBar();
 		virtual ~GUIScrollBar();
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumRenderElements
+		 * @copydoc GUIElement::_getNumRenderElements
 		 */
 		 */
 		virtual UINT32 _getNumRenderElements() const override;
 		virtual UINT32 _getNumRenderElements() const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getMaterial
+		 * @copydoc GUIElement::_getMaterial
 		 */
 		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
+		virtual const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumQuads
+		 * @copydoc GUIElement::_getNumQuads
 		 */
 		 */
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::fillBuffer
+		 * @copydoc GUIElement::_fillBuffer
 		 */
 		 */
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;

+ 175 - 175
BansheeEngine/Include/BsGUISliderHandle.h

@@ -1,176 +1,176 @@
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsGUIElement.h"
-#include "BsImageSprite.h"
-#include "BsEvent.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	A handle that can be dragged from its predefined minimum and maximum position,
-	 *			either horizontally or vertically.
-	 */
-	class BS_EXPORT GUISliderHandle : public GUIElement
-	{
-		/**
-		 * @brief	Visual state of the handle
-		 */
-		enum class State
-		{
-			Normal, Hover, Active
-		};
-
-	public:
-		/**
-		 * Returns type name of the GUI element used for finding GUI element styles. 
-		 */
-		static const String& getGUITypeName();
-
-		/**
-		 * @brief	Creates a new handle.
-		 *
-		 * @param	horizontal		Should the handle be movable vertically or horizontally.
-		 * @param	jumpOnClick		If true clicking on a specific position on the slider will cause
-		 *							the slider handle to jump to that position. Otherwise the slider
-		 *							will just slightly move towards that direction.
-		 * @param	styleName		Optional style to use for the element. Style will be retrieved
-		 *							from GUISkin of the GUIWidget the element is used on. If not specified
-		 *							default style is used.
-		 */
-		static GUISliderHandle* create(bool horizontal, bool jumpOnClick, const String& styleName = StringUtil::BLANK);
-
-		/**
-		 * @brief	Creates a new handle.
-		 *
-		 * @param	horizontal		Should the handle be movable vertically or horizontally.
-		 * @param	jumpOnClick		If true clicking on a specific position on the slider will cause
-		 *							the slider handle to jump to that position. Otherwise the slider
-		 *							will just slightly move towards that direction.
-		 * @param	options			Options that allow you to control how is the element positioned and sized.
-		 *							This will override any similar options set by style.
-		 * @param	styleName		Optional style to use for the element. Style will be retrieved
-		 *							from GUISkin of the GUIWidget the element is used on. If not specified
-		 *							default style is used.
-		 */
-		static GUISliderHandle* create(bool horizontal, bool jumpOnClick, const GUIOptions& options,
-			const String& styleName = StringUtil::BLANK);
-
-		/**
-		 * @brief	Size of the handle in pixels, along the handle drag direction.
-		 *
-		 * @note	Internal method. Does not trigger layout update.
-		 */
-		void _setHandleSize(UINT32 size);
-
-		/**
-		 * @brief	Moves the handle the the specified position in the handle area.
-		 *
-		 * @param	pct	Position to move the handle to, in percent ranging [0.0f, 1.0f]
-		 *
-		 * @note	Internal method. Does not trigger layout update.
-		 */
-		void _setHandlePos(float pct);
-
-		/**
-		 * @brief	Gets the current position of the handle, in percent ranging [0.0f, 1.0f].
-		 */
-		float getHandlePos() const;
-
-		/**
-		 * @brief	Returns the position of the slider handle, in pixels. Relative to this object.
-		 */
-		INT32 getHandlePosPx() const;
-
-		/**
-		 * @brief	Returns remaining length of the scrollable area not covered by the handle, in pixels.
-		 */
-		UINT32 getScrollableSize() const;
-
-		/**
-		 * @brief	Returns the total length of the area the handle can move in, in pixels.
-		 */
-		UINT32 getMaxSize() const;
-
-		/**
-		 * @brief	Sets a step that defines the minimal increment the value can be increased/decreased by. Set to zero
-		 * 			to have no step.
-		 */
-		void setStep(float step);
-
-		/**
-		 * @copydoc	GUIElement::_getOptimalSize
-		 */
-		virtual Vector2I _getOptimalSize() const override;
-
-		Event<void(float newPosition)> onHandleMoved;
-	protected:
-		~GUISliderHandle();
-
-		/**
-		 * @copydoc GUIElement::getNumRenderElements()
-		 */
-		virtual UINT32 _getNumRenderElements() const override;
-
-		/**
-		 * @copydoc GUIElement::getMaterial()
-		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
-
-		/**
-		 * @copydoc GUIElement::getNumQuads()
-		 */
-		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
-
-		/**
-		 * @copydoc GUIElement::fillBuffer()
-		 */
-		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
-			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
-
-		/**
-		 * @copydoc GUIElement::updateRenderElementsInternal()
-		 */
-		virtual void updateRenderElementsInternal() override;
-
-		/**
-		 * @copydoc GUIElement::updateBounds()
-		 */
-		virtual void updateClippedBounds() override;
-	private:
-		GUISliderHandle(bool horizontal, bool jumpOnClick, const String& styleName, const GUIDimensions& dimensions);
-
-		/**
-		 * @copydoc	GUIElement::mouseEvent
-		 */
-		virtual bool _mouseEvent(const GUIMouseEvent& ev) override;
-
-		/**
-		 * @brief	Checks are the specified over the scroll handle. Coordinates are relative
-		 *			to the parent widget.
-		 */
-		bool isOnHandle(const Vector2I& pos) const;
-
-		/**
-		 * @brief	Sets the position of the slider handle, in pixels. Relative to this object. For internal use only.
-		 */
-		void setHandlePosPx(INT32 pos);
-
-		/**
-		 * @brief	Gets the currently active texture, depending on handle state.
-		 */
-		const HSpriteTexture& getActiveTexture() const;
-
-		ImageSprite* mImageSprite;
-		UINT32 mHandleSize;
-
-		bool mHorizontal; // Otherwise its vertical
-		bool mJumpOnClick;
-		float mPctHandlePos;
-		float mStep;
-		INT32 mDragStartPos;
-		bool mMouseOverHandle;
-		bool mHandleDragged;
-		State mState;
-	};
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsGUIElement.h"
+#include "BsImageSprite.h"
+#include "BsEvent.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	A handle that can be dragged from its predefined minimum and maximum position,
+	 *			either horizontally or vertically.
+	 */
+	class BS_EXPORT GUISliderHandle : public GUIElement
+	{
+		/**
+		 * @brief	Visual state of the handle
+		 */
+		enum class State
+		{
+			Normal, Hover, Active
+		};
+
+	public:
+		/**
+		 * Returns type name of the GUI element used for finding GUI element styles. 
+		 */
+		static const String& getGUITypeName();
+
+		/**
+		 * @brief	Creates a new handle.
+		 *
+		 * @param	horizontal		Should the handle be movable vertically or horizontally.
+		 * @param	jumpOnClick		If true clicking on a specific position on the slider will cause
+		 *							the slider handle to jump to that position. Otherwise the slider
+		 *							will just slightly move towards that direction.
+		 * @param	styleName		Optional style to use for the element. Style will be retrieved
+		 *							from GUISkin of the GUIWidget the element is used on. If not specified
+		 *							default style is used.
+		 */
+		static GUISliderHandle* create(bool horizontal, bool jumpOnClick, const String& styleName = StringUtil::BLANK);
+
+		/**
+		 * @brief	Creates a new handle.
+		 *
+		 * @param	horizontal		Should the handle be movable vertically or horizontally.
+		 * @param	jumpOnClick		If true clicking on a specific position on the slider will cause
+		 *							the slider handle to jump to that position. Otherwise the slider
+		 *							will just slightly move towards that direction.
+		 * @param	options			Options that allow you to control how is the element positioned and sized.
+		 *							This will override any similar options set by style.
+		 * @param	styleName		Optional style to use for the element. Style will be retrieved
+		 *							from GUISkin of the GUIWidget the element is used on. If not specified
+		 *							default style is used.
+		 */
+		static GUISliderHandle* create(bool horizontal, bool jumpOnClick, const GUIOptions& options,
+			const String& styleName = StringUtil::BLANK);
+
+		/**
+		 * @brief	Size of the handle in pixels, along the handle drag direction.
+		 *
+		 * @note	Internal method. Does not trigger layout update.
+		 */
+		void _setHandleSize(UINT32 size);
+
+		/**
+		 * @brief	Moves the handle the the specified position in the handle area.
+		 *
+		 * @param	pct	Position to move the handle to, in percent ranging [0.0f, 1.0f]
+		 *
+		 * @note	Internal method. Does not trigger layout update.
+		 */
+		void _setHandlePos(float pct);
+
+		/**
+		 * @brief	Gets the current position of the handle, in percent ranging [0.0f, 1.0f].
+		 */
+		float getHandlePos() const;
+
+		/**
+		 * @brief	Returns the position of the slider handle, in pixels. Relative to this object.
+		 */
+		INT32 getHandlePosPx() const;
+
+		/**
+		 * @brief	Returns remaining length of the scrollable area not covered by the handle, in pixels.
+		 */
+		UINT32 getScrollableSize() const;
+
+		/**
+		 * @brief	Returns the total length of the area the handle can move in, in pixels.
+		 */
+		UINT32 getMaxSize() const;
+
+		/**
+		 * @brief	Sets a step that defines the minimal increment the value can be increased/decreased by. Set to zero
+		 * 			to have no step.
+		 */
+		void setStep(float step);
+
+		/**
+		 * @copydoc	GUIElement::_getOptimalSize
+		 */
+		virtual Vector2I _getOptimalSize() const override;
+
+		Event<void(float newPosition)> onHandleMoved;
+	protected:
+		~GUISliderHandle();
+
+		/**
+		 * @copydoc GUIElement::_getNumRenderElements()
+		 */
+		virtual UINT32 _getNumRenderElements() const override;
+
+		/**
+		 * @copydoc GUIElement::_getMaterial()
+		 */
+		virtual const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
+
+		/**
+		 * @copydoc GUIElement::_getNumQuads()
+		 */
+		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
+
+		/**
+		 * @copydoc GUIElement::_fillBuffer()
+		 */
+		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
+			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
+
+		/**
+		 * @copydoc GUIElement::updateRenderElementsInternal()
+		 */
+		virtual void updateRenderElementsInternal() override;
+
+		/**
+		 * @copydoc GUIElement::updateBounds()
+		 */
+		virtual void updateClippedBounds() override;
+	private:
+		GUISliderHandle(bool horizontal, bool jumpOnClick, const String& styleName, const GUIDimensions& dimensions);
+
+		/**
+		 * @copydoc	GUIElement::mouseEvent
+		 */
+		virtual bool _mouseEvent(const GUIMouseEvent& ev) override;
+
+		/**
+		 * @brief	Checks are the specified over the scroll handle. Coordinates are relative
+		 *			to the parent widget.
+		 */
+		bool isOnHandle(const Vector2I& pos) const;
+
+		/**
+		 * @brief	Sets the position of the slider handle, in pixels. Relative to this object. For internal use only.
+		 */
+		void setHandlePosPx(INT32 pos);
+
+		/**
+		 * @brief	Gets the currently active texture, depending on handle state.
+		 */
+		const HSpriteTexture& getActiveTexture() const;
+
+		ImageSprite* mImageSprite;
+		UINT32 mHandleSize;
+
+		bool mHorizontal; // Otherwise its vertical
+		bool mJumpOnClick;
+		float mPctHandlePos;
+		float mStep;
+		INT32 mDragStartPos;
+		bool mMouseOverHandle;
+		bool mHandleDragged;
+		State mState;
+	};
 }
 }

+ 5 - 5
BansheeEngine/Include/BsGUITexture.h

@@ -177,22 +177,22 @@ namespace BansheeEngine
 		virtual ~GUITexture();
 		virtual ~GUITexture();
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumRenderElements
+		 * @copydoc GUIElement::_getNumRenderElements
 		 */
 		 */
 		virtual UINT32 _getNumRenderElements() const override;
 		virtual UINT32 _getNumRenderElements() const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getMaterial
+		 * @copydoc GUIElement::_getMaterial
 		 */
 		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
+		virtual const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumQuads
+		 * @copydoc GUIElement::_getNumQuads
 		 */
 		 */
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::fillBuffer
+		 * @copydoc GUIElement::_fillBuffer
 		 */
 		 */
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;

+ 6 - 6
BansheeEngine/Include/BsGUIViewport.h

@@ -59,28 +59,28 @@ namespace BansheeEngine
 		~GUIViewport();
 		~GUIViewport();
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumRenderElements
+		 * @copydoc GUIElement::_getNumRenderElements
 		 */
 		 */
 		virtual UINT32 _getNumRenderElements() const override;
 		virtual UINT32 _getNumRenderElements() const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getMaterial
+		 * @copydoc GUIElement::_getMaterial
 		 */
 		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
+		virtual const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::getNumQuads
+		 * @copydoc GUIElement::_getNumQuads
 		 */
 		 */
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::fillBuffer
+		 * @copydoc GUIElement::_fillBuffer
 		 */
 		 */
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
 			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
-		 * @copydoc GUIElement::updateBounds
+		 * @copydoc GUIElement::updateClippedBounds
 		 */
 		 */
 		virtual void updateClippedBounds() override;
 		virtual void updateClippedBounds() override;
 
 

+ 1 - 0
BansheeEngine/Include/BsPrerequisites.h

@@ -102,6 +102,7 @@ namespace BansheeEngine
 	class TextSprite;
 	class TextSprite;
 	class ImageSprite;
 	class ImageSprite;
 	class SpriteTexture;
 	class SpriteTexture;
+	struct SpriteMaterialInfo;
 
 
 	// Components
 	// Components
 	class CRenderable;
 	class CRenderable;

+ 66 - 11
BansheeEngine/Include/BsSprite.h

@@ -1,15 +1,13 @@
 #pragma once
 #pragma once
 
 
 #include "BsPrerequisites.h"
 #include "BsPrerequisites.h"
-#include "BsGUIMaterialInfo.h"
 #include "BsVector2I.h"
 #include "BsVector2I.h"
 #include "BsRect2I.h"
 #include "BsRect2I.h"
+#include "BsColor.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	/**
-	 * @brief	Determines position of the sprite in its bounds.
-	 */
+	/** Determines position of the sprite in its bounds. */
 	enum SpriteAnchor
 	enum SpriteAnchor
 	{
 	{
 		SA_TopLeft,
 		SA_TopLeft,
@@ -23,10 +21,33 @@ namespace BansheeEngine
 		SA_BottomRight
 		SA_BottomRight
 	};
 	};
 
 
-	/**
-	 * @brief	Contains information about a single sprite render element,
-	 *			including its geometry and material.
-	 */
+	/** Types of materials available for rendering sprites. */
+	enum class SpriteMaterial
+	{
+		Text, Image, ImageAlpha
+	};
+
+	/** Contains information for initializing a sprite material. */
+	struct SpriteMaterialInfo
+	{
+		/** Generates a hash value that describes the contents of this object. */
+		UINT64 generateHash() const;
+
+		SpriteMaterial type;
+		UINT64 groupId;
+		HTexture texture;
+		Color tint;
+	};
+
+	/** @cond INTERNAL */
+
+	/** Equals operator for SpriteMaterialInfo. */
+	bool operator==(const SpriteMaterialInfo& lhs, const SpriteMaterialInfo& rhs);
+
+	/** Not equals operator for SpriteMaterialInfo. */
+	bool operator!=(const SpriteMaterialInfo& lhs, const SpriteMaterialInfo& rhs);
+
+	/** Contains information about a single sprite render element, including its geometry and material. */
 	struct SpriteRenderElement
 	struct SpriteRenderElement
 	{
 	{
 		SpriteRenderElement()
 		SpriteRenderElement()
@@ -37,9 +58,11 @@ namespace BansheeEngine
 		Vector2* uvs;
 		Vector2* uvs;
 		UINT32* indexes;
 		UINT32* indexes;
 		UINT32 numQuads;
 		UINT32 numQuads;
-		GUIMaterialInfo matInfo;
+		SpriteMaterialInfo matInfo;
 	};
 	};
 
 
+	/** @endcond */
+
 	/**
 	/**
 	 * @brief	Generates geometry and contains information needed for rendering
 	 * @brief	Generates geometry and contains information needed for rendering
 	 *			a two dimensional element.
 	 *			a two dimensional element.
@@ -77,7 +100,7 @@ namespace BansheeEngine
 		 *
 		 *
 		 * @see		getNumRenderElements()
 		 * @see		getNumRenderElements()
 		 */
 		 */
-		const GUIMaterialInfo& getMaterial(UINT32 renderElementIdx) const;
+		const SpriteMaterialInfo& getMaterialInfo(UINT32 renderElementIdx) const;
 
 
 		/**
 		/**
 		 * @brief	Returns the number of quads that the specified render element will use. You will need this
 		 * @brief	Returns the number of quads that the specified render element will use. You will need this
@@ -139,4 +162,36 @@ namespace BansheeEngine
 		mutable Rect2I mBounds;
 		mutable Rect2I mBounds;
 		mutable Vector<SpriteRenderElement> mCachedRenderElements;
 		mutable Vector<SpriteRenderElement> mCachedRenderElements;
 	};
 	};
-}
+}
+
+/** @cond STDLIB */
+/** @addtogroup GUI
+ *  @{
+ */
+
+/**	Hash value generator for STL reference wrapper for SpriteMaterialInfo. */
+template<>
+struct std::hash<std::reference_wrapper<const BansheeEngine::SpriteMaterialInfo>>
+{
+	size_t operator()(const std::reference_wrapper<const BansheeEngine::SpriteMaterialInfo>& value) const
+	{
+		return (size_t)value.get().generateHash();
+	}
+};
+
+/** Provides equals operator for STL reference wrapper for SpriteMaterialInfo. */
+static bool operator==(const std::reference_wrapper<const BansheeEngine::SpriteMaterialInfo>& lhs, 
+	const std::reference_wrapper<const BansheeEngine::SpriteMaterialInfo>& rhs)
+{
+	return lhs.get() == rhs.get();
+}
+
+/** Provides not equals operator for STL reference wrapper for SpriteMaterialInfo. */
+static bool operator!=(const std::reference_wrapper<const BansheeEngine::SpriteMaterialInfo>& lhs,
+	const std::reference_wrapper<const BansheeEngine::SpriteMaterialInfo>& rhs)
+{
+	return !(lhs == rhs);
+}
+
+/** @} */
+/** @endcond */

+ 1 - 0
BansheeEngine/Include/BsTextSprite.h

@@ -4,6 +4,7 @@
 #include "BsSprite.h"
 #include "BsSprite.h"
 #include "BsTextData.h"
 #include "BsTextData.h"
 #include "BsColor.h"
 #include "BsColor.h"
+#include "BsVector2.h"
 #include "BsStaticAlloc.h"
 #include "BsStaticAlloc.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine

+ 1 - 5
BansheeEngine/Source/BsApplication.cpp

@@ -1,5 +1,4 @@
 #include "BsApplication.h"
 #include "BsApplication.h"
-#include "BsGUIMaterialManager.h"
 #include "BsGUIManager.h"
 #include "BsGUIManager.h"
 #include "BsShapeMeshes2D.h"
 #include "BsShapeMeshes2D.h"
 #include "BsShapeMeshes3D.h"
 #include "BsShapeMeshes3D.h"
@@ -18,6 +17,7 @@
 #include "BsCoreObjectManager.h"
 #include "BsCoreObjectManager.h"
 #include "BsRendererManager.h"
 #include "BsRendererManager.h"
 #include "BsRendererMaterialManager.h"
 #include "BsRendererMaterialManager.h"
+#include "BsPlatform.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -52,11 +52,8 @@ namespace BansheeEngine
 
 
 		Cursor::shutDown();
 		Cursor::shutDown();
 
 
-		GUIMaterialManager::instance().clearMaterials();
-
 		ShortcutManager::shutDown();
 		ShortcutManager::shutDown();
 		GUIManager::shutDown();
 		GUIManager::shutDown();
-		GUIMaterialManager::shutDown();
 		BuiltinResources::shutDown();
 		BuiltinResources::shutDown();
 		RendererMaterialManager::shutDown();
 		RendererMaterialManager::shutDown();
 		VirtualInput::shutDown();
 		VirtualInput::shutDown();
@@ -74,7 +71,6 @@ namespace BansheeEngine
 		RendererMaterialManager::startUp();
 		RendererMaterialManager::startUp();
 		RendererManager::instance().initialize();
 		RendererManager::instance().initialize();
 		GUIManager::startUp();
 		GUIManager::startUp();
-		GUIMaterialManager::startUp();
 		ShortcutManager::startUp();
 		ShortcutManager::startUp();
 
 
 		Cursor::startUp();
 		Cursor::startUp();

+ 6 - 25
BansheeEngine/Source/BsBuiltinResources.cpp

@@ -1018,38 +1018,19 @@ namespace BansheeEngine
 		return gResources().load<Mesh>(meshPath);
 		return gResources().load<Mesh>(meshPath);
 	}
 	}
 
 
-	GUIMaterialInfo BuiltinResources::createSpriteTextMaterial() const
+	HMaterial BuiltinResources::createSpriteTextMaterial() const
 	{
 	{
-		GUIMaterialInfo info;
-		info.material = Material::create(mShaderSpriteText);
-
-		info.mainTexture = info.material->getParamTexture("mainTexture");
-		info.mainTexSampler = info.material->getParamSamplerState("mainTexSamp");
-		info.tint = info.material->getParamVec4("tint");
-
-		return info;
+		return Material::create(mShaderSpriteText);
 	}
 	}
 
 
-	GUIMaterialInfo BuiltinResources::createSpriteImageMaterial() const
+	HMaterial BuiltinResources::createSpriteImageMaterial() const
 	{
 	{
-		GUIMaterialInfo info;
-		info.material = Material::create(mShaderSpriteImage);
-		info.mainTexture = info.material->getParamTexture("mainTexture");
-		info.mainTexSampler = info.material->getParamSamplerState("mainTexSamp");
-		info.tint = info.material->getParamVec4("tint");
-
-		return info;
+		return Material::create(mShaderSpriteImage);
 	}
 	}
 
 
-	GUIMaterialInfo BuiltinResources::createSpriteNonAlphaImageMaterial() const
+	HMaterial BuiltinResources::createSpriteNonAlphaImageMaterial() const
 	{
 	{
-		GUIMaterialInfo info;
-		info.material = Material::create(mShaderSpriteNonAlphaImage);
-		info.mainTexture = info.material->getParamTexture("mainTexture");
-		info.mainTexSampler = info.material->getParamSamplerState("mainTexSamp");
-		info.tint = info.material->getParamVec4("tint");
-
-		return info;
+		return Material::create(mShaderSpriteNonAlphaImage);
 	}
 	}
 
 
 	void BuiltinResourcesHelper::importAssets(const Path& inputFolder, const Path& outputFolder, const ResourceManifestPtr& manifest)
 	void BuiltinResourcesHelper::importAssets(const Path& inputFolder, const Path& outputFolder, const ResourceManifestPtr& manifest)

+ 4 - 4
BansheeEngine/Source/BsGUIButtonBase.cpp

@@ -68,17 +68,17 @@ namespace BansheeEngine
 		return numElements;
 		return numElements;
 	}
 	}
 
 
-	const GUIMaterialInfo& GUIButtonBase::_getMaterial(UINT32 renderElementIdx) const
+	const SpriteMaterialInfo& GUIButtonBase::_getMaterial(UINT32 renderElementIdx) const
 	{
 	{
 		UINT32 textSpriteIdx = mImageSprite->getNumRenderElements();
 		UINT32 textSpriteIdx = mImageSprite->getNumRenderElements();
 		UINT32 contentImgSpriteIdx = textSpriteIdx + mTextSprite->getNumRenderElements();
 		UINT32 contentImgSpriteIdx = textSpriteIdx + mTextSprite->getNumRenderElements();
 
 
 		if(renderElementIdx >= contentImgSpriteIdx)
 		if(renderElementIdx >= contentImgSpriteIdx)
-			return mContentImageSprite->getMaterial(contentImgSpriteIdx - renderElementIdx);
+			return mContentImageSprite->getMaterialInfo(contentImgSpriteIdx - renderElementIdx);
 		else if(renderElementIdx >= textSpriteIdx)
 		else if(renderElementIdx >= textSpriteIdx)
-			return mTextSprite->getMaterial(textSpriteIdx - renderElementIdx);
+			return mTextSprite->getMaterialInfo(textSpriteIdx - renderElementIdx);
 		else
 		else
-			return mImageSprite->getMaterial(renderElementIdx);
+			return mImageSprite->getMaterialInfo(renderElementIdx);
 	}
 	}
 
 
 	UINT32 GUIButtonBase::_getNumQuads(UINT32 renderElementIdx) const
 	UINT32 GUIButtonBase::_getNumQuads(UINT32 renderElementIdx) const

+ 1 - 1
BansheeEngine/Source/BsGUIElementContainer.cpp

@@ -15,7 +15,7 @@ namespace BansheeEngine
 		return 0;
 		return 0;
 	}
 	}
 
 
-	const GUIMaterialInfo& GUIElementContainer::_getMaterial(UINT32 renderElementIdx) const
+	const SpriteMaterialInfo& GUIElementContainer::_getMaterial(UINT32 renderElementIdx) const
 	{
 	{
 		BS_EXCEPT(InvalidStateException, "Trying to retrieve a material from an element with no render elements.");
 		BS_EXCEPT(InvalidStateException, "Trying to retrieve a material from an element with no render elements.");
 	}
 	}

+ 2 - 2
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -124,12 +124,12 @@ namespace BansheeEngine
 		return numElements;
 		return numElements;
 	}
 	}
 
 
-	const GUIMaterialInfo& GUIInputBox::_getMaterial(UINT32 renderElementIdx) const
+	const SpriteMaterialInfo& GUIInputBox::_getMaterial(UINT32 renderElementIdx) const
 	{
 	{
 		UINT32 localRenderElementIdx;
 		UINT32 localRenderElementIdx;
 		Sprite* sprite = renderElemToSprite(renderElementIdx, localRenderElementIdx);
 		Sprite* sprite = renderElemToSprite(renderElementIdx, localRenderElementIdx);
 
 
-		return sprite->getMaterial(localRenderElementIdx);
+		return sprite->getMaterialInfo(localRenderElementIdx);
 	}
 	}
 
 
 	UINT32 GUIInputBox::_getNumQuads(UINT32 renderElementIdx) const
 	UINT32 GUIInputBox::_getNumQuads(UINT32 renderElementIdx) const

+ 2 - 2
BansheeEngine/Source/BsGUILabel.cpp

@@ -25,9 +25,9 @@ namespace BansheeEngine
 		return mTextSprite->getNumRenderElements();
 		return mTextSprite->getNumRenderElements();
 	}
 	}
 
 
-	const GUIMaterialInfo& GUILabel::_getMaterial(UINT32 renderElementIdx) const
+	const SpriteMaterialInfo& GUILabel::_getMaterial(UINT32 renderElementIdx) const
 	{
 	{
-		return mTextSprite->getMaterial(renderElementIdx);
+		return mTextSprite->getMaterialInfo(renderElementIdx);
 	}
 	}
 
 
 	UINT32 GUILabel::_getNumQuads(UINT32 renderElementIdx) const
 	UINT32 GUILabel::_getNumQuads(UINT32 renderElementIdx) const

+ 65 - 47
BansheeEngine/Source/BsGUIManager.cpp

@@ -1,7 +1,6 @@
 #include "BsGUIManager.h"
 #include "BsGUIManager.h"
 #include "BsCGUIWidget.h"
 #include "BsCGUIWidget.h"
 #include "BsGUIElement.h"
 #include "BsGUIElement.h"
-#include "BsImageSprite.h"
 #include "BsSpriteTexture.h"
 #include "BsSpriteTexture.h"
 #include "BsTime.h"
 #include "BsTime.h"
 #include "BsSceneObject.h"
 #include "BsSceneObject.h"
@@ -15,17 +14,11 @@
 #include "BsCoreApplication.h"
 #include "BsCoreApplication.h"
 #include "BsException.h"
 #include "BsException.h"
 #include "BsInput.h"
 #include "BsInput.h"
-#include "BsPass.h"
-#include "BsDebug.h"
 #include "BsGUIInputCaret.h"
 #include "BsGUIInputCaret.h"
 #include "BsGUIInputSelection.h"
 #include "BsGUIInputSelection.h"
-#include "BsGUIListBox.h"
-#include "BsGUIButton.h"
-#include "BsGUIDropDownMenu.h"
 #include "BsGUIContextMenu.h"
 #include "BsGUIContextMenu.h"
 #include "BsDragAndDropManager.h"
 #include "BsDragAndDropManager.h"
 #include "BsGUIDropDownBoxManager.h"
 #include "BsGUIDropDownBoxManager.h"
-#include "BsGUIContextMenu.h"
 #include "BsProfilerCPU.h"
 #include "BsProfilerCPU.h"
 #include "BsMeshHeap.h"
 #include "BsMeshHeap.h"
 #include "BsTransientMesh.h"
 #include "BsTransientMesh.h"
@@ -39,6 +32,9 @@
 #include "BsRendererUtility.h"
 #include "BsRendererUtility.h"
 #include "BsTexture.h"
 #include "BsTexture.h"
 #include "BsRenderTexture.h"
 #include "BsRenderTexture.h"
+#include "BsSamplerState.h"
+#include "BsRenderStateManager.h"
+#include "BsBuiltinResources.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 
@@ -59,7 +55,7 @@ namespace BansheeEngine
 
 
 	struct GUIMaterialGroup
 	struct GUIMaterialGroup
 	{
 	{
-		GUIMaterialInfo matInfo;
+		SpriteMaterialInfo matInfo;
 		UINT32 numQuads;
 		UINT32 numQuads;
 		UINT32 depth;
 		UINT32 depth;
 		UINT32 minDepth;
 		UINT32 minDepth;
@@ -109,7 +105,15 @@ namespace BansheeEngine
 		deferredCall(std::bind(&GUIManager::updateCaretTexture, this));
 		deferredCall(std::bind(&GUIManager::updateCaretTexture, this));
 		deferredCall(std::bind(&GUIManager::updateTextSelectionTexture, this));
 		deferredCall(std::bind(&GUIManager::updateTextSelectionTexture, this));
 
 
-		mCore.store(bs_new<GUIManagerCore>(), std::memory_order_release);
+		GUIManagerCore* core = bs_new<GUIManagerCore>();
+		mCore.store(core, std::memory_order_release);
+
+		HMaterial textMaterial = BuiltinResources::instance().createSpriteTextMaterial();
+		HMaterial imageMaterial = BuiltinResources::instance().createSpriteNonAlphaImageMaterial();
+		HMaterial imageAlphaMaterial = BuiltinResources::instance().createSpriteImageMaterial();
+
+		gCoreAccessor().queueCommand(std::bind(&GUIManagerCore::initialize, core,
+			textMaterial->getCore(), imageMaterial->getCore(), imageAlphaMaterial->getCore()));
 	}
 	}
 
 
 	GUIManager::~GUIManager()
 	GUIManager::~GUIManager()
@@ -383,10 +387,10 @@ namespace BansheeEngine
 				UINT32 meshIdx = 0;
 				UINT32 meshIdx = 0;
 				for (auto& mesh : renderData.cachedMeshes)
 				for (auto& mesh : renderData.cachedMeshes)
 				{
 				{
-					GUIMaterialInfo materialInfo = renderData.cachedMaterials[meshIdx];
+					SpriteMaterialInfo materialInfo = renderData.cachedMaterials[meshIdx];
 					CGUIWidget* widget = renderData.cachedWidgetsPerMesh[meshIdx];
 					CGUIWidget* widget = renderData.cachedWidgetsPerMesh[meshIdx];
 
 
-					if (materialInfo.material == nullptr || !materialInfo.material.isLoaded())
+					if (materialInfo.texture == nullptr || !materialInfo.texture.isLoaded())
 					{
 					{
 						meshIdx++;
 						meshIdx++;
 						continue;
 						continue;
@@ -401,7 +405,9 @@ namespace BansheeEngine
 					cameraData.push_back(GUICoreRenderData());
 					cameraData.push_back(GUICoreRenderData());
 					GUICoreRenderData& newEntry = cameraData.back();
 					GUICoreRenderData& newEntry = cameraData.back();
 
 
-					newEntry.material = materialInfo.material->getCore();
+					newEntry.materialType = materialInfo.type;
+					newEntry.texture = materialInfo.texture->getCore();
+					newEntry.tint = materialInfo.tint;
 					newEntry.mesh = mesh->getCore();
 					newEntry.mesh = mesh->getCore();
 					newEntry.worldTransform = widget->SO()->getWorldTfrm();
 					newEntry.worldTransform = widget->SO()->getWorldTfrm();
 
 
@@ -475,7 +481,7 @@ namespace BansheeEngine
 
 
 				// Group the elements in such a way so that we end up with a smallest amount of
 				// Group the elements in such a way so that we end up with a smallest amount of
 				// meshes, without breaking back to front rendering order
 				// meshes, without breaking back to front rendering order
-				FrameUnorderedMap<UINT64, FrameVector<GUIMaterialGroup>> materialGroups;
+				FrameUnorderedMap<std::reference_wrapper<const SpriteMaterialInfo>, FrameVector<GUIMaterialGroup>> materialGroups;
 				for (auto& elem : allElements)
 				for (auto& elem : allElements)
 				{
 				{
 					GUIElement* guiElem = elem.element;
 					GUIElement* guiElem = elem.element;
@@ -485,23 +491,16 @@ namespace BansheeEngine
 					Rect2I tfrmedBounds = guiElem->_getClippedBounds();
 					Rect2I tfrmedBounds = guiElem->_getClippedBounds();
 					tfrmedBounds.transform(guiElem->_getParentWidget()->SO()->getWorldTfrm());
 					tfrmedBounds.transform(guiElem->_getParentWidget()->SO()->getWorldTfrm());
 
 
-					const GUIMaterialInfo& matInfo = guiElem->_getMaterial(renderElemIdx);
-
-					UINT64 materialId = matInfo.material->getInternalID(); 
-
-					// If this is a new material, add a new list of groups
-					auto findIterMaterial = materialGroups.find(materialId);
-					if (findIterMaterial == end(materialGroups))
-						materialGroups[materialId] = FrameVector<GUIMaterialGroup>();
-
+					const SpriteMaterialInfo& matInfo = guiElem->_getMaterial(renderElemIdx);
+					FrameVector<GUIMaterialGroup>& groupsPerMaterial = materialGroups[std::cref(matInfo)];
+					
 					// Try to find a group this material will fit in:
 					// Try to find a group this material will fit in:
 					//  - Group that has a depth value same or one below elements depth will always be a match
 					//  - Group that has a depth value same or one below elements depth will always be a match
 					//  - Otherwise, we search higher depth values as well, but we only use them if no elements in between those depth values
 					//  - Otherwise, we search higher depth values as well, but we only use them if no elements in between those depth values
 					//    overlap the current elements bounds.
 					//    overlap the current elements bounds.
-					FrameVector<GUIMaterialGroup>& allGroups = materialGroups[materialId];
 					GUIMaterialGroup* foundGroup = nullptr;
 					GUIMaterialGroup* foundGroup = nullptr;
 
 
-					for (auto groupIter = allGroups.rbegin(); groupIter != allGroups.rend(); ++groupIter)
+					for (auto groupIter = groupsPerMaterial.rbegin(); groupIter != groupsPerMaterial.rend(); ++groupIter)
 					{
 					{
 						// If we separate meshes by widget, ignore any groups with widget parents other than mine
 						// If we separate meshes by widget, ignore any groups with widget parents other than mine
 						if (mSeparateMeshesByWidget)
 						if (mSeparateMeshesByWidget)
@@ -559,8 +558,8 @@ namespace BansheeEngine
 
 
 					if (foundGroup == nullptr)
 					if (foundGroup == nullptr)
 					{
 					{
-						allGroups.push_back(GUIMaterialGroup());
-						foundGroup = &allGroups[allGroups.size() - 1];
+						groupsPerMaterial.push_back(GUIMaterialGroup());
+						foundGroup = &groupsPerMaterial[groupsPerMaterial.size() - 1];
 
 
 						foundGroup->depth = elemDepth;
 						foundGroup->depth = elemDepth;
 						foundGroup->minDepth = elemDepth;
 						foundGroup->minDepth = elemDepth;
@@ -1660,6 +1659,21 @@ namespace BansheeEngine
 			activeRenderer->_unregisterRenderCallback(cameraData.first.get(), 30);
 			activeRenderer->_unregisterRenderCallback(cameraData.first.get(), 30);
 	}
 	}
 
 
+	void GUIManagerCore::initialize(const SPtr<MaterialCore>& textMat, const SPtr<MaterialCore>& imageMat,
+		const SPtr<MaterialCore>& imageAlphaMat)
+	{
+		mTextMaterialInfo = MaterialInfo(textMat);
+		mImageMaterialInfo = MaterialInfo(imageMat);
+		mImageAlphaMaterialInfo = MaterialInfo(imageAlphaMat);
+
+		SAMPLER_STATE_DESC ssDesc;
+		ssDesc.magFilter = FO_POINT;
+		ssDesc.minFilter = FO_POINT;
+		ssDesc.mipFilter = FO_POINT;
+
+		mSamplerState = RenderStateCoreManager::instance().createSamplerState(ssDesc);
+	}
+
 	void GUIManagerCore::updateData(const UnorderedMap<SPtr<CameraCore>, Vector<GUIManager::GUICoreRenderData>>& newPerCameraData)
 	void GUIManagerCore::updateData(const UnorderedMap<SPtr<CameraCore>, Vector<GUIManager::GUICoreRenderData>>& newPerCameraData)
 	{
 	{
 		bs_frame_mark();
 		bs_frame_mark();
@@ -1671,7 +1685,7 @@ namespace BansheeEngine
 			for (auto& newCameraData : newPerCameraData)
 			for (auto& newCameraData : newPerCameraData)
 			{
 			{
 				UINT32 idx = 0;
 				UINT32 idx = 0;
-				Vector<RenderData>* renderData = nullptr;
+				Vector<GUIManager::GUICoreRenderData>* renderData = nullptr;
 				for (auto& oldCameraData : mPerCameraData)
 				for (auto& oldCameraData : mPerCameraData)
 				{
 				{
 					if (newCameraData.first == oldCameraData.first)
 					if (newCameraData.first == oldCameraData.first)
@@ -1688,27 +1702,14 @@ namespace BansheeEngine
 				{
 				{
 					SPtr<CameraCore> camera = newCameraData.first;
 					SPtr<CameraCore> camera = newCameraData.first;
 
 
-					auto insertedData = mPerCameraData.insert(std::make_pair(newCameraData.first, Vector<RenderData>()));
+					auto insertedData = mPerCameraData.insert(std::make_pair(newCameraData.first, Vector<GUIManager::GUICoreRenderData>()));
 					renderData = &insertedData.first->second;
 					renderData = &insertedData.first->second;
 
 
 					activeRenderer->_registerRenderCallback(camera.get(), 30, std::bind(&GUIManagerCore::render, this, camera), true);
 					activeRenderer->_registerRenderCallback(camera.get(), 30, std::bind(&GUIManagerCore::render, this, camera), true);
 					validCameras.insert(camera);
 					validCameras.insert(camera);
 				}
 				}
 
 
-				renderData->clear();
-
-				for (auto& entry : newCameraData.second)
-				{
-					renderData->push_back(RenderData());
-					RenderData& newEntry = renderData->back();
-
-					newEntry.mesh = entry.mesh;
-					newEntry.material = entry.material;
-					newEntry.worldTransform = entry.worldTransform;
-					newEntry.invViewportWidthParam = newEntry.material->getParamFloat("invViewportWidth");
-					newEntry.invViewportHeightParam = newEntry.material->getParamFloat("invViewportHeight");
-					newEntry.worldTransformParam = newEntry.material->getParamMat4("worldTransform");
-				}
+				*renderData = newCameraData.second;
 			}
 			}
 
 
 			FrameVector<SPtr<CameraCore>> cameraToRemove;
 			FrameVector<SPtr<CameraCore>> cameraToRemove;
@@ -1731,21 +1732,38 @@ namespace BansheeEngine
 
 
 	void GUIManagerCore::render(const SPtr<CameraCore>& camera)
 	void GUIManagerCore::render(const SPtr<CameraCore>& camera)
 	{
 	{
-		Vector<RenderData>& renderData = mPerCameraData[camera];
+		Vector<GUIManager::GUICoreRenderData>& renderData = mPerCameraData[camera];
 
 
 		float invViewportWidth = 1.0f / (camera->getViewport()->getWidth() * 0.5f);
 		float invViewportWidth = 1.0f / (camera->getViewport()->getWidth() * 0.5f);
 		float invViewportHeight = 1.0f / (camera->getViewport()->getHeight() * 0.5f);
 		float invViewportHeight = 1.0f / (camera->getViewport()->getHeight() * 0.5f);
 		for (auto& entry : renderData)
 		for (auto& entry : renderData)
 		{
 		{
-			entry.invViewportWidthParam.set(invViewportWidth);
-			entry.invViewportHeightParam.set(invViewportHeight);
-			entry.worldTransformParam.set(entry.worldTransform);
+			MaterialInfo& matInfo = entry.materialType == SpriteMaterial::Text ? mTextMaterialInfo :
+				(entry.materialType == SpriteMaterial::Image ? mImageMaterialInfo : mImageAlphaMaterialInfo);
+
+			matInfo.textureParam.set(entry.texture);
+			matInfo.samplerParam.set(mSamplerState);
+			matInfo.tintParam.set(entry.tint);
+			matInfo.invViewportWidthParam.set(invViewportWidth);
+			matInfo.invViewportHeightParam.set(invViewportHeight);
+			matInfo.worldTransformParam.set(entry.worldTransform);
 
 
 			// TODO - I shouldn't be re-applying the entire material for each entry, instead just check which programs
 			// TODO - I shouldn't be re-applying the entire material for each entry, instead just check which programs
 			// changed, and apply only those + the modified constant buffers and/or texture.
 			// changed, and apply only those + the modified constant buffers and/or texture.
 
 
-			gRendererUtility().setPass(entry.material, 0);
+			gRendererUtility().setPass(matInfo.material, 0);
 			gRendererUtility().draw(entry.mesh, entry.mesh->getProperties().getSubMesh(0));
 			gRendererUtility().draw(entry.mesh, entry.mesh->getProperties().getSubMesh(0));
 		}
 		}
 	}
 	}
+
+	GUIManagerCore::MaterialInfo::MaterialInfo(const SPtr<MaterialCore>& material)
+		:material(material)
+	{
+		textureParam = material->getParamTexture("mainTexture");
+		samplerParam = material->getParamSamplerState("mainTexSamp");
+		tintParam = material->getParamColor("tint");
+		invViewportWidthParam = material->getParamFloat("invViewportWidth");
+		invViewportHeightParam = material->getParamFloat("invViewportHeight");
+		worldTransformParam = material->getParamMat4("worldTransform");
+	}
 }
 }

+ 0 - 193
BansheeEngine/Source/BsGUIMaterialManager.cpp

@@ -1,193 +0,0 @@
-#include "BsGUIMaterialManager.h"
-#include "BsMaterial.h"
-#include "BsSamplerState.h"
-#include "BsDebug.h"
-#include "BsBuiltinResources.h"
-#include "BsColor.h"
-
-namespace BansheeEngine
-{
-	GUIMaterialManager::GUIMaterialManager()
-	{
-		SAMPLER_STATE_DESC ssDesc;
-		ssDesc.magFilter = FO_POINT;
-		ssDesc.minFilter = FO_POINT;
-		ssDesc.mipFilter = FO_POINT;
-
-		mGUISamplerState = SamplerState::create(ssDesc);
-	}
-
-	const GUIMaterialInfo& GUIMaterialManager::requestTextMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
-	{
-		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
-
-		const GUIMaterialInfo* matInfo = findExistingTextMaterial(groupId, texture, tint);
-		if(matInfo != nullptr)
-			return *matInfo;
-
-		mTextMaterials.push_back(GUIMaterial());
-
-		GUIMaterial& guiMat = mTextMaterials[mTextMaterials.size() - 1];
-		guiMat.handle = BuiltinResources::instance().createSpriteTextMaterial();
-
-		guiMat.handle.mainTexSampler.set(mGUISamplerState);
-		guiMat.handle.mainTexture.set(texture);
-		guiMat.handle.tint.set(vecColor);
-		guiMat.refCount = 1;
-		guiMat.groupId = groupId;
-
-		return guiMat.handle;
-	}
-
-	const GUIMaterialInfo& GUIMaterialManager::requestImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
-	{
-		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
-
-		const GUIMaterialInfo* matInfo = findExistingImageMaterial(groupId, texture, tint);
-		if(matInfo != nullptr)
-			return *matInfo;
-
-		mImageMaterials.push_back(GUIMaterial());
-
-		GUIMaterial& guiMat = mImageMaterials[mImageMaterials.size() - 1];
-		guiMat.handle = BuiltinResources::instance().createSpriteImageMaterial();
-
-		guiMat.handle.mainTexSampler.set(mGUISamplerState);
-		guiMat.handle.mainTexture.set(texture);
-		guiMat.handle.tint.set(vecColor);
-		guiMat.refCount = 1;
-		guiMat.groupId = groupId;
-
-		return guiMat.handle;
-	}
-
-	const GUIMaterialInfo& GUIMaterialManager::requestNonAlphaImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
-	{
-		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
-
-		const GUIMaterialInfo* matInfo = findExistingNonAlphaImageMaterial(groupId, texture, tint);
-		if (matInfo != nullptr)
-			return *matInfo;
-
-		mNonAlphaImageMaterials.push_back(GUIMaterial());
-
-		GUIMaterial& guiMat = mNonAlphaImageMaterials[mNonAlphaImageMaterials.size() - 1];
-		guiMat.handle = BuiltinResources::instance().createSpriteNonAlphaImageMaterial();
-
-		guiMat.handle.mainTexSampler.set(mGUISamplerState);
-		guiMat.handle.mainTexture.set(texture);
-		guiMat.handle.tint.set(vecColor);
-		guiMat.refCount = 1;
-		guiMat.groupId = groupId;
-
-		return guiMat.handle;
-	}
-
-	const GUIMaterialInfo* GUIMaterialManager::findExistingTextMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
-	{
-		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
-
-		for(auto& matHandle : mTextMaterials)
-		{
-			if (matHandle.handle.mainTexture.get() == texture && matHandle.handle.tint.get() == vecColor && matHandle.groupId == groupId)
-			{
-				matHandle.refCount++;
-				return &matHandle.handle;
-			}
-		}
-
-		return nullptr;
-	}
-
-	const GUIMaterialInfo* GUIMaterialManager::findExistingImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
-	{
-		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
-
-		for(auto& matHandle : mImageMaterials)
-		{
-			if (matHandle.handle.mainTexture.get() == texture && matHandle.handle.tint.get() == vecColor && matHandle.groupId == groupId)
-			{
-				matHandle.refCount++;
-				return &matHandle.handle;
-			}
-		}
-
-		return nullptr;
-	}
-
-	const GUIMaterialInfo* GUIMaterialManager::findExistingNonAlphaImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
-	{
-		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
-
-		for (auto& matHandle : mNonAlphaImageMaterials)
-		{
-			if (matHandle.handle.mainTexture.get() == texture && matHandle.handle.tint.get() == vecColor && matHandle.groupId == groupId)
-			{
-				matHandle.refCount++;
-				return &matHandle.handle;
-			}
-		}
-
-		return nullptr;
-	}
-
-	void GUIMaterialManager::releaseMaterial(const GUIMaterialInfo& material) const
-	{
-		bool released = false;
-
-		UINT32 i = 0;
-		for(auto& matHandle : mTextMaterials)
-		{
-			if(&matHandle.handle == &material)
-			{
-				if(--matHandle.refCount == 0)
-				{
-					mTextMaterials.erase(mTextMaterials.begin() + i);
-					released = true;
-					break;
-				}
-			}
-
-			i++;
-		}
-
-		i = 0;
-		for(auto& matHandle : mImageMaterials)
-		{
-			if(&matHandle.handle == &material)
-			{
-				if(--matHandle.refCount == 0)
-				{
-					mImageMaterials.erase(mImageMaterials.begin() + i);
-					released = true;
-					break;
-				}
-			}
-
-			i++;
-		}
-
-		i = 0;
-		for (auto& matHandle : mNonAlphaImageMaterials)
-		{
-			if (&matHandle.handle == &material)
-			{
-				if (--matHandle.refCount == 0)
-				{
-					mNonAlphaImageMaterials.erase(mNonAlphaImageMaterials.begin() + i);
-					released = true;
-					break;
-				}
-			}
-
-			i++;
-		}
-	}
-
-	void GUIMaterialManager::clearMaterials()
-	{
-		mTextMaterials.clear();
-		mImageMaterials.clear();
-		mNonAlphaImageMaterials.clear();
-	}
-}

+ 2 - 2
BansheeEngine/Source/BsGUIScrollBar.cpp

@@ -70,9 +70,9 @@ namespace BansheeEngine
 		return mImageSprite->getNumRenderElements();
 		return mImageSprite->getNumRenderElements();
 	}
 	}
 
 
-	const GUIMaterialInfo& GUIScrollBar::_getMaterial(UINT32 renderElementIdx) const
+	const SpriteMaterialInfo& GUIScrollBar::_getMaterial(UINT32 renderElementIdx) const
 	{
 	{
-		return mImageSprite->getMaterial(renderElementIdx);
+		return mImageSprite->getMaterialInfo(renderElementIdx);
 	}
 	}
 
 
 	UINT32 GUIScrollBar::_getNumQuads(UINT32 renderElementIdx) const
 	UINT32 GUIScrollBar::_getNumQuads(UINT32 renderElementIdx) const

+ 400 - 400
BansheeEngine/Source/BsGUISliderHandle.cpp

@@ -1,401 +1,401 @@
-#include "BsGUISliderHandle.h"
-#include "BsImageSprite.h"
-#include "BsCGUIWidget.h"
-#include "BsGUISkin.h"
-#include "BsSpriteTexture.h"
-#include "BsTextSprite.h"
-#include "BsGUIDimensions.h"
-#include "BsGUIMouseEvent.h"
-#include "BsDebug.h"
-#include "BsTexture.h"
-
-namespace BansheeEngine
-{
-	const String& GUISliderHandle::getGUITypeName()
-	{
-		static String name = "SliderHandle";
-		return name;
-	}
-
-	GUISliderHandle::GUISliderHandle(bool horizontal, bool jumpOnClick, const String& styleName, const GUIDimensions& dimensions)
-		:GUIElement(styleName, dimensions), mHorizontal(horizontal), mHandleSize(0), mMouseOverHandle(false), mPctHandlePos(0.0f), mDragStartPos(0),
-		mHandleDragged(false), mState(State::Normal), mJumpOnClick(jumpOnClick), mStep(0.0f)
-	{
-		mImageSprite = bs_new<ImageSprite>();
-	}
-
-	GUISliderHandle::~GUISliderHandle()
-	{
-		bs_delete(mImageSprite);
-	}
-
-	GUISliderHandle* GUISliderHandle::create(bool horizontal, bool jumpOnClick, const String& styleName)
-	{
-		return new (bs_alloc<GUISliderHandle>()) GUISliderHandle(horizontal, jumpOnClick, 
-			getStyleName<GUISliderHandle>(styleName), GUIDimensions::create());
-	}
-
-	GUISliderHandle* GUISliderHandle::create(bool horizontal, bool jumpOnClick, const GUIOptions& options, const String& styleName)
-	{
-		return new (bs_alloc<GUISliderHandle>()) GUISliderHandle(horizontal, jumpOnClick, 
-			getStyleName<GUISliderHandle>(styleName), GUIDimensions::create(options));
-	}
-
-	void GUISliderHandle::_setHandleSize(UINT32 size)
-	{
-		mHandleSize = std::min(getMaxSize(), size);
-	}
-
-	void GUISliderHandle::_setHandlePos(float pct)
-	{
-		float maxPct = 1.0f;
-		if (mStep > 0.0f)
-			maxPct = Math::floor(1.0f / mStep) * mStep;
-
-		mPctHandlePos = Math::clamp(pct, 0.0f, maxPct);
-	}
-
-	float GUISliderHandle::getHandlePos() const
-	{
-		return mPctHandlePos;;
-	}
-
-	void GUISliderHandle::setStep(float step)
-	{
-		mStep = Math::clamp01(step);
-	}
-
-	UINT32 GUISliderHandle::getScrollableSize() const
-	{
-		return getMaxSize() - mHandleSize;
-	}
-
-	UINT32 GUISliderHandle::_getNumRenderElements() const
-	{
-		return mImageSprite->getNumRenderElements();
-	}
-
-	const GUIMaterialInfo& GUISliderHandle::_getMaterial(UINT32 renderElementIdx) const
-	{
-		return mImageSprite->getMaterial(renderElementIdx);
-	}
-
-	UINT32 GUISliderHandle::_getNumQuads(UINT32 renderElementIdx) const
-	{
-		return mImageSprite->getNumQuads(renderElementIdx);
-	}
-
-	void GUISliderHandle::updateRenderElementsInternal()
-	{		
-		IMAGE_SPRITE_DESC desc;
-
-		HSpriteTexture activeTex = getActiveTexture();
-		if(SpriteTexture::checkIsLoaded(activeTex))
-			desc.texture = activeTex.getInternalPtr();
-
-		if (mHorizontal)
-		{
-			if (mHandleSize == 0 && desc.texture != nullptr)
-				mHandleSize = desc.texture->getWidth();
-
-			desc.width = mHandleSize;
-			desc.height = mLayoutData.area.height;
-		}
-		else
-		{
-			if (mHandleSize == 0 && desc.texture != nullptr)
-				mHandleSize = desc.texture->getHeight();
-
-			desc.width = mLayoutData.area.width;
-			desc.height = mHandleSize;
-		}
-
-		desc.borderLeft = _getStyle()->border.left;
-		desc.borderRight = _getStyle()->border.right;
-		desc.borderTop = _getStyle()->border.top;
-		desc.borderBottom = _getStyle()->border.bottom;
-		desc.color = getTint();
-		mImageSprite->update(desc, (UINT64)_getParentWidget());
-		
-		GUIElement::updateRenderElementsInternal();
-	}
-
-	void GUISliderHandle::updateClippedBounds()
-	{
-		mClippedBounds = mLayoutData.area;
-		mClippedBounds.clip(mLayoutData.clipRect);
-	}
-
-	Vector2I GUISliderHandle::_getOptimalSize() const
-	{
-		HSpriteTexture activeTex = getActiveTexture();
-
-		if(SpriteTexture::checkIsLoaded(activeTex))
-			return Vector2I(activeTex->getWidth(), activeTex->getHeight());
-
-		return Vector2I();
-	}
-
-	void GUISliderHandle::_fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, UINT32 maxNumQuads, 
-		UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const
-	{
-		Vector2I offset(mLayoutData.area.x, mLayoutData.area.y);
-		if(mHorizontal)
-			offset.x += getHandlePosPx();
-		else
-			offset.y += getHandlePosPx();
-
-		Rect2I clipRect = mLayoutData.getLocalClipRect();
-		if(mHorizontal)
-			clipRect.x -= getHandlePosPx();
-		else
-			clipRect.y -= getHandlePosPx();
-
-		mImageSprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, 
-			vertexStride, indexStride, renderElementIdx, offset, clipRect);
-	}
-
-	bool GUISliderHandle::_mouseEvent(const GUIMouseEvent& ev)
-	{
-		if(ev.getType() == GUIMouseEventType::MouseMove)
-		{
-			if (!_isDisabled())
-			{
-				if (mMouseOverHandle)
-				{
-					if (!isOnHandle(ev.getPosition()))
-					{
-						mMouseOverHandle = false;
-
-						mState = State::Normal;
-						_markLayoutAsDirty();
-
-						return true;
-					}
-				}
-				else
-				{
-					if (isOnHandle(ev.getPosition()))
-					{
-						mMouseOverHandle = true;
-
-						mState = State::Hover;
-						_markLayoutAsDirty();
-
-						return true;
-					}
-				}
-			}
-		}
-
-		if(ev.getType() == GUIMouseEventType::MouseDown && (mMouseOverHandle || mJumpOnClick))
-		{
-			if (!_isDisabled())
-			{
-				mState = State::Active;
-				_markLayoutAsDirty();
-
-				if (mJumpOnClick)
-				{
-					float handlePosPx = 0.0f;
-
-					if (mHorizontal)
-						handlePosPx = (float)(ev.getPosition().x - (INT32)mLayoutData.area.x - mHandleSize * 0.5f);
-					else
-						handlePosPx = (float)(ev.getPosition().y - (INT32)mLayoutData.area.y - mHandleSize * 0.5f);
-
-					setHandlePosPx((INT32)handlePosPx);
-				}
-
-				if (mHorizontal)
-				{
-					INT32 left = (INT32)mLayoutData.area.x + getHandlePosPx();
-					mDragStartPos = ev.getPosition().x - left;
-				}
-				else
-				{
-					INT32 top = (INT32)mLayoutData.area.y + getHandlePosPx();
-					mDragStartPos = ev.getPosition().y - top;
-				}
-
-				mHandleDragged = true;
-			}
-
-			return true;
-		}
-
-		if(ev.getType() == GUIMouseEventType::MouseDrag && mHandleDragged)
-		{
-			if (!_isDisabled())
-			{
-				float handlePosPx = 0.0f;
-				if (mHorizontal)
-				{
-					handlePosPx = (float)(ev.getPosition().x - mDragStartPos - mLayoutData.area.x);
-				}
-				else
-				{
-					handlePosPx = (float)(ev.getPosition().y - mDragStartPos - mLayoutData.area.y);
-				}
-
-				setHandlePosPx((INT32)handlePosPx);
-				onHandleMoved(mPctHandlePos);
-
-				_markLayoutAsDirty();
-			}
-
-			return true;
-		}
-
-		if(ev.getType() == GUIMouseEventType::MouseOut)
-		{
-			if (!_isDisabled())
-			{
-				mMouseOverHandle = false;
-
-				if (!mHandleDragged)
-				{
-					mState = State::Normal;
-					_markLayoutAsDirty();
-				}
-			}
-			
-			return true;
-		}
-
-		if(ev.getType() == GUIMouseEventType::MouseUp)
-		{
-			if (!_isDisabled())
-			{
-				if (mMouseOverHandle)
-					mState = State::Hover;
-				else
-					mState = State::Normal;
-
-				// If we clicked above or below the scroll handle, scroll by one page
-				INT32 handlePosPx = getHandlePosPx();
-				if (!mJumpOnClick)
-				{
-					UINT32 stepSizePx = 0;
-					if (mStep > 0.0f)
-						stepSizePx = (UINT32)(mStep * getMaxSize());
-					else
-						stepSizePx = mHandleSize;
-
-					INT32 handleOffset = 0;
-					if (mHorizontal)
-					{
-						INT32 handleLeft = (INT32)mLayoutData.area.x + handlePosPx;
-						INT32 handleRight = handleLeft + mHandleSize;
-
-						if (ev.getPosition().x < handleLeft)
-							handleOffset -= stepSizePx;
-						else if (ev.getPosition().x > handleRight)
-							handleOffset += stepSizePx;
-					}
-					else
-					{
-						INT32 handleTop = (INT32)mLayoutData.area.y + handlePosPx;
-						INT32 handleBottom = handleTop + mHandleSize;
-
-						if (ev.getPosition().y < handleTop)
-							handleOffset -= stepSizePx;
-						else if (ev.getPosition().y > handleBottom)
-							handleOffset += stepSizePx;
-					}
-
-					handlePosPx += handleOffset;
-				}
-
-				setHandlePosPx(handlePosPx);
-				onHandleMoved(mPctHandlePos);
-
-				mHandleDragged = false;
-				_markLayoutAsDirty();
-			}
-
-			return true;
-		}
-
-		if(ev.getType() == GUIMouseEventType::MouseDragEnd)
-		{
-			if (!_isDisabled())
-			{
-				mHandleDragged = false;
-
-				if (mMouseOverHandle)
-					mState = State::Hover;
-				else
-					mState = State::Normal;
-
-				_markLayoutAsDirty();
-			}
-
-			return true;
-		}
-		
-		return false;
-	}
-
-	bool GUISliderHandle::isOnHandle(const Vector2I& pos) const
-	{
-		if(mHorizontal)
-		{
-			INT32 left = (INT32)mLayoutData.area.x + getHandlePosPx();
-			INT32 right = left + mHandleSize;
-
-			if(pos.x >= left && pos.x < right)
-				return true;
-		}
-		else
-		{
-			INT32 top = (INT32)mLayoutData.area.y + getHandlePosPx();
-			INT32 bottom = top + mHandleSize;
-
-			if(pos.y >= top && pos.y < bottom)
-				return true;
-		}
-		
-		return false;
-	}
-
-	INT32 GUISliderHandle::getHandlePosPx() const
-	{
-		UINT32 maxScrollAmount = getMaxSize() - mHandleSize;
-		return Math::floorToInt(mPctHandlePos * maxScrollAmount);
-	}
-
-	void GUISliderHandle::setHandlePosPx(INT32 pos)
-	{
-		float maxScrollAmount = (float)getMaxSize() - mHandleSize;
-		float maxPct = 1.0f;
-		if (mStep > 0.0f)
-			maxPct = Math::floor(1.0f / mStep) * mStep;
-
-		mPctHandlePos = Math::clamp(pos / maxScrollAmount, 0.0f, maxPct);
-	}
-
-	UINT32 GUISliderHandle::getMaxSize() const
-	{
-		UINT32 maxSize = mLayoutData.area.height;
-		if(mHorizontal)
-			maxSize = mLayoutData.area.width;
-
-		return maxSize;
-	}
-
-	const HSpriteTexture& GUISliderHandle::getActiveTexture() const
-	{
-		switch(mState)
-		{
-		case State::Active:
-			return _getStyle()->active.texture;
-		case State::Hover:
-			return _getStyle()->hover.texture;
-		case State::Normal:
-			return _getStyle()->normal.texture;
-		}
-
-		return _getStyle()->normal.texture;
-	}
+#include "BsGUISliderHandle.h"
+#include "BsImageSprite.h"
+#include "BsCGUIWidget.h"
+#include "BsGUISkin.h"
+#include "BsSpriteTexture.h"
+#include "BsTextSprite.h"
+#include "BsGUIDimensions.h"
+#include "BsGUIMouseEvent.h"
+#include "BsDebug.h"
+#include "BsTexture.h"
+
+namespace BansheeEngine
+{
+	const String& GUISliderHandle::getGUITypeName()
+	{
+		static String name = "SliderHandle";
+		return name;
+	}
+
+	GUISliderHandle::GUISliderHandle(bool horizontal, bool jumpOnClick, const String& styleName, const GUIDimensions& dimensions)
+		:GUIElement(styleName, dimensions), mHorizontal(horizontal), mHandleSize(0), mMouseOverHandle(false), mPctHandlePos(0.0f), mDragStartPos(0),
+		mHandleDragged(false), mState(State::Normal), mJumpOnClick(jumpOnClick), mStep(0.0f)
+	{
+		mImageSprite = bs_new<ImageSprite>();
+	}
+
+	GUISliderHandle::~GUISliderHandle()
+	{
+		bs_delete(mImageSprite);
+	}
+
+	GUISliderHandle* GUISliderHandle::create(bool horizontal, bool jumpOnClick, const String& styleName)
+	{
+		return new (bs_alloc<GUISliderHandle>()) GUISliderHandle(horizontal, jumpOnClick, 
+			getStyleName<GUISliderHandle>(styleName), GUIDimensions::create());
+	}
+
+	GUISliderHandle* GUISliderHandle::create(bool horizontal, bool jumpOnClick, const GUIOptions& options, const String& styleName)
+	{
+		return new (bs_alloc<GUISliderHandle>()) GUISliderHandle(horizontal, jumpOnClick, 
+			getStyleName<GUISliderHandle>(styleName), GUIDimensions::create(options));
+	}
+
+	void GUISliderHandle::_setHandleSize(UINT32 size)
+	{
+		mHandleSize = std::min(getMaxSize(), size);
+	}
+
+	void GUISliderHandle::_setHandlePos(float pct)
+	{
+		float maxPct = 1.0f;
+		if (mStep > 0.0f)
+			maxPct = Math::floor(1.0f / mStep) * mStep;
+
+		mPctHandlePos = Math::clamp(pct, 0.0f, maxPct);
+	}
+
+	float GUISliderHandle::getHandlePos() const
+	{
+		return mPctHandlePos;;
+	}
+
+	void GUISliderHandle::setStep(float step)
+	{
+		mStep = Math::clamp01(step);
+	}
+
+	UINT32 GUISliderHandle::getScrollableSize() const
+	{
+		return getMaxSize() - mHandleSize;
+	}
+
+	UINT32 GUISliderHandle::_getNumRenderElements() const
+	{
+		return mImageSprite->getNumRenderElements();
+	}
+
+	const SpriteMaterialInfo& GUISliderHandle::_getMaterial(UINT32 renderElementIdx) const
+	{
+		return mImageSprite->getMaterialInfo(renderElementIdx);
+	}
+
+	UINT32 GUISliderHandle::_getNumQuads(UINT32 renderElementIdx) const
+	{
+		return mImageSprite->getNumQuads(renderElementIdx);
+	}
+
+	void GUISliderHandle::updateRenderElementsInternal()
+	{		
+		IMAGE_SPRITE_DESC desc;
+
+		HSpriteTexture activeTex = getActiveTexture();
+		if(SpriteTexture::checkIsLoaded(activeTex))
+			desc.texture = activeTex.getInternalPtr();
+
+		if (mHorizontal)
+		{
+			if (mHandleSize == 0 && desc.texture != nullptr)
+				mHandleSize = desc.texture->getWidth();
+
+			desc.width = mHandleSize;
+			desc.height = mLayoutData.area.height;
+		}
+		else
+		{
+			if (mHandleSize == 0 && desc.texture != nullptr)
+				mHandleSize = desc.texture->getHeight();
+
+			desc.width = mLayoutData.area.width;
+			desc.height = mHandleSize;
+		}
+
+		desc.borderLeft = _getStyle()->border.left;
+		desc.borderRight = _getStyle()->border.right;
+		desc.borderTop = _getStyle()->border.top;
+		desc.borderBottom = _getStyle()->border.bottom;
+		desc.color = getTint();
+		mImageSprite->update(desc, (UINT64)_getParentWidget());
+		
+		GUIElement::updateRenderElementsInternal();
+	}
+
+	void GUISliderHandle::updateClippedBounds()
+	{
+		mClippedBounds = mLayoutData.area;
+		mClippedBounds.clip(mLayoutData.clipRect);
+	}
+
+	Vector2I GUISliderHandle::_getOptimalSize() const
+	{
+		HSpriteTexture activeTex = getActiveTexture();
+
+		if(SpriteTexture::checkIsLoaded(activeTex))
+			return Vector2I(activeTex->getWidth(), activeTex->getHeight());
+
+		return Vector2I();
+	}
+
+	void GUISliderHandle::_fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, UINT32 maxNumQuads, 
+		UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const
+	{
+		Vector2I offset(mLayoutData.area.x, mLayoutData.area.y);
+		if(mHorizontal)
+			offset.x += getHandlePosPx();
+		else
+			offset.y += getHandlePosPx();
+
+		Rect2I clipRect = mLayoutData.getLocalClipRect();
+		if(mHorizontal)
+			clipRect.x -= getHandlePosPx();
+		else
+			clipRect.y -= getHandlePosPx();
+
+		mImageSprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, 
+			vertexStride, indexStride, renderElementIdx, offset, clipRect);
+	}
+
+	bool GUISliderHandle::_mouseEvent(const GUIMouseEvent& ev)
+	{
+		if(ev.getType() == GUIMouseEventType::MouseMove)
+		{
+			if (!_isDisabled())
+			{
+				if (mMouseOverHandle)
+				{
+					if (!isOnHandle(ev.getPosition()))
+					{
+						mMouseOverHandle = false;
+
+						mState = State::Normal;
+						_markLayoutAsDirty();
+
+						return true;
+					}
+				}
+				else
+				{
+					if (isOnHandle(ev.getPosition()))
+					{
+						mMouseOverHandle = true;
+
+						mState = State::Hover;
+						_markLayoutAsDirty();
+
+						return true;
+					}
+				}
+			}
+		}
+
+		if(ev.getType() == GUIMouseEventType::MouseDown && (mMouseOverHandle || mJumpOnClick))
+		{
+			if (!_isDisabled())
+			{
+				mState = State::Active;
+				_markLayoutAsDirty();
+
+				if (mJumpOnClick)
+				{
+					float handlePosPx = 0.0f;
+
+					if (mHorizontal)
+						handlePosPx = (float)(ev.getPosition().x - (INT32)mLayoutData.area.x - mHandleSize * 0.5f);
+					else
+						handlePosPx = (float)(ev.getPosition().y - (INT32)mLayoutData.area.y - mHandleSize * 0.5f);
+
+					setHandlePosPx((INT32)handlePosPx);
+				}
+
+				if (mHorizontal)
+				{
+					INT32 left = (INT32)mLayoutData.area.x + getHandlePosPx();
+					mDragStartPos = ev.getPosition().x - left;
+				}
+				else
+				{
+					INT32 top = (INT32)mLayoutData.area.y + getHandlePosPx();
+					mDragStartPos = ev.getPosition().y - top;
+				}
+
+				mHandleDragged = true;
+			}
+
+			return true;
+		}
+
+		if(ev.getType() == GUIMouseEventType::MouseDrag && mHandleDragged)
+		{
+			if (!_isDisabled())
+			{
+				float handlePosPx = 0.0f;
+				if (mHorizontal)
+				{
+					handlePosPx = (float)(ev.getPosition().x - mDragStartPos - mLayoutData.area.x);
+				}
+				else
+				{
+					handlePosPx = (float)(ev.getPosition().y - mDragStartPos - mLayoutData.area.y);
+				}
+
+				setHandlePosPx((INT32)handlePosPx);
+				onHandleMoved(mPctHandlePos);
+
+				_markLayoutAsDirty();
+			}
+
+			return true;
+		}
+
+		if(ev.getType() == GUIMouseEventType::MouseOut)
+		{
+			if (!_isDisabled())
+			{
+				mMouseOverHandle = false;
+
+				if (!mHandleDragged)
+				{
+					mState = State::Normal;
+					_markLayoutAsDirty();
+				}
+			}
+			
+			return true;
+		}
+
+		if(ev.getType() == GUIMouseEventType::MouseUp)
+		{
+			if (!_isDisabled())
+			{
+				if (mMouseOverHandle)
+					mState = State::Hover;
+				else
+					mState = State::Normal;
+
+				// If we clicked above or below the scroll handle, scroll by one page
+				INT32 handlePosPx = getHandlePosPx();
+				if (!mJumpOnClick)
+				{
+					UINT32 stepSizePx = 0;
+					if (mStep > 0.0f)
+						stepSizePx = (UINT32)(mStep * getMaxSize());
+					else
+						stepSizePx = mHandleSize;
+
+					INT32 handleOffset = 0;
+					if (mHorizontal)
+					{
+						INT32 handleLeft = (INT32)mLayoutData.area.x + handlePosPx;
+						INT32 handleRight = handleLeft + mHandleSize;
+
+						if (ev.getPosition().x < handleLeft)
+							handleOffset -= stepSizePx;
+						else if (ev.getPosition().x > handleRight)
+							handleOffset += stepSizePx;
+					}
+					else
+					{
+						INT32 handleTop = (INT32)mLayoutData.area.y + handlePosPx;
+						INT32 handleBottom = handleTop + mHandleSize;
+
+						if (ev.getPosition().y < handleTop)
+							handleOffset -= stepSizePx;
+						else if (ev.getPosition().y > handleBottom)
+							handleOffset += stepSizePx;
+					}
+
+					handlePosPx += handleOffset;
+				}
+
+				setHandlePosPx(handlePosPx);
+				onHandleMoved(mPctHandlePos);
+
+				mHandleDragged = false;
+				_markLayoutAsDirty();
+			}
+
+			return true;
+		}
+
+		if(ev.getType() == GUIMouseEventType::MouseDragEnd)
+		{
+			if (!_isDisabled())
+			{
+				mHandleDragged = false;
+
+				if (mMouseOverHandle)
+					mState = State::Hover;
+				else
+					mState = State::Normal;
+
+				_markLayoutAsDirty();
+			}
+
+			return true;
+		}
+		
+		return false;
+	}
+
+	bool GUISliderHandle::isOnHandle(const Vector2I& pos) const
+	{
+		if(mHorizontal)
+		{
+			INT32 left = (INT32)mLayoutData.area.x + getHandlePosPx();
+			INT32 right = left + mHandleSize;
+
+			if(pos.x >= left && pos.x < right)
+				return true;
+		}
+		else
+		{
+			INT32 top = (INT32)mLayoutData.area.y + getHandlePosPx();
+			INT32 bottom = top + mHandleSize;
+
+			if(pos.y >= top && pos.y < bottom)
+				return true;
+		}
+		
+		return false;
+	}
+
+	INT32 GUISliderHandle::getHandlePosPx() const
+	{
+		UINT32 maxScrollAmount = getMaxSize() - mHandleSize;
+		return Math::floorToInt(mPctHandlePos * maxScrollAmount);
+	}
+
+	void GUISliderHandle::setHandlePosPx(INT32 pos)
+	{
+		float maxScrollAmount = (float)getMaxSize() - mHandleSize;
+		float maxPct = 1.0f;
+		if (mStep > 0.0f)
+			maxPct = Math::floor(1.0f / mStep) * mStep;
+
+		mPctHandlePos = Math::clamp(pos / maxScrollAmount, 0.0f, maxPct);
+	}
+
+	UINT32 GUISliderHandle::getMaxSize() const
+	{
+		UINT32 maxSize = mLayoutData.area.height;
+		if(mHorizontal)
+			maxSize = mLayoutData.area.width;
+
+		return maxSize;
+	}
+
+	const HSpriteTexture& GUISliderHandle::getActiveTexture() const
+	{
+		switch(mState)
+		{
+		case State::Active:
+			return _getStyle()->active.texture;
+		case State::Hover:
+			return _getStyle()->hover.texture;
+		case State::Normal:
+			return _getStyle()->normal.texture;
+		}
+
+		return _getStyle()->normal.texture;
+	}
 }
 }

+ 2 - 2
BansheeEngine/Source/BsGUITexture.cpp

@@ -122,9 +122,9 @@ namespace BansheeEngine
 		return mImageSprite->getNumRenderElements();
 		return mImageSprite->getNumRenderElements();
 	}
 	}
 
 
-	const GUIMaterialInfo& GUITexture::_getMaterial(UINT32 renderElementIdx) const
+	const SpriteMaterialInfo& GUITexture::_getMaterial(UINT32 renderElementIdx) const
 	{
 	{
-		return mImageSprite->getMaterial(renderElementIdx);
+		return mImageSprite->getMaterialInfo(renderElementIdx);
 	}
 	}
 
 
 	UINT32 GUITexture::_getNumQuads(UINT32 renderElementIdx) const
 	UINT32 GUITexture::_getNumQuads(UINT32 renderElementIdx) const

+ 1 - 1
BansheeEngine/Source/BsGUIViewport.cpp

@@ -45,7 +45,7 @@ namespace BansheeEngine
 		return 0;
 		return 0;
 	}
 	}
 
 
-	const GUIMaterialInfo& GUIViewport::_getMaterial(UINT32 renderElementIdx) const
+	const SpriteMaterialInfo& GUIViewport::_getMaterial(UINT32 renderElementIdx) const
 	{
 	{
 		BS_EXCEPT(InternalErrorException, "This element has no render element so no material can be retrieved.");
 		BS_EXCEPT(InternalErrorException, "This element has no render element so no material can be retrieved.");
 	}
 	}

+ 5 - 42
BansheeEngine/Source/BsImageSprite.cpp

@@ -1,11 +1,7 @@
 #include "BsImageSprite.h"
 #include "BsImageSprite.h"
 #include "BsSpriteTexture.h"
 #include "BsSpriteTexture.h"
-#include "BsGUIMaterialManager.h"
-#include "BsSpriteTexture.h"
 #include "BsTexture.h"
 #include "BsTexture.h"
 
 
-#include "BsProfilerCPU.h"
-
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	ImageSprite::ImageSprite()
 	ImageSprite::ImageSprite()
@@ -59,39 +55,11 @@ namespace BansheeEngine
 
 
 			const HTexture& tex = desc.texture->getTexture();
 			const HTexture& tex = desc.texture->getTexture();
 
 
-			bool getNewMaterial = false;
-			if(renderElem.matInfo.material == nullptr)
-				getNewMaterial = true;
-			else
-			{
-				const GUIMaterialInfo* matInfo = nullptr;
-				
-				if (desc.transparent)
-					matInfo = GUIMaterialManager::instance().findExistingImageMaterial(groupId, tex, desc.color);
-				else
-					matInfo = GUIMaterialManager::instance().findExistingNonAlphaImageMaterial(groupId, tex, desc.color);
-
-				if(matInfo == nullptr)
-				{
-					getNewMaterial = true;
-				}
-				else
-				{
-					if(matInfo->material != renderElem.matInfo.material)
-					{
-						GUIMaterialManager::instance().releaseMaterial(renderElem.matInfo);
-						getNewMaterial = true;
-					}
-				}
-			}
-
-			if (getNewMaterial)
-			{
-				if (desc.transparent)
-					renderElem.matInfo = GUIMaterialManager::instance().requestImageMaterial(groupId, tex, desc.color);
-				else
-					renderElem.matInfo = GUIMaterialManager::instance().requestNonAlphaImageMaterial(groupId, tex, desc.color);
-			}
+			SpriteMaterialInfo& matInfo = renderElem.matInfo;
+			matInfo.groupId = groupId;
+			matInfo.texture = tex;
+			matInfo.tint = desc.color;
+			matInfo.type = desc.transparent ? SpriteMaterial::ImageAlpha : SpriteMaterial::Image;
 
 
 			texPage++;
 			texPage++;
 		}
 		}
@@ -291,11 +259,6 @@ namespace BansheeEngine
 				bs_deleteN(renderElem.indexes, indexCount);
 				bs_deleteN(renderElem.indexes, indexCount);
 				renderElem.indexes = nullptr;
 				renderElem.indexes = nullptr;
 			}
 			}
-
-			if (renderElem.matInfo.material != nullptr)
-			{
-				GUIMaterialManager::instance().releaseMaterial(renderElem.matInfo);
-			}
 		}
 		}
 
 
 		mCachedRenderElements.clear();
 		mCachedRenderElements.clear();

+ 27 - 3
BansheeEngine/Source/BsSprite.cpp

@@ -1,7 +1,6 @@
 #include "BsTextSprite.h"
 #include "BsTextSprite.h"
-#include "BsGUIMaterialManager.h"
 #include "BsVector2.h"
 #include "BsVector2.h"
-#include "BsProfilerCPU.h"
+#include "BsTexture.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -29,7 +28,7 @@ namespace BansheeEngine
 		return (UINT32)mCachedRenderElements.size();
 		return (UINT32)mCachedRenderElements.size();
 	}
 	}
 
 
-	const GUIMaterialInfo& Sprite::getMaterial(UINT32 renderElementIdx) const
+	const SpriteMaterialInfo& Sprite::getMaterialInfo(UINT32 renderElementIdx) const
 	{
 	{
 		return mCachedRenderElements.at(renderElementIdx).matInfo;
 		return mCachedRenderElements.at(renderElementIdx).matInfo;
 	}
 	}
@@ -318,4 +317,29 @@ namespace BansheeEngine
 			uv += vertStride * 4;
 			uv += vertStride * 4;
 		}
 		}
 	}
 	}
+
+	UINT64 SpriteMaterialInfo::generateHash() const
+	{
+		UINT64 textureId = 0;
+		if (texture.isLoaded())
+			textureId = texture->getInternalID();
+
+		size_t hash = 0;
+		hash_combine(hash, groupId);
+		hash_combine(hash, type);
+		hash_combine(hash, textureId);
+		hash_combine(hash, tint);
+
+		return (UINT64)hash;
+	}
+
+	bool operator==(const SpriteMaterialInfo& lhs, const SpriteMaterialInfo& rhs)
+	{
+		return lhs.groupId == rhs.groupId && lhs.texture == rhs.texture && lhs.type == rhs.type && lhs.tint == rhs.tint;
+	}
+
+	bool operator!=(const SpriteMaterialInfo& lhs, const SpriteMaterialInfo& rhs)
+	{
+		return !(lhs == rhs);
+	}
 }
 }

+ 5 - 39
BansheeEngine/Source/BsTextSprite.cpp

@@ -1,11 +1,7 @@
 #include "BsTextSprite.h"
 #include "BsTextSprite.h"
-#include "BsGUIMaterialManager.h"
 #include "BsTextData.h"
 #include "BsTextData.h"
-#include "BsFont.h"
 #include "BsVector2.h"
 #include "BsVector2.h"
 
 
-#include "BsProfilerCPU.h" // PROFILING ONLY
-
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	TextSprite::TextSprite()
 	TextSprite::TextSprite()
@@ -38,14 +34,6 @@ namespace BansheeEngine
 			mAlloc.clear();
 			mAlloc.clear();
 
 
 			// Resize cached mesh array to needed size
 			// Resize cached mesh array to needed size
-			for (UINT32 i = numPages; i < (UINT32)mCachedRenderElements.size(); i++)
-			{
-				auto& renderElem = mCachedRenderElements[i];
-
-				if (renderElem.matInfo.material != nullptr)
-					GUIMaterialManager::instance().releaseMaterial(renderElem.matInfo);
-			}
-
 			if (mCachedRenderElements.size() != numPages)
 			if (mCachedRenderElements.size() != numPages)
 				mCachedRenderElements.resize(numPages);
 				mCachedRenderElements.resize(numPages);
 
 
@@ -62,28 +50,11 @@ namespace BansheeEngine
 
 
 				const HTexture& tex = textData.getTextureForPage(texPage);
 				const HTexture& tex = textData.getTextureForPage(texPage);
 
 
-				bool getNewMaterial = false;
-				if (cachedElem.matInfo.material == nullptr)
-					getNewMaterial = true;
-				else
-				{
-					const GUIMaterialInfo* matInfo = GUIMaterialManager::instance().findExistingTextMaterial(groupId, tex, desc.color);
-					if (matInfo == nullptr)
-					{
-						getNewMaterial = true;
-					}
-					else
-					{
-						if (matInfo->material != cachedElem.matInfo.material)
-						{
-							GUIMaterialManager::instance().releaseMaterial(cachedElem.matInfo);
-							getNewMaterial = true;
-						}
-					}
-				}
-
-				if (getNewMaterial)
-					cachedElem.matInfo = GUIMaterialManager::instance().requestTextMaterial(groupId, tex, desc.color);
+				SpriteMaterialInfo& matInfo = cachedElem.matInfo;
+				matInfo.groupId = groupId;
+				matInfo.texture = tex;
+				matInfo.tint = desc.color;
+				matInfo.type = SpriteMaterial::Text;
 
 
 				texPage++;
 				texPage++;
 			}
 			}
@@ -244,11 +215,6 @@ namespace BansheeEngine
 				mAlloc.free(renderElem.indexes);
 				mAlloc.free(renderElem.indexes);
 				renderElem.indexes = nullptr;
 				renderElem.indexes = nullptr;
 			}
 			}
-
-			if (renderElem.matInfo.material != nullptr)
-			{
-				GUIMaterialManager::instance().releaseMaterial(renderElem.matInfo);
-			}
 		}
 		}
 
 
 		mCachedRenderElements.clear();
 		mCachedRenderElements.clear();