Prechádzať zdrojové kódy

Fixed an issue with DX11 $Globals shader buffer where it was incorrectly marked as shareable
Added tint to sprite shaders
Added ToggleField and Color GUI fields

Marko Pintera 11 rokov pred
rodič
commit
1ea161f89a

+ 4 - 0
BansheeEditor/BansheeEditor.vcxproj

@@ -275,9 +275,11 @@
     <ClInclude Include="Include\BsEditorWidgetLayout.h" />
     <ClInclude Include="Include\BsEditorWidgetLayout.h" />
     <ClInclude Include="Include\BsEditorWidgetLayoutRTTI.h" />
     <ClInclude Include="Include\BsEditorWidgetLayoutRTTI.h" />
     <ClInclude Include="Include\BsEditorWidgetManager.h" />
     <ClInclude Include="Include\BsEditorWidgetManager.h" />
+    <ClInclude Include="Include\BsGUIColor.h" />
     <ClInclude Include="Include\BsGUIFloatField.h" />
     <ClInclude Include="Include\BsGUIFloatField.h" />
     <ClInclude Include="Include\BsGUIIntField.h" />
     <ClInclude Include="Include\BsGUIIntField.h" />
     <ClInclude Include="Include\BsGUITextField.h" />
     <ClInclude Include="Include\BsGUITextField.h" />
+    <ClInclude Include="Include\BsGUIToggleField.h" />
     <ClInclude Include="Include\BsGUIVector3Field.h" />
     <ClInclude Include="Include\BsGUIVector3Field.h" />
     <ClInclude Include="Include\BsGUIVector4Field.h" />
     <ClInclude Include="Include\BsGUIVector4Field.h" />
     <ClInclude Include="Include\BsProjectLibraryEntriesRTTI.h" />
     <ClInclude Include="Include\BsProjectLibraryEntriesRTTI.h" />
@@ -324,6 +326,7 @@
     <ClCompile Include="Source\BsEditorWindow.cpp" />
     <ClCompile Include="Source\BsEditorWindow.cpp" />
     <ClCompile Include="Source\BsEditorWindowBase.cpp" />
     <ClCompile Include="Source\BsEditorWindowBase.cpp" />
     <ClCompile Include="Source\BsEditorWindowManager.cpp" />
     <ClCompile Include="Source\BsEditorWindowManager.cpp" />
+    <ClCompile Include="Source\BsGUIColor.cpp" />
     <ClCompile Include="Source\BsGUIDockSlider.cpp" />
     <ClCompile Include="Source\BsGUIDockSlider.cpp" />
     <ClCompile Include="Source\BsGUIFloatField.cpp" />
     <ClCompile Include="Source\BsGUIFloatField.cpp" />
     <ClCompile Include="Source\BsGUIIntField.cpp" />
     <ClCompile Include="Source\BsGUIIntField.cpp" />
@@ -333,6 +336,7 @@
     <ClCompile Include="Source\BsGUITabbedTitleBar.cpp" />
     <ClCompile Include="Source\BsGUITabbedTitleBar.cpp" />
     <ClCompile Include="Source\BsGUITabButton.cpp" />
     <ClCompile Include="Source\BsGUITabButton.cpp" />
     <ClCompile Include="Source\BsGUITextField.cpp" />
     <ClCompile Include="Source\BsGUITextField.cpp" />
+    <ClCompile Include="Source\BsGUIToggleField.cpp" />
     <ClCompile Include="Source\BsGUITreeView.cpp" />
     <ClCompile Include="Source\BsGUITreeView.cpp" />
     <ClCompile Include="Source\BsGUITreeViewEditBox.cpp" />
     <ClCompile Include="Source\BsGUITreeViewEditBox.cpp" />
     <ClCompile Include="Source\BsGUIVector2Field.cpp" />
     <ClCompile Include="Source\BsGUIVector2Field.cpp" />

+ 12 - 0
BansheeEditor/BansheeEditor.vcxproj.filters

@@ -171,6 +171,12 @@
     <ClInclude Include="Include\BsGUIVector2Field.h">
     <ClInclude Include="Include\BsGUIVector2Field.h">
       <Filter>Header Files\Editor</Filter>
       <Filter>Header Files\Editor</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsGUIToggleField.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGUIColor.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsEditorWidgetContainer.cpp">
     <ClCompile Include="Source\BsEditorWidgetContainer.cpp">
@@ -293,5 +299,11 @@
     <ClCompile Include="Source\BsGUIVector2Field.cpp">
     <ClCompile Include="Source\BsGUIVector2Field.cpp">
       <Filter>Source Files\Editor</Filter>
       <Filter>Source Files\Editor</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsGUIToggleField.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGUIColor.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 71 - 0
BansheeEditor/Include/BsGUIColor.h

@@ -0,0 +1,71 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsGUIElement.h"
+#include "BsImageSprite.h"
+#include "BsGUIContent.h"
+
+namespace BansheeEditor
+{
+	class GUIColor : public BS::GUIElement
+	{
+	public:
+		static const CM::String& getGUITypeName();
+
+		static GUIColor* create(BS::GUIWidget& parent, const BS::GUIElementStyle* style = nullptr);
+		static GUIColor* create(BS::GUIWidget& parent, const BS::GUIOptions& layoutOptions, const BS::GUIElementStyle* style = nullptr);
+
+		virtual CM::Vector2I _getOptimalSize() const;
+
+		void setColor(const CM::Color& color);
+		CM::Color getColor() const { return mColor; }
+
+	protected:
+		GUIColor(BS::GUIWidget& parent, const BS::GUIElementStyle* style, const BS::GUILayoutOptions& layoutOptions);
+		virtual ~GUIColor();
+
+		/**
+		 * @copydoc GUIElement::getNumRenderElements()
+		 */
+		virtual CM::UINT32 getNumRenderElements() const;
+
+		/**
+		 * @copydoc GUIElement::getMaterial()
+		 */
+		virtual const BS::GUIMaterialInfo& getMaterial(CM::UINT32 renderElementIdx) const;
+
+		/**
+		 * @copydoc GUIElement::getNumQuads()
+		 */
+		virtual CM::UINT32 getNumQuads(CM::UINT32 renderElementIdx) const;
+
+		/**
+		 * @copydoc GUIElement::fillBuffer()
+		 */
+		virtual void fillBuffer(CM::UINT8* vertices, CM::UINT8* uv, CM::UINT32* indices, CM::UINT32 startingQuad, 
+			CM::UINT32 maxNumQuads, CM::UINT32 vertexStride, CM::UINT32 indexStride, CM::UINT32 renderElementIdx) const;
+
+		/**
+		 * @copydoc GUIElement::updateRenderElementsInternal()
+		 */
+		virtual void updateRenderElementsInternal();
+
+		/**
+		 * @copydoc GUIElement::updateBounds()
+		 */
+		virtual void updateClippedBounds();
+
+		virtual bool mouseEvent(const BS::GUIMouseEvent& ev);
+
+	private:
+		static const float ALPHA_SPLIT_POSITION;
+
+		BS::ImageSprite* mColorSprite;
+		BS::ImageSprite* mAlphaSprite;
+
+		BS::IMAGE_SPRITE_DESC mColorImageDesc;
+		BS::IMAGE_SPRITE_DESC mAlphaImageDesc;
+
+		CM::Color mColor;
+	};
+}

