Prechádzať zdrojové kódy

Added support for GUI sub-styles
Updated editor fields so they resize properly, handle UndoRedo and handle focus

Marko Pintera 11 rokov pred
rodič
commit
b0236b0eb1
30 zmenil súbory, kde vykonal 815 pridanie a 264 odobranie
  1. 1 0
      BansheeEditor/Include/BsGUIColor.h
  2. 18 14
      BansheeEditor/Include/BsGUIColorField.h
  3. 79 32
      BansheeEditor/Include/BsGUIFieldBase.h
  4. 18 8
      BansheeEditor/Include/BsGUIFloatField.h
  5. 16 24
      BansheeEditor/Include/BsGUIGameObjectField.h
  6. 14 13
      BansheeEditor/Include/BsGUIIntField.h
  7. 15 3
      BansheeEditor/Include/BsGUITextField.h
  8. 8 3
      BansheeEditor/Include/BsGUIToggleField.h
  9. 8 1
      BansheeEditor/Include/BsGUIVector2Field.h
  10. 8 2
      BansheeEditor/Include/BsGUIVector3Field.h
  11. 8 2
      BansheeEditor/Include/BsGUIVector4Field.h
  12. 108 2
      BansheeEditor/Source/BsEditorGUI.cpp
  13. 2 1
      BansheeEditor/Source/BsGUIColor.cpp
  14. 77 27
      BansheeEditor/Source/BsGUIColorField.cpp
  15. 12 4
      BansheeEditor/Source/BsGUIFieldBase.cpp
  16. 48 9
      BansheeEditor/Source/BsGUIFloatField.cpp
  17. 92 37
      BansheeEditor/Source/BsGUIGameObjectField.cpp
  18. 20 18
      BansheeEditor/Source/BsGUIIntField.cpp
  19. 45 7
      BansheeEditor/Source/BsGUITextField.cpp
  20. 32 8
      BansheeEditor/Source/BsGUIToggleField.cpp
  21. 37 4
      BansheeEditor/Source/BsGUIVector2Field.cpp
  22. 40 5
      BansheeEditor/Source/BsGUIVector3Field.cpp
  23. 42 6
      BansheeEditor/Source/BsGUIVector4Field.cpp
  24. 16 0
      BansheeEngine/Include/BsGUIElement.h
  25. 2 0
      BansheeEngine/Include/BsGUIElementStyle.h
  26. 16 0
      BansheeEngine/Source/BsGUIElement.cpp
  27. 20 16
      Inspector.txt
  28. 5 6
      MBansheeEditor/GUI/GUIIntField.cs
  29. 2 2
      SBansheeEditor/Include/BsScriptGUIIntField.h
  30. 6 10
      SBansheeEditor/Source/BsScriptGUIIntField.cpp

+ 1 - 0
BansheeEditor/Include/BsGUIColor.h

@@ -20,6 +20,7 @@ namespace BansheeEngine
 		void setColor(const Color& color);
 		void setColor(const Color& color);
 		Color getColor() const { return mColor; }
 		Color getColor() const { return mColor; }
 
 
+		Event<void(const Color&)> onValueChanged;
 	protected:
 	protected:
 		GUIColor(const String& styleName, const GUILayoutOptions& layoutOptions);
 		GUIColor(const String& styleName, const GUILayoutOptions& layoutOptions);
 		virtual ~GUIColor();
 		virtual ~GUIColor();

+ 18 - 14
BansheeEditor/Include/BsGUIColorField.h

@@ -2,6 +2,7 @@
 
 
 #include "BsEditorPrerequisites.h"
 #include "BsEditorPrerequisites.h"
 #include "BsGUIElementContainer.h"
 #include "BsGUIElementContainer.h"
+#include "BsColor.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -11,31 +12,29 @@ namespace BansheeEngine
 
 
 	public:
 	public:
 		static const String& getGUITypeName();
 		static const String& getGUITypeName();
+		static const String& getLabelStyleType();
+		static const String& getColorInputStyleType();
 
 
 		static GUIColorField* create(const GUIContent& labelContent, 
 		static GUIColorField* create(const GUIContent& labelContent, 
-			const GUIOptions& layoutOptions, const String& labelStyle = StringUtil::BLANK, const String& toggleStyle = StringUtil::BLANK);
+			const GUIOptions& layoutOptions, const String& style = StringUtil::BLANK);
 
 
 		static GUIColorField* create(const HString& labelText, 
 		static GUIColorField* create(const HString& labelText, 
-			const GUIOptions& layoutOptions, const String& labelStyle = StringUtil::BLANK, const String& toggleStyle = StringUtil::BLANK);
+			const GUIOptions& layoutOptions, const String& style = StringUtil::BLANK);
 
 
-		static GUIColorField* create(const GUIOptions& layoutOptions, const String& labelStyle = StringUtil::BLANK, 
-			const String& toggleStyle = StringUtil::BLANK);
+		static GUIColorField* create(const GUIOptions& layoutOptions, const String& style = StringUtil::BLANK);
 
 
-		static GUIColorField* create(const GUIContent& labelContent, const String& labelStyle = StringUtil::BLANK, 
-			const String& toggleStyle = StringUtil::BLANK);
+		static GUIColorField* create(const GUIContent& labelContent, const String& style = StringUtil::BLANK);
 
 
-		static GUIColorField* create(const HString& labelText, const String& labelStyle = StringUtil::BLANK,
-			const String& toggleStyle = StringUtil::BLANK);
+		static GUIColorField* create(const HString& labelText, const String& style = StringUtil::BLANK);
 
 
-		static GUIColorField* create(const String& labelStyle = StringUtil::BLANK, const String& toggleStyle = StringUtil::BLANK);
+		static GUIColorField* create(const String& style = StringUtil::BLANK);
 
 
 		GUIColorField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
 		GUIColorField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
-			const String& labelStyle, const String& toggleStyle, const GUILayoutOptions& layoutOptions);
+			const String& style, const GUILayoutOptions& layoutOptions);
 
 
-		GUIColorField(const PrivatelyConstruct& dummy, const String& labelStyle, const String& toggleStyle, 
-			const GUILayoutOptions& layoutOptions);
+		GUIColorField(const PrivatelyConstruct& dummy, const String& style, const GUILayoutOptions& layoutOptions);
 
 
-		Color getValue() const;
+		Color getValue() const { return mValue; }
 		void setValue(const Color& value);
 		void setValue(const Color& value);
 
 
 		void setLabelWidth(UINT32 width);
 		void setLabelWidth(UINT32 width);
@@ -44,11 +43,16 @@ namespace BansheeEngine
 			RectI clipRect, UINT8 widgetDepth, UINT16 areaDepth);
 			RectI clipRect, UINT8 widgetDepth, UINT16 areaDepth);
 
 
 		Vector2I _getOptimalSize() const;
 		Vector2I _getOptimalSize() const;
+
+		Event<void(const Color&)> onValueChanged;
 	protected:
 	protected:
 		virtual ~GUIColorField();
 		virtual ~GUIColorField();
 
 
-	protected:
+		void styleUpdated();
+		void valueChanged(const Color& newValue);
+
 		UINT32 mLabelWidth;
 		UINT32 mLabelWidth;
+		Color mValue;
 		GUILabel* mLabel;
 		GUILabel* mLabel;
 		GUIColor* mColor;
 		GUIColor* mColor;
 	};
 	};

+ 79 - 32
BansheeEditor/Include/BsGUIFieldBase.h

@@ -18,10 +18,18 @@ namespace BansheeEngine
 			RectI clipRect, UINT8 widgetDepth, UINT16 areaDepth);
 			RectI clipRect, UINT8 widgetDepth, UINT16 areaDepth);
 
 
 		virtual Vector2I _getOptimalSize() const;
 		virtual Vector2I _getOptimalSize() const;
+
+		static const String& getLabelStyleType()
+		{
+			static String LABEL_STYLE_TYPE = "EditorFieldLabel";
+			return LABEL_STYLE_TYPE;
+		}
+
 	protected:
 	protected:
 		virtual ~GUIFieldBase() { }
 		virtual ~GUIFieldBase() { }
 
 
-	protected:
+		virtual void styleUpdated();
+
 		static const UINT32 DEFAULT_LABEL_WIDTH;
 		static const UINT32 DEFAULT_LABEL_WIDTH;
 
 
 		GUILayout* mLayout;
 		GUILayout* mLayout;
