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

Removed GUILayoutEntry and made spaces derived from GUIElementBase

Marko Pintera 12 лет назад
Родитель
Сommit
73ff6dc3c4

+ 1 - 0
BansheeEngine/Include/BsGUIElement.h

@@ -96,6 +96,7 @@ namespace BansheeEngine
 		CM::UINT32 _getHeight() const { return mHeight; }
 		CM::Int2 _getOffset() const { return mOffset; }
 		virtual CM::UINT32 _getRenderElementDepth(CM::UINT32 renderElementIdx) const { return _getDepth(); }
+		Type _getType() const { return GUIElementBase::Type::Element; }
 
 		const CM::Rect& _getBounds() const { return mBounds; }
 		CM::UINT32 _getDepth() const { return mDepth; }

+ 3 - 44
BansheeEngine/Include/BsGUIElementBase.h

@@ -9,7 +9,7 @@ namespace BansheeEngine
 {
 	class BS_EXPORT GUIElementBase
 	{
-	protected:
+	public:
 		enum class Type
 		{
 			Layout,
@@ -18,48 +18,6 @@ namespace BansheeEngine
 			FlexibleSpace
 		};
 
-		struct GUILayoutEntry
-		{
-			union
-			{
-				GUIElement* element;
-				GUILayout* layout;
-				GUIFixedSpace* space;
-				GUIFlexibleSpace* flexibleSpace;
-			};
-
-			bool isElement() const { return mType == Type::Element; }
-			bool isLayout() const { return mType == Type::Layout; }
-			bool isFixedSpace() const { return mType == Type::FixedSpace; }
-			bool isFlexibleSpace() const { return mType == Type::FlexibleSpace; }
-
-			void setElement(GUIElement* _element)
-			{
-				element = _element;
-				mType = Type::Element;
-			}
-
-			void setLayout(GUILayout* _layout)
-			{
-				layout = _layout;
-				mType = Type::Layout;
-			}
-
-			void setSpace(GUIFixedSpace* _space)
-			{
-				space = _space;
-				mType = Type::FixedSpace;
-			}
-
-			void setFlexibleSpace(GUIFlexibleSpace* _space)
-			{
-				flexibleSpace = _space;
-				mType = Type::FlexibleSpace;
-			}
-
-			Type mType;
-		};
-
 	public:
 		GUIElementBase();
 		virtual ~GUIElementBase() {}
@@ -77,6 +35,7 @@ namespace BansheeEngine
 
 		virtual CM::UINT32 _getOptimalWidth() const = 0;
 		virtual CM::UINT32 _getOptimalHeight() const = 0;
+		virtual Type _getType() const = 0;
 
 		GUILayout* _getParentLayout() const { return mParentLayout; }
 		void _setParentLayout(GUILayout* layout) { mParentLayout = layout; }
@@ -100,7 +59,7 @@ namespace BansheeEngine
 		void markMeshAsDirty();
 
 		GUILayout* mParentLayout;
-		CM::Vector<GUILayoutEntry>::type mChildren;	
+		CM::Vector<GUIElementBase*>::type mChildren;	
 		CM::UINT8 mIsDirty;
 	};
 }

+ 1 - 0
BansheeEngine/Include/BsGUILayout.h

@@ -37,6 +37,7 @@ namespace BansheeEngine
 
 		CM::UINT32 _getOptimalWidth() const { return mOptimalWidth; }
 		CM::UINT32 _getOptimalHeight() const { return mOptimalHeight; }
+		Type _getType() const { return GUIElementBase::Type::Layout; }
 
 	protected:
 		CM::Vector<CM::Int2>::type mOptimalSizes;

+ 13 - 5
BansheeEngine/Include/BsGUISpace.h

@@ -1,27 +1,35 @@
 #pragma once
 
 #include "BsPrerequisites.h"