+ 56 - 0
BansheeEditor/Include/BsGUIToggleField.h

@@ -0,0 +1,56 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsGUIElementContainer.h"
+
+namespace BansheeEditor
+{
+	class BS_ED_EXPORT GUIToggleField : public BS::GUIElementContainer
+	{
+		struct PrivatelyConstruct {};
+
+	public:
+		static const CM::String& getGUITypeName();
+
+		static GUIToggleField* create(BS::GUIWidget& parent, const BS::GUIContent& labelContent, 
+			const BS::GUIOptions& layoutOptions, BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* toggleStyle = nullptr);
+
+		static GUIToggleField* create(BS::GUIWidget& parent, const CM::HString& labelText, 
+			const BS::GUIOptions& layoutOptions, BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* toggleStyle = nullptr);
+
+		static GUIToggleField* create(BS::GUIWidget& parent, 
+			const BS::GUIOptions& layoutOptions, BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* toggleStyle = nullptr);
+
+		static GUIToggleField* create(BS::GUIWidget& parent, const BS::GUIContent& labelContent, 
+			BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* toggleStyle = nullptr);
+
+		static GUIToggleField* create(BS::GUIWidget& parent, const CM::HString& labelText, 
+			BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* toggleStyle = nullptr);
+
+		static GUIToggleField* create(BS::GUIWidget& parent, 
+			BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* toggleStyle = nullptr);
+
+		GUIToggleField(const PrivatelyConstruct& dummy, BS::GUIWidget& parent, const BS::GUIContent& labelContent, 
+			BS::GUIElementStyle* labelStyle, BS::GUIElementStyle* toggleStyle, const BS::GUILayoutOptions& layoutOptions);
+
+		GUIToggleField(const PrivatelyConstruct& dummy, BS::GUIWidget& parent, 
+			BS::GUIElementStyle* labelStyle, BS::GUIElementStyle* toggleStyle, const BS::GUILayoutOptions& layoutOptions);
+
+		bool getValue() const;
+		void setValue(bool value);
+
+		void setLabelWidth(CM::UINT32 width);
+
+		void _updateLayoutInternal(CM::INT32 x, CM::INT32 y, CM::UINT32 width, CM::UINT32 height,
+			CM::RectI clipRect, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
+
+		CM::Vector2I _getOptimalSize() const;
+	protected:
+		virtual ~GUIToggleField();
+
+	protected:
+		CM::UINT32 mLabelWidth;
+		BS::GUILabel* mLabel;
+		BS::GUIToggle* mToggle;
+	};
+}

+ 175 - 0
BansheeEditor/Source/BsGUIColor.cpp

@@ -0,0 +1,175 @@
+#include "BsGUIColor.h"
+#include "BsImageSprite.h"
+#include "BsGUIWidget.h"
+#include "BsGUISkin.h"
+#include "BsSpriteTexture.h"
+#include "BsGUILayoutOptions.h"
+#include "BsGUIMouseEvent.h"
+#include "BsGUIHelper.h"
+#include "BsBuiltinResources.h"
+#include "CmTexture.h"
+
+using namespace CamelotFramework;
+using namespace BansheeEngine;
+
+namespace BansheeEditor
+{
+	const float GUIColor::ALPHA_SPLIT_POSITION = 0.75f;
+
+	GUIColor::GUIColor(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions)
+		:GUIElement(parent, style, layoutOptions), mColorSprite(nullptr), mAlphaSprite(nullptr)
+	{
+		mColorSprite = cm_new<ImageSprite, PoolAlloc>();
+		mAlphaSprite = cm_new<ImageSprite, PoolAlloc>();
+
+		mColorImageDesc.texture = BuiltinResources::instance().getWhiteSpriteTexture().getInternalPtr();
+		mAlphaImageDesc.texture = BuiltinResources::instance().getWhiteSpriteTexture().getInternalPtr();
+	}
+
+	GUIColor::~GUIColor()
+	{
+		cm_delete<PoolAlloc>(mColorSprite);
+		cm_delete<PoolAlloc>(mAlphaSprite);
+	}
+
+	const String& GUIColor::getGUITypeName()
+	{
+		static String name = "Color";
+		return name;
+	}
+
+	GUIColor* GUIColor::create(GUIWidget& parent, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin& skin = parent.getSkin();
+			style = skin.getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUIColor, PoolAlloc>()) GUIColor(parent, style, GUILayoutOptions::create(style));
+	}
+
+	GUIColor* GUIColor::create(GUIWidget& parent, const GUIOptions& layoutOptions, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin& skin = parent.getSkin();
+			style = skin.getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUIColor, PoolAlloc>()) GUIColor(parent, style, GUILayoutOptions::create(layoutOptions, style));
+	}
+
+	void GUIColor::setColor(const Color& color)
+	{
+		mColor = color;
+
+		mColorImageDesc.color = mColor;
+		mColorImageDesc.color.a = 1.0f;
+
+		mAlphaImageDesc.color = Color::White * mColor.a;
+		mAlphaImageDesc.color.a = 1.0f;
+
+		markContentAsDirty();
+	}
+
+	UINT32 GUIColor::getNumRenderElements() const
+	{
+		UINT32 numElements = mColorSprite->getNumRenderElements();
+		numElements += mAlphaSprite->getNumRenderElements();
+
+		return numElements;
+	}
+
+	const GUIMaterialInfo& GUIColor::getMaterial(UINT32 renderElementIdx) const
+	{
+		UINT32 alphaSpriteIdx = mColorSprite->getNumRenderElements();
+
+		if(renderElementIdx >= alphaSpriteIdx)
+			return mAlphaSprite->getMaterial(alphaSpriteIdx - renderElementIdx);
+		else
+			return mColorSprite->getMaterial(renderElementIdx);
+	}
+
+	UINT32 GUIColor::getNumQuads(UINT32 renderElementIdx) const
+	{
+		UINT32 alphaSpriteIdx = mColorSprite->getNumRenderElements();
+
+		UINT32 numQuads = 0;
+		if(renderElementIdx >= alphaSpriteIdx)
+			numQuads = mAlphaSprite->getNumQuads(alphaSpriteIdx - renderElementIdx);
+		else
+			numQuads = mColorSprite->getNumQuads(renderElementIdx);
+
+		return numQuads;
+	}
+
+	void GUIColor::updateRenderElementsInternal()
+	{		
+		mColorImageDesc.width = (UINT32)(mWidth * ALPHA_SPLIT_POSITION);
+		mColorImageDesc.height = mHeight;
+
+		mAlphaImageDesc.width = mWidth - mColorImageDesc.width;
+		mAlphaImageDesc.height = mHeight;
+
+		mColorSprite->update(mColorImageDesc);
+		mAlphaSprite->update(mAlphaImageDesc);
+
+		GUIElement::updateRenderElementsInternal();
+	}
+
+	void GUIColor::updateClippedBounds()
+	{
+		mClippedBounds = RectI(0, 0, mWidth, mHeight);
+
+		if(mClipRect.width > 0 && mClipRect.height > 0)
+			mClippedBounds.clip(mClipRect);
+
+		mClippedBounds.x += mOffset.x;
+		mClippedBounds.y += mOffset.y;
+	}
+
+	Vector2I GUIColor::_getOptimalSize() const
+	{
+		return Vector2I(80, 20); // Arbitrary
+	}
+
+	void GUIColor::fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, UINT32 maxNumQuads, 
+		UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const
+	{
+		UINT32 alphaSpriteIdx = mColorSprite->getNumRenderElements();
+
+		if(renderElementIdx < alphaSpriteIdx)
+		{
+			mColorSprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, 
+				vertexStride, indexStride, renderElementIdx, mOffset, mClipRect);
+
+			return;
+		}
+		else if(renderElementIdx >= alphaSpriteIdx)
+		{
+			Vector2I alphaOffset = mOffset;
+			UINT32 xOffset = (UINT32)(mWidth * ALPHA_SPLIT_POSITION);
+			alphaOffset.x += xOffset;
+
+			RectI alphaClipRect = mClipRect;
+			alphaClipRect.x -= xOffset;
+			alphaClipRect.width = (UINT32)std::max(0, (INT32)alphaClipRect.width - (INT32)xOffset);
+
+			mAlphaSprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, 
+				vertexStride, indexStride, alphaSpriteIdx - renderElementIdx, alphaOffset, alphaClipRect);
+		}
+	}
+
+	bool GUIColor::mouseEvent(const GUIMouseEvent& ev)
+	{
+		if(ev.getType() == GUIMouseEventType::MouseUp)
+		{
+			// TODO
+
+			return true;
+		}
+
+		return false;
+	}
+}