@@ -32,77 +40,116 @@ namespace BansheeEngine
 	class TGUIField : public GUIFieldBase
 	class TGUIField : public GUIFieldBase
 	{
 	{
 	public:
 	public:
-		static T* create(const GUIContent& labelContent, UINT32 labelWidth, const GUIOptions& layoutOptions, 
-			const String& labelStyle = StringUtil::BLANK, const String& entryElementStyle = StringUtil::BLANK)
+		static T* create(const GUIContent& labelContent, UINT32 labelWidth, const GUIOptions& layoutOptions,
+			const String& style = StringUtil::BLANK)
 		{
 		{
-			return bs_new<T>(PrivatelyConstruct(), labelContent, labelWidth, labelStyle, entryElementStyle, 
+			const String* curStyle = &style;
+			if (*curStyle == StringUtil::BLANK)
+				curStyle = &T::getGUITypeName();
+
+			return bs_new<T>(PrivatelyConstruct(), labelContent, labelWidth, *curStyle,
 				GUILayoutOptions::create(layoutOptions), true);
 				GUILayoutOptions::create(layoutOptions), true);
 		}
 		}
 
 
-		static T* create(const GUIContent& labelContent, const GUIOptions& layoutOptions, 
-			const String& labelStyle = StringUtil::BLANK, const String& entryElementStyle = StringUtil::BLANK)
+		static T* create(const GUIContent& labelContent, const GUIOptions& layoutOptions,
+			const String& style = StringUtil::BLANK)
 		{
 		{
-			return bs_new<T>(PrivatelyConstruct(), labelContent, DEFAULT_LABEL_WIDTH, labelStyle, entryElementStyle, 
+			const String* curStyle = &style;
+			if (*curStyle == StringUtil::BLANK)
+				curStyle = &T::getGUITypeName();
+
+			return bs_new<T>(PrivatelyConstruct(), labelContent, DEFAULT_LABEL_WIDTH, *curStyle,
 				GUILayoutOptions::create(layoutOptions), true);
 				GUILayoutOptions::create(layoutOptions), true);
 		}
 		}
 
 
-		static T* create(const HString& labelText, UINT32 labelWidth, const GUIOptions& layoutOptions, 
-			const String& labelStyle = StringUtil::BLANK, const String& entryElementStyle = StringUtil::BLANK)
+		static T* create(const HString& labelText, UINT32 labelWidth, const GUIOptions& layoutOptions,
+			const String& style = StringUtil::BLANK)
 		{
 		{
-			return bs_new<T>(PrivatelyConstruct(), GUIContent(labelText), labelWidth, labelStyle, entryElementStyle, 
+			const String* curStyle = &style;
+			if (*curStyle == StringUtil::BLANK)
+				curStyle = &T::getGUITypeName();
+
+			return bs_new<T>(PrivatelyConstruct(), GUIContent(labelText), labelWidth, *curStyle,
 				GUILayoutOptions::create(layoutOptions), true);
 				GUILayoutOptions::create(layoutOptions), true);
 		}
 		}
 
 
-		static T* create(const HString& labelText, const GUIOptions& layoutOptions, 
-			const String& labelStyle = StringUtil::BLANK, const String& entryElementStyle = StringUtil::BLANK)
+		static T* create(const HString& labelText, const GUIOptions& layoutOptions,
+			const String& style = StringUtil::BLANK)
 		{
 		{
-			return bs_new<T>(PrivatelyConstruct(), GUIContent(labelText), DEFAULT_LABEL_WIDTH, labelStyle, entryElementStyle, 
+			const String* curStyle = &style;
+			if (*curStyle == StringUtil::BLANK)
+				curStyle = &T::getGUITypeName();
+
+			return bs_new<T>(PrivatelyConstruct(), GUIContent(labelText), DEFAULT_LABEL_WIDTH, *curStyle,
 				GUILayoutOptions::create(layoutOptions), true);
 				GUILayoutOptions::create(layoutOptions), true);
 		}
 		}
 
 
-		static T* create(const GUIOptions& layoutOptions, const String& entryElementStyle = StringUtil::BLANK)
+		static T* create(const GUIOptions& layoutOptions, const String& style = StringUtil::BLANK)
 		{
 		{
-			return bs_new<T>(PrivatelyConstruct(), GUIContent(), 0, StringUtil::BLANK, entryElementStyle,
+			const String* curStyle = &style;
+			if (*curStyle == StringUtil::BLANK)
+				curStyle = &T::getGUITypeName();
+
+			return bs_new<T>(PrivatelyConstruct(), GUIContent(), 0, *curStyle,
 				GUILayoutOptions::create(layoutOptions), false);
 				GUILayoutOptions::create(layoutOptions), false);
 		}
 		}
 
 
-		static T* create(const GUIContent& labelContent, UINT32 labelWidth, 
-			const String& labelStyle = StringUtil::BLANK, const String& entryElementStyle = StringUtil::BLANK)
+		static T* create(const GUIContent& labelContent, UINT32 labelWidth,
+			const String& style = StringUtil::BLANK)
 		{
 		{
-			return bs_new<T>(PrivatelyConstruct(), labelContent, labelWidth, labelStyle, entryElementStyle, 
-				GUILayoutOptions::create(), true);
+			const String* curStyle = &style;
+			if (*curStyle == StringUtil::BLANK)
+				curStyle = &T::getGUITypeName();
+
+			return bs_new<T>(PrivatelyConstruct(), labelContent, labelWidth, *curStyle, GUILayoutOptions::create(), true);
 		}
 		}
 
 
-		static T* create(const GUIContent& labelContent, 
-			const String& labelStyle = StringUtil::BLANK, const String& entryElementStyle = StringUtil::BLANK)
+		static T* create(const GUIContent& labelContent,
+			const String& style = StringUtil::BLANK)
 		{
 		{
-			return bs_new<T>(PrivatelyConstruct(), labelContent, DEFAULT_LABEL_WIDTH, labelStyle, entryElementStyle, 
+			const String* curStyle = &style;
+			if (*curStyle == StringUtil::BLANK)
+				curStyle = &T::getGUITypeName();
+
+			return bs_new<T>(PrivatelyConstruct(), labelContent, DEFAULT_LABEL_WIDTH, *curStyle,
 				GUILayoutOptions::create(), true);
 				GUILayoutOptions::create(), true);
 		}
 		}
 
 
-		static T* create(const HString& labelText, UINT32 labelWidth, 
-			const String& labelStyle = StringUtil::BLANK, const String& entryElementStyle = StringUtil::BLANK)
+		static T* create(const HString& labelText, UINT32 labelWidth,
+			const String& style = StringUtil::BLANK)
 		{
 		{
-			return bs_new<T>(PrivatelyConstruct(), GUIContent(labelText), labelWidth, labelStyle, entryElementStyle, 
+			const String* curStyle = &style;
+			if (*curStyle == StringUtil::BLANK)
+				curStyle = &T::getGUITypeName();
+
+			return bs_new<T>(PrivatelyConstruct(), GUIContent(labelText), labelWidth, *curStyle,
 				GUILayoutOptions::create(), true);
 				GUILayoutOptions::create(), true);
 		}
 		}
 
 
-		static T* create(const HString& labelText, 
-			const String& labelStyle = StringUtil::BLANK, const String& entryElementStyle = StringUtil::BLANK)
+		static T* create(const HString& labelText,
+			const String& style = StringUtil::BLANK)
 		{
 		{
-			return bs_new<T>(PrivatelyConstruct(), GUIContent(labelText), DEFAULT_LABEL_WIDTH, labelStyle, entryElementStyle, 
+			const String* curStyle = &style;
+			if (*curStyle == StringUtil::BLANK)
+				curStyle = &T::getGUITypeName();
+
+			return bs_new<T>(PrivatelyConstruct(), GUIContent(labelText), DEFAULT_LABEL_WIDTH, *curStyle,
 				GUILayoutOptions::create(), true);
 				GUILayoutOptions::create(), true);
 		}
 		}
 
 
-		static T* create(const String& entryElementStyle = StringUtil::BLANK)
+		static T* create(const String& style = StringUtil::BLANK)
 		{
 		{
-			return bs_new<T>(PrivatelyConstruct(), GUIContent(), 0, StringUtil::BLANK, entryElementStyle,
+			const String* curStyle = &style;
+			if (*curStyle == StringUtil::BLANK)
+				curStyle = &T::getGUITypeName();
+
+			return bs_new<T>(PrivatelyConstruct(), GUIContent(), 0, *curStyle,
 				GUILayoutOptions::create(), false);
 				GUILayoutOptions::create(), false);
 		}
 		}
 
 
 		TGUIField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 		TGUIField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
-			const String& labelStyle, const GUILayoutOptions& layoutOptions, bool withLabel)
-			:GUIFieldBase(dummy, labelContent, labelWidth, labelStyle, layoutOptions, withLabel)
+			const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
+			:GUIFieldBase(dummy, labelContent, labelWidth, style, layoutOptions, withLabel)
 		{ }
 		{ }
 	};
 	};
 }
 }

+ 18 - 8
BansheeEditor/Include/BsGUIFloatField.h

@@ -9,28 +9,38 @@ namespace BansheeEngine
 	{
 	{
 	public:
 	public:
 		static const String& getGUITypeName();
 		static const String& getGUITypeName();
+		static const String& getInputStyleType();
 
 
 		GUIFloatField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 		GUIFloatField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
-			const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel);
+			const String& style, const GUILayoutOptions& layoutOptions, bool withLabel);
 
 
-		float getValue() const;
+		float getValue() const { return mValue; }
 		void setValue(float value);
 		void setValue(float value);
 
 
+		bool hasInputFocus() const { return mHasInputFocus; }
+
+		Event<void(float)> onValueChanged;
 	protected:
 	protected:
 		virtual ~GUIFloatField();
 		virtual ~GUIFloatField();
 
 
 		void updateClippedBounds();
 		void updateClippedBounds();
 
 
-	protected:
+		bool _hasCustomCursor(const Vector2I position, CursorType& type) const;
+		virtual bool mouseEvent(const GUIMouseEvent& ev);
+		void styleUpdated();
+
+		void valueChanged(const WString& newValue);
+		void focusGained();
+		void focusLost();
+
+		static bool floatFilter(const WString& str);
+
 		static const float DRAG_SPEED;
 		static const float DRAG_SPEED;
 
 
 		GUIInputBox* mInputBox;
 		GUIInputBox* mInputBox;
+		float mValue;
 		INT32 mLastDragPos;
 		INT32 mLastDragPos;
 		bool mIsDragging;
 		bool mIsDragging;
-
-		bool _hasCustomCursor(const Vector2I position, CursorType& type) const;
-		virtual bool mouseEvent(const GUIMouseEvent& ev);
-
-		static bool floatFilter(const WString& str);
+		bool mHasInputFocus;
 	};
 	};
 }
 }

+ 16 - 24
BansheeEditor/Include/BsGUIGameObjectField.h

@@ -11,48 +11,40 @@ namespace BansheeEngine
 
 
 	public:
 	public:
 		static const String& getGUITypeName();
 		static const String& getGUITypeName();
+		static const String& getLabelStyleType();
+		static const String& getDropButtonStyleType();
+		static const String& getClearButtonStyleType();
 
 
 		static GUIGameObjectField* create(const GUIContent& labelContent, UINT32 labelWidth, const GUIOptions& layoutOptions, 
 		static GUIGameObjectField* create(const GUIContent& labelContent, UINT32 labelWidth, const GUIOptions& layoutOptions, 
-			const String& labelStyle = StringUtil::BLANK, const String& dropButtonStyle = StringUtil::BLANK,
-			const String& clearButtonStyle = StringUtil::BLANK);
+			const String& style = StringUtil::BLANK);
 
 
 		static GUIGameObjectField* create(const GUIContent& labelContent, const GUIOptions& layoutOptions, 
 		static GUIGameObjectField* create(const GUIContent& labelContent, const GUIOptions& layoutOptions, 
-			const String& labelStyle = StringUtil::BLANK, const String& dropButtonStyle = StringUtil::BLANK,
-			const String& clearButtonStyle = StringUtil::BLANK);
+			const String& style = StringUtil::BLANK);
 
 
 		static GUIGameObjectField* create(const HString& labelText, UINT32 labelWidth, const GUIOptions& layoutOptions, 
 		static GUIGameObjectField* create(const HString& labelText, UINT32 labelWidth, const GUIOptions& layoutOptions, 
-			const String& labelStyle = StringUtil::BLANK, const String& dropButtonStyle = StringUtil::BLANK,
-			const String& clearButtonStyle = StringUtil::BLANK);
+			const String& style = StringUtil::BLANK);
 
 
 		static GUIGameObjectField* create(const HString& labelText, const GUIOptions& layoutOptions, 
 		static GUIGameObjectField* create(const HString& labelText, const GUIOptions& layoutOptions, 
-			const String& labelStyle = StringUtil::BLANK, const String& dropButtonStyle = StringUtil::BLANK,
-			const String& clearButtonStyle = StringUtil::BLANK);
+			const String& style = StringUtil::BLANK);
 
 
-		static GUIGameObjectField* create(const GUIOptions& layoutOptions, const String& dropButtonStyle = StringUtil::BLANK,
-			const String& clearButtonStyle = StringUtil::BLANK);
+		static GUIGameObjectField* create(const GUIOptions& layoutOptions, const String& style = StringUtil::BLANK);
 
 
 		static GUIGameObjectField* create(const GUIContent& labelContent, UINT32 labelWidth, 
 		static GUIGameObjectField* create(const GUIContent& labelContent, UINT32 labelWidth, 
-			const String& labelStyle = StringUtil::BLANK, const String& dropButtonStyle = StringUtil::BLANK,
-			const String& clearButtonStyle = StringUtil::BLANK);
+			const String& style = StringUtil::BLANK);
 
 
 		static GUIGameObjectField* create(const GUIContent& labelContent, 
 		static GUIGameObjectField* create(const GUIContent& labelContent, 
-			const String& labelStyle = StringUtil::BLANK, const String& dropButtonStyle = StringUtil::BLANK,
-			const String& clearButtonStyle = StringUtil::BLANK);
+			const String& style = StringUtil::BLANK);
 
 
 		static GUIGameObjectField* create(const HString& labelText, UINT32 labelWidth, 
 		static GUIGameObjectField* create(const HString& labelText, UINT32 labelWidth, 
-			const String& labelStyle = StringUtil::BLANK, const String& dropButtonStyle = StringUtil::BLANK,
-			const String& clearButtonStyle = StringUtil::BLANK);
+			const String& style = StringUtil::BLANK);
 
 
 		static GUIGameObjectField* create(const HString& labelText, 
 		static GUIGameObjectField* create(const HString& labelText, 
-			const String& labelStyle = StringUtil::BLANK, const String& dropButtonStyle = StringUtil::BLANK,
-			const String& clearButtonStyle = StringUtil::BLANK);
+			const String& style = StringUtil::BLANK);
 
 
-		static GUIGameObjectField* create(const String& dropButtonStyle = StringUtil::BLANK,
-			const String& clearButtonStyle = StringUtil::BLANK);
+		static GUIGameObjectField* create(const String& style = StringUtil::BLANK);
 
 
 		GUIGameObjectField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
 		GUIGameObjectField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
-			UINT32 labelWidth, const String& labelStyle, const String& dropButtonStyle,
-			const String& clearButtonStyle, const GUILayoutOptions& layoutOptions, bool withLabel);
+			UINT32 labelWidth, const String& style, const GUILayoutOptions& layoutOptions, bool withLabel);
 
 
 		HGameObject getValue() const;
 		HGameObject getValue() const;
 		void setValue(const HGameObject& value);
 		void setValue(const HGameObject& value);
@@ -64,12 +56,12 @@ namespace BansheeEngine
 	private:
 	private:
 		virtual ~GUIGameObjectField();
 		virtual ~GUIGameObjectField();
 
 
+		void styleUpdated();
+
 		void dataDropped(void* data);
 		void dataDropped(void* data);
 
 
 	private:
 	private:
 		static const UINT32 DEFAULT_LABEL_WIDTH;
 		static const UINT32 DEFAULT_LABEL_WIDTH;
-		static const String DROP_BUTTON_STYLE;
-		static const String CLEAR_BUTTON_STYLE;
 
 
 		GUILayout* mLayout;
 		GUILayout* mLayout;
 		GUILabel* mLabel;
 		GUILabel* mLabel;

+ 14 - 13
BansheeEditor/Include/BsGUIIntField.h