+#include "BsGUIElementBase.h"
 
 namespace BansheeEngine
 {
-	class BS_EXPORT GUIFixedSpace
+	class BS_EXPORT GUIFixedSpace : public GUIElementBase
 	{
 	public:
 		GUIFixedSpace(CM::UINT32 size)
 			:mSize(size)
-		{
-
-		}
+		{ }
 
 		CM::UINT32 getSize() const { return mSize; }
+		Type _getType() const { return GUIElementBase::Type::FixedSpace; }
+
+		virtual CM::UINT32 _getOptimalWidth() const { return getSize(); }
+		virtual CM::UINT32 _getOptimalHeight() const { return getSize(); }
 
 	protected:
 		CM::UINT32 mSize;
 	};
 
-	class BS_EXPORT GUIFlexibleSpace
+	class BS_EXPORT GUIFlexibleSpace : public GUIElementBase
 	{
 	public:
 		GUIFlexibleSpace() {}
+
+		Type _getType() const { return GUIElementBase::Type::FlexibleSpace; }
+
+		virtual CM::UINT32 _getOptimalWidth() const { return 0; }
+		virtual CM::UINT32 _getOptimalHeight() const { return 0; }
 	};
 }

+ 6 - 6
BansheeEngine/Source/BsGUIElementBase.cpp

@@ -18,9 +18,9 @@ namespace BansheeEngine
 
 		for(auto& child : mChildren)
 		{
-			if(child.isLayout())
+			if(child->_getType() == Type::Layout)
 			{
-				if(child.layout->_isContentDirty())
+				if(child->_isContentDirty())
 					return true;
 			}
 		}
@@ -59,8 +59,8 @@ namespace BansheeEngine
 	{
 		for(auto& child : mChildren)
 		{
-			if(child.isLayout())
-				child.layout->_updateOptimalLayoutSizes();
+			if(child->_getType() == Type::Layout)
+				child->_updateOptimalLayoutSizes();
 		}
 	}
 
@@ -68,8 +68,8 @@ namespace BansheeEngine
 	{
 		for(auto& child : mChildren)
 		{
-			if(child.isLayout())
-				child.layout->_updateLayout(x, y, width, height, widgetDepth, areaDepth);
+			if(child->_getType() == Type::Layout)
+				child->_updateLayout(x, y, width, height, widgetDepth, areaDepth);
 		}
 	}
 }

+ 33 - 59
BansheeEngine/Source/BsGUILayout.cpp

@@ -19,23 +19,11 @@ namespace BansheeEngine
 	{
 		for(auto& child : mChildren)
 		{
-			if(child.isLayout())
-			{
-				// Child layouts are directly owned by us
-				cm_delete<PoolAlloc>(child.layout);
-			}
-			else if(child.isFixedSpace())
-			{
-				cm_delete<PoolAlloc>(child.space);
-			}
-			else if(child.isFlexibleSpace())
-			{
-				cm_delete<PoolAlloc>(child.flexibleSpace);
-			}
+			// Non-GUIElement are owned by us
+			if(child->_getType() != GUIElementBase::Type::Element)
+				cm_delete<PoolAlloc>(child);
 			else
-			{
-				child.element->_setParentLayout(nullptr);
-			}
+				child->_setParentLayout(nullptr);
 		}
 	}
 
@@ -44,11 +32,8 @@ namespace BansheeEngine
 		if(element->_getParentLayout() != nullptr)
 			element->_getParentLayout()->removeElement(element);
 
-		GUILayoutEntry entry;
-		entry.setElement(element);
-
 		element->_setParentLayout(this);
-		mChildren.push_back(entry);
+		mChildren.push_back(element);
 
 		markContentAsDirty();
 	}