+ 178 - 0
BansheeEditor/Source/BsGUIToggleField.cpp

@@ -0,0 +1,178 @@
+#include "BsGUIToggleField.h"
+#include "BsGUIArea.h"
+#include "BsGUILayout.h"
+#include "BsGUILabel.h"
+#include "BsGUIToggle.h"
+#include "BsBuiltinResources.h"
+#include "BsGUIWidget.h"
+#include "BsGUIMouseEvent.h"
+#include "BsGUIWidget.h"
+
+using namespace CamelotFramework;
+using namespace BansheeEngine;
+
+namespace BansheeEditor
+{
+	GUIToggleField::GUIToggleField(const PrivatelyConstruct& dummy, GUIWidget& parent, const GUIContent& labelContent, 
+		GUIElementStyle* labelStyle, GUIElementStyle* toggleStyle, const GUILayoutOptions& layoutOptions)
+		:GUIElementContainer(parent, layoutOptions), mLabel(nullptr), mToggle(nullptr), mLabelWidth(100)
+	{
+		const GUIElementStyle* curLabelStyle = labelStyle;
+		const GUIElementStyle* curToggleStyle = toggleStyle;
+
+		if(curLabelStyle == nullptr)
+			curLabelStyle = parent.getSkin().getStyle("Label");
+
+		if(curToggleStyle == nullptr)
+			curToggleStyle = parent.getSkin().getStyle("Toggle");
+
+		mLabel = GUILabel::create(parent, labelContent, curLabelStyle);
+		mToggle = GUIToggle::create(parent, HString(L""), curToggleStyle);
+
+		_registerChildElement(mLabel);
+		_registerChildElement(mToggle);
+	}
+
+	GUIToggleField::GUIToggleField(const PrivatelyConstruct& dummy, GUIWidget& parent, 
+		GUIElementStyle* labelStyle, GUIElementStyle* toggleStyle, const GUILayoutOptions& layoutOptions)
+		:GUIElementContainer(parent, layoutOptions), mLabel(nullptr), mToggle(nullptr), mLabelWidth(100)
+	{
+		const GUIElementStyle* curToggleStyle = toggleStyle;
+
+		if(curToggleStyle == nullptr)
+			curToggleStyle = parent.getSkin().getStyle("Toggle");
+
+		mToggle = GUIToggle::create(parent, HString(L""), curToggleStyle);
+
+		_registerChildElement(mToggle);
+	}
+
+	GUIToggleField::~GUIToggleField()
+	{
+
+	}
+
+	GUIToggleField* GUIToggleField::create(GUIWidget& parent, const GUIContent& labelContent, const GUIOptions& layoutOptions, 
+		GUIElementStyle* labelStyle, GUIElementStyle* toggleStyle)
+	{
+		return cm_new<GUIToggleField>(PrivatelyConstruct(), parent, labelContent, labelStyle, toggleStyle, 
+			GUILayoutOptions::create(layoutOptions, &GUISkin::DefaultStyle));
+	}
+
+	GUIToggleField* GUIToggleField::create(GUIWidget& parent, const GUIContent& labelContent, GUIElementStyle* labelStyle, 
+		GUIElementStyle* toggleStyle)
+	{
+		return cm_new<GUIToggleField>(PrivatelyConstruct(), parent, labelContent, labelStyle, toggleStyle, 
+			GUILayoutOptions::create(&GUISkin::DefaultStyle));
+	}
+
+	GUIToggleField* GUIToggleField::create(GUIWidget& parent, const HString& labelContent, const GUIOptions& layoutOptions, 
+		GUIElementStyle* labelStyle, GUIElementStyle* toggleStyle)
+	{
+		return cm_new<GUIToggleField>(PrivatelyConstruct(), parent, GUIContent(labelContent), labelStyle, 
+			toggleStyle, GUILayoutOptions::create(layoutOptions, &GUISkin::DefaultStyle));
+	}
+
+	GUIToggleField* GUIToggleField::create(GUIWidget& parent, const HString& labelContent, GUIElementStyle* labelStyle, 
+		GUIElementStyle* toggleStyle)
+	{
+		return cm_new<GUIToggleField>(PrivatelyConstruct(), parent, GUIContent(labelContent), labelStyle, toggleStyle, 
+			GUILayoutOptions::create(&GUISkin::DefaultStyle));
+	}
+
+	GUIToggleField* GUIToggleField::create(GUIWidget& parent, const GUIOptions& layoutOptions, GUIElementStyle* labelStyle, 
+		GUIElementStyle* toggleStyle)
+	{
+		return cm_new<GUIToggleField>(PrivatelyConstruct(), parent, labelStyle, toggleStyle, 
+			GUILayoutOptions::create(layoutOptions, &GUISkin::DefaultStyle));
+	}
+
+	GUIToggleField* GUIToggleField::create(GUIWidget& parent, GUIElementStyle* labelStyle, GUIElementStyle* toggleStyle)
+	{
+		return cm_new<GUIToggleField>(PrivatelyConstruct(), parent, labelStyle, toggleStyle, GUILayoutOptions::create(&GUISkin::DefaultStyle));
+	}
+
+	bool GUIToggleField::getValue() const
+	{
+		return mToggle->isToggled();
+	}
+
+	void GUIToggleField::setValue(bool value)
+	{
+		if(value) 
+			mToggle->toggleOn();
+		else
+			mToggle->toggleOff();
+	}
+
+	void GUIToggleField::setLabelWidth(UINT32 width)
+	{
+		mLabelWidth = width;
+
+		markContentAsDirty();
+	}
+
+	void GUIToggleField::_updateLayoutInternal(INT32 x, INT32 y, UINT32 width, UINT32 height,
+		RectI clipRect, UINT8 widgetDepth, UINT16 areaDepth)
+	{
+		UINT32 toggleOffset = 0;
+		UINT32 toggleWidth = width;
+
+		if(mLabel != nullptr)
+		{
+			UINT32 labelWidth = mLabelWidth;
+
+			Vector2I optimalSize = mLabel->_getOptimalSize();
+			INT32 yOffset = Math::roundToInt((height - optimalSize.y) * 0.5f);
+
+			Vector2I offset(x, y + yOffset);
+			mLabel->_setOffset(offset);
+			mLabel->_setWidth(labelWidth);
+			mLabel->_setHeight(optimalSize.y);
+			mLabel->_setAreaDepth(areaDepth);
+			mLabel->_setWidgetDepth(widgetDepth);
+
+			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
+			mLabel->_setClipRect(elemClipRect);
+
+			toggleOffset = labelWidth;
+			toggleWidth = width - labelWidth;
+		}
+
+		Vector2I toggleSize = mToggle->_getOptimalSize();
+
+		{
+			Vector2I optimalSize = mToggle->_getOptimalSize();
+			INT32 yOffset = Math::roundToInt((height - optimalSize.y) * 0.5f);
+
+			Vector2I offset(x + toggleOffset, y + yOffset);
+			mToggle->_setOffset(offset);
+			mToggle->_setWidth(toggleWidth);
+			mToggle->_setHeight(optimalSize.y);
+			mToggle->_setAreaDepth(areaDepth);
+			mToggle->_setWidgetDepth(widgetDepth);
+
+			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
+			mToggle->_setClipRect(elemClipRect);
+		}
+	}
+
+	Vector2I GUIToggleField::_getOptimalSize() const
+	{
+		Vector2I optimalsize = mToggle->_getOptimalSize();
+
+		if(mLabel != nullptr)
+		{
+			optimalsize.x += mLabel->_getOptimalSize().x;
+			optimalsize.y = std::max(optimalsize.y, mLabel->_getOptimalSize().y);
+		}
+
+		return optimalsize;
+	}
+
+	const String& GUIToggleField::getGUITypeName()
+	{
+		static String typeName = "GUIToggleField";
+		return typeName;
+	}
+}