@@ -9,38 +9,39 @@ namespace BansheeEngine
 	{
 	{
 	public:
 	public:
 		static const String& getGUITypeName();
 		static const String& getGUITypeName();
+		static const String& getInputStyleType();
 
 
 		GUIIntField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 		GUIIntField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
-			const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel);
+			const String& style, const GUILayoutOptions& layoutOptions, bool withLabel);
 
 
 		INT32 getValue() const { return mValue; }
 		INT32 getValue() const { return mValue; }
 		void setValue(INT32 value);
 		void setValue(INT32 value);
 
 
-		Event<void(INT32)> onValueChanged;
-
-		virtual Vector2I _getOptimalSize() const;
+		bool hasInputFocus() const { return mHasInputFocus; }
 
 
+		Event<void(INT32)> onValueChanged;
 	protected:
 	protected:
 		virtual ~GUIIntField();
 		virtual ~GUIIntField();
 
 
 		void updateClippedBounds();
 		void updateClippedBounds();
 
 
-	protected:
-		static const INT32 DRAG_SPEED;
-
-		GUIInputBox* mInputBox;
-		INT32 mValue;
-		INT32 mLastDragPos;
-		bool mIsDragging;
-		bool mIsDragCursorSet;
-
 		bool _hasCustomCursor(const Vector2I position, CursorType& type) const;
 		bool _hasCustomCursor(const Vector2I position, CursorType& type) const;
 		virtual bool mouseEvent(const GUIMouseEvent& ev);
 		virtual bool mouseEvent(const GUIMouseEvent& ev);
+		void styleUpdated();
 
 
 		void valueChanged(const WString& newValue);
 		void valueChanged(const WString& newValue);
 		void focusGained();
 		void focusGained();
 		void focusLost();
 		void focusLost();
 
 
 		static bool intFilter(const WString& str);
 		static bool intFilter(const WString& str);
+
+		static const INT32 DRAG_SPEED;
+
+		GUIInputBox* mInputBox;
+		INT32 mValue;
+		INT32 mLastDragPos;
+		bool mIsDragging;
+		bool mIsDragCursorSet;
+		bool mHasInputFocus;
 	};
 	};
 }
 }

+ 15 - 3
BansheeEditor/Include/BsGUITextField.h

@@ -9,16 +9,28 @@ namespace BansheeEngine
 	{
 	{
 	public:
 	public:
 		static const String& getGUITypeName();
 		static const String& getGUITypeName();
+		static const String& getInputStyleType();
 
 
 		GUITextField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 		GUITextField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
-			const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel);
+			const String& style, const GUILayoutOptions& layoutOptions, bool withLabel);
 
 
-		WString getValue() const;
+		WString getValue() const { return mValue; }
 		void setValue(const WString& value);
 		void setValue(const WString& value);
+
+		bool hasInputFocus() const { return mHasInputFocus; }
+
+		Event<void(const WString&)> onValueChanged;
 	protected:
 	protected:
 		virtual ~GUITextField();
 		virtual ~GUITextField();
 
 
-	protected:
+		void styleUpdated();
+
+		void valueChanged(const WString& newValue);
+		void focusGained();
+		void focusLost();
+
 		GUIInputBox* mInputBox;
 		GUIInputBox* mInputBox;
+		bool mHasInputFocus;
+		WString mValue;
 	};
 	};
 }
 }

+ 8 - 3
BansheeEditor/Include/BsGUIToggleField.h

@@ -9,17 +9,22 @@ namespace BansheeEngine
 	{
 	{
 	public:
 	public:
 		static const String& getGUITypeName();
 		static const String& getGUITypeName();
+		static const String& getToggleStyleType();
 
 
 		GUIToggleField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 		GUIToggleField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
-			const String& labelStyle, const String& toggleStyle, const GUILayoutOptions& layoutOptions, bool withLabel);
+			const String& style, const GUILayoutOptions& layoutOptions, bool withLabel);
 
 
-		bool getValue() const;
+		bool getValue() const { return mValue; }
 		void setValue(bool value);
 		void setValue(bool value);
 
 
+		Event<void(bool)> onValueChanged;
 	protected:
 	protected:
 		virtual ~GUIToggleField() { }
 		virtual ~GUIToggleField() { }
 
 
-	protected:
+		void styleUpdated();
+		void valueChanged(bool newValue);
+
 		GUIToggle* mToggle;
 		GUIToggle* mToggle;
+		bool mValue;
 	};
 	};
 }
 }

+ 8 - 1
BansheeEditor/Include/BsGUIVector2Field.h

@@ -10,19 +10,26 @@ namespace BansheeEngine
 	{
 	{
 	public:
 	public:
 		static const String& getGUITypeName();
 		static const String& getGUITypeName();
+		static const String& getFloatFieldStyleType();
 
 
 		GUIVector2Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 		GUIVector2Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
-			const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel);
+			const String& style, const GUILayoutOptions& layoutOptions, bool withLabel);
 
 
 		Vector2 getValue() const;
 		Vector2 getValue() const;
 		void setValue(const Vector2& value);
 		void setValue(const Vector2& value);
 
 
+		bool hasInputFocus() const;
+
+		Event<void(const Vector2&)> onValueChanged;
 	protected:
 	protected:
 		virtual ~GUIVector2Field() { }
 		virtual ~GUIVector2Field() { }
 
 
 	protected:
 	protected:
 		static const UINT32 ELEMENT_LABEL_WIDTH;
 		static const UINT32 ELEMENT_LABEL_WIDTH;
 
 
+		void styleUpdated();
+		void valueChanged(float newValue);
+
 		GUIFloatField* mFieldX;
 		GUIFloatField* mFieldX;
 		GUIFloatField* mFieldY;
 		GUIFloatField* mFieldY;
 	};
 	};

+ 8 - 2
BansheeEditor/Include/BsGUIVector3Field.h

@@ -10,17 +10,23 @@ namespace BansheeEngine
 	{
 	{
 	public:
 	public:
 		static const String& getGUITypeName();
 		static const String& getGUITypeName();
+		static const String& getFloatFieldStyleType();
 
 
 		GUIVector3Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 		GUIVector3Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
-			const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel);
+			const String& style, const GUILayoutOptions& layoutOptions, bool withLabel);
 
 
 		Vector3 getValue() const;
 		Vector3 getValue() const;
 		void setValue(const Vector3& value);
 		void setValue(const Vector3& value);
 
 
+		bool hasInputFocus() const;
+
+		Event<void(const Vector3&)> onValueChanged;
 	protected:
 	protected:
 		virtual ~GUIVector3Field() { }
 		virtual ~GUIVector3Field() { }
 
 
-	protected:
+		void styleUpdated();
+		void valueChanged(float newValue);
+
 		static const UINT32 ELEMENT_LABEL_WIDTH;
 		static const UINT32 ELEMENT_LABEL_WIDTH;
 
 
 		GUIFloatField* mFieldX;
 		GUIFloatField* mFieldX;

+ 8 - 2
BansheeEditor/Include/BsGUIVector4Field.h

@@ -10,17 +10,23 @@ namespace BansheeEngine
 	{
 	{
 	public:
 	public:
 		static const String& getGUITypeName();
 		static const String& getGUITypeName();
+		static const String& getFloatFieldStyleType();
 
 
 		GUIVector4Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 		GUIVector4Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
-			const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel);
+			const String& style, const GUILayoutOptions& layoutOptions, bool withLabel);
 
 
 		Vector4 getValue() const;
 		Vector4 getValue() const;
 		void setValue(const Vector4& value);
 		void setValue(const Vector4& value);
 
 
+		bool hasInputFocus() const;
+
+		Event<void(const Vector4&)> onValueChanged;
 	protected:
 	protected:
 		virtual ~GUIVector4Field() { }
 		virtual ~GUIVector4Field() { }
 
 
-	protected:
+		void styleUpdated();
+		void valueChanged(float newValue);
+
 		static const UINT32 ELEMENT_LABEL_WIDTH;
 		static const UINT32 ELEMENT_LABEL_WIDTH;
 
 
 		GUIFloatField* mFieldX;
 		GUIFloatField* mFieldX;

+ 108 - 2
BansheeEditor/Source/BsEditorGUI.cpp

@@ -10,6 +10,16 @@
 #include "BsSpriteTexture.h"
 #include "BsSpriteTexture.h"
 #include "BsGUITreeViewEditBox.h"
 #include "BsGUITreeViewEditBox.h"
 
 
+#include "BsGUIIntField.h"
+#include "BsGUIFloatField.h"
+#include "BsGUIColorField.h"
+#include "BsGUITextField.h"
+#include "BsGUIToggleField.h"
+#include "BsGUIVector2Field.h"
+#include "BsGUIVector3Field.h"
+#include "BsGUIVector4Field.h"
+#include "BsGUIGameObjectField.h"
+
 #include "BsFont.h"
 #include "BsFont.h"
 #include "BsFontImportOptions.h"
 #include "BsFontImportOptions.h"
 #include "BsImporter.h"
 #include "BsImporter.h"
@@ -803,7 +813,7 @@ namespace BansheeEngine
 		objectDropStyle.textHorzAlign = THA_Center;
 		objectDropStyle.textHorzAlign = THA_Center;
 		objectDropStyle.textVertAlign = TVA_Center;
 		objectDropStyle.textVertAlign = TVA_Center;
 
 
-		mSkin.setStyle("DropButton", objectDropStyle);
+		mSkin.setStyle(GUIGameObjectField::getDropButtonStyleType(), objectDropStyle);
 
 
 		GUIElementStyle objectClearBtnStyle;
 		GUIElementStyle objectClearBtnStyle;
 		objectClearBtnStyle.normal.texture = getTexture(ObjectClearBtnNormalTex);
 		objectClearBtnStyle.normal.texture = getTexture(ObjectClearBtnNormalTex);
@@ -814,8 +824,104 @@ namespace BansheeEngine
 		objectClearBtnStyle.height = 15;
 		objectClearBtnStyle.height = 15;
 		objectClearBtnStyle.width = 13;
 		objectClearBtnStyle.width = 13;
 
 
