浏览代码

Added text and Vector4 fields

Marko Pintera 11 年之前
父节点
当前提交
5554a2ff28

+ 4 - 0
BansheeEditor/BansheeEditor.vcxproj

@@ -277,6 +277,8 @@
     <ClInclude Include="Include\BsEditorWidgetManager.h" />
     <ClInclude Include="Include\BsGUIFloatField.h" />
     <ClInclude Include="Include\BsGUIIntField.h" />
+    <ClInclude Include="Include\BsGUITextField.h" />
+    <ClInclude Include="Include\BsGUIVector4Field.h" />
     <ClInclude Include="Include\BsProjectLibraryEntriesRTTI.h" />
     <ClInclude Include="Include\BsEditorPrerequisites.h" />
     <ClInclude Include="Include\BsEditorWidget.h" />
@@ -328,8 +330,10 @@
     <ClCompile Include="Source\BsGUISceneTreeView.cpp" />
     <ClCompile Include="Source\BsGUITabbedTitleBar.cpp" />
     <ClCompile Include="Source\BsGUITabButton.cpp" />
+    <ClCompile Include="Source\BsGUITextField.cpp" />
     <ClCompile Include="Source\BsGUITreeView.cpp" />
     <ClCompile Include="Source\BsGUITreeViewEditBox.cpp" />
+    <ClCompile Include="Source\BsGUIVector4Field.cpp" />
     <ClCompile Include="Source\BsGUIWindowFrame.cpp" />
     <ClCompile Include="Source\BsGUIWindowFrameWidget.cpp" />
     <ClCompile Include="Source\BsGUIWindowDropArea.cpp" />

+ 12 - 0
BansheeEditor/BansheeEditor.vcxproj.filters

@@ -159,6 +159,12 @@
     <ClInclude Include="Include\BsGUIFloatField.h">
       <Filter>Header Files\Editor</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsGUITextField.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGUIVector4Field.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsEditorWidgetContainer.cpp">
@@ -269,5 +275,11 @@
     <ClCompile Include="Source\BsGUIFloatField.cpp">
       <Filter>Source Files\Editor</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsGUITextField.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGUIVector4Field.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 3 - 0
BansheeEditor/Include/BsEditorPrerequisites.h

@@ -31,6 +31,9 @@ namespace BansheeEditor
 	class GUITabButton;
 	class GUIWindowDropArea;
 	class GUIWindowFrame;
+	class GUIIntField;
+	class GUIFloatField;
+	class GUITextField;
 	class EditorWindowManager;
 	class DockManager;
 	class DockManagerLayout;

+ 7 - 4
BansheeEditor/Include/BsGUIFloatField.h

@@ -39,17 +39,20 @@ namespace BansheeEditor
 		float getValue() const;
 		void setValue(float value);
 
+		void setLabelWidth(CM::UINT32 value);
+
+		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 ~GUIFloatField();
 
 		void updateClippedBounds();