@@ -58,9 +43,9 @@ namespace BansheeEngine
 		bool foundElem = false;
 		for(auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
 		{
-			GUILayoutEntry& child = *iter;
+			GUIElementBase* child = *iter;
 
-			if(child.isElement() && child.element == element)
+			if(child->_getType() == GUIElementBase::Type::Element && child == element)
 			{
 				mChildren.erase(iter);
 				foundElem = true;
@@ -82,35 +67,30 @@ namespace BansheeEngine
 		if(element->_getParentLayout() != nullptr)
 			element->_getParentLayout()->removeElement(element);
 
-		GUILayoutEntry entry;
-		entry.setElement(element);
-
 		element->_setParentLayout(this);
-		mChildren.insert(mChildren.begin() + idx, entry);
+		mChildren.insert(mChildren.begin() + idx, element);
 		
 		markContentAsDirty();
 	}
 
 	GUILayout& GUILayout::addLayoutX()
 	{
-		GUILayoutEntry entry;
-		entry.setLayout(cm_new<GUILayoutX, PoolAlloc>());
+		GUILayoutX* entry = cm_new<GUILayoutX, PoolAlloc>();
 
 		mChildren.push_back(entry);
 		markContentAsDirty();
 
-		return *entry.layout;
+		return *entry;
 	}
 
 	GUILayout& GUILayout::addLayoutY()
 	{
-		GUILayoutEntry entry;
-		entry.setLayout(cm_new<GUILayoutY, PoolAlloc>());
+		GUILayoutY* entry = cm_new<GUILayoutY, PoolAlloc>();
 
 		mChildren.push_back(entry);
 		markContentAsDirty();
 
-		return *entry.layout;
+		return *entry;
 	}
 
 	void GUILayout::removeLayout(GUILayout& layout)
@@ -118,11 +98,11 @@ namespace BansheeEngine
 		bool foundElem = false;
 		for(auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
 		{
-			GUILayoutEntry& child = *iter;
+			GUIElementBase* child = *iter;
 
-			if(child.isLayout() && child.layout == &layout)
+			if(child->_getType() == GUIElementBase::Type::Layout && child == &layout)
 			{
-				cm_delete<PoolAlloc>(child.layout);
+				cm_delete<PoolAlloc>(child);
 
 				mChildren.erase(iter);
 				foundElem = true;
@@ -140,13 +120,12 @@ namespace BansheeEngine
 		if(idx < 0 || idx >= (UINT32)mChildren.size())
 			CM_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx) + ". Valid range: 0 .. " + toString((UINT32)mChildren.size()));
 
-		GUILayoutEntry entry;
-		entry.setLayout(cm_new<GUILayoutX, PoolAlloc>());
+		GUILayoutX* entry = cm_new<GUILayoutX, PoolAlloc>();
 
 		mChildren.insert(mChildren.begin() + idx, entry);
 		markContentAsDirty();
 
-		return *entry.layout;
+		return *entry;
 	}
 
 	GUILayout& GUILayout::insertLayoutY(UINT32 idx)
@@ -154,24 +133,22 @@ namespace BansheeEngine
 		if(idx < 0 || idx >= (UINT32)mChildren.size())
 			CM_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx) + ". Valid range: 0 .. " + toString((UINT32)mChildren.size()));
 
-		GUILayoutEntry entry;
-		entry.setLayout(cm_new<GUILayoutY, PoolAlloc>());;
+		GUILayoutY* entry = cm_new<GUILayoutY, PoolAlloc>();
 
 		mChildren.insert(mChildren.begin() + idx, entry);
 		markContentAsDirty();
 
-		return *entry.layout;
+		return *entry;
 	}
 
 	GUIFixedSpace& GUILayout::addSpace(UINT32 size)
 	{
-		GUILayoutEntry entry;
-		entry.setSpace(cm_new<GUIFixedSpace, PoolAlloc>(size));
+		GUIFixedSpace* entry = cm_new<GUIFixedSpace, PoolAlloc>(size);
 
 		mChildren.push_back(entry);
 		markContentAsDirty();
 
-		return *entry.space;
+		return *entry;
 	}
 
 	void GUILayout::removeSpace(GUIFixedSpace& space)