-		mSkin.setStyle("ObjectClearButton", objectClearBtnStyle);
+		mSkin.setStyle(GUIGameObjectField::getClearButtonStyleType(), objectClearBtnStyle);
+
+		GUIElementStyle editorObjectFieldStyle;
+		editorObjectFieldStyle.fixedHeight = true;
+		editorObjectFieldStyle.height = 15;
+		editorObjectFieldStyle.minWidth = 30;
+		editorObjectFieldStyle.subStyles[GUIGameObjectField::getLabelStyleType()] = GUITextField::getLabelStyleType();
+		editorObjectFieldStyle.subStyles[GUIGameObjectField::getDropButtonStyleType()] = GUIGameObjectField::getDropButtonStyleType();
+		editorObjectFieldStyle.subStyles[GUIGameObjectField::getClearButtonStyleType()] = GUIGameObjectField::getClearButtonStyleType();
+
+		mSkin.setStyle(GUIGameObjectField::getGUITypeName(), editorObjectFieldStyle);
+
+		/************************************************************************/
+		/* 								EDITOR FIELDS                      		*/
+		/************************************************************************/
 
 
+		GUIElementStyle editorFieldLabelStyle;
+		editorFieldLabelStyle.font = font;
+		editorFieldLabelStyle.fontSize = DefaultFontSize;
+		editorFieldLabelStyle.fixedWidth = false;
+		editorFieldLabelStyle.fixedHeight = true;
+		editorFieldLabelStyle.height = 11;
+		editorFieldLabelStyle.minWidth = 10;
+		editorFieldLabelStyle.textHorzAlign = THA_Left;
+
+		mSkin.setStyle(GUITextField::getLabelStyleType(), editorFieldLabelStyle);
+
+		GUIElementStyle editorIntFieldStyle;
+		editorIntFieldStyle.fixedHeight = true;
+		editorIntFieldStyle.height = 15;
+		editorIntFieldStyle.minWidth = 30;
+		editorIntFieldStyle.subStyles[GUIIntField::getLabelStyleType()] = GUITextField::getLabelStyleType();
+		editorIntFieldStyle.subStyles[GUIIntField::getInputStyleType()] = GUIInputBox::getGUITypeName();
+
+		mSkin.setStyle(GUIIntField::getGUITypeName(), editorIntFieldStyle);
+
+		GUIElementStyle editorFloatFieldStyle;
+		editorFloatFieldStyle.fixedHeight = true;
+		editorFloatFieldStyle.height = 15;
+		editorFloatFieldStyle.minWidth = 30;
+		editorFloatFieldStyle.subStyles[GUIFloatField::getLabelStyleType()] = GUITextField::getLabelStyleType();
+		editorFloatFieldStyle.subStyles[GUIFloatField::getInputStyleType()] = GUIInputBox::getGUITypeName();
+
+		mSkin.setStyle(GUIFloatField::getGUITypeName(), editorFloatFieldStyle);
+
+		GUIElementStyle editorTextFieldStyle;
+		editorTextFieldStyle.fixedHeight = true;
+		editorTextFieldStyle.height = 15;
+		editorTextFieldStyle.minWidth = 30;
+		editorTextFieldStyle.subStyles[GUITextField::getLabelStyleType()] = GUITextField::getLabelStyleType();
+		editorTextFieldStyle.subStyles[GUITextField::getInputStyleType()] = GUIInputBox::getGUITypeName();
+
+		mSkin.setStyle(GUITextField::getGUITypeName(), editorTextFieldStyle);
+
+		GUIElementStyle editorColorFieldStyle;
+		editorColorFieldStyle.fixedHeight = true;
+		editorColorFieldStyle.height = 15;
+		editorColorFieldStyle.minWidth = 30;
+		editorColorFieldStyle.subStyles[GUIColorField::getLabelStyleType()] = GUITextField::getLabelStyleType();
+		editorColorFieldStyle.subStyles[GUIColorField::getColorInputStyleType()] = GUIColor::getGUITypeName();
+
+		mSkin.setStyle(GUIColorField::getGUITypeName(), editorColorFieldStyle);
+
+		GUIElementStyle editorToggleFieldStyle;
+		editorToggleFieldStyle.fixedHeight = true;
+		editorToggleFieldStyle.height = 15;
+		editorToggleFieldStyle.minWidth = 30;
+		editorToggleFieldStyle.subStyles[GUIToggleField::getLabelStyleType()] = GUITextField::getLabelStyleType();
+		editorToggleFieldStyle.subStyles[GUIToggleField::getToggleStyleType()] = GUIToggle::getGUITypeName();
+
+		mSkin.setStyle(GUIToggleField::getGUITypeName(), editorToggleFieldStyle);
+
+		GUIElementStyle editorVector2FieldStyle;
+		editorVector2FieldStyle.fixedHeight = true;
+		editorVector2FieldStyle.height = 30;
+		editorVector2FieldStyle.minWidth = 30;
+		editorVector2FieldStyle.subStyles[GUIVector2Field::getLabelStyleType()] = GUITextField::getLabelStyleType();
+		editorVector2FieldStyle.subStyles[GUIVector2Field::getFloatFieldStyleType()] = GUIFloatField::getGUITypeName();
+
+		mSkin.setStyle(GUIVector2Field::getGUITypeName(), editorVector2FieldStyle);
+
+		GUIElementStyle editorVector3FieldStyle;
+		editorVector3FieldStyle.fixedHeight = true;
+		editorVector3FieldStyle.height = 30;
+		editorVector3FieldStyle.minWidth = 30;
+		editorVector3FieldStyle.subStyles[GUIVector3Field::getLabelStyleType()] = GUITextField::getLabelStyleType();
+		editorVector3FieldStyle.subStyles[GUIVector3Field::getFloatFieldStyleType()] = GUIFloatField::getGUITypeName();
+
+		mSkin.setStyle(GUIVector3Field::getGUITypeName(), editorVector3FieldStyle);
+
+		GUIElementStyle editorVector4FieldStyle;
+		editorVector4FieldStyle.fixedHeight = true;
+		editorVector4FieldStyle.height = 30;
+		editorVector4FieldStyle.minWidth = 30;
+		editorVector4FieldStyle.subStyles[GUIVector4Field::getLabelStyleType()] = GUITextField::getLabelStyleType();
+		editorVector4FieldStyle.subStyles[GUIVector4Field::getFloatFieldStyleType()] = GUIFloatField::getGUITypeName();
+
+		mSkin.setStyle(GUIVector4Field::getGUITypeName(), editorVector4FieldStyle);
 	}
 	}
 
 
 	HSpriteTexture EditorGUI::getTexture(const WString& name)
 	HSpriteTexture EditorGUI::getTexture(const WString& name)

+ 2 - 1
BansheeEditor/Source/BsGUIColor.cpp

@@ -149,7 +149,8 @@ namespace BansheeEngine
 	{
 	{
 		if(ev.getType() == GUIMouseEventType::MouseUp)
 		if(ev.getType() == GUIMouseEventType::MouseUp)
 		{
 		{
-			// TODO
+			// TODO - Open color picker window
+			//      - Trigger onValueChanged when done
 
 
 			return true;
 			return true;
 		}
 		}

+ 77 - 27
BansheeEditor/Source/BsGUIColorField.cpp

@@ -7,25 +7,30 @@
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 #include "BsGUIMouseEvent.h"
 #include "BsGUIMouseEvent.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
+#include "BsCmdInputFieldValueChange.h"
+
+using namespace std::placeholders;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	GUIColorField::GUIColorField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
 	GUIColorField::GUIColorField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
-		const String& labelStyle, const String& colorStyle, const GUILayoutOptions& layoutOptions)
-		:GUIElementContainer(layoutOptions), mLabel(nullptr), mColor(nullptr), mLabelWidth(100)
+		const String& style, const GUILayoutOptions& layoutOptions)
+		:GUIElementContainer(layoutOptions, style), mLabel(nullptr), mColor(nullptr), mLabelWidth(100)
 	{
 	{
-		mLabel = GUILabel::create(labelContent, labelStyle);
-		mColor = GUIColor::create(colorStyle);
+		mLabel = GUILabel::create(labelContent, getSubStyleName(getLabelStyleType()));
+		mColor = GUIColor::create(getSubStyleName(getColorInputStyleType()));
+
+		mColor->onValueChanged.connect(std::bind(&GUIColorField::valueChanged, this, _1));
 
 
 		_registerChildElement(mLabel);
 		_registerChildElement(mLabel);
 		_registerChildElement(mColor);
 		_registerChildElement(mColor);
 	}
 	}
 
 
 	GUIColorField::GUIColorField(const PrivatelyConstruct& dummy, 
 	GUIColorField::GUIColorField(const PrivatelyConstruct& dummy, 
-		const String& labelStyle, const String& colorStyle, const GUILayoutOptions& layoutOptions)
-		:GUIElementContainer(layoutOptions), mLabel(nullptr), mColor(nullptr), mLabelWidth(100)
+		const String& style, const GUILayoutOptions& layoutOptions)
+		:GUIElementContainer(layoutOptions, style), mLabel(nullptr), mColor(nullptr), mLabelWidth(100)
 	{
 	{
-		mColor = GUIColor::create(colorStyle);
+		mColor = GUIColor::create(style);
 
 
 		_registerChildElement(mColor);
 		_registerChildElement(mColor);
 	}
 	}
@@ -36,52 +41,69 @@ namespace BansheeEngine
 	}
 	}
 
 
 	GUIColorField* GUIColorField::create(const GUIContent& labelContent, const GUIOptions& layoutOptions, 
 	GUIColorField* GUIColorField::create(const GUIContent& labelContent, const GUIOptions& layoutOptions, 
-		const String& labelStyle, const String& toggleStyle)
+		const String& style)
 	{
 	{
-		return bs_new<GUIColorField>(PrivatelyConstruct(), labelContent, labelStyle, toggleStyle, 
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIColorField>(PrivatelyConstruct(), labelContent, *curStyle,
 			GUILayoutOptions::create(layoutOptions));
 			GUILayoutOptions::create(layoutOptions));
 	}
 	}
 
 
-	GUIColorField* GUIColorField::create(const GUIContent& labelContent, const String& labelStyle, 
-		const String& toggleStyle)
+	GUIColorField* GUIColorField::create(const GUIContent& labelContent, const String& style)
 	{
 	{
-		return bs_new<GUIColorField>(PrivatelyConstruct(), labelContent, labelStyle, toggleStyle, 
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIColorField>(PrivatelyConstruct(), labelContent, *curStyle,
 			GUILayoutOptions::create());
 			GUILayoutOptions::create());
 	}
 	}
 
 
 	GUIColorField* GUIColorField::create(const HString& labelContent, const GUIOptions& layoutOptions, 
 	GUIColorField* GUIColorField::create(const HString& labelContent, const GUIOptions& layoutOptions, 
-		const String& labelStyle, const String& toggleStyle)
+		const String& style)
 	{
 	{
-		return bs_new<GUIColorField>(PrivatelyConstruct(), GUIContent(labelContent), labelStyle, 
-			toggleStyle, GUILayoutOptions::create(layoutOptions));
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIColorField>(PrivatelyConstruct(), GUIContent(labelContent), *curStyle,
+			GUILayoutOptions::create(layoutOptions));
 	}
 	}
 
 
-	GUIColorField* GUIColorField::create( const HString& labelContent, const String& labelStyle, 
-		const String& toggleStyle)
+	GUIColorField* GUIColorField::create(const HString& labelContent, const String& style)
 	{
 	{
-		return bs_new<GUIColorField>(PrivatelyConstruct(), GUIContent(labelContent), labelStyle, toggleStyle, 
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIColorField>(PrivatelyConstruct(), GUIContent(labelContent), *curStyle,
 			GUILayoutOptions::create());
 			GUILayoutOptions::create());
 	}
 	}
 
 
-	GUIColorField* GUIColorField::create(const GUIOptions& layoutOptions, const String& labelStyle, 
-		const String& toggleStyle)
+	GUIColorField* GUIColorField::create(const GUIOptions& layoutOptions, const String& style)
 	{
 	{
-		return bs_new<GUIColorField>(PrivatelyConstruct(), labelStyle, toggleStyle, 
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIColorField>(PrivatelyConstruct(), *curStyle,
 			GUILayoutOptions::create(layoutOptions));
 			GUILayoutOptions::create(layoutOptions));
 	}
 	}
 
 
-	GUIColorField* GUIColorField::create(const String& labelStyle, const String& toggleStyle)
+	GUIColorField* GUIColorField::create(const String& style)
 	{
 	{
-		return bs_new<GUIColorField>(PrivatelyConstruct(), labelStyle, toggleStyle, GUILayoutOptions::create());
-	}
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
 
 
-	Color GUIColorField::getValue() const
-	{
-		return mColor->getColor();
+		return bs_new<GUIColorField>(PrivatelyConstruct(), *curStyle, GUILayoutOptions::create());
 	}
 	}
 
 
 	void GUIColorField::setValue(const Color& color)
 	void GUIColorField::setValue(const Color& color)
 	{
 	{
+		mValue = color;
 		mColor->setColor(color);
 		mColor->setColor(color);
 	}
 	}
 
 
@@ -148,9 +170,37 @@ namespace BansheeEngine
 		return optimalsize;
 		return optimalsize;
 	}
 	}
 
 
+	void GUIColorField::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mColor->setStyle(getSubStyleName(getColorInputStyleType()));
+	}
+
+	void GUIColorField::valueChanged(const Color& newValue)
+	{
+		setValue(newValue);
+
+		if (!onValueChanged.empty())
+			onValueChanged(newValue);
+	}
+
 	const String& GUIColorField::getGUITypeName()
 	const String& GUIColorField::getGUITypeName()
 	{
 	{
 		static String typeName = "GUIColorField";
 		static String typeName = "GUIColorField";
 		return typeName;
 		return typeName;
 	}
 	}
+
+	const String& GUIColorField::getLabelStyleType()
+	{
+		static String STYLE_TYPE = "EditorFieldLabel";
+		return STYLE_TYPE;
+	}
+
+	const String& GUIColorField::getColorInputStyleType()
+	{
+		static String STYLE_TYPE = "EditorFieldColor";
+		return STYLE_TYPE;
+	}
 }
 }

+ 12 - 4
BansheeEditor/Source/BsGUIFieldBase.cpp

@@ -3,20 +3,21 @@
 #include "BsGUILayout.h"
 #include "BsGUILayout.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 #include "BsGUISkin.h"
 #include "BsGUISkin.h"