+ 6 - 0
BansheeEngine/Include/BsBuiltinResources.h

@@ -16,6 +16,8 @@ namespace BansheeEngine
 
 
 		const GUISkin& getSkin() const { return mSkin; }
 		const GUISkin& getSkin() const { return mSkin; }
 
 
+		const HSpriteTexture getWhiteSpriteTexture() const { return mWhiteSpriteTexture; }
+
 		const CM::PixelData& getCursorArrow(CM::Vector2I& hotSpot);
 		const CM::PixelData& getCursorArrow(CM::Vector2I& hotSpot);
 		const CM::PixelData& getCursorArrowDrag(CM::Vector2I& hotSpot);
 		const CM::PixelData& getCursorArrowDrag(CM::Vector2I& hotSpot);
 		const CM::PixelData& getCursorWait(CM::Vector2I& hotSpot);
 		const CM::PixelData& getCursorWait(CM::Vector2I& hotSpot);
@@ -41,12 +43,16 @@ namespace BansheeEngine
 		CM::PixelDataPtr mCursorSizeNWSE;
 		CM::PixelDataPtr mCursorSizeNWSE;
 		CM::PixelDataPtr mCursorSizeWE;
 		CM::PixelDataPtr mCursorSizeWE;
 
 
+		HSpriteTexture mWhiteSpriteTexture;
+
 		static const CM::WString DefaultSkinFolder;
 		static const CM::WString DefaultSkinFolder;
 		static const CM::WString DefaultCursorFolder;
 		static const CM::WString DefaultCursorFolder;
 
 
 		static const CM::WString DefaultFontPath;
 		static const CM::WString DefaultFontPath;
 		static const CM::UINT32 DefaultFontSize;
 		static const CM::UINT32 DefaultFontSize;
 
 
+		static const CM::WString WhiteTex;
+
 		static const CM::WString ButtonNormalTex;
 		static const CM::WString ButtonNormalTex;
 		static const CM::WString ButtonHoverTex;
 		static const CM::WString ButtonHoverTex;
 
 

+ 1 - 0
BansheeEngine/Include/BsGUIMaterialInfo.h

@@ -12,5 +12,6 @@ namespace BansheeEngine
 		CM::GpuParamFloat invViewportWidth;
 		CM::GpuParamFloat invViewportWidth;
 		CM::GpuParamFloat invViewportHeight;
 		CM::GpuParamFloat invViewportHeight;
 		CM::GpuParamTexture mainTexture;
 		CM::GpuParamTexture mainTexture;
+		CM::GpuParamVec4 tint;
 	};
 	};
 }
 }

+ 5 - 2
BansheeEngine/Include/BsGUIMaterialManager.h