@@ -179,11 +156,11 @@ namespace BansheeEngine
 		bool foundElem = false;
 		for(auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
 		{
-			GUILayoutEntry& child = *iter;
+			GUIElementBase* child = *iter;
 
-			if(child.isFixedSpace() && child.space == &space)
+			if(child->_getType() == GUIElementBase::Type::FixedSpace && child == &space)
 			{
-				cm_delete<PoolAlloc>(child.space);
+				cm_delete<PoolAlloc>(child);
 
 				mChildren.erase(iter);
 				foundElem = true;
@@ -201,24 +178,22 @@ namespace BansheeEngine
 		if(idx < 0 || idx >= (UINT32)mChildren.size())
 			CM_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx) + ". Valid range: 0 .. " + toString((UINT32)mChildren.size()));
 
-		GUILayoutEntry entry;
-		entry.setSpace(cm_new<GUIFixedSpace, PoolAlloc>(size));
+		GUIFixedSpace* entry = cm_new<GUIFixedSpace, PoolAlloc>(size);
 
 		mChildren.insert(mChildren.begin() + idx, entry);
 		markContentAsDirty();
 
-		return *entry.space;
+		return *entry;
 	}
 
 	GUIFlexibleSpace& GUILayout::addFlexibleSpace()
 	{
-		GUILayoutEntry entry;
-		entry.setFlexibleSpace(cm_new<GUIFlexibleSpace, PoolAlloc>());
+		GUIFlexibleSpace* entry = cm_new<GUIFlexibleSpace, PoolAlloc>();
 
 		mChildren.push_back(entry);
 		markContentAsDirty();
 
-		return *entry.flexibleSpace;
+		return *entry;
 	}
 
 	void GUILayout::removeFlexibleSpace(GUIFlexibleSpace& space)
@@ -226,11 +201,11 @@ namespace BansheeEngine
 		bool foundElem = false;
 		for(auto iter = mChildren.begin(); iter != mChildren.end(); ++iter)
 		{
-			GUILayoutEntry& child = *iter;
+			GUIElementBase* child = *iter;
 
-			if(child.isFlexibleSpace() && child.flexibleSpace == &space)
+			if(child->_getType() == GUIElementBase::Type::FlexibleSpace && child == &space)
 			{
-				cm_delete<PoolAlloc>(child.flexibleSpace);
+				cm_delete<PoolAlloc>(child);
 
 				mChildren.erase(iter);
 				foundElem = true;
@@ -248,13 +223,12 @@ namespace BansheeEngine
 		if(idx < 0 || idx >= (UINT32)mChildren.size())
 			CM_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx) + ". Valid range: 0 .. " + toString((UINT32)mChildren.size()));
 
-		GUILayoutEntry entry;
-		entry.setFlexibleSpace(cm_new<GUIFlexibleSpace, PoolAlloc>());
+		GUIFlexibleSpace* entry = cm_new<GUIFlexibleSpace, PoolAlloc>();
 
 		mChildren.insert(mChildren.begin() + idx, entry);
 		markContentAsDirty();
 
-		return *entry.flexibleSpace;
+		return *entry;
 	}
 
 	UINT32 GUILayout::getNumChildren() const

+ 44 - 37
BansheeEngine/Source/BsGUILayoutX.cpp

@@ -13,8 +13,8 @@ namespace BansheeEngine
 		// Update all children first, otherwise we can't determine out own optimal size
 		for(auto& child : mChildren)
 		{
-			if(child.isLayout())
-				child.layout->_updateOptimalLayoutSizes();
+			if(child->_getType() == GUIElementBase::Type::Layout)
+				child->_updateOptimalLayoutSizes();
 		}
 
 		if(mChildren.size() != mOptimalSizes.size())
@@ -29,13 +29,15 @@ namespace BansheeEngine
 			UINT32 optimalWidth = 0;
 			UINT32 optimalHeight = 0;
 
-			if(child.isFixedSpace())
+			if(child->_getType() == GUIElementBase::Type::FixedSpace)
 			{
-				optimalWidth = child.space->getSize();
+				GUIFixedSpace* space = static_cast<GUIFixedSpace*>(child);
+				optimalWidth = space->getSize();
 			}