+#include "BsGUILayoutUtility.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	const UINT32 GUIFieldBase::DEFAULT_LABEL_WIDTH = 100;
 	const UINT32 GUIFieldBase::DEFAULT_LABEL_WIDTH = 100;
 
 
 	GUIFieldBase::GUIFieldBase(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 	GUIFieldBase::GUIFieldBase(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
-		const String& labelStyle, const GUILayoutOptions& layoutOptions, bool withLabel)
-		:GUIElementContainer(layoutOptions), mLabel(nullptr)
+		const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
+		:GUIElementContainer(layoutOptions, style), mLabel(nullptr)
 	{
 	{
 		mLayout = &addLayoutXInternal(this);
 		mLayout = &addLayoutXInternal(this);
 
 
 		if(withLabel)
 		if(withLabel)
 		{
 		{
-			mLabel = GUILabel::create(labelContent, GUIOptions(GUIOption::fixedWidth(labelWidth)), labelStyle);
+			mLabel = GUILabel::create(labelContent, GUIOptions(GUIOption::fixedWidth(labelWidth)), getSubStyleName(getLabelStyleType()));
 			mLayout->addElement(mLabel);
 			mLayout->addElement(mLabel);
 		}
 		}
 	}
 	}
@@ -29,6 +30,13 @@ namespace BansheeEngine
 
 
 	Vector2I GUIFieldBase::_getOptimalSize() const
 	Vector2I GUIFieldBase::_getOptimalSize() const
 	{
 	{
-		return mLayout->_getOptimalSize();
+		return GUILayoutUtility::calcOptimalSize(mLayout);
+	}
+
+
+	void GUIFieldBase::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
 	}
 	}
 }
 }

+ 48 - 9
BansheeEditor/Source/BsGUIFloatField.cpp

@@ -10,20 +10,27 @@
 #include "BsCursor.h"
 #include "BsCursor.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 #include "BsViewport.h"
 #include "BsViewport.h"
+#include "BsCmdInputFieldValueChange.h"
 #include <regex>
 #include <regex>
 
 
+using namespace std::placeholders;
+
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	const float GUIFloatField::DRAG_SPEED = 0.05f;
 	const float GUIFloatField::DRAG_SPEED = 0.05f;
 
 
 	GUIFloatField::GUIFloatField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth, 
 	GUIFloatField::GUIFloatField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth, 
-		const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel)
-		:TGUIField(dummy, labelContent, labelWidth, labelStyle, layoutOptions, withLabel), mInputBox(nullptr), mIsDragging(false),
-		mLastDragPos(0)
+		const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
+		:TGUIField(dummy, labelContent, labelWidth, style, layoutOptions, withLabel), mInputBox(nullptr), mIsDragging(false),
+		mLastDragPos(0), mHasInputFocus(false), mValue(0.0f)
 	{
 	{
-		mInputBox = GUIInputBox::create(false, GUIOptions(GUIOption::flexibleWidth()), inputBoxStyle);
+		mInputBox = GUIInputBox::create(false, GUIOptions(GUIOption::flexibleWidth()), getSubStyleName(getInputStyleType()));
 		mInputBox->setFilter(&GUIFloatField::floatFilter);
 		mInputBox->setFilter(&GUIFloatField::floatFilter);
 
 
+		mInputBox->onValueChanged.connect(std::bind(&GUIFloatField::valueChanged, this, _1));
+		mInputBox->onFocusGained.connect(std::bind(&GUIFloatField::focusGained, this));
+		mInputBox->onFocusLost.connect(std::bind(&GUIFloatField::focusLost, this));
+
 		mLayout->addElement(mInputBox);
 		mLayout->addElement(mInputBox);
 
 
 		setValue(0);
 		setValue(0);
@@ -114,13 +121,9 @@ namespace BansheeEngine
 		return false;
 		return false;
 	}
 	}
 
 
-	float GUIFloatField::getValue() const
-	{
-		return parseFloat(mInputBox->getText());
-	}
-
 	void GUIFloatField::setValue(float value)
 	void GUIFloatField::setValue(float value)
 	{
 	{
+		mValue = value;
 		mInputBox->setText(toWString(value));
 		mInputBox->setText(toWString(value));
 	}
 	}
 
 
@@ -136,6 +139,42 @@ namespace BansheeEngine
 		return typeName;
 		return typeName;
 	}
 	}
 
 
+	const String& GUIFloatField::getInputStyleType()
+	{
+		static String LABEL_STYLE_TYPE = "EditorFieldInput";
+		return LABEL_STYLE_TYPE;
+	}
+
+	void GUIFloatField::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mInputBox->setStyle(getSubStyleName(getInputStyleType()));
+	}
+
+	void GUIFloatField::valueChanged(const WString& newValue)
+	{
+		float newFloatValue = parseFloat(newValue);
+
+		CmdInputFieldValueChange<GUIFloatField, float>::execute(this, newFloatValue);
+
+		if (!onValueChanged.empty())
+			onValueChanged(newFloatValue);
+	}
+
+	void GUIFloatField::focusGained()
+	{
+		UndoRedo::instance().pushGroup("InputBox");
+		mHasInputFocus = true;
+	}
+
+	void GUIFloatField::focusLost()
+	{
+		UndoRedo::instance().popGroup("InputBox");
+		mHasInputFocus = false;
+	}
+
 	bool GUIFloatField::floatFilter(const WString& str)
 	bool GUIFloatField::floatFilter(const WString& str)
 	{
 	{
 		return std::regex_match(str, std::wregex(L"-?(\\d+(\\.\\d*)?)?"));
 		return std::regex_match(str, std::wregex(L"-?(\\d+(\\.\\d*)?)?"));

+ 92 - 37
BansheeEditor/Source/BsGUIGameObjectField.cpp

@@ -16,32 +16,21 @@ using namespace std::placeholders;
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	const UINT32 GUIGameObjectField::DEFAULT_LABEL_WIDTH = 100;
 	const UINT32 GUIGameObjectField::DEFAULT_LABEL_WIDTH = 100;
-	const String GUIGameObjectField::DROP_BUTTON_STYLE = "DropButton";
-	const String GUIGameObjectField::CLEAR_BUTTON_STYLE = "ObjectClearButton";
 
 
 	GUIGameObjectField::GUIGameObjectField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 	GUIGameObjectField::GUIGameObjectField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
-		const String& labelStyle, const String& dropButtonStyle, const String& clearButtonStyle, const GUILayoutOptions& layoutOptions, bool withLabel)
-		:GUIElementContainer(layoutOptions), mLabel(nullptr), mClearButton(nullptr), mDropButton(nullptr), mInstanceId(0)
+		const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
+		:GUIElementContainer(layoutOptions, style), mLabel(nullptr), mClearButton(nullptr), mDropButton(nullptr), mInstanceId(0)
 	{
 	{
 		mLayout = &addLayoutXInternal(this);
 		mLayout = &addLayoutXInternal(this);
 
 
 		if(withLabel)
 		if(withLabel)
 		{
 		{
-			mLabel = GUILabel::create(labelContent, GUIOptions(GUIOption::fixedWidth(labelWidth)), labelStyle);
+			mLabel = GUILabel::create(labelContent, GUIOptions(GUIOption::fixedWidth(labelWidth)), getSubStyleName(getLabelStyleType()));
 			mLayout->addElement(mLabel);
 			mLayout->addElement(mLabel);
 		}
 		}
 
 
-		const String* curDropButtonStyle = &dropButtonStyle;
-		const String* curClearButtonStyle = &clearButtonStyle;
-
-		if(*curDropButtonStyle == StringUtil::BLANK)
-			curDropButtonStyle = &DROP_BUTTON_STYLE;
-
-		if(*curClearButtonStyle == StringUtil::BLANK)
-			curClearButtonStyle = &CLEAR_BUTTON_STYLE;
-
-		mDropButton = GUIDropButton::create((UINT32)DragAndDropType::SceneObject, GUIOptions(GUIOption::flexibleWidth()), *curDropButtonStyle);
-		mClearButton = GUIButton::create(HString(L""), *curClearButtonStyle);
+		mDropButton = GUIDropButton::create((UINT32)DragAndDropType::SceneObject, GUIOptions(GUIOption::flexibleWidth()), getSubStyleName(getDropButtonStyleType()));
+		mClearButton = GUIButton::create(HString(L""), getSubStyleName(getClearButtonStyleType()));
 
 
 		mLayout->addElement(mDropButton);
 		mLayout->addElement(mDropButton);
 		mLayout->addElement(mClearButton);
 		mLayout->addElement(mClearButton);
@@ -55,71 +44,110 @@ namespace BansheeEngine
 	}
 	}
 
 
 	GUIGameObjectField* GUIGameObjectField::create(const GUIContent& labelContent, UINT32 labelWidth, const GUIOptions& layoutOptions, 
 	GUIGameObjectField* GUIGameObjectField::create(const GUIContent& labelContent, UINT32 labelWidth, const GUIOptions& layoutOptions, 
-		const String& labelStyle, const String& dropButtonStyle, const String& clearButtonStyle)
+		const String& style)
 	{
 	{
-		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), labelContent, labelWidth, labelStyle, dropButtonStyle, clearButtonStyle,
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), labelContent, labelWidth, *curStyle,
 			GUILayoutOptions::create(layoutOptions), true);
 			GUILayoutOptions::create(layoutOptions), true);
 	}
 	}
 
 
 	GUIGameObjectField* GUIGameObjectField::create(const GUIContent& labelContent, const GUIOptions& layoutOptions, 
 	GUIGameObjectField* GUIGameObjectField::create(const GUIContent& labelContent, const GUIOptions& layoutOptions, 
-		const String& labelStyle, const String& dropButtonStyle, const String& clearButtonStyle)
+		const String& style)
 	{
 	{
-		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), labelContent, DEFAULT_LABEL_WIDTH, labelStyle, dropButtonStyle, clearButtonStyle,
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), labelContent, DEFAULT_LABEL_WIDTH, *curStyle,
 			GUILayoutOptions::create(layoutOptions), true);
 			GUILayoutOptions::create(layoutOptions), true);
 	}
 	}
 
 
 	GUIGameObjectField* GUIGameObjectField::create(const HString& labelText, UINT32 labelWidth, const GUIOptions& layoutOptions, 
 	GUIGameObjectField* GUIGameObjectField::create(const HString& labelText, UINT32 labelWidth, const GUIOptions& layoutOptions, 
-		const String& labelStyle, const String& dropButtonStyle, const String& clearButtonStyle)
+		const String& style)
 	{
 	{
-		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(labelText), labelWidth, labelStyle, dropButtonStyle, clearButtonStyle,
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(labelText), labelWidth, *curStyle,
 			GUILayoutOptions::create(layoutOptions), true);
 			GUILayoutOptions::create(layoutOptions), true);
 	}
 	}
 
 
 	GUIGameObjectField* GUIGameObjectField::create(const HString& labelText, const GUIOptions& layoutOptions, 
 	GUIGameObjectField* GUIGameObjectField::create(const HString& labelText, const GUIOptions& layoutOptions, 
-		const String& labelStyle, const String& dropButtonStyle, const String& clearButtonStyle)
+		const String& style)
 	{
 	{
-		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(labelText), DEFAULT_LABEL_WIDTH, labelStyle, dropButtonStyle, clearButtonStyle, 
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(labelText), DEFAULT_LABEL_WIDTH, *curStyle,
 			GUILayoutOptions::create(layoutOptions), true);
 			GUILayoutOptions::create(layoutOptions), true);
 	}
 	}
 
 