@@ -21,7 +21,7 @@ namespace BansheeEngine
 		 *			
 		 *			
 		 *			Make sure to release all materials with a call to "releaseMaterial()".
 		 *			Make sure to release all materials with a call to "releaseMaterial()".
 		 */
 		 */
-		const GUIMaterialInfo& requestTextMaterial(const CM::HTexture& texture) const;
+		const GUIMaterialInfo& requestTextMaterial(const CM::HTexture& texture, const CM::Color& tint) const;
 
 
 		/**
 		/**
 		 * @brief	Creates a new material, or returns a reference to an existing one based on
 		 * @brief	Creates a new material, or returns a reference to an existing one based on
@@ -31,7 +31,7 @@ namespace BansheeEngine
 		 *			
 		 *			
 		 *			Make sure to release all materials with a call to "releaseMaterial()".
 		 *			Make sure to release all materials with a call to "releaseMaterial()".
 		 */
 		 */
-		const GUIMaterialInfo& requestImageMaterial(const CM::HTexture& texture) const;
+		const GUIMaterialInfo& requestImageMaterial(const CM::HTexture& texture, const CM::Color& tint) const;
 
 
 		/**
 		/**
 		 * @brief	Releases the held reference to the material. This allows us to fully unload a material
 		 * @brief	Releases the held reference to the material. This allows us to fully unload a material
@@ -39,6 +39,9 @@ namespace BansheeEngine
 		 */
 		 */
 		void releaseMaterial(const GUIMaterialInfo& material) const;
 		void releaseMaterial(const GUIMaterialInfo& material) const;
 
 
+		const GUIMaterialInfo* findExistingTextMaterial(const CM::HTexture& texture, const CM::Color& tint) const;
+		const GUIMaterialInfo* findExistingImageMaterial(const CM::HTexture& texture, const CM::Color& tint) const;
+
 		void forceReleaseAllMaterials();
 		void forceReleaseAllMaterials();
 	private:
 	private:
 		struct GUIMaterial
 		struct GUIMaterial

+ 2 - 0
BansheeEngine/Include/BsGUIToggle.h

@@ -32,6 +32,8 @@ namespace BansheeEngine
 		void toggleOn();
 		void toggleOn();
 		void toggleOff();
 		void toggleOff();
 
 
+		bool isToggled() const { return mIsToggled; }
+
 		virtual ElementType getElementType() const { return ElementType::Toggle; }
 		virtual ElementType getElementType() const { return ElementType::Toggle; }
 
 
 		void _setToggleGroup(std::shared_ptr<GUIToggleGroup> toggleGroup);
 		void _setToggleGroup(std::shared_ptr<GUIToggleGroup> toggleGroup);

+ 1 - 0
BansheeEngine/Include/BsImageSprite.h

@@ -20,6 +20,7 @@ namespace BansheeEngine
 		CM::Vector2 uvOffset;
 		CM::Vector2 uvOffset;
 
 
 		SpriteTexturePtr texture;
 		SpriteTexturePtr texture;
+		CM::Color color;
 		CM::UINT32 borderLeft, borderRight, borderTop, borderBottom;
 		CM::UINT32 borderLeft, borderRight, borderTop, borderBottom;
 	};
 	};
 
 

+ 1 - 0
BansheeEngine/Include/BsTextSprite.h

@@ -30,6 +30,7 @@ namespace BansheeEngine
 		CM::WString text;
 		CM::WString text;
 		CM::HFont font;
 		CM::HFont font;
 		CM::UINT32 fontSize;
 		CM::UINT32 fontSize;
+		CM::Color color;
 		TextHorzAlign horzAlign;
 		TextHorzAlign horzAlign;
 		TextVertAlign vertAlign;
 		TextVertAlign vertAlign;
 		bool wordWrap;
 		bool wordWrap;

+ 2 - 0
BansheeEngine/Source/BsBuiltinMaterialManager.cpp

@@ -30,6 +30,7 @@ namespace BansheeEngine
 		info.invViewportHeight = info.material->getParamFloat("invViewportHeight");
 		info.invViewportHeight = info.material->getParamFloat("invViewportHeight");
 		info.worldTransform = info.material->getParamMat4("worldTransform");
 		info.worldTransform = info.material->getParamMat4("worldTransform");
 		info.mainTexture = info.material->getParamTexture("mainTexture");
 		info.mainTexture = info.material->getParamTexture("mainTexture");
+		info.tint = info.material->getParamVec4("tint");
 
 
 		return info;
 		return info;
 	}
 	}
@@ -44,6 +45,7 @@ namespace BansheeEngine
 		info.invViewportHeight = info.material->getParamFloat("invViewportHeight");
 		info.invViewportHeight = info.material->getParamFloat("invViewportHeight");
 		info.worldTransform = info.material->getParamMat4("worldTransform");
 		info.worldTransform = info.material->getParamMat4("worldTransform");
 		info.mainTexture = info.material->getParamTexture("mainTexture");
 		info.mainTexture = info.material->getParamTexture("mainTexture");
+		info.tint = info.material->getParamVec4("tint");
 
 
 		return info;
 		return info;
 	}
 	}

+ 4 - 0
BansheeEngine/Source/BsBuiltinResources.cpp

@@ -24,6 +24,8 @@ namespace BansheeEngine
 	const WString BuiltinResources::DefaultSkinFolder = L"..\\..\\..\\..\\Data\\Engine\\Skin\\";
 	const WString BuiltinResources::DefaultSkinFolder = L"..\\..\\..\\..\\Data\\Engine\\Skin\\";
 	const WString BuiltinResources::DefaultCursorFolder = L"..\\..\\..\\..\\Data\\Engine\\Cursors\\";
 	const WString BuiltinResources::DefaultCursorFolder = L"..\\..\\..\\..\\Data\\Engine\\Cursors\\";
 
 
+	const WString BuiltinResources::WhiteTex = L"White.psd";
+
 	const WString BuiltinResources::ButtonNormalTex = L"ButtonNormal.psd";
 	const WString BuiltinResources::ButtonNormalTex = L"ButtonNormal.psd";
 	const WString BuiltinResources::ButtonHoverTex = L"ButtonHover.psd";
 	const WString BuiltinResources::ButtonHoverTex = L"ButtonHover.psd";
 
 