-
-		void _updateLayoutInternal(CM::INT32 x, CM::INT32 y, CM::UINT32 width, CM::UINT32 height,
-			CM::RectI clipRect, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
 	protected:
-		static const float SPLIT_POSITION;
 		static const float DRAG_SPEED;
 
+		CM::UINT32 mLabelWidth;
 		BS::GUILabel* mLabel;
 		BS::GUIInputBox* mInputBox;
 		CM::INT32 mLastDragPos;

+ 7 - 3
BansheeEditor/Include/BsGUIIntField.h

@@ -39,17 +39,21 @@ namespace BansheeEditor
 		CM::INT32 getValue() const;
 		void setValue(CM::INT32 value);
 
+		void setLabelWidth(CM::UINT32 value);
+
+		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 ~GUIIntField();
 
 		void updateClippedBounds();
 
-		void _updateLayoutInternal(CM::INT32 x, CM::INT32 y, CM::UINT32 width, CM::UINT32 height,
-			CM::RectI clipRect, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
 	protected:
-		static const float SPLIT_POSITION;
 		static const CM::INT32 DRAG_SPEED;
 
+		CM::UINT32 mLabelWidth;
 		BS::GUILabel* mLabel;
 		BS::GUIInputBox* mInputBox;
 		CM::INT32 mLastDragPos;

+ 56 - 0
BansheeEditor/Include/BsGUITextField.h

@@ -0,0 +1,56 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsGUIElementContainer.h"
+
+namespace BansheeEditor
+{
+	class BS_ED_EXPORT GUITextField : public BS::GUIElementContainer
+	{
+		struct PrivatelyConstruct {};
+
+	public:
+		static const CM::String& getGUITypeName();
+
+		static GUITextField* create(BS::GUIWidget& parent, const BS::GUIContent& labelContent, 
+			const BS::GUIOptions& layoutOptions, BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		static GUITextField* create(BS::GUIWidget& parent, const CM::HString& labelText, 
+			const BS::GUIOptions& layoutOptions, BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		static GUITextField* create(BS::GUIWidget& parent, 
+			const BS::GUIOptions& layoutOptions, BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		static GUITextField* create(BS::GUIWidget& parent, const BS::GUIContent& labelContent, 
+			BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		static GUITextField* create(BS::GUIWidget& parent, const CM::HString& labelText, 
+			BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		static GUITextField* create(BS::GUIWidget& parent, 
+			BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		GUITextField(const PrivatelyConstruct& dummy, BS::GUIWidget& parent, const BS::GUIContent& labelContent, 
+			BS::GUIElementStyle* labelStyle, BS::GUIElementStyle* inputBoxStyle, const BS::GUILayoutOptions& layoutOptions);
+
+		GUITextField(const PrivatelyConstruct& dummy, BS::GUIWidget& parent, 
+			BS::GUIElementStyle* labelStyle, BS::GUIElementStyle* inputBoxStyle, const BS::GUILayoutOptions& layoutOptions);
+
+		CM::WString getValue() const;
+		void setValue(const CM::WString& 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 ~GUITextField();
+
+	protected:
+		CM::UINT32 mLabelWidth;
+		BS::GUILabel* mLabel;
+		BS::GUIInputBox* mInputBox;
+	};
+}

+ 62 - 0
BansheeEditor/Include/BsGUIVector4Field.h

@@ -0,0 +1,62 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsGUIElementContainer.h"
+#include "CmVector4.h"
+
+namespace BansheeEditor
+{
+	class BS_ED_EXPORT GUIVector4Field : public BS::GUIElementContainer
+	{
+		struct PrivatelyConstruct {};
+
+	public:
+		static const CM::String& getGUITypeName();
+
+		static GUIVector4Field* create(BS::GUIWidget& parent, const BS::GUIContent& labelContent, 
+			const BS::GUIOptions& layoutOptions, BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		static GUIVector4Field* create(BS::GUIWidget& parent, const CM::HString& labelText, 
+			const BS::GUIOptions& layoutOptions, BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		static GUIVector4Field* create(BS::GUIWidget& parent, 
+			const BS::GUIOptions& layoutOptions, BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		static GUIVector4Field* create(BS::GUIWidget& parent, const BS::GUIContent& labelContent, 
+			BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		static GUIVector4Field* create(BS::GUIWidget& parent, const CM::HString& labelText, 
+			BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		static GUIVector4Field* create(BS::GUIWidget& parent, 
+			BS::GUIElementStyle* labelStyle = nullptr, BS::GUIElementStyle* inputBoxStyle = nullptr);
+
+		GUIVector4Field(const PrivatelyConstruct& dummy, BS::GUIWidget& parent, const BS::GUIContent& labelContent, 
+			BS::GUIElementStyle* labelStyle, BS::GUIElementStyle* inputBoxStyle, const BS::GUILayoutOptions& layoutOptions);
+
+		GUIVector4Field(const PrivatelyConstruct& dummy, BS::GUIWidget& parent, 
+			BS::GUIElementStyle* labelStyle, BS::GUIElementStyle* inputBoxStyle, const BS::GUILayoutOptions& layoutOptions);
+
+		CM::Vector4 getValue() const;
+		void setValue(const CM::Vector4& value);
+
+		CM::Vector2I _getOptimalSize() const;
+	protected:
+		virtual ~GUIVector4Field();
+
+		void _updateLayoutInternal(CM::INT32 x, CM::INT32 y, CM::UINT32 width, CM::UINT32 height,
+			CM::RectI clipRect, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
+
+	protected:
+		static const CM::UINT32 ELEMENT_LABEL_WIDTH;
+
+		BS::GUILabel* mLabel;
+		GUIFloatField* mFieldX;
+		GUIFloatField* mFieldY;
+		GUIFloatField* mFieldZ;
+		GUIFloatField* mFieldW;
+
+		void construct(BS::GUIWidget& parent, const BS::GUIContent& labelContent, BS::GUIElementStyle* labelStyle, 
+			BS::GUIElementStyle* inputBoxStyle, const BS::GUILayoutOptions& layoutOptions, bool withLabel);
+	};
+}

+ 23 - 4
BansheeEditor/Source/BsGUIFloatField.cpp

@@ -17,13 +17,12 @@ using namespace BansheeEngine;
 
 namespace BansheeEditor
 {
-	const float GUIFloatField::SPLIT_POSITION = 0.5f;
 	const float GUIFloatField::DRAG_SPEED = 0.05f;
 
 	GUIFloatField::GUIFloatField(const PrivatelyConstruct& dummy, GUIWidget& parent, const GUIContent& labelContent, 
 		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle, const GUILayoutOptions& layoutOptions)
 		:GUIElementContainer(parent, layoutOptions), mLabel(nullptr), mInputBox(nullptr), mIsDragging(false),
-		mLastDragPos(0), mIsDragCursorSet(false)
+		mLastDragPos(0), mIsDragCursorSet(false), mLabelWidth(100)
 	{
 		const GUIElementStyle* curLabelStyle = labelStyle;
 		const GUIElementStyle* curInputBoxStyle = inputBoxStyle;
@@ -47,7 +46,7 @@ namespace BansheeEditor
 	GUIFloatField::GUIFloatField(const PrivatelyConstruct& dummy, GUIWidget& parent, 
 		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle, const GUILayoutOptions& layoutOptions)
 		:GUIElementContainer(parent, layoutOptions), mLabel(nullptr), mInputBox(nullptr), mIsDragging(false),
-		mLastDragPos(0)
+		mLastDragPos(0), mLabelWidth(100)
 	{
 		const GUIElementStyle* curInputBoxStyle = inputBoxStyle;
 
@@ -221,6 +220,13 @@ namespace BansheeEditor
 		mInputBox->setText(toWString(value));
 	}
 
+	void GUIFloatField::setLabelWidth(UINT32 width)
+	{
+		mLabelWidth = width;
+
+		markContentAsDirty();
+	}
+
 	void GUIFloatField::updateClippedBounds()
 	{
 		Vector2I offset = _getOffset();
@@ -235,7 +241,7 @@ namespace BansheeEditor
 
 		if(mLabel != nullptr)
 		{
-			UINT32 labelWidth = Math::roundToInt(width * SPLIT_POSITION);
+			UINT32 labelWidth = mLabelWidth;
 
 			Vector2I optimalSize = mLabel->_getOptimalSize();
 			INT32 yOffset = Math::roundToInt((height - optimalSize.y) * 0.5f);
@@ -272,6 +278,19 @@ namespace BansheeEditor
 		}
 	}
 
+	Vector2I GUIFloatField::_getOptimalSize() const
+	{
+		Vector2I optimalsize = mInputBox->_getOptimalSize();
+
+		if(mLabel != nullptr)
+		{
+			optimalsize.x += mLabel->_getOptimalSize().x;
+			optimalsize.y = std::max(optimalsize.y, mLabel->_getOptimalSize().y);
+		}
+
+		return optimalsize;
+	}
+
 	const String& GUIFloatField::getGUITypeName()
 	{
 		static String typeName = "GUIFloatField";

+ 23 - 4
BansheeEditor/Source/BsGUIIntField.cpp

@@ -17,13 +17,12 @@ using namespace BansheeEngine;
 
 namespace BansheeEditor
 {
-	const float GUIIntField::SPLIT_POSITION = 0.5f;
 	const INT32 GUIIntField::DRAG_SPEED = 5;
 
 	GUIIntField::GUIIntField(const PrivatelyConstruct& dummy, GUIWidget& parent, const GUIContent& labelContent, 
 		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle, const GUILayoutOptions& layoutOptions)
 		:GUIElementContainer(parent, layoutOptions), mLabel(nullptr), mInputBox(nullptr), mIsDragging(false),
-		mLastDragPos(0), mIsDragCursorSet(false)
+		mLastDragPos(0), mIsDragCursorSet(false), mLabelWidth(100)
 	{
 		const GUIElementStyle* curLabelStyle = labelStyle;
 		const GUIElementStyle* curInputBoxStyle = inputBoxStyle;
@@ -47,7 +46,7 @@ namespace BansheeEditor
 	GUIIntField::GUIIntField(const PrivatelyConstruct& dummy, GUIWidget& parent, 
 		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle, const GUILayoutOptions& layoutOptions)
 		:GUIElementContainer(parent, layoutOptions), mLabel(nullptr), mInputBox(nullptr), mIsDragging(false),
-		mLastDragPos(0)
+		mLastDragPos(0), mLabelWidth(100)
 	{
 		const GUIElementStyle* curInputBoxStyle = inputBoxStyle;
 
@@ -238,6 +237,13 @@ namespace BansheeEditor
 		mInputBox->setText(toWString(value));
 	}
 
+	void GUIIntField::setLabelWidth(UINT32 width)
+	{
+		mLabelWidth = width;
+
+		markContentAsDirty();
+	}
+
 	void GUIIntField::updateClippedBounds()
 	{
 		Vector2I offset = _getOffset();
@@ -252,7 +258,7 @@ namespace BansheeEditor
 
 		if(mLabel != nullptr)
 		{
-			UINT32 labelWidth = Math::roundToInt(width * SPLIT_POSITION);
+			UINT32 labelWidth = mLabelWidth;
 
 			Vector2I optimalSize = mLabel->_getOptimalSize();
 			INT32 yOffset = Math::roundToInt((height - optimalSize.y) * 0.5f);
@@ -289,6 +295,19 @@ namespace BansheeEditor
 		}
 	}
 
+	Vector2I GUIIntField::_getOptimalSize() const
+	{
+		Vector2I optimalsize = mInputBox->_getOptimalSize();
+
+		if(mLabel != nullptr)
+		{
+			optimalsize.x += mLabel->_getOptimalSize().x;
+			optimalsize.y = std::max(optimalsize.y, mLabel->_getOptimalSize().y);
+		}
+
+		return optimalsize;
+	}
+
 	const String& GUIIntField::getGUITypeName()
 	{
 		static String typeName = "GUIIntField";

+ 175 - 0
BansheeEditor/Source/BsGUITextField.cpp

@@ -0,0 +1,175 @@
+#include "BsGUITextField.h"
+#include "BsGUIArea.h"
+#include "BsGUILayout.h"
+#include "BsGUILabel.h"
+#include "BsGUIInputBox.h"
+#include "BsBuiltinResources.h"
+#include "BsGUIWidget.h"
+#include "BsGUIMouseEvent.h"
+#include "BsGUIWidget.h"
+
+using namespace CamelotFramework;
+using namespace BansheeEngine;
+
+namespace BansheeEditor
+{
+	GUITextField::GUITextField(const PrivatelyConstruct& dummy, GUIWidget& parent, const GUIContent& labelContent, 
+		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle, const GUILayoutOptions& layoutOptions)
+		:GUIElementContainer(parent, layoutOptions), mLabel(nullptr), mInputBox(nullptr), mLabelWidth(100)
+	{
+		const GUIElementStyle* curLabelStyle = labelStyle;
+		const GUIElementStyle* curInputBoxStyle = inputBoxStyle;
+
+		if(curLabelStyle == nullptr)
+			curLabelStyle = parent.getSkin().getStyle("Label");
+
+		if(curInputBoxStyle == nullptr)
+			curInputBoxStyle = parent.getSkin().getStyle("InputBox");
+
+		mLabel = GUILabel::create(parent, labelContent, curLabelStyle);
+		mInputBox = GUIInputBox::create(parent, false, inputBoxStyle);
+
+		_registerChildElement(mLabel);
+		_registerChildElement(mInputBox);
+	}
+
+	GUITextField::GUITextField(const PrivatelyConstruct& dummy, GUIWidget& parent, 
+		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle, const GUILayoutOptions& layoutOptions)
+		:GUIElementContainer(parent, layoutOptions), mLabel(nullptr), mInputBox(nullptr), mLabelWidth(100)
+	{
+		const GUIElementStyle* curInputBoxStyle = inputBoxStyle;
+
+		if(curInputBoxStyle == nullptr)
+			curInputBoxStyle = parent.getSkin().getStyle("InputBox");
+
+		mInputBox = GUIInputBox::create(parent, false, inputBoxStyle);
+
+		_registerChildElement(mInputBox);
+	}
+
+	GUITextField::~GUITextField()
+	{
+
+	}
+
+	GUITextField* GUITextField::create(GUIWidget& parent, const GUIContent& labelContent, const GUIOptions& layoutOptions, 
+		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUITextField>(PrivatelyConstruct(), parent, labelContent, labelStyle, inputBoxStyle, 
+			GUILayoutOptions::create(layoutOptions, &GUISkin::DefaultStyle));
+	}
+
+	GUITextField* GUITextField::create(GUIWidget& parent, const GUIContent& labelContent, GUIElementStyle* labelStyle, 
+		GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUITextField>(PrivatelyConstruct(), parent, labelContent, labelStyle, inputBoxStyle, 
+			GUILayoutOptions::create(&GUISkin::DefaultStyle));
+	}
+
+	GUITextField* GUITextField::create(GUIWidget& parent, const HString& labelContent, const GUIOptions& layoutOptions, 
+		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUITextField>(PrivatelyConstruct(), parent, GUIContent(labelContent), labelStyle, 
+			inputBoxStyle, GUILayoutOptions::create(layoutOptions, &GUISkin::DefaultStyle));
+	}
+
+	GUITextField* GUITextField::create(GUIWidget& parent, const HString& labelContent, GUIElementStyle* labelStyle, 
+		GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUITextField>(PrivatelyConstruct(), parent, GUIContent(labelContent), labelStyle, inputBoxStyle, 
+			GUILayoutOptions::create(&GUISkin::DefaultStyle));
+	}
+
+	GUITextField* GUITextField::create(GUIWidget& parent, const GUIOptions& layoutOptions, GUIElementStyle* labelStyle, 
+		GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUITextField>(PrivatelyConstruct(), parent, labelStyle, inputBoxStyle, 
+			GUILayoutOptions::create(layoutOptions, &GUISkin::DefaultStyle));
+	}
+
+	GUITextField* GUITextField::create(GUIWidget& parent, GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUITextField>(PrivatelyConstruct(), parent, labelStyle, inputBoxStyle, GUILayoutOptions::create(&GUISkin::DefaultStyle));
+	}
+	
+	WString GUITextField::getValue() const
+	{
+		return mInputBox->getText();
+	}
+
+	void GUITextField::setValue(const WString& value)
+	{
+		mInputBox->setText(value);
+	}
+
+	void GUITextField::setLabelWidth(UINT32 width)
+	{
+		mLabelWidth = width;
+
+		markContentAsDirty();
+	}
+
+	void GUITextField::_updateLayoutInternal(INT32 x, INT32 y, UINT32 width, UINT32 height,
+		RectI clipRect, UINT8 widgetDepth, UINT16 areaDepth)
+	{
+		UINT32 inputBoxOffset = 0;
+		UINT32 inputBoxWidth = 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);
+
+			inputBoxOffset = labelWidth;
+			inputBoxWidth = width - labelWidth;
+		}
+
+		Vector2I inputBoxSize = mInputBox->_getOptimalSize();
+
+		{
+			Vector2I optimalSize = mInputBox->_getOptimalSize();
+			INT32 yOffset = Math::roundToInt((height - optimalSize.y) * 0.5f);
+
+			Vector2I offset(x + inputBoxOffset, y + yOffset);
+			mInputBox->_setOffset(offset);
+			mInputBox->_setWidth(inputBoxWidth);
+			mInputBox->_setHeight(optimalSize.y);
+			mInputBox->_setAreaDepth(areaDepth);
+			mInputBox->_setWidgetDepth(widgetDepth);
+
+			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
+			mInputBox->_setClipRect(elemClipRect);
+		}
+	}
+
+	Vector2I GUITextField::_getOptimalSize() const
+	{
+		Vector2I optimalsize = mInputBox->_getOptimalSize();
+
+		if(mLabel != nullptr)
+		{
+			optimalsize.x += mLabel->_getOptimalSize().x;
+			optimalsize.y = std::max(optimalsize.y, mLabel->_getOptimalSize().y);
+		}
+
+		return optimalsize;
+	}
+
+	const String& GUITextField::getGUITypeName()
+	{
+		static String typeName = "GUITextField";
+		return typeName;
+	}
+}

+ 205 - 0
BansheeEditor/Source/BsGUIVector4Field.cpp

@@ -0,0 +1,205 @@
+#include "BsGUIVector4Field.h"
+#include "BsGUIArea.h"
+#include "BsGUILayout.h"
+#include "BsGUILabel.h"
+#include "BsGUIFloatField.h"
+#include "BsBuiltinResources.h"
+#include "BsGUIWidget.h"
+#include "BsGUIMouseEvent.h"
+#include "BsGUIWidget.h"
+
+using namespace CamelotFramework;
+using namespace BansheeEngine;
+
+namespace BansheeEditor
+{
+	const UINT32 GUIVector4Field::ELEMENT_LABEL_WIDTH = 10;
+
+	GUIVector4Field::GUIVector4Field(const PrivatelyConstruct& dummy, GUIWidget& parent, const GUIContent& labelContent, 
+		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle, const GUILayoutOptions& layoutOptions)
+		:GUIElementContainer(parent, layoutOptions), mLabel(nullptr), mFieldX(nullptr), mFieldY(nullptr),
+		mFieldZ(nullptr), mFieldW(nullptr)
+	{
+		construct(parent, labelContent, labelStyle, inputBoxStyle, layoutOptions, true);
+	}
+
+	GUIVector4Field::GUIVector4Field(const PrivatelyConstruct& dummy, GUIWidget& parent, 
+		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle, const GUILayoutOptions& layoutOptions)
+		:GUIElementContainer(parent, layoutOptions), mLabel(nullptr), mFieldX(nullptr), mFieldY(nullptr),
+		mFieldZ(nullptr), mFieldW(nullptr)
+	{
+		construct(parent, GUIContent(HString()), labelStyle, inputBoxStyle, layoutOptions, false);
+	}
+
+	GUIVector4Field::~GUIVector4Field()
+	{
+
+	}
+
+	GUIVector4Field* GUIVector4Field::create(GUIWidget& parent, const GUIContent& labelContent, const GUIOptions& layoutOptions, 
+		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUIVector4Field>(PrivatelyConstruct(), parent, labelContent, labelStyle, inputBoxStyle, 
+			GUILayoutOptions::create(layoutOptions, &GUISkin::DefaultStyle));
+	}
+
+	GUIVector4Field* GUIVector4Field::create(GUIWidget& parent, const GUIContent& labelContent, GUIElementStyle* labelStyle, 
+		GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUIVector4Field>(PrivatelyConstruct(), parent, labelContent, labelStyle, inputBoxStyle, 
+			GUILayoutOptions::create(&GUISkin::DefaultStyle));
+	}
+
+	GUIVector4Field* GUIVector4Field::create(GUIWidget& parent, const HString& labelContent, const GUIOptions& layoutOptions, 
+		GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUIVector4Field>(PrivatelyConstruct(), parent, GUIContent(labelContent), labelStyle, 
+			inputBoxStyle, GUILayoutOptions::create(layoutOptions, &GUISkin::DefaultStyle));
+	}
+
+	GUIVector4Field* GUIVector4Field::create(GUIWidget& parent, const HString& labelContent, GUIElementStyle* labelStyle, 
+		GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUIVector4Field>(PrivatelyConstruct(), parent, GUIContent(labelContent), labelStyle, inputBoxStyle, 
+			GUILayoutOptions::create(&GUISkin::DefaultStyle));
+	}
+
+	GUIVector4Field* GUIVector4Field::create(GUIWidget& parent, const GUIOptions& layoutOptions, GUIElementStyle* labelStyle, 
+		GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUIVector4Field>(PrivatelyConstruct(), parent, labelStyle, inputBoxStyle, 
+			GUILayoutOptions::create(layoutOptions, &GUISkin::DefaultStyle));
+	}
+
+	GUIVector4Field* GUIVector4Field::create(GUIWidget& parent, GUIElementStyle* labelStyle, GUIElementStyle* inputBoxStyle)
+	{
+		return cm_new<GUIVector4Field>(PrivatelyConstruct(), parent, labelStyle, inputBoxStyle, GUILayoutOptions::create(&GUISkin::DefaultStyle));
+	}
+
+	void GUIVector4Field::construct(GUIWidget& parent, const GUIContent& labelContent, GUIElementStyle* labelStyle, 
+		GUIElementStyle* inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel)
+	{
+		if(withLabel)
+		{
+			const GUIElementStyle* curLabelStyle = labelStyle;
+
+			if(curLabelStyle == nullptr)
+				curLabelStyle = parent.getSkin().getStyle("Label");
+
+			mLabel = GUILabel::create(parent, labelContent, curLabelStyle);
+		}
+
+		mFieldX = GUIFloatField::create(parent, HString(L"X"), labelStyle, inputBoxStyle);
+		mFieldY = GUIFloatField::create(parent, HString(L"Y"), labelStyle, inputBoxStyle);
+		mFieldZ = GUIFloatField::create(parent, HString(L"Z"), labelStyle, inputBoxStyle);
+		mFieldW = GUIFloatField::create(parent, HString(L"W"), labelStyle, inputBoxStyle);
+
+		mFieldX->setLabelWidth(ELEMENT_LABEL_WIDTH);
+		mFieldY->setLabelWidth(ELEMENT_LABEL_WIDTH);
+		mFieldZ->setLabelWidth(ELEMENT_LABEL_WIDTH);
+		mFieldW->setLabelWidth(ELEMENT_LABEL_WIDTH);
+
+		_registerChildElement(mLabel);
+		_registerChildElement(mFieldX);
+		_registerChildElement(mFieldY);
+		_registerChildElement(mFieldZ);
+		_registerChildElement(mFieldW);
+	}
+
+	Vector4 GUIVector4Field::getValue() const
+	{
+		Vector4 value;
+		value.x = mFieldX->getValue();
+		value.y = mFieldY->getValue();
+		value.z = mFieldZ->getValue();
+		value.w = mFieldW->getValue();
+
+		return value;
+	}
+
+	void GUIVector4Field::setValue(const Vector4& value)
+	{
+		mFieldX->setValue(value.x);
+		mFieldY->setValue(value.y);
+		mFieldZ->setValue(value.z);
+		mFieldW->setValue(value.w);
+	}
+
+	void GUIVector4Field::_updateLayoutInternal(INT32 x, INT32 y, UINT32 width, UINT32 height,
+		RectI clipRect, UINT8 widgetDepth, UINT16 areaDepth)
+	{
+		UINT32 inputBoxYOffset = 0;
+
+		if(mLabel != nullptr)
+		{
+			Vector2I optimalSize = mLabel->_getOptimalSize();
+			Vector2I offset(x, y);
+			mLabel->_setOffset(offset);
+			mLabel->_setWidth(width);
+			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);
+
+			inputBoxYOffset = optimalSize.y;
+		}
+
+		GUIFloatField* fields[4] = { mFieldX, mFieldY, mFieldZ, mFieldW };
+		UINT32 numFields = sizeof(fields) / sizeof(fields[0]);
+
+		UINT32 sizePerField = width / numFields;
+		UINT32 inputBoxXOffset = 0;
+
+		for(UINT32 i = 0; i < numFields; i++)
+		{
+			Vector2I optimalSize = fields[i]->_getOptimalSize();
+			INT32 yOffset = Math::roundToInt((height - optimalSize.y) * 0.5f);
+
+			Vector2I offset(x + inputBoxXOffset, y + inputBoxYOffset);
+			fields[i]->_setOffset(offset);
+			fields[i]->_setWidth(sizePerField);
+			fields[i]->_setHeight(optimalSize.y);
+			fields[i]->_setAreaDepth(areaDepth);
+			fields[i]->_setWidgetDepth(widgetDepth);
+
+			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
+			fields[i]->_setClipRect(elemClipRect);
+
+			RectI newClipRect(offset.x, offset.y, sizePerField, optimalSize.y);
+			newClipRect.clip(clipRect);
+			fields[i]->_updateLayoutInternal(offset.x, offset.y, sizePerField, optimalSize.y, newClipRect, widgetDepth, areaDepth);
+
+			inputBoxXOffset += sizePerField;
+		}
+	}
+
+	Vector2I GUIVector4Field::_getOptimalSize() const
+	{
+		GUIFloatField* fields[4] = { mFieldX, mFieldY, mFieldZ, mFieldW };
+		UINT32 numFields = sizeof(fields) / sizeof(fields[0]);
+
+		Vector2I optimalSize;
+
+		for(UINT32 i = 0; i < numFields; i++)
+		{
+			optimalSize.x += fields[i]->_getOptimalSize().x;
+			optimalSize.y = std::max(optimalSize.y, fields[i]->_getOptimalSize().y);
+		}
+
+		if(mLabel != nullptr)
+		{
+			optimalSize.x = std::max(optimalSize.x, mLabel->_getOptimalSize().x);
+			optimalSize.y += mLabel->_getOptimalSize().y;
+		}
+
+		return optimalSize;
+	}
+
+	const String& GUIVector4Field::getGUITypeName()
+	{
+		static String typeName = "GUIVector4Field";
+		return typeName;
+	}
+}

+ 8 - 1
BansheeEditor/Source/DbgEditorWidget2.cpp

@@ -8,6 +8,8 @@
 #include "BsGUISkin.h"
 #include "BsGUIIntField.h"
 #include "BsGUIFloatField.h"
+#include "BsGUITextField.h"
+#include "BsGUIVector4Field.h"
 #include "BsGUISpace.h"
 #include "CmHString.h"
 
@@ -21,12 +23,17 @@ namespace BansheeEditor
 	DbgEditorWidget2::DbgEditorWidget2(const ConstructPrivately& dummy, EditorWidgetContainer& parentContainer)
 		:EditorWidget<DbgEditorWidget2>(HString(L"DbgEditorWidget2"), parentContainer)
 	{
-		GUILayout& layout = mContent->getLayout();
+		GUILayout& layout = mContent->getLayout().addLayoutY();
 
 		GUIIntField* intField = GUIIntField::create(getParentWidget(), HString(L"Int Field"), GUIOptions(GUIOption::fixedWidth(200)));
 		GUIFloatField* floatField = GUIFloatField::create(getParentWidget(), HString(L"Float Field"), GUIOptions(GUIOption::fixedWidth(200)));
+		GUITextField* textField = GUITextField::create(getParentWidget(), HString(L"Text Field"), GUIOptions(GUIOption::fixedWidth(200)));
+		GUIVector4Field* vec4Field = GUIVector4Field::create(getParentWidget(), HString(L"Vec4 Field"), GUIOptions(GUIOption::fixedWidth(200)));
+
 		layout.addElement(intField);
 		layout.addElement(floatField);
+		layout.addElement(textField);
+		layout.addElement(vec4Field);
 
 		layout.addFlexibleSpace();
 	}

+ 1 - 0
Inspector.txt

@@ -1,6 +1,7 @@
 Needed controls:
 IntField (With drag sliding)
 FloatField (With drag sliding)
+ToggleFIeld
 Vector2 field
 Vector3 field
 Vector4 field