-	GUIGameObjectField* GUIGameObjectField::create(const GUIOptions& layoutOptions, const String& dropButtonStyle,
-		const String& clearButtonStyle)
+	GUIGameObjectField* GUIGameObjectField::create(const GUIOptions& layoutOptions, const String& style)
 	{
 	{
-		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(), 0, nullptr, dropButtonStyle, clearButtonStyle,
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(), 0, *curStyle,
 			GUILayoutOptions::create(layoutOptions), false);
 			GUILayoutOptions::create(layoutOptions), false);
 	}
 	}
 
 
 	GUIGameObjectField* GUIGameObjectField::create(const GUIContent& labelContent, UINT32 labelWidth, 
 	GUIGameObjectField* GUIGameObjectField::create(const GUIContent& labelContent, UINT32 labelWidth, 
-		const String& labelStyle, const String& dropButtonStyle, const String& clearButtonStyle)
+		const String& style)
 	{
 	{
-		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), labelContent, labelWidth, labelStyle, dropButtonStyle, clearButtonStyle,
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), labelContent, labelWidth, *curStyle,
 			GUILayoutOptions::create(), true);
 			GUILayoutOptions::create(), true);
 	}
 	}
 
 
 	GUIGameObjectField* GUIGameObjectField::create(const GUIContent& labelContent, 
 	GUIGameObjectField* GUIGameObjectField::create(const GUIContent& labelContent, 
-		const String& labelStyle, const String& dropButtonStyle, const String& clearButtonStyle)
+		const String& style)
 	{
 	{
-		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), labelContent, DEFAULT_LABEL_WIDTH, labelStyle, dropButtonStyle, clearButtonStyle,
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), labelContent, DEFAULT_LABEL_WIDTH, *curStyle,
 			GUILayoutOptions::create(), true);
 			GUILayoutOptions::create(), true);
 	}
 	}
 
 
 	GUIGameObjectField* GUIGameObjectField::create(const HString& labelText, UINT32 labelWidth, 
 	GUIGameObjectField* GUIGameObjectField::create(const HString& labelText, UINT32 labelWidth, 
-		const String& labelStyle, const String& dropButtonStyle, const String& clearButtonStyle)
+		const String& style)
 	{
 	{
-		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(labelText), labelWidth, labelStyle, dropButtonStyle, clearButtonStyle,
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(labelText), labelWidth, *curStyle,
 			GUILayoutOptions::create(), true);
 			GUILayoutOptions::create(), true);
 	}
 	}
 
 
 	GUIGameObjectField* GUIGameObjectField::create(const HString& labelText, 
 	GUIGameObjectField* GUIGameObjectField::create(const HString& labelText, 
-		const String& labelStyle, const String& dropButtonStyle, const String& clearButtonStyle)
+		const String& style)
 	{
 	{
-		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(labelText), DEFAULT_LABEL_WIDTH, labelStyle, dropButtonStyle, clearButtonStyle, 
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(labelText), DEFAULT_LABEL_WIDTH, *curStyle,
 			GUILayoutOptions::create(), true);
 			GUILayoutOptions::create(), true);
 	}
 	}
 
 
-	GUIGameObjectField* GUIGameObjectField::create(const String& dropButtonStyle, const String& clearButtonStyle)
+	GUIGameObjectField* GUIGameObjectField::create(const String& style)
 	{
 	{
-		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(), 0, nullptr, dropButtonStyle, clearButtonStyle,
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIGameObjectField>(PrivatelyConstruct(), GUIContent(), 0, *curStyle,
 			GUILayoutOptions::create(), false);
 			GUILayoutOptions::create(), false);
 	}
 	}
 
 
@@ -165,9 +193,36 @@ namespace BansheeEngine
 		// TODO
 		// TODO
 	}
 	}
 
 
+	void GUIGameObjectField::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mDropButton->setStyle(getSubStyleName(getDropButtonStyleType()));
+		mClearButton->setStyle(getSubStyleName(getClearButtonStyleType()));
+	}
+
 	const String& GUIGameObjectField::getGUITypeName()
 	const String& GUIGameObjectField::getGUITypeName()
 	{
 	{
 		static String typeName = "GUIGameObjectField";
 		static String typeName = "GUIGameObjectField";
 		return typeName;
 		return typeName;
 	}
 	}
+
+	const String& GUIGameObjectField::getLabelStyleType()
+	{
+		static String STYLE_TYPE = "EditorFieldLabel";
+		return STYLE_TYPE;
+	}
+
+	const String& GUIGameObjectField::getDropButtonStyleType()
+	{
+		static String typeName = "DropButton";
+		return typeName;
+	}
+
+	const String& GUIGameObjectField::getClearButtonStyleType()
+	{
+		static String typeName = "ObjectClearButton";
+		return typeName;
+	}
 }
 }

+ 20 - 18
BansheeEditor/Source/BsGUIIntField.cpp

@@ -21,11 +21,11 @@ namespace BansheeEngine
 	const INT32 GUIIntField::DRAG_SPEED = 5;
 	const INT32 GUIIntField::DRAG_SPEED = 5;
 
 
 	GUIIntField::GUIIntField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 	GUIIntField::GUIIntField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
-		const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel)
-		:TGUIField(dummy, labelContent, labelWidth, labelStyle, layoutOptions, withLabel), mInputBox(nullptr), mIsDragging(false),
-		mLastDragPos(0), mIsDragCursorSet(false)
+		const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
+		:TGUIField(dummy, labelContent, labelWidth, style, layoutOptions, withLabel), mInputBox(nullptr), mIsDragging(false),
+		mLastDragPos(0), mIsDragCursorSet(false), mHasInputFocus(false)
 	{
 	{
-		mInputBox = GUIInputBox::create(false, GUIOptions(GUIOption::flexibleWidth()), inputBoxStyle);
+		mInputBox = GUIInputBox::create(false, GUIOptions(GUIOption::flexibleWidth()), getSubStyleName(getInputStyleType()));
 		mInputBox->setFilter(&GUIIntField::intFilter);
 		mInputBox->setFilter(&GUIIntField::intFilter);
 
 
 		mInputBox->onValueChanged.connect(std::bind(&GUIIntField::valueChanged, this, _1));
 		mInputBox->onValueChanged.connect(std::bind(&GUIIntField::valueChanged, this, _1));
@@ -42,20 +42,6 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	Vector2I GUIIntField::_getOptimalSize() const
-	{
-		UINT32 width = (UINT32)mInputBox->_getOptimalSize().x;
-		UINT32 height = (UINT32)mInputBox->_getOptimalSize().y;
-
-		if (mLabel != nullptr)
-		{
-			width += mLabel->_getOptimalSize().x;
-			height = std::max(height, (UINT32)mLabel->_getOptimalSize().y);
-		}
-
-		return Vector2I(width, height);
-	}
-
 	bool GUIIntField::_hasCustomCursor(const Vector2I position, CursorType& type) const
 	bool GUIIntField::_hasCustomCursor(const Vector2I position, CursorType& type) const
 	{
 	{
 		RectI draggableArea;
 		RectI draggableArea;
@@ -153,6 +139,14 @@ namespace BansheeEngine
 		return false;
 		return false;
 	}
 	}
 
 
+	void GUIIntField::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mInputBox->setStyle(getSubStyleName(getInputStyleType()));
+	}
+
 	void GUIIntField::setValue(INT32 value)
 	void GUIIntField::setValue(INT32 value)
 	{
 	{
 		mValue = value;
 		mValue = value;
@@ -171,6 +165,12 @@ namespace BansheeEngine
 		return typeName;
 		return typeName;
 	}
 	}
 
 
+	const String& GUIIntField::getInputStyleType()
+	{
+		static String LABEL_STYLE_TYPE = "EditorFieldInput";
+		return LABEL_STYLE_TYPE;
+	}
+
 	void GUIIntField::valueChanged(const WString& newValue)
 	void GUIIntField::valueChanged(const WString& newValue)
 	{
 	{
 		INT32 newIntValue = parseInt(newValue);
 		INT32 newIntValue = parseInt(newValue);
@@ -184,11 +184,13 @@ namespace BansheeEngine
 	void GUIIntField::focusGained()
 	void GUIIntField::focusGained()
 	{
 	{
 		UndoRedo::instance().pushGroup("InputBox");
 		UndoRedo::instance().pushGroup("InputBox");
+		mHasInputFocus = true;
 	}
 	}
 
 
 	void GUIIntField::focusLost()
 	void GUIIntField::focusLost()
 	{
 	{
 		UndoRedo::instance().popGroup("InputBox");
 		UndoRedo::instance().popGroup("InputBox");
+		mHasInputFocus = false;
 	}
 	}
 
 
 	bool GUIIntField::intFilter(const WString& str)
 	bool GUIIntField::intFilter(const WString& str)

+ 45 - 7
BansheeEditor/Source/BsGUITextField.cpp

@@ -7,15 +7,23 @@
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 #include "BsGUIMouseEvent.h"
 #include "BsGUIMouseEvent.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
+#include "BsCmdInputFieldValueChange.h"
+
+using namespace std::placeholders;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	GUITextField::GUITextField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth, 
 	GUITextField::GUITextField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth, 
-		const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel)
-		:TGUIField(dummy, labelContent, labelWidth, labelStyle, layoutOptions, withLabel), mInputBox(nullptr)
+		const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
+		:TGUIField(dummy, labelContent, labelWidth, style, layoutOptions, withLabel), 
+		mInputBox(nullptr), mValue(L""), mHasInputFocus(false)
 	{
 	{
-		mInputBox = GUIInputBox::create(false, inputBoxStyle);
+		mInputBox = GUIInputBox::create(false, getSubStyleName(getInputStyleType()));
 		mLayout->addElement(mInputBox);
 		mLayout->addElement(mInputBox);
+
+		mInputBox->onValueChanged.connect(std::bind(&GUITextField::valueChanged, this, _1));
+		mInputBox->onFocusGained.connect(std::bind(&GUITextField::focusGained, this));
+		mInputBox->onFocusLost.connect(std::bind(&GUITextField::focusLost, this));
 	}
 	}
 
 
 	GUITextField::~GUITextField()
 	GUITextField::~GUITextField()
@@ -23,14 +31,38 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	WString GUITextField::getValue() const
+	void GUITextField::setValue(const WString& value)
 	{
 	{
-		return mInputBox->getText();
+		mValue = value;
+		mInputBox->setText(value);
 	}
 	}
 
 
-	void GUITextField::setValue(const WString& value)
+	void GUITextField::styleUpdated()
 	{
 	{
-		mInputBox->setText(value);
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mInputBox->setStyle(getSubStyleName(getInputStyleType()));
+	}
+
+	void GUITextField::valueChanged(const WString& newValue)
+	{
+		CmdInputFieldValueChange<GUITextField, WString>::execute(this, newValue);
+
+		if (!onValueChanged.empty())
+			onValueChanged(newValue);
+	}
+
+	void GUITextField::focusGained()
+	{
+		UndoRedo::instance().pushGroup("InputBox");
+		mHasInputFocus = true;
+	}
+
+	void GUITextField::focusLost()
+	{
+		UndoRedo::instance().popGroup("InputBox");
+		mHasInputFocus = false;
 	}
 	}
 
 
 	const String& GUITextField::getGUITypeName()
 	const String& GUITextField::getGUITypeName()
@@ -38,4 +70,10 @@ namespace BansheeEngine
 		static String typeName = "GUITextField";
 		static String typeName = "GUITextField";
 		return typeName;
 		return typeName;
 	}
 	}
+
+	const String& GUITextField::getInputStyleType()
+	{
+		static String LABEL_STYLE_TYPE = "EditorFieldInput";
+		return LABEL_STYLE_TYPE;
+	}
 }
 }

+ 32 - 8
BansheeEditor/Source/BsGUIToggleField.cpp

@@ -7,33 +7,57 @@
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 #include "BsGUIMouseEvent.h"
 #include "BsGUIMouseEvent.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
+#include "BsCmdInputFieldValueChange.h"
+
+using namespace std::placeholders;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	GUIToggleField::GUIToggleField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
 	GUIToggleField::GUIToggleField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
-		UINT32 labelWidth, const String& labelStyle, const String& toggleStyle, const GUILayoutOptions& layoutOptions, bool withLabel)
-		:TGUIField(dummy, labelContent, labelWidth, labelStyle, layoutOptions, withLabel), mToggle(nullptr)
+		UINT32 labelWidth, const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
+		:TGUIField(dummy, labelContent, labelWidth, style, layoutOptions, withLabel), mToggle(nullptr), mValue(false)
 	{
 	{
-		mToggle = GUIToggle::create(HString(L""), toggleStyle);
-		mLayout->addElement(mToggle);
-	}
+		mToggle = GUIToggle::create(HString(L""), getSubStyleName(getToggleStyleType()));
+		mToggle->onToggled.connect(std::bind(&GUIToggleField::valueChanged, this, _1));
 
 
-	bool GUIToggleField::getValue() const
-	{
-		return mToggle->isToggled();
+		mLayout->addElement(mToggle);
 	}
 	}
 
 
 	void GUIToggleField::setValue(bool value)
 	void GUIToggleField::setValue(bool value)
 	{
 	{
+		mValue = value;
+
 		if(value) 
 		if(value) 
 			mToggle->toggleOn();
 			mToggle->toggleOn();
 		else
 		else
 			mToggle->toggleOff();
 			mToggle->toggleOff();
 	}
 	}
 
 