@@ -104,6 +106,8 @@ namespace BansheeEngine
 	{
 	{
 		// TODO - Normally I want to load this from some file
 		// TODO - Normally I want to load this from some file
 		
 		
+		mWhiteSpriteTexture = getSkinTexture(WhiteTex);
+
 		/************************************************************************/
 		/************************************************************************/
 		/* 								CURSOR		                     		*/
 		/* 								CURSOR		                     		*/
 		/************************************************************************/
 		/************************************************************************/

+ 6 - 2
BansheeEngine/Source/BsD3D11BuiltinMaterialFactory.cpp

@@ -108,10 +108,11 @@ namespace BansheeEngine
 		String psCode = "																			\
 		String psCode = "																			\
 			SamplerState mainTexSamp : register(s0);												\
 			SamplerState mainTexSamp : register(s0);												\
 			Texture2D mainTexture : register(t0);													\
 			Texture2D mainTexture : register(t0);													\
+			float4 tint;																			\
 																									\
 																									\
 			float4 ps_main(in float4 inPos : SV_Position, float2 uv : TEXCOORD0) : SV_Target		\
 			float4 ps_main(in float4 inPos : SV_Position, float2 uv : TEXCOORD0) : SV_Target		\
 			{																						\
 			{																						\
-				float4 color = float4(1.0f, 1.0f, 1.0f, mainTexture.Sample(mainTexSamp, uv).r);		\
+				float4 color = float4(tint.rgb, mainTexture.Sample(mainTexSamp, uv).r * tint.a);	\
 				return color;																		\
 				return color;																		\
 			}";
 			}";
 
 
@@ -128,6 +129,7 @@ namespace BansheeEngine
 		mSpriteTextShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mSpriteTextShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mSpriteTextShader->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
 		mSpriteTextShader->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
 		mSpriteTextShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 		mSpriteTextShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
+		mSpriteTextShader->addParameter("tint", "tint", GPDT_FLOAT4);
 
 
 		TechniquePtr newTechnique = mSpriteTextShader->addTechnique("D3D11RenderSystem", RendererManager::getCoreRendererName()); 
 		TechniquePtr newTechnique = mSpriteTextShader->addTechnique("D3D11RenderSystem", RendererManager::getCoreRendererName()); 
 		PassPtr newPass = newTechnique->addPass();
 		PassPtr newPass = newTechnique->addPass();
@@ -178,11 +180,12 @@ namespace BansheeEngine
 		String psCode = "																					\
 		String psCode = "																					\
 						SamplerState mainTexSamp : register(s0);											\
 						SamplerState mainTexSamp : register(s0);											\
 						Texture2D mainTexture : register(t0);												\
 						Texture2D mainTexture : register(t0);												\
+						float4 tint;																		\
 																											\
 																											\
 						float4 ps_main(in float4 inPos : SV_Position, float2 uv : TEXCOORD0) : SV_Target	\
 						float4 ps_main(in float4 inPos : SV_Position, float2 uv : TEXCOORD0) : SV_Target	\
 						{																					\
 						{																					\
 						float4 color = mainTexture.Sample(mainTexSamp, uv);									\
 						float4 color = mainTexture.Sample(mainTexSamp, uv);									\
-						return color;																		\
+						return color * tint;																\
 						}";
 						}";
 
 
 		HHighLevelGpuProgram vsProgram = HighLevelGpuProgram::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
 		HHighLevelGpuProgram vsProgram = HighLevelGpuProgram::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
@@ -198,6 +201,7 @@ namespace BansheeEngine
 		mSpriteImageShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mSpriteImageShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mSpriteImageShader->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
 		mSpriteImageShader->addParameter("mainTexSamp", "mainTexSamp", GPOT_SAMPLER2D);
 		mSpriteImageShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 		mSpriteImageShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
+		mSpriteImageShader->addParameter("tint", "tint", GPDT_FLOAT4);
 
 
 		TechniquePtr newTechnique = mSpriteImageShader->addTechnique("D3D11RenderSystem", RendererManager::getCoreRendererName()); 
 		TechniquePtr newTechnique = mSpriteImageShader->addTechnique("D3D11RenderSystem", RendererManager::getCoreRendererName()); 
 		PassPtr newPass = newTechnique->addPass();
 		PassPtr newPass = newTechnique->addPass();

+ 7 - 3
BansheeEngine/Source/BsD3D9BuiltinMaterialFactory.cpp

@@ -107,10 +107,11 @@ namespace BansheeEngine
 
 
 		String psCode = "																\
 		String psCode = "																\
 			sampler2D mainTexture;														\
 			sampler2D mainTexture;														\
+			float4 tint;																\
 																						\
 																						\
 			float4 ps_main(float2 uv : TEXCOORD0) : COLOR0								\
 			float4 ps_main(float2 uv : TEXCOORD0) : COLOR0								\
 			{																			\
 			{																			\
-				float4 color = float4(1.0f, 1.0f, 1.0f, tex2D(mainTexture, uv).r);		\
+				float4 color = float4(tint.rgb, tex2D(mainTexture, uv).r * tint.a);		\
 				return color;															\
 				return color;															\
 			}";
 			}";
 
 
@@ -127,6 +128,7 @@ namespace BansheeEngine
 		mSpriteTextShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mSpriteTextShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mSpriteTextShader->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 		mSpriteTextShader->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 		mSpriteTextShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 		mSpriteTextShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
+		mSpriteTextShader->addParameter("tint", "tint", GPDT_FLOAT4);
 
 
 		TechniquePtr newTechnique = mSpriteTextShader->addTechnique("D3D9RenderSystem", RendererManager::getCoreRendererName()); 
 		TechniquePtr newTechnique = mSpriteTextShader->addTechnique("D3D9RenderSystem", RendererManager::getCoreRendererName()); 
 		PassPtr newPass = newTechnique->addPass();
 		PassPtr newPass = newTechnique->addPass();
@@ -176,11 +178,12 @@ namespace BansheeEngine
 
 
 		String psCode = "												\
 		String psCode = "												\
 						sampler2D mainTexture;							\
 						sampler2D mainTexture;							\
-						\
+						float4 tint;									\
+																		\
 						float4 ps_main(float2 uv : TEXCOORD0) : COLOR0	\
 						float4 ps_main(float2 uv : TEXCOORD0) : COLOR0	\
 						{												\
 						{												\
 						float4 color = tex2D(mainTexture, uv);			\
 						float4 color = tex2D(mainTexture, uv);			\
-						return color;									\
+						return color * tint;							\
 						}";
 						}";
 
 
 		HHighLevelGpuProgram vsProgram = HighLevelGpuProgram::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 		HHighLevelGpuProgram vsProgram = HighLevelGpuProgram::create(vsCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
@@ -196,6 +199,7 @@ namespace BansheeEngine
 		mSpriteImageShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mSpriteImageShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mSpriteImageShader->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 		mSpriteImageShader->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 		mSpriteImageShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 		mSpriteImageShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
+		mSpriteImageShader->addParameter("tint", "tint", GPDT_FLOAT4);
 
 
 		TechniquePtr newTechnique = mSpriteImageShader->addTechnique("D3D9RenderSystem", RendererManager::getCoreRendererName()); 
 		TechniquePtr newTechnique = mSpriteImageShader->addTechnique("D3D9RenderSystem", RendererManager::getCoreRendererName()); 
 		PassPtr newPass = newTechnique->addPass();
 		PassPtr newPass = newTechnique->addPass();

+ 10 - 6
BansheeEngine/Source/BsGLBuiltinMaterialFactory.cpp

@@ -106,14 +106,15 @@ namespace BansheeEngine
 						";
 						";
 
 
 		String psCode = "#version 400\n										\
 		String psCode = "#version 400\n										\
-						\
+																			\
 						uniform sampler2D mainTexture;						\
 						uniform sampler2D mainTexture;						\
+						uniform vec4 tint;									\
 						in vec2 texcoord0;									\
 						in vec2 texcoord0;									\
 						out vec4 fragColor;									\
 						out vec4 fragColor;									\
-						\
-						void main()										\
+																			\
+						void main()											\
 						{													\
 						{													\
-						vec4 color = vec4(1.0f, 1.0f, 1.0f, texture2D(mainTexture, texcoord0.st).r);	\
+						vec4 color = vec4(tint.rgb, texture2D(mainTexture, texcoord0.st).r * tint.a);	\
 						fragColor = color;									\
 						fragColor = color;									\
 						}";
 						}";
 
 
@@ -128,6 +129,7 @@ namespace BansheeEngine
 		mSpriteTextShader->addParameter("worldTransform", "worldTransform", GPDT_MATRIX_4X4);
 		mSpriteTextShader->addParameter("worldTransform", "worldTransform", GPDT_MATRIX_4X4);
 		mSpriteTextShader->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
 		mSpriteTextShader->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
 		mSpriteTextShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mSpriteTextShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
+		mSpriteTextShader->addParameter("tint", "tint", GPDT_FLOAT4);
 		mSpriteTextShader->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 		mSpriteTextShader->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 		mSpriteTextShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 		mSpriteTextShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 
 
@@ -180,13 +182,14 @@ namespace BansheeEngine
 		String psCode = "#version 400\n										\
 		String psCode = "#version 400\n										\
 						\
 						\
 						uniform sampler2D mainTexture;						\
 						uniform sampler2D mainTexture;						\
+						uniform vec4 tint;									\
 						in vec2 texcoord0;									\
 						in vec2 texcoord0;									\
 						out vec4 fragColor;									\
 						out vec4 fragColor;									\
 						\
 						\
-						void main()										\
+						void main()											\
 						{													\
 						{													\
 						vec4 color = texture2D(mainTexture, texcoord0.st);	\
 						vec4 color = texture2D(mainTexture, texcoord0.st);	\
-						fragColor = color;									\
+						fragColor = color * tint;							\
 						}";
 						}";
 
 
 		HHighLevelGpuProgram vsProgram = HighLevelGpuProgram::create(vsCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
 		HHighLevelGpuProgram vsProgram = HighLevelGpuProgram::create(vsCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_4_0);
@@ -200,6 +203,7 @@ namespace BansheeEngine
 		mSpriteImageShader->addParameter("worldTransform", "worldTransform", GPDT_MATRIX_4X4);
 		mSpriteImageShader->addParameter("worldTransform", "worldTransform", GPDT_MATRIX_4X4);
 		mSpriteImageShader->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
 		mSpriteImageShader->addParameter("invViewportWidth", "invViewportWidth", GPDT_FLOAT1);
 		mSpriteImageShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
 		mSpriteImageShader->addParameter("invViewportHeight", "invViewportHeight", GPDT_FLOAT1);
+		mSpriteImageShader->addParameter("tint", "tint", GPDT_FLOAT4);
 		mSpriteImageShader->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 		mSpriteImageShader->addParameter("mainTexSamp", "mainTexture", GPOT_SAMPLER2D);
 		mSpriteImageShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 		mSpriteImageShader->addParameter("mainTexture", "mainTexture", GPOT_TEXTURE2D);
 
 

+ 46 - 18
BansheeEngine/Source/BsGUIMaterialManager.cpp

@@ -7,16 +7,13 @@ using namespace CamelotFramework;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	const GUIMaterialInfo& GUIMaterialManager::requestTextMaterial(const HTexture& texture) const
+	const GUIMaterialInfo& GUIMaterialManager::requestTextMaterial(const HTexture& texture, const CM::Color& tint) const
 	{
 	{
-		for(auto& matHandle : mTextMaterials)
-		{
-			if(matHandle.handle.mainTexture.get() == texture)
-			{
-				matHandle.refCount++;
-				return matHandle.handle;
-			}
-		}
+		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
+
+		const GUIMaterialInfo* matInfo = findExistingTextMaterial(texture, tint);
+		if(matInfo != nullptr)
+			return *matInfo;
 
 
 		mTextMaterials.push_back(GUIMaterial());
 		mTextMaterials.push_back(GUIMaterial());
 
 
@@ -24,21 +21,19 @@ namespace BansheeEngine
 		guiMat.handle = BuiltinMaterialManager::instance().createSpriteTextMaterial();
 		guiMat.handle = BuiltinMaterialManager::instance().createSpriteTextMaterial();
 
 
 		guiMat.handle.mainTexture.set(texture);
 		guiMat.handle.mainTexture.set(texture);
+		guiMat.handle.tint.set(vecColor);
 		guiMat.refCount = 1;		
 		guiMat.refCount = 1;		
 
 
 		return guiMat.handle;
 		return guiMat.handle;
 	}
 	}
 
 
-	const GUIMaterialInfo& GUIMaterialManager::requestImageMaterial(const HTexture& texture) const
+	const GUIMaterialInfo& GUIMaterialManager::requestImageMaterial(const HTexture& texture, const CM::Color& tint) const
 	{
 	{
-		for(auto& matHandle : mImageMaterials)
-		{
-			if(matHandle.handle.mainTexture.get() == texture)
-			{
-				matHandle.refCount++;
-				return matHandle.handle;
-			}
-		}
+		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
+
+		const GUIMaterialInfo* matInfo = findExistingImageMaterial(texture, tint);
+		if(matInfo != nullptr)
+			return *matInfo;
 
 
 		mImageMaterials.push_back(GUIMaterial());
 		mImageMaterials.push_back(GUIMaterial());
 
 
@@ -46,11 +41,44 @@ namespace BansheeEngine
 		guiMat.handle = BuiltinMaterialManager::instance().createSpriteImageMaterial();
 		guiMat.handle = BuiltinMaterialManager::instance().createSpriteImageMaterial();
 
 
 		guiMat.handle.mainTexture.set(texture);
 		guiMat.handle.mainTexture.set(texture);
+		guiMat.handle.tint.set(vecColor);
 		guiMat.refCount = 1;		
 		guiMat.refCount = 1;		
 
 
 		return guiMat.handle;
 		return guiMat.handle;
 	}
 	}
 
 
+	const GUIMaterialInfo* GUIMaterialManager::findExistingTextMaterial(const CM::HTexture& texture, const CM::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.refCount++;
+				return &matHandle.handle;
+			}
+		}
+
+		return nullptr;
+	}
+
+	const GUIMaterialInfo* GUIMaterialManager::findExistingImageMaterial(const CM::HTexture& texture, const CM::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.refCount++;
+				return &matHandle.handle;
+			}
+		}
+
+		return nullptr;
+	}
+
 	void GUIMaterialManager::releaseMaterial(const GUIMaterialInfo& material) const
 	void GUIMaterialManager::releaseMaterial(const GUIMaterialInfo& material) const
 	{
 	{
 		bool released = false;
 		bool released = false;

+ 11 - 3
BansheeEngine/Source/BsImageSprite.cpp

@@ -63,15 +63,23 @@ namespace BansheeEngine
 				getNewMaterial = true;
 				getNewMaterial = true;
 			else
 			else
 			{
 			{
-				if(renderElem.matInfo.mainTexture.get() != tex)
+				const GUIMaterialInfo* matInfo = GUIMaterialManager::instance().findExistingImageMaterial(tex, desc.color);
+				if(matInfo == nullptr)
 				{
 				{
-					GUIMaterialManager::instance().releaseMaterial(renderElem.matInfo);
 					getNewMaterial = true;
 					getNewMaterial = true;
 				}
 				}
+				else
+				{
+					if(matInfo->material != renderElem.matInfo.material)
+					{
+						GUIMaterialManager::instance().releaseMaterial(renderElem.matInfo);
+						getNewMaterial = true;
+					}
+				}
 			}
 			}
 
 
 			if(getNewMaterial)
 			if(getNewMaterial)
-				renderElem.matInfo = GUIMaterialManager::instance().requestImageMaterial(tex);
+				renderElem.matInfo = GUIMaterialManager::instance().requestImageMaterial(tex, desc.color);
 
 
 			texPage++;
 			texPage++;
 		}
 		}