-			else if(child.isElement())
+			else if(child->_getType() == GUIElementBase::Type::Element)
 			{
-				const GUILayoutOptions& layoutOptions = child.element->_getLayoutOptions();
+				GUIElement* element = static_cast<GUIElement*>(child);
+				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 
 				if(layoutOptions.fixedWidth)
 				{
@@ -43,7 +45,7 @@ namespace BansheeEngine
 				}
 				else
 				{
-					optimalWidth = child.element->_getOptimalWidth();
+					optimalWidth = child->_getOptimalWidth();
 
 					if(layoutOptions.minWidth > 0)
 						optimalWidth = std::max(layoutOptions.minWidth, optimalWidth);
@@ -56,7 +58,7 @@ namespace BansheeEngine
 					optimalHeight = layoutOptions.height;
 				else
 				{
-					optimalHeight = child.element->_getOptimalHeight();
+					optimalHeight = child->_getOptimalHeight();
 
 					if(layoutOptions.minHeight > 0)
 						optimalHeight = std::max(layoutOptions.minHeight, optimalHeight);
@@ -65,9 +67,9 @@ namespace BansheeEngine
 						optimalHeight = std::min(layoutOptions.maxHeight, optimalHeight);
 				}
 			}
-			else if(child.isLayout())
+			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
-				optimalWidth = child.layout->_getOptimalWidth();
+				optimalWidth = child->_getOptimalWidth();
 			}
 
 			mOptimalSizes[childIdx].x = optimalWidth;
@@ -102,13 +104,14 @@ namespace BansheeEngine
 		{
 			elementSizes[childIdx] = mOptimalSizes[childIdx].x;
 
-			if(child.isFixedSpace())
+			if(child->_getType() == GUIElementBase::Type::FixedSpace)
 			{
 				processedElements[childIdx] = true;
 			}
-			else if(child.isElement())
+			else if(child->_getType() == GUIElementBase::Type::Element)
 			{
-				const GUILayoutOptions& layoutOptions = child.element->_getLayoutOptions();
+				GUIElement* element = static_cast<GUIElement*>(child);
+				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 
 				if(layoutOptions.fixedWidth)
 					processedElements[childIdx] = true;
@@ -118,12 +121,12 @@ namespace BansheeEngine
 					totalNonClampedSize += elementSizes[childIdx];
 				}
 			}
-			else if(child.isLayout())
+			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
 				numNonClampedElements++;
 				totalNonClampedSize += elementSizes[childIdx];
 			}