+	void GUIToggleField::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mToggle->setStyle(getSubStyleName(getToggleStyleType()));
+	}
+
+	void GUIToggleField::valueChanged(bool newValue)
+	{
+		CmdInputFieldValueChange<GUIToggleField, bool>::execute(this, newValue);
+
+		if (!onValueChanged.empty())
+			onValueChanged(newValue);
+	}
+
 	const String& GUIToggleField::getGUITypeName()
 	const String& GUIToggleField::getGUITypeName()
 	{
 	{
 		static String typeName = "GUIToggleField";
 		static String typeName = "GUIToggleField";
 		return typeName;
 		return typeName;
 	}
 	}
+
+	const String& GUIToggleField::getToggleStyleType()
+	{
+		static String STYLE_TYPE = "EditorFieldToggleInput";
+		return STYLE_TYPE;
+	}
 }
 }

+ 37 - 4
BansheeEditor/Source/BsGUIVector2Field.cpp

@@ -6,23 +6,31 @@
 #include "BsBuiltinResources.h"
 #include "BsBuiltinResources.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 #include "BsGUIMouseEvent.h"
 #include "BsGUIMouseEvent.h"
+#include "BsGUISpace.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 
 
+using namespace std::placeholders;
+
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	const UINT32 GUIVector2Field::ELEMENT_LABEL_WIDTH = 10;
 	const UINT32 GUIVector2Field::ELEMENT_LABEL_WIDTH = 10;
 
 
 	GUIVector2Field::GUIVector2Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
 	GUIVector2Field::GUIVector2Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
-		UINT32 labelWidth, const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel)
-		:TGUIField(dummy, labelContent, labelWidth, labelStyle, layoutOptions, withLabel), mFieldX(nullptr), mFieldY(nullptr)
+		UINT32 labelWidth, const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
+		:TGUIField(dummy, labelContent, labelWidth, style, layoutOptions, withLabel), 
+		mFieldX(nullptr), mFieldY(nullptr)
 	{
 	{
-		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, labelStyle, inputBoxStyle);
-		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, labelStyle, inputBoxStyle);
+		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+
+		mFieldX->onValueChanged.connect(std::bind(&GUIVector2Field::valueChanged, this, _1));
+		mFieldY->onValueChanged.connect(std::bind(&GUIVector2Field::valueChanged, this, _1));
 
 
 		mLayout->removeElement(mLabel);
 		mLayout->removeElement(mLabel);
 
 
 		GUILayout* layout = &mLayout->addLayoutY();
 		GUILayout* layout = &mLayout->addLayoutY();
 		layout->addElement(mLabel);
 		layout->addElement(mLabel);
+		mLabel->setLayoutOptions(GUIOptions());
 
 
 		GUILayout* elementLayout = &layout->addLayoutX();
 		GUILayout* elementLayout = &layout->addLayoutX();
 
 
@@ -45,9 +53,34 @@ namespace BansheeEngine
 		mFieldY->setValue(value.y);
 		mFieldY->setValue(value.y);
 	}
 	}
 
 
+	bool GUIVector2Field::hasInputFocus() const
+	{
+		return mFieldX->hasInputFocus() || mFieldY->hasInputFocus();
+	}
+
+	void GUIVector2Field::valueChanged(float newValue)
+	{
+		onValueChanged(getValue());
+	}
+
+	void GUIVector2Field::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mFieldX->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldY->setStyle(getSubStyleName(getFloatFieldStyleType()));
+	}
+
 	const String& GUIVector2Field::getGUITypeName()
 	const String& GUIVector2Field::getGUITypeName()
 	{
 	{
 		static String typeName = "GUIVector2Field";
 		static String typeName = "GUIVector2Field";
 		return typeName;
 		return typeName;
 	}
 	}
+
+	const String& GUIVector2Field::getFloatFieldStyleType()
+	{
+		static String LABEL_STYLE_TYPE = "EditorFloatField";
+		return LABEL_STYLE_TYPE;
+	}
 }
 }

+ 40 - 5
BansheeEditor/Source/BsGUIVector3Field.cpp

@@ -6,24 +6,33 @@
 #include "BsBuiltinResources.h"
 #include "BsBuiltinResources.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 #include "BsGUIMouseEvent.h"
 #include "BsGUIMouseEvent.h"
+#include "BsGUISpace.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 
 
+using namespace std::placeholders;
+
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	const UINT32 GUIVector3Field::ELEMENT_LABEL_WIDTH = 10;
 	const UINT32 GUIVector3Field::ELEMENT_LABEL_WIDTH = 10;
 
 
 	GUIVector3Field::GUIVector3Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
 	GUIVector3Field::GUIVector3Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
-		UINT32 labelWidth, const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel)
-		:TGUIField(dummy, labelContent, labelWidth, labelStyle, layoutOptions, withLabel), mFieldX(nullptr), mFieldY(nullptr)
+		UINT32 labelWidth, const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
+		:TGUIField(dummy, labelContent, labelWidth, style, layoutOptions, withLabel), 
+		mFieldX(nullptr), mFieldY(nullptr), mFieldZ(nullptr)
 	{
 	{
-		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, labelStyle, inputBoxStyle);
-		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, labelStyle, inputBoxStyle);
-		mFieldZ = GUIFloatField::create(HString(L"Z"), ELEMENT_LABEL_WIDTH, labelStyle, inputBoxStyle);
+		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldZ = GUIFloatField::create(HString(L"Z"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+
+		mFieldX->onValueChanged.connect(std::bind(&GUIVector3Field::valueChanged, this, _1));
+		mFieldY->onValueChanged.connect(std::bind(&GUIVector3Field::valueChanged, this, _1));
+		mFieldZ->onValueChanged.connect(std::bind(&GUIVector3Field::valueChanged, this, _1));
 
 
 		mLayout->removeElement(mLabel);
 		mLayout->removeElement(mLabel);
 
 
 		GUILayout* layout = &mLayout->addLayoutY();
 		GUILayout* layout = &mLayout->addLayoutY();
 		layout->addElement(mLabel);
 		layout->addElement(mLabel);
+		mLabel->setLayoutOptions(GUIOptions());
 
 
 		GUILayout* elementLayout = &layout->addLayoutX();
 		GUILayout* elementLayout = &layout->addLayoutX();
 
 
@@ -49,9 +58,35 @@ namespace BansheeEngine
 		mFieldZ->setValue(value.z);
 		mFieldZ->setValue(value.z);
 	}
 	}
 
 
+	bool GUIVector3Field::hasInputFocus() const
+	{
+		return mFieldX->hasInputFocus() || mFieldY->hasInputFocus() || mFieldZ->hasInputFocus();
+	}
+
+	void GUIVector3Field::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mFieldX->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldY->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldZ->setStyle(getSubStyleName(getFloatFieldStyleType()));
+	}
+
+	void GUIVector3Field::valueChanged(float newValue)
+	{
+		onValueChanged(getValue());
+	}
+
 	const String& GUIVector3Field::getGUITypeName()
 	const String& GUIVector3Field::getGUITypeName()
 	{
 	{
 		static String typeName = "GUIVector3Field";
 		static String typeName = "GUIVector3Field";
 		return typeName;
 		return typeName;
 	}
 	}
+
+	const String& GUIVector3Field::getFloatFieldStyleType()
+	{
+		static String LABEL_STYLE_TYPE = "EditorFloatField";
+		return LABEL_STYLE_TYPE;
+	}
 }
 }

+ 42 - 6
BansheeEditor/Source/BsGUIVector4Field.cpp

@@ -6,25 +6,34 @@
 #include "BsBuiltinResources.h"
 #include "BsBuiltinResources.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 #include "BsGUIMouseEvent.h"
 #include "BsGUIMouseEvent.h"
+#include "BsGUISpace.h"
 #include "BsGUIWidget.h"
 #include "BsGUIWidget.h"
 
 
+using namespace std::placeholders;
+
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
 	const UINT32 GUIVector4Field::ELEMENT_LABEL_WIDTH = 10;
 	const UINT32 GUIVector4Field::ELEMENT_LABEL_WIDTH = 10;
 
 
 	GUIVector4Field::GUIVector4Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
 	GUIVector4Field::GUIVector4Field(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
-		UINT32 labelWidth, const String& labelStyle, const String& inputBoxStyle, const GUILayoutOptions& layoutOptions, bool withLabel)
-		:TGUIField(dummy, labelContent, labelWidth, labelStyle, layoutOptions, withLabel), mFieldX(nullptr), mFieldY(nullptr)
+		UINT32 labelWidth, const String& style, const GUILayoutOptions& layoutOptions, bool withLabel)
+		:TGUIField(dummy, labelContent, labelWidth, style, layoutOptions, withLabel), mFieldX(nullptr), mFieldY(nullptr)
 	{
 	{
-		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, labelStyle, inputBoxStyle);
-		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, labelStyle, inputBoxStyle);
-		mFieldZ = GUIFloatField::create(HString(L"Z"), ELEMENT_LABEL_WIDTH, labelStyle, inputBoxStyle);
-		mFieldW = GUIFloatField::create(HString(L"W"), ELEMENT_LABEL_WIDTH, labelStyle, inputBoxStyle);
+		mFieldX = GUIFloatField::create(HString(L"X"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldY = GUIFloatField::create(HString(L"Y"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldZ = GUIFloatField::create(HString(L"Z"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+		mFieldW = GUIFloatField::create(HString(L"W"), ELEMENT_LABEL_WIDTH, getSubStyleName(getFloatFieldStyleType()));
+
+		mFieldX->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
+		mFieldY->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
+		mFieldZ->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
+		mFieldW->onValueChanged.connect(std::bind(&GUIVector4Field::valueChanged, this, _1));
 
 
 		mLayout->removeElement(mLabel);
 		mLayout->removeElement(mLabel);
 
 
 		GUILayout* layout = &mLayout->addLayoutY();
 		GUILayout* layout = &mLayout->addLayoutY();
 		layout->addElement(mLabel);
 		layout->addElement(mLabel);
+		mLabel->setLayoutOptions(GUIOptions());
 
 
 		GUILayout* elementLayout = &layout->addLayoutX();
 		GUILayout* elementLayout = &layout->addLayoutX();
 
 
@@ -53,9 +62,36 @@ namespace BansheeEngine
 		mFieldW->setValue(value.w);
 		mFieldW->setValue(value.w);
 	}
 	}
 
 
+	bool GUIVector4Field::hasInputFocus() const
+	{
+		return mFieldX->hasInputFocus() || mFieldY->hasInputFocus() || mFieldZ->hasInputFocus() || mFieldW->hasInputFocus();
+	}
+
+	void GUIVector4Field::styleUpdated()
+	{
+		if (mLabel != nullptr)
+			mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+
+		mFieldX->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldY->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldZ->setStyle(getSubStyleName(getFloatFieldStyleType()));
+		mFieldW->setStyle(getSubStyleName(getFloatFieldStyleType()));
+	}
+
+	void GUIVector4Field::valueChanged(float newValue)
+	{
+		onValueChanged(getValue());
+	}
+
 	const String& GUIVector4Field::getGUITypeName()
 	const String& GUIVector4Field::getGUITypeName()
 	{
 	{
 		static String typeName = "GUIVector4Field";
 		static String typeName = "GUIVector4Field";
 		return typeName;
 		return typeName;
 	}
 	}
+
+	const String& GUIVector4Field::getFloatFieldStyleType()
+	{
+		static String LABEL_STYLE_TYPE = "EditorFloatField";
+		return LABEL_STYLE_TYPE;
+	}
 }
 }

+ 16 - 0
BansheeEngine/Include/BsGUIElement.h

@@ -109,6 +109,11 @@ namespace BansheeEngine
 		 */
 		 */
 		void setLayoutOptions(const GUIOptions& layoutOptions);
 		void setLayoutOptions(const GUIOptions& layoutOptions);
 
 
+		/**
+		 * @brief	Sets new style to be used by the element.
+		 */
+		void setStyle(const String& styleName);
+
 		/**
 		/**
 		 * @brief	Gets internal element style representing the exact type of GUI element
 		 * @brief	Gets internal element style representing the exact type of GUI element
 		 *			in this object.
 		 *			in this object.
@@ -390,6 +395,17 @@ namespace BansheeEngine
 			return overrideStyle;
 			return overrideStyle;
 		}
 		}
 
 
+		/**
+		 * @brief	Attempts to find a sub-style for the specified type in the currently
+		 *			set GUI element style. If one cannot be found empty string is returned.
+		 */
+		const String& getSubStyleName(const String& subStyleTypeName);
+
+		/**
+		 * @brief	Method that gets triggered whenever element style changes.
+		 */
+		virtual void styleUpdated() { }
+
 		/**
 		/**
 		 * @brief	Returns clipped bounds excluding the margins. Relative to parent widget.
 		 * @brief	Returns clipped bounds excluding the margins. Relative to parent widget.
 		 */
 		 */

+ 2 - 0
BansheeEngine/Include/BsGUIElementStyle.h

@@ -68,5 +68,7 @@ namespace BansheeEngine
 		UINT32 minHeight, maxHeight; /**< Minimum and maximum height allowed for this object. Used by the layout only when exact height is not specified. */
 		UINT32 minHeight, maxHeight; /**< Minimum and maximum height allowed for this object. Used by the layout only when exact height is not specified. */
 		bool fixedWidth; /**< If width is fixed, layout will not attempt to resize the element depending on available size. */
 		bool fixedWidth; /**< If width is fixed, layout will not attempt to resize the element depending on available size. */
 		bool fixedHeight; /**< If height is fixed, layout will not attempt to resize the element depending on available size. */
 		bool fixedHeight; /**< If height is fixed, layout will not attempt to resize the element depending on available size. */
+
+		Map<String, String> subStyles; /**< Sub-styles used by certain more complex elements. */
 	};
 	};
 }
 }