+ 11 - 3
BansheeEngine/Source/BsTextSprite.cpp

@@ -85,15 +85,23 @@ namespace BansheeEngine
 				getNewMaterial = true;
 				getNewMaterial = true;
 			else
 			else
 			{
 			{
-				if(cachedElem.matInfo.mainTexture.get() != tex)
+				const GUIMaterialInfo* matInfo = GUIMaterialManager::instance().findExistingImageMaterial(tex, desc.color);
+				if(matInfo == nullptr)
 				{
 				{
-					GUIMaterialManager::instance().releaseMaterial(cachedElem.matInfo);
 					getNewMaterial = true;
 					getNewMaterial = true;
 				}
 				}
+				else
+				{
+					if(matInfo->material != cachedElem.matInfo.material)
+					{
+						GUIMaterialManager::instance().releaseMaterial(cachedElem.matInfo);
+						getNewMaterial = true;
+					}
+				}
 			}
 			}
 
 
 			if(getNewMaterial)
 			if(getNewMaterial)
-				cachedElem.matInfo = GUIMaterialManager::instance().requestTextMaterial(tex);
+				cachedElem.matInfo = GUIMaterialManager::instance().requestTextMaterial(tex, desc.color);
 
 
 			texPage++;
 			texPage++;
 		}
 		}