-			else if(child.isFlexibleSpace())
+			else if(child->_getType() == GUIElementBase::Type::FlexibleSpace)
 			{
 				numFlexibleSpaces++;
 				numNonClampedElements++;
@@ -156,7 +159,7 @@ namespace BansheeEngine
 					UINT32 elementWidth = elementSizes[childIdx] + extraWidth;
 
 					// Clamp if needed
-					if(child.isFlexibleSpace())
+					if(child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					{
 						processedElements[childIdx] = true;
 						numNonClampedElements--;
@@ -216,9 +219,10 @@ namespace BansheeEngine
 					UINT32 elementWidth = (UINT32)std::max(0, (INT32)elementSizes[childIdx] - (INT32)extraWidth);
 
 					// Clamp if needed
-					if(child.isElement())
+					if(child->_getType() == GUIElementBase::Type::Element)
 					{
-						const GUILayoutOptions& layoutOptions = child.element->_getLayoutOptions();
+						GUIElement* element = static_cast<GUIElement*>(child);
+						const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 
 						if(elementWidth == 0)
 						{
@@ -237,7 +241,7 @@ namespace BansheeEngine
 						elementSizes[childIdx] = elementWidth;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraWidth);
 					}
-					else if(child.isLayout())
+					else if(child->_getType() == GUIElementBase::Type::Layout)
 					{
 						if(elementWidth == 0)
 						{
@@ -249,7 +253,7 @@ namespace BansheeEngine
 						elementSizes[childIdx] = elementWidth;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraWidth);
 					}
-					else if(child.isFlexibleSpace())
+					else if(child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					{
 						elementSizes[childIdx] = 0;
 						processedElements[childIdx] = true;
@@ -285,9 +289,10 @@ namespace BansheeEngine
 					UINT32 elementWidth = elementSizes[childIdx] + extraWidth;
 
 					// Clamp if needed
-					if(child.isElement())
+					if(child->_getType() == GUIElementBase::Type::Element)
 					{
-						const GUILayoutOptions& layoutOptions = child.element->_getLayoutOptions();
+						GUIElement* element = static_cast<GUIElement*>(child);
+						const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 
 						if(elementWidth == 0)
 						{
@@ -306,12 +311,12 @@ namespace BansheeEngine
 						elementSizes[childIdx] = elementWidth;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraWidth);
 					}
-					else if(child.isLayout())
+					else if(child->_getType() == GUIElementBase::Type::Layout)
 					{
 						elementSizes[childIdx] = elementWidth;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraWidth);
 					}
-					else if(child.isFlexibleSpace())
+					else if(child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					{
 						processedElements[childIdx] = true;
 						numNonClampedElements--;
@@ -330,12 +335,13 @@ namespace BansheeEngine
 		{
 			UINT32 elementWidth = elementSizes[childIdx];
 
-			if(child.isElement())
+			if(child->_getType() == GUIElementBase::Type::Element)
 			{
-				child.element->_setWidth(elementWidth);
+				GUIElement* element = static_cast<GUIElement*>(child);
+				element->_setWidth(elementWidth);
 
 				UINT32 elemHeight = mOptimalSizes[childIdx].y;
-				const GUILayoutOptions& layoutOptions = child.element->_getLayoutOptions();
+				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 				if(!layoutOptions.fixedHeight)
 				{
 					elemHeight = height;
@@ -346,23 +352,24 @@ namespace BansheeEngine
 						elemHeight = layoutOptions.maxHeight;
 				}
 
-				child.element->_setHeight(elemHeight);
+				element->_setHeight(elemHeight);
 
-				UINT32 yOffset = (UINT32)Math::CeilToInt((height - child.element->_getHeight()) * 0.5f);
+				UINT32 yOffset = (UINT32)Math::CeilToInt((height - element->_getHeight()) * 0.5f);
 
 				Int2 offset(x + xOffset, y + yOffset);
-				child.element->_setOffset(offset);
-				child.element->_setWidgetDepth(widgetDepth);
-				child.element->_setAreaDepth(areaDepth);
+				element->_setOffset(offset);
+				element->_setWidgetDepth(widgetDepth);
+				element->_setAreaDepth(areaDepth);
 
-				UINT32 clippedWidth = (UINT32)std::min((INT32)child.element->_getWidth(), (INT32)width - (INT32)xOffset);
-				UINT32 clippedHeight = (UINT32)std::min((INT32)child.element->_getHeight(), (INT32)height - (INT32)yOffset);
+				UINT32 clippedWidth = (UINT32)std::min((INT32)element->_getWidth(), (INT32)width - (INT32)xOffset);
+				UINT32 clippedHeight = (UINT32)std::min((INT32)element->_getHeight(), (INT32)height - (INT32)yOffset);
 
-				child.element->_setClipRect(Rect(0, 0, clippedWidth, clippedHeight));
+				element->_setClipRect(Rect(0, 0, clippedWidth, clippedHeight));
 			}
-			else if(child.isLayout())
+			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
-				child.layout->_updateLayout(x + xOffset, y, elementWidth, height, widgetDepth, areaDepth);
+				GUILayout* layout = static_cast<GUILayout*>(child);
+				layout->_updateLayout(x + xOffset, y, elementWidth, height, widgetDepth, areaDepth);
 			}
 
 			xOffset += elementWidth;

+ 45 - 37
BansheeEngine/Source/BsGUILayoutY.cpp

@@ -13,8 +13,8 @@ namespace BansheeEngine
 		// Update all children first, otherwise we can't determine out own optimal size
 		for(auto& child : mChildren)
 		{
-			if(child.isLayout())
-				child.layout->_updateOptimalLayoutSizes();
+			if(child->_getType() == GUIElementBase::Type::Layout)
+				child->_updateOptimalLayoutSizes();
 		}
 
 		if(mChildren.size() != mOptimalSizes.size())
@@ -29,13 +29,15 @@ namespace BansheeEngine
 			UINT32 optimalWidth = 0;
 			UINT32 optimalHeight = 0;
 
-			if(child.isFixedSpace())
+			if(child->_getType() == GUIElementBase::Type::FixedSpace)
 			{
-				optimalHeight = child.space->getSize();
+				GUIFixedSpace* fixedSpace = static_cast<GUIFixedSpace*>(child);
+				optimalHeight = fixedSpace->getSize();
 			}
-			else if(child.isElement())
+			else if(child->_getType() == GUIElementBase::Type::Element)
 			{
-				const GUILayoutOptions& layoutOptions = child.element->_getLayoutOptions();
+				GUIElement* element = static_cast<GUIElement*>(child);
+				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 
 				if(layoutOptions.fixedHeight)
 				{
@@ -43,7 +45,7 @@ namespace BansheeEngine
 				}
 				else
 				{
-					optimalHeight = child.element->_getOptimalHeight();
+					optimalHeight = element->_getOptimalHeight();
 
 					if(layoutOptions.minHeight > 0)
 						optimalHeight = std::max(layoutOptions.minHeight, optimalHeight);
@@ -56,7 +58,7 @@ namespace BansheeEngine
 					optimalWidth = layoutOptions.width;
 				else
 				{
-					optimalWidth = child.element->_getOptimalWidth();
+					optimalWidth = element->_getOptimalWidth();
 
 					if(layoutOptions.minWidth > 0)
 						optimalWidth = std::max(layoutOptions.minWidth, optimalWidth);
@@ -65,9 +67,10 @@ namespace BansheeEngine
 						optimalWidth = std::min(layoutOptions.maxWidth, optimalWidth);
 				}
 			}
-			else if(child.isLayout())
+			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
-				optimalHeight = child.layout->_getOptimalHeight();
+				GUILayout* layout = static_cast<GUILayout*>(child);
+				optimalHeight = layout->_getOptimalHeight();
 			}
 
 			mOptimalSizes[childIdx].y = optimalHeight;
@@ -102,13 +105,14 @@ namespace BansheeEngine
 		{
 			elementSizes[childIdx] = mOptimalSizes[childIdx].y;
 
-			if(child.isFixedSpace())
+			if(child->_getType() == GUIElementBase::Type::FixedSpace)
 			{
 				processedElements[childIdx] = true;
 			}
-			else if(child.isElement())
+			else if(child->_getType() == GUIElementBase::Type::Element)
 			{
-				const GUILayoutOptions& layoutOptions = child.element->_getLayoutOptions();
+				GUIElement* element = static_cast<GUIElement*>(child);
+				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 
 				if(layoutOptions.fixedHeight)
 					processedElements[childIdx] = true;
@@ -118,12 +122,12 @@ namespace BansheeEngine
 					totalNonClampedSize += elementSizes[childIdx];
 				}
 			}
-			else if(child.isLayout())
+			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
 				numNonClampedElements++;
 				totalNonClampedSize += elementSizes[childIdx];
 			}
-			else if(child.isFlexibleSpace())
+			else if(child->_getType() == GUIElementBase::Type::FlexibleSpace)
 			{
 				numFlexibleSpaces++;
 				numNonClampedElements++;
@@ -156,7 +160,7 @@ namespace BansheeEngine
 					UINT32 elementHeight = elementSizes[childIdx] + extraHeight;
 
 					// Clamp if needed
-					if(child.isFlexibleSpace())
+					if(child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					{
 						processedElements[childIdx] = true;
 						numNonClampedElements--;
@@ -216,9 +220,10 @@ namespace BansheeEngine
 					UINT32 elementHeight = (UINT32)std::max(0, (INT32)elementSizes[childIdx] - (INT32)extraHeight);
 
 					// Clamp if needed
-					if(child.isElement())
+					if(child->_getType() == GUIElementBase::Type::Element)
 					{
-						const GUILayoutOptions& layoutOptions = child.element->_getLayoutOptions();
+						GUIElement* element = static_cast<GUIElement*>(child);
+						const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 
 						if(elementHeight == 0)
 						{
@@ -237,7 +242,7 @@ namespace BansheeEngine
 						elementSizes[childIdx] = elementHeight;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraHeight);
 					}
-					else if(child.isLayout())
+					else if(child->_getType() == GUIElementBase::Type::Layout)
 					{
 						if(elementHeight == 0)
 						{
@@ -249,7 +254,7 @@ namespace BansheeEngine
 						elementSizes[childIdx] = elementHeight;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraHeight);
 					}
-					else if(child.isFlexibleSpace())
+					else if(child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					{
 						elementSizes[childIdx] = 0;
 						processedElements[childIdx] = true;
@@ -285,9 +290,10 @@ namespace BansheeEngine
 					UINT32 elementHeight = elementSizes[childIdx] + extraHeight;
 
 					// Clamp if needed
-					if(child.isElement())
+					if(child->_getType() == GUIElementBase::Type::Element)
 					{
-						const GUILayoutOptions& layoutOptions = child.element->_getLayoutOptions();
+						GUIElement* element = static_cast<GUIElement*>(child);
+						const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 
 						if(elementHeight == 0)
 						{
@@ -306,12 +312,12 @@ namespace BansheeEngine
 						elementSizes[childIdx] = elementHeight;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraHeight);
 					}
-					else if(child.isLayout())
+					else if(child->_getType() == GUIElementBase::Type::Layout)
 					{
 						elementSizes[childIdx] = elementHeight;
 						remainingSize = (UINT32)std::max(0, (INT32)remainingSize - (INT32)extraHeight);
 					}
-					else if(child.isFlexibleSpace())
+					else if(child->_getType() == GUIElementBase::Type::FlexibleSpace)
 					{
 						processedElements[childIdx] = true;
 						numNonClampedElements--;
@@ -330,10 +336,11 @@ namespace BansheeEngine
 		{
 			UINT32 elementHeight = elementSizes[childIdx];
 
-			if(child.isElement())
+			if(child->_getType() == GUIElementBase::Type::Element)
 			{
+				GUIElement* element = static_cast<GUIElement*>(child);
 				UINT32 elemWidth = mOptimalSizes[childIdx].x;
-				const GUILayoutOptions& layoutOptions = child.element->_getLayoutOptions();
+				const GUILayoutOptions& layoutOptions = element->_getLayoutOptions();
 				if(!layoutOptions.fixedWidth)
 				{
 					elemWidth = width;
@@ -344,24 +351,25 @@ namespace BansheeEngine
 						elemWidth = layoutOptions.maxWidth;
 				}
 
-				child.element->_setWidth(elemWidth);
-				child.element->_setHeight(elementHeight);
+				element->_setWidth(elemWidth);
+				element->_setHeight(elementHeight);
 
-				UINT32 xOffset = (UINT32)Math::CeilToInt((width - child.element->_getHeight()) * 0.5f);
+				UINT32 xOffset = (UINT32)Math::CeilToInt((width - element->_getHeight()) * 0.5f);
 
 				Int2 offset(x + xOffset, y + yOffset);
-				child.element->_setOffset(offset);
-				child.element->_setWidgetDepth(widgetDepth);
-				child.element->_setAreaDepth(areaDepth);
+				element->_setOffset(offset);
+				element->_setWidgetDepth(widgetDepth);
+				element->_setAreaDepth(areaDepth);
 
-				UINT32 clippedWidth = (UINT32)std::min((INT32)child.element->_getWidth(), (INT32)width - (INT32)xOffset);
-				UINT32 clippedHeight = (UINT32)std::min((INT32)child.element->_getHeight(), (INT32)height - (INT32)yOffset);
+				UINT32 clippedWidth = (UINT32)std::min((INT32)element->_getWidth(), (INT32)width - (INT32)xOffset);
+				UINT32 clippedHeight = (UINT32)std::min((INT32)element->_getHeight(), (INT32)height - (INT32)yOffset);
 
-				child.element->_setClipRect(Rect(0, 0, clippedWidth, clippedHeight));
+				element->_setClipRect(Rect(0, 0, clippedWidth, clippedHeight));
 			}
-			else if(child.isLayout())
+			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
-				child.layout->_updateLayout(x, y + yOffset, width, elementHeight, widgetDepth, areaDepth);
+				GUILayout* layout = static_cast<GUILayout*>(child);
+				layout->_updateLayout(x, y + yOffset, width, elementHeight, widgetDepth, areaDepth);
 			}
 
 			yOffset += elementHeight;