+ 16 - 0
BansheeEngine/Source/BsGUIElement.cpp

@@ -48,6 +48,11 @@ namespace BansheeEngine
 		mLayoutOptions = layoutOptions; 
 		mLayoutOptions = layoutOptions; 
 	}
 	}
 
 
+	void GUIElement::setStyle(const String& styleName)
+	{
+		mStyleName = styleName;
+		_refreshStyle();
+	}
 
 
 	bool GUIElement::mouseEvent(const GUIMouseEvent& ev)
 	bool GUIElement::mouseEvent(const GUIMouseEvent& ev)
 	{
 	{
@@ -272,11 +277,22 @@ namespace BansheeEngine
 		{
 		{
 			mStyle = newStyle;
 			mStyle = newStyle;
 			mLayoutOptions.updateWithStyle(mStyle);
 			mLayoutOptions.updateWithStyle(mStyle);
+			styleUpdated();
 
 
 			markContentAsDirty();
 			markContentAsDirty();
 		}
 		}
 	}
 	}
 
 
+	const String& GUIElement::getSubStyleName(const String& subStyleTypeName)
+	{
+		auto iterFind = mStyle->subStyles.find(subStyleTypeName);
+
+		if (iterFind != mStyle->subStyles.end())
+			return iterFind->second;
+		else
+			return StringUtil::BLANK;
+	}
+
 	void GUIElement::destroy(GUIElement* element)
 	void GUIElement::destroy(GUIElement* element)
 	{
 	{
 		if(element->mIsDestroyed)
 		if(element->mIsDestroyed)

+ 20 - 16
Inspector.txt

@@ -1,20 +1,18 @@
-
-IMPLEMENTATION STEPS:
-2. Each GUIElement needs to be aware of its parent GUIArea
-
-3. In ScriptGUILayoutUtility I have no way of casting a MonoObject to GUIElementBase. This will likely require a refactor.
-
-4. When constructing ScriptObject I store it as actual type. But in ScriptGUIElement internal methods I expect ScriptGUIElementBase type.
-   This will also likely require a refactor. Related to above.
+Update all elements to use new sub-styles
+ - Including GUIFoldout and potentially others
+ - Override styleUpdated()
+Update C# GUIElementStyle
 
 
 TODO:
 TODO:
  - Hook up int field set/get callbacks
  - Hook up int field set/get callbacks
     - Ensure int field isn't updated from app when in focus
     - Ensure int field isn't updated from app when in focus
  - Hook up foldout expand/collapse callbacks
  - Hook up foldout expand/collapse callbacks
  - Think about how to handle arrays, adding and deleting elements from them.
  - Think about how to handle arrays, adding and deleting elements from them.
- - Add labels to foldouts
+   - Will likely need GUILayout::GetElementIndex()
+ - I should add project and scene tree views to the main editor window to make inspector testing easier
+ - Entire foldout should be clickable, not just the toggle button
  - Extend text field so it can be multi-line
  - Extend text field so it can be multi-line
- - Port to C# (+ see below for additional fixes to C++ versions):
+ - Port to C#:
    - IntField
    - IntField
    - FloatField
    - FloatField
    - ColorField
    - ColorField
@@ -30,8 +28,18 @@ TODO:
  - Extend GameObject field so it can only accept a certain type
  - Extend GameObject field so it can only accept a certain type
  - Ensure Undo/redo works as intended
  - Ensure Undo/redo works as intended
    - This task needs decomposing. Likely need to port UndoRedo to C# first.
    - This task needs decomposing. Likely need to port UndoRedo to C# first.
+ - GUIColor needs to be hooked up to a window that actually changes its value.
+ - Need to add GUIResourceField along with GUIGameObjectField and figure out a way to make them
+   accept arbitrary types.
+     - Probably move them to SBansheeEditor
+ - I need to register UndoRedo command after user finishes modifying a field. This should be referencing an object using an URI?
+
+TO PONDER:
+ - How to limit resource/object fields to a custom type (user created type possibly)
+ - Need to figure out a better way of setting styles for container GUI elements (e.g. GUIFoldout requires three different styles)
 
 
 KEEP IN MIND:
 KEEP IN MIND:
+ - Clicking on an object/resource in inspector should ping it in their window
  - Inspector needs to be organized in such a way that scroll areas work. That should be possible with GUIPanelContainer.
  - Inspector needs to be organized in such a way that scroll areas work. That should be possible with GUIPanelContainer.
  - When inspector object changes I need to rebuild that inspector element
  - When inspector object changes I need to rebuild that inspector element
    - This can happen if user drags a new object
    - This can happen if user drags a new object
@@ -40,11 +48,8 @@ KEEP IN MIND:
  - Modify C++ Editor fields so that calling setValue doesn't update the visual value until focus is lost
  - Modify C++ Editor fields so that calling setValue doesn't update the visual value until focus is lost
   - When user is currently writing in an input box I don't want refresh to overwrite that value.
   - When user is currently writing in an input box I don't want refresh to overwrite that value.
 
 
-BUGS
- - Composite GUI elements like Vector3Field need to set a style with min/max or fixed bounds to their GUIElementContainer
-   otherwise they get clipped when their parent layout is too small
- - Modify all editor fields so they implement virtual Vector2I _getOptimalSize() const; and remove it from GUIFieldBase.
-   See IntField for example
+
+
 
 
 
 
 
 
@@ -90,7 +95,6 @@ UndoRedo should work on URI type basis where it remembers object ID, and path ac
  ----------------------
  ----------------------
 
 
  Non-inspector:
  Non-inspector:
-
   - Deleting first entry in input field moves the cursor incorrectly
   - Deleting first entry in input field moves the cursor incorrectly
   - Test if parsing int/float value from int/float field actually works
   - Test if parsing int/float value from int/float field actually works
   - ProfilerOverlay elements are constantly dirty? even though I'm not calling update
   - ProfilerOverlay elements are constantly dirty? even though I'm not calling update

+ 5 - 6
MBansheeEditor/GUI/GUIIntField.cs

@@ -16,15 +16,14 @@ namespace BansheeEditor
             set { Internal_SetValue(mCachedPtr, value); }
             set { Internal_SetValue(mCachedPtr, value); }
         }
         }
 
 
-        public GUIIntField(GUIContent title, int titleWidth = 100, string titleStyle = "",
-                           string inputStyle = "", params GUIOption[] options)
+        public GUIIntField(GUIContent title, int titleWidth = 100, string style = "", params GUIOption[] options)
         {
         {
-            Internal_CreateInstance(this, title, titleWidth, titleStyle, inputStyle, options, true);
+            Internal_CreateInstance(this, title, titleWidth, style, options, true);
         }
         }
 
 
-        public GUIIntField(string inputStyle = "", params GUIOption[] options)
+        public GUIIntField(string style = "", params GUIOption[] options)
         {
         {
-            Internal_CreateInstance(this, null, 0, "", inputStyle, options, false);
+            Internal_CreateInstance(this, null, 0, style, options, false);
         }
         }
 
 
         private void DoOnChanged(int newValue)
         private void DoOnChanged(int newValue)
@@ -35,7 +34,7 @@ namespace BansheeEditor
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_CreateInstance(GUIIntField instance, GUIContent title, int titleWidth, 
         private static extern void Internal_CreateInstance(GUIIntField instance, GUIContent title, int titleWidth, 
-            string titleStyle, string inputStyle, GUIOption[] options, bool withTitle);
+            string style, GUIOption[] options, bool withTitle);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern int Internal_GetValue(IntPtr nativeInstance);
         private static extern int Internal_GetValue(IntPtr nativeInstance);

+ 2 - 2
SBansheeEditor/Include/BsScriptGUIIntField.h

@@ -11,8 +11,8 @@ namespace BansheeEngine
 		SCRIPT_OBJ(BansheeEditorAssemblyName, "BansheeEditor", "GUIIntField")
 		SCRIPT_OBJ(BansheeEditorAssemblyName, "BansheeEditor", "GUIIntField")
 
 
 	private:
 	private:
-		static void internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth, MonoString* titleStyle, 
-			MonoString* inputStyle, MonoArray* guiOptions, bool withTitle);
+		static void internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth, 
+			MonoString* style, MonoArray* guiOptions, bool withTitle);
 
 
 		static INT32 internal_getValue(ScriptGUIIntField* nativeInstance);
 		static INT32 internal_getValue(ScriptGUIIntField* nativeInstance);
 		static void internal_setValue(ScriptGUIIntField* nativeInstance, INT32 value);
 		static void internal_setValue(ScriptGUIIntField* nativeInstance, INT32 value);

+ 6 - 10
SBansheeEditor/Source/BsScriptGUIIntField.cpp

@@ -37,8 +37,8 @@ namespace BansheeEngine
 		onChangedThunk = (OnChangedThunkDef)metaData.scriptClass->getMethod("DoOnChanged", 1).getThunk();
 		onChangedThunk = (OnChangedThunkDef)metaData.scriptClass->getMethod("DoOnChanged", 1).getThunk();
 	}
 	}
 
 
-	void ScriptGUIIntField::internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth, MonoString* titleStyle, 
-		MonoString* inputStyle, MonoArray* guiOptions, bool withTitle)
+	void ScriptGUIIntField::internal_createInstance(MonoObject* instance, MonoObject* title, UINT32 titleWidth, 
+		MonoString* style, MonoArray* guiOptions, bool withTitle)
 	{
 	{
 		GUIOptions options;
 		GUIOptions options;
 
 
@@ -46,21 +46,17 @@ namespace BansheeEngine
 		for(UINT32 i = 0; i < arrayLen; i++)
 		for(UINT32 i = 0; i < arrayLen; i++)
 			options.addOption(mono_array_get(guiOptions, GUIOption, i));
 			options.addOption(mono_array_get(guiOptions, GUIOption, i));
 
 
+		String styleName = toString(MonoUtil::monoToWString(style));
+
 		GUIIntField* guiIntField = nullptr;
 		GUIIntField* guiIntField = nullptr;
 		if(withTitle)
 		if(withTitle)
 		{
 		{
-			String titleStyleName = toString(MonoUtil::monoToWString(titleStyle));
-			String inputStyleName = toString(MonoUtil::monoToWString(inputStyle));
-
 			GUIContent nativeContent(ScriptGUIContent::getText(title), ScriptGUIContent::getImage(title), ScriptGUIContent::getTooltip(title));
 			GUIContent nativeContent(ScriptGUIContent::getText(title), ScriptGUIContent::getImage(title), ScriptGUIContent::getTooltip(title));
-			guiIntField = GUIIntField::create(nativeContent, titleWidth, options,
-				titleStyleName, inputStyleName);
+			guiIntField = GUIIntField::create(nativeContent, titleWidth, options, styleName);
 		}
 		}
 		else
 		else
 		{
 		{
-			String inputStyleName = toString(MonoUtil::monoToWString(inputStyle));
-
-			guiIntField = GUIIntField::create(options, inputStyleName);
+			guiIntField = GUIIntField::create(options, styleName);
 		}
 		}
 
 
 		guiIntField->onValueChanged.connect(std::bind(&ScriptGUIIntField::onChanged, instance, _1));
 		guiIntField->onValueChanged.connect(std::bind(&ScriptGUIIntField::onChanged, instance, _1));