+ 1 - 1
CamelotD3D11RenderSystem/Source/CmD3D11HLSLParamParser.cpp

@@ -85,7 +85,7 @@ namespace CamelotFramework
 				blockDesc.slot = resourceDesc.BindPoint + i;
 				blockDesc.slot = resourceDesc.BindPoint + i;
 				blockDesc.blockSize = 0; // Calculated manually as we add parameters
 				blockDesc.blockSize = 0; // Calculated manually as we add parameters
 
 
-				if(resourceDesc.Name == "$Global" || resourceDesc.Name == "$Param") // Special buffers, as defined by DX11 docs
+				if(strcmp(resourceDesc.Name, "$Globals") == 0 || strcmp(resourceDesc.Name, "$Param") == 0) // Special buffers, as defined by DX11 docs
 					blockDesc.isShareable = false;
 					blockDesc.isShareable = false;
 				else
 				else
 					blockDesc.isShareable = true;
 					blockDesc.isShareable = true;

+ 32 - 0
Inspector.txt

@@ -22,6 +22,38 @@ Other:
 
 
 -------------
 -------------
 
 
+How will I add editor fields to GUILayout? Right now I have a bunch of Add* methods and that won't work for Editor-only fields. I could extend GUILayout to EditorGUILayout but then GUIArea needs to be aware of that as well...
+
+GUIElement has GetChild/GetNumChildren, which isn't really useful for elements like GUIToggle, GUIButton, etc.
+ - GUIElements and GUILayout should still share same base class, but make it GUIElementBase, that doesn't include children
+
+Refactor GUILayout so it has AddElement, RemoveElement, InsertElement, GetChildren, GetNumChildren methods
+ - GUIElement reference should be kept by parent layout, so if it is ever removed (or never added) it will get garbage collected and destroyed
+
+Layouts/Areas/Elements need SetVisible(true/false) toggle
+
+-------------
+Implementation order:
+
+Today:
+ - Ensure color and toggle compile correctly
+ - Add normal toggle icon (I think I already have the graphic)
+ - Component foldout
+
+Then:
+ - GameObject/resource field
+ - Matrix fields
+ - Refactor C# GUI
+ - Basic InspectableObject and basic Inspector that open Inspector window, display SceneManager base fields and a list of components
+ - Per-component generic and custom inspectors
+
+-------------
+IMPORTANT:
+ - I should probably consider making each Component part of the inspector its own separate GUIWidget, otherwise I wont
+   be able to use multiple GUIAreas in the Inspectors, which is fairly limiting.
+     - Each has a separate EditorGUI instance?
+
+
 TOMORROW:
 TOMORROW:
  - InspectableObject calls a C++ method which gets all SerializableFields, and C++ in turn
  - InspectableObject calls a C++ method which gets all SerializableFields, and C++ in turn
    generates a list of InspectableFields
    generates a list of InspectableFields