Browse Source

Feature: Added GUI fields for 2D and 3D vector distributions

BearishSun 7 years ago
parent
commit
e88e2014f3
24 changed files with 1412 additions and 133 deletions
  1. 48 0
      Data/Raw/GUISkin.json
  2. 199 83
      Source/EditorCore/GUI/BsGUIFloatDistributionField.cpp
  3. 94 22
      Source/EditorCore/GUI/BsGUIFloatDistributionField.h
  4. 1 1
      Source/Scripting/MBansheeEditor/GUI/GUIFloatDistributionField.cs
  5. 76 0
      Source/Scripting/MBansheeEditor/GUI/GUIVector2DistributionField.cs
  6. 76 0
      Source/Scripting/MBansheeEditor/GUI/GUIVector3DistributionField.cs
  7. 5 4
      Source/Scripting/MBansheeEditor/Generated/GUIFloatDistributionField.generated.cs
  8. 144 0
      Source/Scripting/MBansheeEditor/Generated/GUIVector2DistributionField.generated.cs
  9. 144 0
      Source/Scripting/MBansheeEditor/Generated/GUIVector3DistributionField.generated.cs
  10. 4 0
      Source/Scripting/MBansheeEditor/MBansheeEditor.csproj
  11. 2 2
      Source/Scripting/MBansheeEditor/Windows/Animation/EditorAnimInfo.cs
  12. 6 0
      Source/Scripting/MBansheeEditor/Windows/Inspector/InspectableField.cs
  13. 82 0
      Source/Scripting/MBansheeEditor/Windows/Inspector/InspectableVector2Distribution.cs
  14. 82 0
      Source/Scripting/MBansheeEditor/Windows/Inspector/InspectableVector3Distribution.cs
  15. 22 6
      Source/Scripting/MBansheeEngine/Generated/AnimationUtility.generated.cs
  16. 7 1
      Source/Scripting/MBansheeEngine/Serialization/SerializableProperty.cs
  17. 4 4
      Source/Scripting/SBansheeEditor/Generated/BsScriptGUIFloatDistributionField.generated.cpp
  18. 2 2
      Source/Scripting/SBansheeEditor/Generated/BsScriptGUIFloatDistributionField.generated.h
  19. 137 0
      Source/Scripting/SBansheeEditor/Generated/BsScriptGUIVector2DistributionField.generated.cpp
  20. 41 0
      Source/Scripting/SBansheeEditor/Generated/BsScriptGUIVector2DistributionField.generated.h
  21. 137 0
      Source/Scripting/SBansheeEditor/Generated/BsScriptGUIVector3DistributionField.generated.cpp
  22. 41 0
      Source/Scripting/SBansheeEditor/Generated/BsScriptGUIVector3DistributionField.generated.h
  23. 54 6
      Source/Scripting/SBansheeEngine/Generated/BsScriptAnimationUtility.generated.cpp
  24. 4 2
      Source/Scripting/SBansheeEngine/Generated/BsScriptAnimationUtility.generated.h

+ 48 - 0
Data/Raw/GUISkin.json

@@ -3135,6 +3135,54 @@
             }
         ]
     },
+    {
+        "name": "GUIVector2DistributionField",
+        "minHeight": 40,
+		"maxHeight": 100,
+        "minWidth": 30,
+        "subStyles": [
+            {
+                "name": "FloatField",
+                "style": "GUIFloatField"
+            },
+            {
+                "name": "CurvesField",
+                "style": "GUICurves"
+            },
+            {
+                "name": "DropDownButton",
+                "style": "DropDownArrowButton"
+            },
+            {
+                "name": "EditorFieldLabel",
+                "style": "EditorFieldLabel"
+            }
+        ]
+    },
+    {
+        "name": "GUIVector3DistributionField",
+        "minHeight": 60,
+		"maxHeight": 150,
+        "minWidth": 30,
+        "subStyles": [
+            {
+                "name": "FloatField",
+                "style": "GUIFloatField"
+            },
+            {
+                "name": "CurvesField",
+                "style": "GUICurves"
+            },
+            {
+                "name": "DropDownButton",
+                "style": "DropDownArrowButton"
+            },
+            {
+                "name": "EditorFieldLabel",
+                "style": "EditorFieldLabel"
+            }
+        ]
+    },
     {
         "fixedHeight": true,
         "height": 21,

+ 199 - 83
Source/EditorCore/GUI/BsGUIFloatDistributionField.cpp

@@ -2,9 +2,12 @@
 //**************** Copyright (c) 2018 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "GUI/BsGUIFloatDistributionField.h"
 #include "GUI/BsGUILayout.h"
+#include "GUI/BsGUILayoutY.h"
 #include "GUI/BsGUILabel.h"
 #include "GUI/BsGUIColor.h"
 #include "GUI/BsGUIFloatField.h"
+#include "GUI/BsGUIVector2Field.h"
+#include "GUI/BsGUIVector3Field.h"
 #include "GUI/BsGUICurves.h"
 #include "GUI/BsGUIButton.h"
 #include "GUI/BsGUIContextMenu.h"
@@ -14,7 +17,17 @@ using namespace std::placeholders;
 
 namespace bs
 {
-	GUIFloatDistributionField::GUIFloatDistributionField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
+	namespace impl
+	{
+		template<class T>
+		bool isVertical() { return true; }
+
+		template<>
+		bool isVertical<float>() { return false; }
+	}
+
+	template<class T, class SELF>
+	TGUIDistributionField<T, SELF>::TGUIDistributionField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, 
 		UINT32 labelWidth, const String& style, const GUIDimensions& dimensions, bool withLabel)
 		: TGUIField(dummy, labelContent, labelWidth, style, dimensions, withLabel)
 	{
@@ -22,32 +35,42 @@ namespace bs
 
 		mContextMenu->addMenuItem("Constant", [this]()
 		{
-			mValue = FloatDistribution(mMinConstant);
+			mValue = TDistribution<T>(mMinConstant);
 			rebuild();
 		}, 50);
 
 		mContextMenu->addMenuItem("Range", [this]()
 		{
-			mValue = FloatDistribution(mMinConstant, mMaxConstant);
+			mValue = TDistribution<T>(mMinConstant, mMaxConstant);
 			rebuild();
 		}, 40);
 
 		mContextMenu->addMenuItem("Curve", [this]()
 		{
-			mValue = FloatDistribution(mCurves[0]);
+			TAnimationCurve<T> combinedCurve;
+			AnimationUtility::combineCurve<T>(mMinCurve, combinedCurve);
+
+			mValue = TDistribution<T>(combinedCurve);
 			rebuild();
 		}, 30);
 
 		mContextMenu->addMenuItem("Curve range", [this]()
 		{
-			mValue = FloatDistribution(mCurves[0], mCurves[1]);
+			TAnimationCurve<T> combinedCurveMin;
+			AnimationUtility::combineCurve<T>(mMinCurve, combinedCurveMin);
+
+			TAnimationCurve<T> combinedCurveMax;
+			AnimationUtility::combineCurve<T>(mMaxCurve, combinedCurveMax);
+
+			mValue = TDistribution<T>(combinedCurveMin, combinedCurveMax);
 			rebuild();
 		}, 20);
 
 		rebuild();
 	}
 
-	void GUIFloatDistributionField::setValue(const FloatDistribution& value)
+	template<class T, class SELF>
+	void TGUIDistributionField<T, SELF>::setValue(const TDistribution<T>& value)
 	{
 		mValue = value;
 
@@ -57,41 +80,63 @@ namespace bs
 		case PDT_Constant:
 			mMinConstant = mValue.getMinConstant();
 			mMaxConstant = mMinConstant;
-			mCurves[0] = TAnimationCurve<float>({
-				{ mMinConstant, 0.0f, 0.0f, 0.0f}, 
-				{ mMinConstant, 0.0f, 0.0f, 1.0f}});
-			mCurves[1] = TAnimationCurve<float>({
-				{ mMinConstant, 0.0f, 0.0f, 0.0f}, 
-				{ mMinConstant, 0.0f, 0.0f, 1.0f}});
+
+			for(UINT32 i = 0; i < NumComponents; i++)
+			{
+				mMinCurve[i] = TAnimationCurve<float>({
+					{ TCurveProperties<T>::getComponent(mMinConstant, i), 0.0f, 0.0f, 0.0f},
+					{ TCurveProperties<T>::getComponent(mMinConstant, i), 0.0f, 0.0f, 1.0f} });
+
+				mMaxCurve[1] = TAnimationCurve<float>({
+					{ TCurveProperties<T>::getComponent(mMinConstant, i), 0.0f, 0.0f, 0.0f},
+					{ TCurveProperties<T>::getComponent(mMinConstant, i), 0.0f, 0.0f, 1.0f} });
+			}
+
 			break;
 		case PDT_RandomRange: 
 			mMinConstant = mValue.getMinConstant();
 			mMaxConstant = mValue.getMaxConstant();
-			mCurves[0] = TAnimationCurve<float>({
-				{ mMinConstant, 0.0f, 0.0f, 0.0f}, 
-				{ mMinConstant, 0.0f, 0.0f, 1.0f}});
-			mCurves[1] = TAnimationCurve<float>({
-				{ mMaxConstant, 0.0f, 0.0f, 0.0f}, 
-				{ mMaxConstant, 0.0f, 0.0f, 1.0f}});
+
+			for(UINT32 i = 0; i < NumComponents; i++)
+			{
+				mMinCurve[i] = TAnimationCurve<float>({
+					{ TCurveProperties<T>::getComponent(mMinConstant, i), 0.0f, 0.0f, 0.0f},
+					{ TCurveProperties<T>::getComponent(mMinConstant, i), 0.0f, 0.0f, 1.0f} });
+
+				mMaxCurve[1] = TAnimationCurve<float>({
+					{ TCurveProperties<T>::getComponent(mMaxConstant, i), 0.0f, 0.0f, 0.0f},
+					{ TCurveProperties<T>::getComponent(mMaxConstant, i), 0.0f, 0.0f, 1.0f} });
+			}
 			break;
-		case PDT_Curve: 
-			mCurves[0] = mValue.getMinCurve();
-			mCurves[1] = mValue.getMinCurve();
-			mMinConstant = mCurves[0].evaluate(0.0f);
-			mMaxConstant = mCurves[1].evaluate(0.0f);
+		case PDT_Curve:
+			AnimationUtility::splitCurve(mValue.getMinCurve(), mMinCurve);
+			AnimationUtility::splitCurve(mValue.getMinCurve(), mMaxCurve);
+
+			for(UINT32 i = 0; i < NumComponents; i++)
+			{
+				TCurveProperties<T>::setComponent(mMinConstant, i, mMinCurve[i].evaluate(0.0f));
+				TCurveProperties<T>::setComponent(mMaxConstant, i, mMaxCurve[i].evaluate(0.0f));
+			}
+
 			break;
 		case PDT_RandomCurveRange: 
-			mCurves[0] = mValue.getMinCurve();
-			mCurves[1] = mValue.getMaxCurve();
-			mMinConstant = mCurves[0].evaluate(0.0f);
-			mMaxConstant = mCurves[1].evaluate(0.0f);
+			AnimationUtility::splitCurve(mValue.getMinCurve(), mMinCurve);
+			AnimationUtility::splitCurve(mValue.getMaxCurve(), mMaxCurve);
+
+			for(UINT32 i = 0; i < NumComponents; i++)
+			{
+				TCurveProperties<T>::setComponent(mMinConstant, i, mMinCurve[i].evaluate(0.0f));
+				TCurveProperties<T>::setComponent(mMaxConstant, i, mMaxCurve[i].evaluate(0.0f));
+			}
+
 			break;
 		}
 
 		rebuild();
 	}
 
-	bool GUIFloatDistributionField::hasInputFocus() const
+	template<class T, class SELF>
+	bool TGUIDistributionField<T, SELF>::hasInputFocus() const
 	{
 		if(mMinInput && mMinInput->hasInputFocus())
 			return true;
@@ -102,7 +147,8 @@ namespace bs
 		return false;
 	}
 
-	void GUIFloatDistributionField::setTint(const Color& color)
+	template<class T, class SELF>
+	void TGUIDistributionField<T, SELF>::setTint(const Color& color)
 	{
 		mDropDownButton->setTint(color);
 
@@ -115,11 +161,15 @@ namespace bs
 		if(mMaxInput)
 			mMaxInput->setTint(color);
 
-		if(mCurveDisplay)
-			mCurveDisplay->setTint(color);
+		for(int i = 0; i < NumComponents; i++)
+		{
+			if(mCurveDisplay[i])
+				mCurveDisplay[i]->setTint(color);
+		}
 	}
 
-	Vector2I GUIFloatDistributionField::_getOptimalSize() const
+	template<class T, class SELF>
+	Vector2I TGUIDistributionField<T, SELF>::_getOptimalSize() const
 	{
 		Vector2I optimalsize = mDropDownButton->_getOptimalSize();
 
@@ -129,28 +179,58 @@ namespace bs
 			optimalsize.y = std::max(optimalsize.y, mLabel->_getOptimalSize().y);
 		}
 
-		if(mMinInput)
+		if(impl::isVertical<T>())
 		{
-			optimalsize.x += mMinInput->_getOptimalSize().x;
-			optimalsize.y = std::max(optimalsize.y, mMinInput->_getOptimalSize().y);
-		}
+			if (mMinInput)
+			{
+				optimalsize.x = std::max(optimalsize.x, mMinInput->_getOptimalSize().x);
+				optimalsize.y += mMinInput->_getOptimalSize().y;
+			}
 
-		if(mMaxInput)
-		{
-			optimalsize.x += mMaxInput->_getOptimalSize().x;
-			optimalsize.y = std::max(optimalsize.y, mMaxInput->_getOptimalSize().y);
-		}
+			if (mMaxInput)
+			{
+				optimalsize.x = std::max(optimalsize.x, mMaxInput->_getOptimalSize().x);
+				optimalsize.y += mMaxInput->_getOptimalSize().y;
+			}
 
-		if(mCurveDisplay)
+			for(UINT32 i = 0; i < NumComponents; i++)
+			{
+				if (mCurveDisplay[i])
+				{
+					optimalsize.x = std::max(optimalsize.x, 50);
+					optimalsize.y += mCurveDisplay[i]->_getOptimalSize().y;
+				}
+			}
+		}
+		else
 		{
-			optimalsize.x += mCurveDisplay->_getOptimalSize().x;
-			optimalsize.y = std::max(optimalsize.y, 50);
+			if (mMinInput)
+			{
+				optimalsize.x += mMinInput->_getOptimalSize().x;
+				optimalsize.y = std::max(optimalsize.y, mMinInput->_getOptimalSize().y);
+			}
+
+			if (mMaxInput)
+			{
+				optimalsize.x += mMaxInput->_getOptimalSize().x;
+				optimalsize.y = std::max(optimalsize.y, mMaxInput->_getOptimalSize().y);
+			}
+
+			for(UINT32 i = 0; i < NumComponents; i++)
+			{
+				if (mCurveDisplay[i])
+				{
+					optimalsize.x += mCurveDisplay[i]->_getOptimalSize().x;
+					optimalsize.y = std::max(optimalsize.y, 50);
+				}
+			}
 		}
 
 		return optimalsize;
 	}
 
-	void GUIFloatDistributionField::styleUpdated()
+	template<class T, class SELF>
+	void TGUIDistributionField<T, SELF>::styleUpdated()
 	{
 		mDropDownButton->setStyle(getSubStyleName(DROP_DOWN_FIELD_STYLE_TYPE));
 
@@ -163,11 +243,15 @@ namespace bs
 		if (mMaxInput)
 			mMaxInput->setStyle(getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
 
-		if (mCurveDisplay)
-			mCurveDisplay->setStyle(getSubStyleName(CURVES_FIELD_STYLE_TYPE));
+		for(int i = 0; i < NumComponents; i++)
+		{
+			if (mCurveDisplay[i])
+				mCurveDisplay[i]->setStyle(getSubStyleName(CURVES_FIELD_STYLE_TYPE));
+		}
 	}
 
-	void GUIFloatDistributionField::rebuild()
+	template<class T, class SELF>
+	void TGUIDistributionField<T, SELF>::rebuild()
 	{
 		if(mLabel)
 			mLayout->removeElement(mLabel);
@@ -175,88 +259,104 @@ namespace bs
 		mLayout->clear();
 		mLayout->addElement(mLabel);
 
+		GUILayout* valueLayout;
+		
+		if(impl::isVertical<T>())
+			valueLayout = mLayout->addNewElement<GUILayoutY>();
+		else
+			valueLayout = mLayout;
+
 		switch (mValue.getType())
 		{
 		default:
 		case PDT_Constant:
-			mMinInput = GUIFloatField::create(HString("Constant"), 50, GUIOptions(), getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
+			mMinInput = GUIConstantType::create(HString("Constant"), 50, GUIOptions(), getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
 			mMaxInput = nullptr;
-			mCurveDisplay = nullptr;
+
+			for(int i = 0; i < NumComponents; i++)
+				mCurveDisplay[i] = nullptr;
 
 			mMinInput->setValue(mMinConstant);
-			mMinInput->onValueChanged.connect([this](float value)
+			mMinInput->onValueChanged.connect([this](T value)
 			{
 				mMinConstant = value;
-				mValue = FloatDistribution(value);
+				mValue = TDistribution<T>(value);
 
 				onConstantModified();
 			});
 			mMinInput->onConfirm.connect([this]() { onConstantConfirmed(); });
 
-			mLayout->addElement(mMinInput);
+			valueLayout->addElement(mMinInput);
 			break;
 		case PDT_RandomRange: 
-			mMinInput = GUIFloatField::create(HString("Min."), 40, GUIOptions(), getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
-			mMaxInput = GUIFloatField::create(HString("Max."), 40, GUIOptions(), getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
-			mCurveDisplay = nullptr;
+			mMinInput = GUIConstantType::create(HString("Min."), 40, GUIOptions(), getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
+			mMaxInput = GUIConstantType::create(HString("Max."), 40, GUIOptions(), getSubStyleName(FLOAT_FIELD_STYLE_TYPE));
+
+			for(int i = 0; i < NumComponents; i++)
+				mCurveDisplay[i] = nullptr;
 
 			mMinInput->setValue(mMinConstant);
-			mMinInput->onValueChanged.connect([this](float value)
+			mMinInput->onValueChanged.connect([this](T value)
 			{
 				mMinConstant = value;
-				mValue = FloatDistribution(value, mMaxConstant);
+				mValue = TDistribution<T>(value, mMaxConstant);
 
 				onConstantModified();
 			});
 			mMinInput->onConfirm.connect([this]() { onConstantConfirmed(); });
 
 			mMaxInput->setValue(mMaxConstant);
-			mMaxInput->onValueChanged.connect([this](float value)
+			mMaxInput->onValueChanged.connect([this](T value)
 			{
 				mMaxConstant = value;
-				mValue = FloatDistribution(mMinConstant, value);
+				mValue = TDistribution<T>(mMinConstant, value);
 
 				onConstantModified();
 			});
 			mMaxInput->onConfirm.connect([this]() { onConstantConfirmed(); });
 
-			mLayout->addElement(mMinInput);
-			mLayout->addElement(mMaxInput);
+			valueLayout->addElement(mMinInput);
+			valueLayout->addElement(mMaxInput);
 			break;
 		case PDT_Curve: 
 			mMinInput = nullptr;
 			mMaxInput = nullptr;
-			mCurveDisplay = GUICurves::create(CurveDrawOption::DrawMarkers, 
-				getSubStyleName(CURVES_FIELD_STYLE_TYPE));
 
-			mCurveDisplay->setCurves(
-				{
-					CurveDrawInfo(mValue.getMinCurve(), Color::BansheeOrange)
-				});
+			for(int i = 0; i < NumComponents; i++)
+			{
+				mCurveDisplay[i] = GUICurves::create(CurveDrawOption::DrawMarkers, getSubStyleName(CURVES_FIELD_STYLE_TYPE));
+				mCurveDisplay[i]->setCurves({ CurveDrawInfo(mMinCurve[i], Color::BansheeOrange) });
 
-			mCurveDisplay->setPadding(3);
-			mCurveDisplay->centerAndZoom();
-			mCurveDisplay->onClicked.connect([this](){ onClicked(); });
+				mCurveDisplay[i]->setPadding(3);
+				mCurveDisplay[i]->centerAndZoom();
+				mCurveDisplay[i]->onClicked.connect([this,i]() { onClicked(i); });
+
+				valueLayout->addElement(mCurveDisplay[i]);
+			}
 
-			mLayout->addElement(mCurveDisplay);
 			break;
 		case PDT_RandomCurveRange: 
 			mMinInput = nullptr;
 			mMaxInput = nullptr;
-			mCurveDisplay = GUICurves::create(CurveDrawOption::DrawMarkers | CurveDrawOption::DrawRange, 
-				getSubStyleName(CURVES_FIELD_STYLE_TYPE));
 
-			mCurveDisplay->setCurves(
-				{
-					CurveDrawInfo(mValue.getMinCurve(), Color::BansheeOrange),
-					CurveDrawInfo(mValue.getMaxCurve(), Color::Red)
-				});
+			for(int i = 0; i < NumComponents; i++)
+			{
+				mCurveDisplay[i] = GUICurves::create(CurveDrawOption::DrawMarkers | CurveDrawOption::DrawRange,
+					getSubStyleName(CURVES_FIELD_STYLE_TYPE));
+
+				mCurveDisplay[i]->setCurves(
+					{
+						CurveDrawInfo(mMinCurve[i], Color::BansheeOrange),
+						CurveDrawInfo(mMaxCurve[i], Color::Red)
+					});
 
-			mCurveDisplay->setPadding(3);
-			mCurveDisplay->centerAndZoom();
-			mCurveDisplay->onClicked.connect([this](){ onClicked(); });
+				mCurveDisplay[i]->setPadding(3);
+				mCurveDisplay[i]->centerAndZoom();
+				mCurveDisplay[i]->onClicked.connect([this,i]() { onClicked(i); });
+
+				valueLayout->addElement(mCurveDisplay[i]);
+			}
 
-			mLayout->addElement(mCurveDisplay);
 			break;
 		}
 
@@ -273,9 +373,25 @@ namespace bs
 		mLayout->addElement(mDropDownButton);
 	}
 
+	template class BS_ED_EXPORT TGUIDistributionField<float, GUIFloatDistributionField>;
+	template class BS_ED_EXPORT TGUIDistributionField<Vector2, GUIVector2DistributionField>;
+	template class BS_ED_EXPORT TGUIDistributionField<Vector3, GUIVector3DistributionField>;
+
 	const String& GUIFloatDistributionField::getGUITypeName()
 	{
 		static String typeName = "GUIFloatDistributionField";
 		return typeName;
 	}
+
+	const String& GUIVector2DistributionField::getGUITypeName()
+	{
+		static String typeName = "GUIVector2DistributionField";
+		return typeName;
+	}
+
+	const String& GUIVector3DistributionField::getGUITypeName()
+	{
+		static String typeName = "GUIVector3DistributionField";
+		return typeName;
+	}
 }

+ 94 - 22
Source/EditorCore/GUI/BsGUIFloatDistributionField.h

@@ -5,22 +5,47 @@
 #include "BsEditorPrerequisites.h"
 #include "GUI/BsGUIFieldBase.h"
 #include "Particles/BsParticleDistribution.h"
+#include "Animation/BsAnimationUtility.h"
 
 namespace bs
 {
 	class GUICurves;
 
-	/** @addtogroup GUI-Editor
+	/** @addtogroup GUI-Editor-Internal
 	 *  @{
 	 */
 
-	/**
-	 * A composite GUI object representing an editor field. Editor fields are a combination of a label and an input field.
-	 * Label is optional. This specific implementation displays an input field for a floating point distribution.
-	 */
-	class BS_ED_EXPORT BS_SCRIPT_EXPORT(ed:true,m:GUIEditor) 
-	GUIFloatDistributionField final : public TGUIField<GUIFloatDistributionField>
+	namespace impl
+	{
+		template<class T>
+		struct TGUIDistributionMeta { };
+
+		template<>
+		struct TGUIDistributionMeta<float>
+		{
+			using ConstantField = GUIFloatField;
+		};
+
+		template<>
+		struct TGUIDistributionMeta<Vector2>
+		{
+			using ConstantField = GUIVector2Field;
+		};
+
+		template<>
+		struct TGUIDistributionMeta<Vector3>
+		{
+			using ConstantField = GUIVector3Field;
+		};
+	}
+
+	/** Templated common class for all GUI distribution field types. */
+	template<class T, class SELF>
+	class BS_ED_EXPORT TGUIDistributionField : public TGUIField<SELF>
 	{
+		using GUIConstantType = typename impl::TGUIDistributionMeta<T>::ConstantField;
+		enum { NumComponents = TCurveProperties<T>::NumComponents };
+
 	public:
 		/** Style type name for the internal float fields. */
 		static constexpr const char* FLOAT_FIELD_STYLE_TYPE = "FloatField";
@@ -31,19 +56,16 @@ namespace bs
 		/** Style type name for the internal drop down button. */
 		static constexpr const char* DROP_DOWN_FIELD_STYLE_TYPE = "DropDownButton";
 
-		/** Returns type name of the GUI element used for finding GUI element styles. */
-		static const String& getGUITypeName();
-
-		GUIFloatDistributionField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
+		TGUIDistributionField(const PrivatelyConstruct& dummy, const GUIContent& labelContent, UINT32 labelWidth,
 			const String& style, const GUIDimensions& dimensions, bool withLabel);
 
 		/**	Returns the value of the field. */
 		BS_SCRIPT_EXPORT(pr:getter,n:Value)
-		FloatDistribution getValue() const { return mValue; }
+		TDistribution<T> getValue() const { return mValue; }
 
 		/**	Changes the value of the field. */
 		BS_SCRIPT_EXPORT(pr:setter,n:Value)
-		void setValue(const FloatDistribution& value);
+		void setValue(const TDistribution<T>& value);
 
 		/** @copydoc GUIElement::setTint */
 		void setTint(const Color& color) override;
@@ -54,9 +76,10 @@ namespace bs
 
 		/** 
 		 * Triggered when the user clicks on the curve display. Only relevant if the distribution is a curve distribution. 
+		 * Provides the sequential index of the clicked curve (0 - x, 1 - y, 2 - z).
 		 */
 		BS_SCRIPT_EXPORT(in:true)
-		Event<void()> onClicked;
+		Event<void(INT32)> onClicked;
 
 		/** 
 		 * Triggered when the user modifies either of the non-curve (constant) values of the distribution. Only relevant
@@ -88,17 +111,66 @@ namespace bs
 		/** Rebuilds the internal GUI components for the current property type. */
 		void rebuild();
 
-		FloatDistribution mValue = 0.0f;
+		TDistribution<T> mValue = TCurveProperties<T>::getZero();
 		GUIButton* mDropDownButton = nullptr;
-		GUIFloatField* mMinInput = nullptr;
-		GUIFloatField* mMaxInput = nullptr;
-		GUICurves* mCurveDisplay = nullptr;
-
-		float mMinConstant = 0.0f;
-		float mMaxConstant = 0.0f;
-		TAnimationCurve<float> mCurves[2];
+		GUIConstantType* mMinInput = nullptr;
+		GUIConstantType* mMaxInput = nullptr;
+		GUICurves* mCurveDisplay[NumComponents] = { };
+
+		T mMinConstant = TCurveProperties<T>::getZero();
+		T mMaxConstant = TCurveProperties<T>::getZero();
+		TAnimationCurve<float> mMinCurve[NumComponents];
+		TAnimationCurve<float> mMaxCurve[NumComponents];
 		SPtr<GUIContextMenu> mContextMenu;
 	};
 
 	/** @} */
+
+	/** @addtogroup GUI-Editor
+	 *  @{
+	 */
+
+	/**
+	 * A composite GUI object representing an editor field. Editor fields are a combination of a label and an input field.
+	 * Label is optional. This specific implementation displays an input field for a floating point distribution.
+	 */
+	class BS_ED_EXPORT BS_SCRIPT_EXPORT(ed:true,m:GUIEditor) 
+	GUIFloatDistributionField final : public TGUIDistributionField<float, GUIFloatDistributionField>
+	{
+	public:
+		using TGUIDistributionField::TGUIDistributionField;
+
+		/** Returns type name of the GUI element used for finding GUI element styles. */
+		static const String& getGUITypeName();
+	};
+	
+	/**
+	 * A composite GUI object representing an editor field. Editor fields are a combination of a label and an input field.
+	 * Label is optional. This specific implementation displays an input field for a 2D vector distribution.
+	 */
+	class BS_ED_EXPORT BS_SCRIPT_EXPORT(ed:true,m:GUIEditor) 
+	GUIVector2DistributionField final : public TGUIDistributionField<Vector2, GUIVector2DistributionField>
+	{
+	public:
+		using TGUIDistributionField::TGUIDistributionField;
+
+		/** Returns type name of the GUI element used for finding GUI element styles. */
+		static const String& getGUITypeName();
+	};
+
+	/**
+	 * A composite GUI object representing an editor field. Editor fields are a combination of a label and an input field.
+	 * Label is optional. This specific implementation displays an input field for a 3D vector distribution.
+	 */
+	class BS_ED_EXPORT BS_SCRIPT_EXPORT(ed:true,m:GUIEditor) 
+	GUIVector3DistributionField final : public TGUIDistributionField<Vector3, GUIVector3DistributionField>
+	{
+	public:
+		using TGUIDistributionField::TGUIDistributionField;
+
+		/** Returns type name of the GUI element used for finding GUI element styles. */
+		static const String& getGUITypeName();
+	};
+
+	/** @} */
 }

+ 1 - 1
Source/Scripting/MBansheeEditor/GUI/GUIFloatDistributionField.cs

@@ -15,7 +15,7 @@ namespace BansheeEditor
         /// </summary>
         public event Action OnConfirmed;
 
-        partial void OnClicked()
+        partial void OnClicked(int component)
         {
             FloatDistribution distribution = Value;
 

+ 76 - 0
Source/Scripting/MBansheeEditor/GUI/GUIVector2DistributionField.cs

@@ -0,0 +1,76 @@
+using System;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    partial class GUIVector2DistributionField
+    {
+        /// <summary>
+        /// Triggered when the distribution in the field changes.
+        /// </summary>
+        public event Action OnChanged;
+
+        /// <summary>
+        /// Triggered whenever user confirms input in one of the floating point fields.
+        /// </summary>
+        public event Action OnConfirmed;
+
+        partial void OnClicked(int component)
+        {
+            Vector2Distribution distribution = Value;
+
+            if (distribution.DistributionType == PropertyDistributionType.Curve)
+            {
+                AnimationCurve[] curves = AnimationUtility.SplitCurve2D(distribution.GetMinCurve());
+                if (component < curves.Length)
+                {
+                    CurveEditorWindow.Show(curves[component], (success, curve) =>
+                    {
+                        if (!success)
+                            return;
+
+                        curves[component] = curve;
+
+                        Vector2Curve compoundCurve = AnimationUtility.CombineCurve2D(curves);
+                        Value = new Vector2Distribution(compoundCurve);
+                        OnChanged?.Invoke();
+                    });
+                }
+            }
+            else if (distribution.DistributionType == PropertyDistributionType.RandomCurveRange)
+            {
+                AnimationCurve[] minCurves = AnimationUtility.SplitCurve2D(distribution.GetMinCurve());
+                AnimationCurve[] maxCurves = AnimationUtility.SplitCurve2D(distribution.GetMaxCurve());
+
+                if (component < minCurves.Length && component < maxCurves.Length)
+                {
+                    CurveEditorWindow.Show(minCurves[component], maxCurves[component],
+                        (success, minCurve, maxCurve) =>
+                        {
+                            if (!success)
+                                return;
+
+                            minCurves[component] = minCurve;
+                            maxCurves[component] = maxCurve;
+
+                            Vector2Curve minCompoundCurves = AnimationUtility.CombineCurve2D(minCurves);
+                            Vector2Curve maxCompoundCurves = AnimationUtility.CombineCurve2D(maxCurves);
+
+                            Value = new Vector2Distribution(minCompoundCurves, maxCompoundCurves);
+                            OnChanged?.Invoke();
+                        });
+                }
+            }
+        }
+
+        partial void OnConstantModified()
+        {
+            OnChanged?.Invoke();
+        }
+
+        partial void OnConstantConfirmed()
+        {
+            OnConfirmed?.Invoke();
+        }
+    }
+}

+ 76 - 0
Source/Scripting/MBansheeEditor/GUI/GUIVector3DistributionField.cs

@@ -0,0 +1,76 @@
+using System;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    partial class GUIVector3DistributionField
+    {
+        /// <summary>
+        /// Triggered when the distribution in the field changes.
+        /// </summary>
+        public event Action OnChanged;
+
+        /// <summary>
+        /// Triggered whenever user confirms input in one of the floating point fields.
+        /// </summary>
+        public event Action OnConfirmed;
+
+        partial void OnClicked(int component)
+        {
+            Vector3Distribution distribution = Value;
+
+            if (distribution.DistributionType == PropertyDistributionType.Curve)
+            {
+                AnimationCurve[] curves = AnimationUtility.SplitCurve3D(distribution.GetMinCurve());
+                if (component < curves.Length)
+                {
+                    CurveEditorWindow.Show(curves[component], (success, curve) =>
+                    {
+                        if (!success)
+                            return;
+
+                        curves[component] = curve;
+
+                        Vector3Curve compoundCurve = AnimationUtility.CombineCurve3D(curves);
+                        Value = new Vector3Distribution(compoundCurve);
+                        OnChanged?.Invoke();
+                    });
+                }
+            }
+            else if (distribution.DistributionType == PropertyDistributionType.RandomCurveRange)
+            {
+                AnimationCurve[] minCurves = AnimationUtility.SplitCurve3D(distribution.GetMinCurve());
+                AnimationCurve[] maxCurves = AnimationUtility.SplitCurve3D(distribution.GetMaxCurve());
+
+                if (component < minCurves.Length && component < maxCurves.Length)
+                {
+                    CurveEditorWindow.Show(minCurves[component], maxCurves[component],
+                        (success, minCurve, maxCurve) =>
+                        {
+                            if (!success)
+                                return;
+
+                            minCurves[component] = minCurve;
+                            maxCurves[component] = maxCurve;
+
+                            Vector3Curve minCompoundCurves = AnimationUtility.CombineCurve3D(minCurves);
+                            Vector3Curve maxCompoundCurves = AnimationUtility.CombineCurve3D(maxCurves);
+
+                            Value = new Vector3Distribution(minCompoundCurves, maxCompoundCurves);
+                            OnChanged?.Invoke();
+                        });
+                }
+            }
+        }
+
+        partial void OnConstantModified()
+        {
+            OnChanged?.Invoke();
+        }
+
+        partial void OnConstantConfirmed()
+        {
+            OnConfirmed?.Invoke();
+        }
+    }
+}

+ 5 - 4
Source/Scripting/MBansheeEditor/Generated/GUIFloatDistributionField.generated.cs

@@ -93,9 +93,10 @@ namespace BansheeEditor
 		}
 
 		/// <summary>
-		/// Triggered when the user clicks on the curve display. Only relevant if the distribution is a curve distribution.
+		/// Triggered when the user clicks on the curve display. Only relevant if the distribution is a curve distribution.  
+		/// Provides the sequential index of the clicked curve (0 - x, 1 - y, 2 - z).
 		/// </summary>
-		partial void OnClicked();
+		partial void OnClicked(int p0);
 
 		/// <summary>
 		/// Triggered when the user modifies either of the non-curve (constant) values of the distribution. Only relevant if the 
@@ -125,9 +126,9 @@ namespace BansheeEditor
 		private static extern void Internal_create2(GUIFloatDistributionField managedInstance, LocString labelText, string style);
 		[MethodImpl(MethodImplOptions.InternalCall)]
 		private static extern void Internal_create3(GUIFloatDistributionField managedInstance, string style);
-		private void Internal_onClicked()
+		private void Internal_onClicked(int p0)
 		{
-			OnClicked();
+			OnClicked(p0);
 		}
 		private void Internal_onConstantModified()
 		{

+ 144 - 0
Source/Scripting/MBansheeEditor/Generated/GUIVector2DistributionField.generated.cs

@@ -0,0 +1,144 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+	/** @addtogroup GUIEditor
+	 *  @{
+	 */
+
+	/// <summary>
+	/// A composite GUI object representing an editor field. Editor fields are a combination of a label and an input field. 
+	/// Label is optional. This specific implementation displays an input field for a 2D vector distribution.
+	/// </summary>
+	[ShowInInspector]
+	public partial class GUIVector2DistributionField : GUIElement
+	{
+		private GUIVector2DistributionField(bool __dummy0) { }
+		protected GUIVector2DistributionField() { }
+
+		/// <summary>Creates a new GUI editor field with a label.</summary>
+		/// <param name="labelContent">Content to display in the editor field label.</param>
+		/// <param name="labelWidth">Width of the label in pixels.</param>
+		/// <param name="style">
+		/// Optional style to use for the element. Style will be retrieved from GUISkin of the GUIWidget the element is used on. 
+		/// If not specified default style is used.
+		/// </param>
+		public GUIVector2DistributionField(GUIContent labelContent, uint labelWidth, string style = "")
+		{
+			Internal_create(this, ref labelContent, labelWidth, style);
+		}
+
+		/// <summary>Creates a new GUI editor field with a label.</summary>
+		/// <param name="labelContent">Content to display in the editor field label.</param>
+		/// <param name="style">
+		/// Optional style to use for the element. Style will be retrieved from GUISkin of the GUIWidget the element is used on. 
+		/// If not specified default style is used.
+		/// </param>
+		public GUIVector2DistributionField(GUIContent labelContent, string style = "")
+		{
+			Internal_create0(this, ref labelContent, style);
+		}
+
+		/// <summary>Creates a new GUI editor field with a label.</summary>
+		/// <param name="labelText">String to display in the editor field label.</param>
+		/// <param name="labelWidth">Width of the label in pixels.</param>
+		/// <param name="style">
+		/// Optional style to use for the element. Style will be retrieved from GUISkin of the GUIWidget the element is used on. 
+		/// If not specified default style is used.
+		/// </param>
+		public GUIVector2DistributionField(LocString labelText, uint labelWidth, string style = "")
+		{
+			Internal_create1(this, labelText, labelWidth, style);
+		}
+
+		/// <summary>Creates a new GUI editor field with a label.</summary>
+		/// <param name="labelText">String to display in the editor field label.</param>
+		/// <param name="style">
+		/// Optional style to use for the element. Style will be retrieved from GUISkin of the GUIWidget the element is used on. 
+		/// If not specified default style is used.
+		/// </param>
+		public GUIVector2DistributionField(LocString labelText, string style = "")
+		{
+			Internal_create2(this, labelText, style);
+		}
+
+		/// <summary>Creates a new GUI editor field without a label.</summary>
+		/// <param name="style">
+		/// Optional style to use for the element. Style will be retrieved from GUISkin of the GUIWidget the element is used on. 
+		/// If not specified default style is used.
+		/// </param>
+		public GUIVector2DistributionField(string style = "")
+		{
+			Internal_create3(this, style);
+		}
+
+		/// <summary>Changes the value of the field.</summary>
+		[ShowInInspector]
+		public Vector2Distribution Value
+		{
+			get { return Internal_getValue(mCachedPtr); }
+			set { Internal_setValue(mCachedPtr, value); }
+		}
+
+		/// <summary>
+		/// Checks if any of the float input fields currently have input focus. Only relevant for non-curve distributions.
+		/// </summary>
+		[ShowInInspector]
+		public bool HasInputFocus
+		{
+			get { return Internal_hasInputFocus(mCachedPtr); }
+		}
+
+		/// <summary>
+		/// Triggered when the user clicks on the curve display. Only relevant if the distribution is a curve distribution.  
+		/// Provides the sequential index of the clicked curve (0 - x, 1 - y, 2 - z).
+		/// </summary>
+		partial void OnClicked(int p0);
+
+		/// <summary>
+		/// Triggered when the user modifies either of the non-curve (constant) values of the distribution. Only relevant if the 
+		/// distribution is not a curve distribution.
+		/// </summary>
+		partial void OnConstantModified();
+
+		/// <summary>
+		/// Triggered when the user confirms inputs in either of the non-curve (constant) values of the distribution. Only  
+		/// relevant if the distribution is not a curve distribution.
+		/// </summary>
+		partial void OnConstantConfirmed();
+
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern Vector2Distribution Internal_getValue(IntPtr thisPtr);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_setValue(IntPtr thisPtr, Vector2Distribution value);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern bool Internal_hasInputFocus(IntPtr thisPtr);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_create(GUIVector2DistributionField managedInstance, ref GUIContent labelContent, uint labelWidth, string style);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_create0(GUIVector2DistributionField managedInstance, ref GUIContent labelContent, string style);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_create1(GUIVector2DistributionField managedInstance, LocString labelText, uint labelWidth, string style);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_create2(GUIVector2DistributionField managedInstance, LocString labelText, string style);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_create3(GUIVector2DistributionField managedInstance, string style);
+		private void Internal_onClicked(int p0)
+		{
+			OnClicked(p0);
+		}
+		private void Internal_onConstantModified()
+		{
+			OnConstantModified();
+		}
+		private void Internal_onConstantConfirmed()
+		{
+			OnConstantConfirmed();
+		}
+	}
+
+	/** @} */
+}

+ 144 - 0
Source/Scripting/MBansheeEditor/Generated/GUIVector3DistributionField.generated.cs

@@ -0,0 +1,144 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+	/** @addtogroup GUIEditor
+	 *  @{
+	 */
+
+	/// <summary>
+	/// A composite GUI object representing an editor field. Editor fields are a combination of a label and an input field. 
+	/// Label is optional. This specific implementation displays an input field for a 3D vector distribution.
+	/// </summary>
+	[ShowInInspector]
+	public partial class GUIVector3DistributionField : GUIElement
+	{
+		private GUIVector3DistributionField(bool __dummy0) { }
+		protected GUIVector3DistributionField() { }
+
+		/// <summary>Creates a new GUI editor field with a label.</summary>
+		/// <param name="labelContent">Content to display in the editor field label.</param>
+		/// <param name="labelWidth">Width of the label in pixels.</param>
+		/// <param name="style">
+		/// Optional style to use for the element. Style will be retrieved from GUISkin of the GUIWidget the element is used on. 
+		/// If not specified default style is used.
+		/// </param>
+		public GUIVector3DistributionField(GUIContent labelContent, uint labelWidth, string style = "")
+		{
+			Internal_create(this, ref labelContent, labelWidth, style);
+		}
+
+		/// <summary>Creates a new GUI editor field with a label.</summary>
+		/// <param name="labelContent">Content to display in the editor field label.</param>
+		/// <param name="style">
+		/// Optional style to use for the element. Style will be retrieved from GUISkin of the GUIWidget the element is used on. 
+		/// If not specified default style is used.
+		/// </param>
+		public GUIVector3DistributionField(GUIContent labelContent, string style = "")
+		{
+			Internal_create0(this, ref labelContent, style);
+		}
+
+		/// <summary>Creates a new GUI editor field with a label.</summary>
+		/// <param name="labelText">String to display in the editor field label.</param>
+		/// <param name="labelWidth">Width of the label in pixels.</param>
+		/// <param name="style">
+		/// Optional style to use for the element. Style will be retrieved from GUISkin of the GUIWidget the element is used on. 
+		/// If not specified default style is used.
+		/// </param>
+		public GUIVector3DistributionField(LocString labelText, uint labelWidth, string style = "")
+		{
+			Internal_create1(this, labelText, labelWidth, style);
+		}
+
+		/// <summary>Creates a new GUI editor field with a label.</summary>
+		/// <param name="labelText">String to display in the editor field label.</param>
+		/// <param name="style">
+		/// Optional style to use for the element. Style will be retrieved from GUISkin of the GUIWidget the element is used on. 
+		/// If not specified default style is used.
+		/// </param>
+		public GUIVector3DistributionField(LocString labelText, string style = "")
+		{
+			Internal_create2(this, labelText, style);
+		}
+
+		/// <summary>Creates a new GUI editor field without a label.</summary>
+		/// <param name="style">
+		/// Optional style to use for the element. Style will be retrieved from GUISkin of the GUIWidget the element is used on. 
+		/// If not specified default style is used.
+		/// </param>
+		public GUIVector3DistributionField(string style = "")
+		{
+			Internal_create3(this, style);
+		}
+
+		/// <summary>Changes the value of the field.</summary>
+		[ShowInInspector]
+		public Vector3Distribution Value
+		{
+			get { return Internal_getValue(mCachedPtr); }
+			set { Internal_setValue(mCachedPtr, value); }
+		}
+
+		/// <summary>
+		/// Checks if any of the float input fields currently have input focus. Only relevant for non-curve distributions.
+		/// </summary>
+		[ShowInInspector]
+		public bool HasInputFocus
+		{
+			get { return Internal_hasInputFocus(mCachedPtr); }
+		}
+
+		/// <summary>
+		/// Triggered when the user clicks on the curve display. Only relevant if the distribution is a curve distribution.  
+		/// Provides the sequential index of the clicked curve (0 - x, 1 - y, 2 - z).
+		/// </summary>
+		partial void OnClicked(int p0);
+
+		/// <summary>
+		/// Triggered when the user modifies either of the non-curve (constant) values of the distribution. Only relevant if the 
+		/// distribution is not a curve distribution.
+		/// </summary>
+		partial void OnConstantModified();
+
+		/// <summary>
+		/// Triggered when the user confirms inputs in either of the non-curve (constant) values of the distribution. Only  
+		/// relevant if the distribution is not a curve distribution.
+		/// </summary>
+		partial void OnConstantConfirmed();
+
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern Vector3Distribution Internal_getValue(IntPtr thisPtr);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_setValue(IntPtr thisPtr, Vector3Distribution value);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern bool Internal_hasInputFocus(IntPtr thisPtr);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_create(GUIVector3DistributionField managedInstance, ref GUIContent labelContent, uint labelWidth, string style);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_create0(GUIVector3DistributionField managedInstance, ref GUIContent labelContent, string style);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_create1(GUIVector3DistributionField managedInstance, LocString labelText, uint labelWidth, string style);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_create2(GUIVector3DistributionField managedInstance, LocString labelText, string style);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_create3(GUIVector3DistributionField managedInstance, string style);
+		private void Internal_onClicked(int p0)
+		{
+			OnClicked(p0);
+		}
+		private void Internal_onConstantModified()
+		{
+			OnConstantModified();
+		}
+		private void Internal_onConstantConfirmed()
+		{
+			OnConstantConfirmed();
+		}
+	}
+
+	/** @} */
+}

+ 4 - 0
Source/Scripting/MBansheeEditor/MBansheeEditor.csproj

@@ -41,6 +41,8 @@
     <Compile Include="GUI\GUIColorGradientField.cs" />
     <Compile Include="GUI\GUICurvesField.cs" />
     <Compile Include="GUI\GUIFloatDistributionField.cs" />
+    <Compile Include="GUI\GUIVector2DistributionField.cs" />
+    <Compile Include="GUI\GUIVector3DistributionField.cs" />
     <Compile Include="Inspectors\AnimationClipInspector.cs" />
     <Compile Include="Inspectors\AnimationInspector.cs" />
     <Compile Include="Inspectors\AudioClipInspector.cs" />
@@ -103,6 +105,8 @@
     <Compile Include="Windows\Inspector\InspectableLayerMask.cs" />
     <Compile Include="Windows\Inspector\InspectableQuaternion.cs" />
     <Compile Include="Windows\Inspector\InspectableRRef.cs" />
+    <Compile Include="Windows\Inspector\InspectableVector2Distribution.cs" />
+    <Compile Include="Windows\Inspector\InspectableVector3Distribution.cs" />
     <Compile Include="Windows\Inspector\Style\InspectableFieldRangeStyle.cs" />
     <Compile Include="Windows\Inspector\Style\InspectableFieldStepStyle.cs" />
     <Compile Include="Windows\Inspector\Style\InspectableFieldStyle.cs" />

+ 2 - 2
Source/Scripting/MBansheeEditor/Windows/Animation/EditorAnimInfo.cs

@@ -141,7 +141,7 @@ namespace BansheeEditor
                         }
 
                         // Convert compound curve to three per-component curves
-                        AnimationCurve[] componentCurves = AnimationUtility.SplitCurve(curveEntry.curve);
+                        AnimationCurve[] componentCurves = AnimationUtility.SplitCurve3D(curveEntry.curve);
 
                         FieldAnimCurves fieldCurves = new FieldAnimCurves();
                         fieldCurves.type = SerializableProperty.FieldType.Vector3;
@@ -382,7 +382,7 @@ namespace BansheeEditor
 
                     NamedVector3Curve curve = new NamedVector3Curve();
                     curve.name = curvePath;
-                    curve.curve = AnimationUtility.CombineCurve(new[]
+                    curve.curve = AnimationUtility.CombineCurve3D(new[]
                     {
                         new AnimationCurve(kvp.Value.curveInfos[0].curve.KeyFrames),
                         new AnimationCurve(kvp.Value.curveInfos[1].curve.KeyFrames),

+ 6 - 0
Source/Scripting/MBansheeEditor/Windows/Inspector/InspectableField.cs

@@ -183,6 +183,12 @@ namespace BansheeEditor
                     case SerializableProperty.FieldType.FloatDistribution:
                         field = new InspectableFloatDistribution(parent, title, path, depth, layout, property);
                         break;
+                    case SerializableProperty.FieldType.Vector2Distribution:
+                        field = new InspectableVector2Distribution(parent, title, path, depth, layout, property);
+                        break;
+                    case SerializableProperty.FieldType.Vector3Distribution:
+                        field = new InspectableVector3Distribution(parent, title, path, depth, layout, property);
+                        break;
                     case SerializableProperty.FieldType.ColorDistribution:
                         field = new InspectableColorDistribution(parent, title, path, depth, layout, property);
                         break;

+ 82 - 0
Source/Scripting/MBansheeEditor/Windows/Inspector/InspectableVector2Distribution.cs

@@ -0,0 +1,82 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2018 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /** @addtogroup Inspector
+     *  @{
+     */
+
+    /// <summary>
+    /// Displays GUI for a serializable property containing a 2D vector distribution. GUI elements will switch between
+    /// vector and curve input depending on the distribution type. 
+    /// </summary>
+    public class InspectableVector2Distribution : InspectableField
+    {
+        private GUIVector2DistributionField guiDistributionField;
+        private InspectableState state;
+
+        /// <summary>
+        /// Creates a new inspectable 2D vector distribution GUI for the specified property.
+        /// </summary>
+        /// <param name="parent">Parent Inspector this field belongs to.</param>
+        /// <param name="title">Name of the property, or some other value to set as the title.</param>
+        /// <param name="path">Full path to this property (includes name of this property and all parent properties).</param>
+        /// <param name="depth">Determines how deep within the inspector nesting hierarchy is this field. Some fields may
+        ///                     contain other fields, in which case you should increase this value by one.</param>
+        /// <param name="layout">Parent layout that all the field elements will be added to.</param>
+        /// <param name="property">Serializable property referencing the field whose contents to display.</param>
+        public InspectableVector2Distribution(Inspector parent, string title, string path, int depth, 
+            InspectableFieldLayout layout, SerializableProperty property)
+            : base(parent, title, path, SerializableProperty.FieldType.Vector2Distribution, depth, layout, property)
+        { }
+
+        /// <inheritoc/>
+        protected internal override void Initialize(int layoutIndex)
+        {
+            if (property != null)
+            {
+                guiDistributionField = new GUIVector2DistributionField(new GUIContent(title));
+                guiDistributionField.OnChanged += OnFieldValueChanged;
+                guiDistributionField.OnConfirmed += OnFieldValueConfirm;
+                guiDistributionField.OnFocusLost += OnFieldValueConfirm;
+
+                layout.AddElement(layoutIndex, guiDistributionField);
+            }
+        }
+
+        /// <inheritdoc/>
+        public override InspectableState Refresh(int layoutIndex)
+        {
+            if (guiDistributionField != null && !guiDistributionField.HasInputFocus)
+                guiDistributionField.Value = property.GetValue<Vector2Distribution>();
+
+            InspectableState oldState = state;
+            if (state.HasFlag(InspectableState.Modified))
+                state = InspectableState.NotModified;
+
+            return oldState;
+        }
+
+        /// <summary>
+        /// Triggered when the user edits the distribution.
+        /// </summary>
+        private void OnFieldValueChanged()
+        {
+            property.SetValue(guiDistributionField.Value);
+            state |= InspectableState.ModifyInProgress;
+        }
+
+        /// <summary>
+        /// Triggered when the user confirms input in the float fields used for displaying the non-curve distribution.
+        /// </summary>
+        private void OnFieldValueConfirm()
+        {
+            if (state.HasFlag(InspectableState.ModifyInProgress))
+                state |= InspectableState.Modified;
+        }
+    }
+
+    /** @} */
+}

+ 82 - 0
Source/Scripting/MBansheeEditor/Windows/Inspector/InspectableVector3Distribution.cs

@@ -0,0 +1,82 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2018 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /** @addtogroup Inspector
+     *  @{
+     */
+
+    /// <summary>
+    /// Displays GUI for a serializable property containing a 3D vector distribution. GUI elements will switch between
+    /// vector and curve input depending on the distribution type. 
+    /// </summary>
+    public class InspectableVector3Distribution : InspectableField
+    {
+        private GUIVector3DistributionField guiDistributionField;
+        private InspectableState state;
+
+        /// <summary>
+        /// Creates a new inspectable 3D vector distribution GUI for the specified property.
+        /// </summary>
+        /// <param name="parent">Parent Inspector this field belongs to.</param>
+        /// <param name="title">Name of the property, or some other value to set as the title.</param>
+        /// <param name="path">Full path to this property (includes name of this property and all parent properties).</param>
+        /// <param name="depth">Determines how deep within the inspector nesting hierarchy is this field. Some fields may
+        ///                     contain other fields, in which case you should increase this value by one.</param>
+        /// <param name="layout">Parent layout that all the field elements will be added to.</param>
+        /// <param name="property">Serializable property referencing the field whose contents to display.</param>
+        public InspectableVector3Distribution(Inspector parent, string title, string path, int depth, 
+            InspectableFieldLayout layout, SerializableProperty property)
+            : base(parent, title, path, SerializableProperty.FieldType.Vector3Distribution, depth, layout, property)
+        { }
+
+        /// <inheritoc/>
+        protected internal override void Initialize(int layoutIndex)
+        {
+            if (property != null)
+            {
+                guiDistributionField = new GUIVector3DistributionField(new GUIContent(title));
+                guiDistributionField.OnChanged += OnFieldValueChanged;
+                guiDistributionField.OnConfirmed += OnFieldValueConfirm;
+                guiDistributionField.OnFocusLost += OnFieldValueConfirm;
+
+                layout.AddElement(layoutIndex, guiDistributionField);
+            }
+        }
+
+        /// <inheritdoc/>
+        public override InspectableState Refresh(int layoutIndex)
+        {
+            if (guiDistributionField != null && !guiDistributionField.HasInputFocus)
+                guiDistributionField.Value = property.GetValue<Vector3Distribution>();
+
+            InspectableState oldState = state;
+            if (state.HasFlag(InspectableState.Modified))
+                state = InspectableState.NotModified;
+
+            return oldState;
+        }
+
+        /// <summary>
+        /// Triggered when the user edits the distribution.
+        /// </summary>
+        private void OnFieldValueChanged()
+        {
+            property.SetValue(guiDistributionField.Value);
+            state |= InspectableState.ModifyInProgress;
+        }
+
+        /// <summary>
+        /// Triggered when the user confirms input in the float fields used for displaying the non-curve distribution.
+        /// </summary>
+        private void OnFieldValueConfirm()
+        {
+            if (state.HasFlag(InspectableState.ModifyInProgress))
+                state |= InspectableState.Modified;
+        }
+    }
+
+    /** @} */
+}

+ 22 - 6
Source/Scripting/MBansheeEngine/Generated/AnimationUtility.generated.cs

@@ -28,15 +28,27 @@ namespace BansheeEngine
 		}
 
 		/// <summary>Splits a Vector3 curve into three individual curves, one for each component.</summary>
-		public static AnimationCurve[] SplitCurve(Vector3Curve compoundCurve)
+		public static AnimationCurve[] SplitCurve3D(Vector3Curve compoundCurve)
 		{
-			return Internal_splitCurve(compoundCurve);
+			return Internal_splitCurve3D(compoundCurve);
 		}
 
 		/// <summary>Combines three single component curves into a Vector3 curve.</summary>
-		public static Vector3Curve CombineCurve(AnimationCurve[] curveComponents)
+		public static Vector3Curve CombineCurve3D(AnimationCurve[] curveComponents)
 		{
-			return Internal_combineCurve(curveComponents);
+			return Internal_combineCurve3D(curveComponents);
+		}
+
+		/// <summary>Splits a Vector2 curve into two individual curves, one for each component.</summary>
+		public static AnimationCurve[] SplitCurve2D(Vector2Curve compoundCurve)
+		{
+			return Internal_splitCurve2D(compoundCurve);
+		}
+
+		/// <summary>Combines two single component curves into a Vector2 curve.</summary>
+		public static Vector2Curve CombineCurve2D(AnimationCurve[] curveComponents)
+		{
+			return Internal_combineCurve2D(curveComponents);
 		}
 
 		/// <summary>Calculates the total range covered by a set of curves.</summary>
@@ -55,9 +67,13 @@ namespace BansheeEngine
 		[MethodImpl(MethodImplOptions.InternalCall)]
 		private static extern Vector3Curve Internal_quaternionToEulerCurve(QuaternionCurve quatCurve);
 		[MethodImpl(MethodImplOptions.InternalCall)]
-		private static extern AnimationCurve[] Internal_splitCurve(Vector3Curve compoundCurve);
+		private static extern AnimationCurve[] Internal_splitCurve3D(Vector3Curve compoundCurve);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern Vector3Curve Internal_combineCurve3D(AnimationCurve[] curveComponents);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern AnimationCurve[] Internal_splitCurve2D(Vector2Curve compoundCurve);
 		[MethodImpl(MethodImplOptions.InternalCall)]
-		private static extern Vector3Curve Internal_combineCurve(AnimationCurve[] curveComponents);
+		private static extern Vector2Curve Internal_combineCurve2D(AnimationCurve[] curveComponents);
 		[MethodImpl(MethodImplOptions.InternalCall)]
 		private static extern void Internal_calculateRange(AnimationCurve[] curves, out float xMin, out float xMax, out float yMin, out float yMax);
 	}

+ 7 - 1
Source/Scripting/MBansheeEngine/Serialization/SerializableProperty.cs

@@ -42,7 +42,9 @@ namespace BansheeEngine
             FloatDistribution,
             ColorDistribution,
             Quaternion,
-            Enum
+            Enum,
+            Vector2Distribution,
+            Vector3Distribution
         }
 
         public delegate object Getter();
@@ -402,6 +404,10 @@ namespace BansheeEngine
                     return FieldType.Curve;
                 else if (internalType == typeof(FloatDistribution))
                     return FieldType.FloatDistribution;
+                else if (internalType == typeof(Vector2Distribution))
+                    return FieldType.Vector2Distribution;
+                else if (internalType == typeof(Vector3Distribution))
+                    return FieldType.Vector3Distribution;
                 else if (internalType == typeof(ColorDistribution))
                     return FieldType.ColorDistribution;
                 else if (internalType.IsSubclassOf(typeof (GameObject)))

+ 4 - 4
Source/Scripting/SBansheeEditor/Generated/BsScriptGUIFloatDistributionField.generated.cpp

@@ -17,7 +17,7 @@ namespace bs
 	ScriptGUIFloatDistributionField::ScriptGUIFloatDistributionField(MonoObject* managedInstance, GUIFloatDistributionField* value)
 		:TScriptGUIElement(managedInstance, value)
 	{
-		value->onClicked.connect(std::bind(&ScriptGUIFloatDistributionField::onClicked, this));
+		value->onClicked.connect(std::bind(&ScriptGUIFloatDistributionField::onClicked, this, std::placeholders::_1));
 		value->onConstantModified.connect(std::bind(&ScriptGUIFloatDistributionField::onConstantModified, this));
 		value->onConstantConfirmed.connect(std::bind(&ScriptGUIFloatDistributionField::onConstantConfirmed, this));
 	}
@@ -33,14 +33,14 @@ namespace bs
 		metaData.scriptClass->addInternalCall("Internal_create2", (void*)&ScriptGUIFloatDistributionField::Internal_create2);
 		metaData.scriptClass->addInternalCall("Internal_create3", (void*)&ScriptGUIFloatDistributionField::Internal_create3);
 
-		onClickedThunk = (onClickedThunkDef)metaData.scriptClass->getMethodExact("Internal_onClicked", "")->getThunk();
+		onClickedThunk = (onClickedThunkDef)metaData.scriptClass->getMethodExact("Internal_onClicked", "int")->getThunk();
 		onConstantModifiedThunk = (onConstantModifiedThunkDef)metaData.scriptClass->getMethodExact("Internal_onConstantModified", "")->getThunk();
 		onConstantConfirmedThunk = (onConstantConfirmedThunkDef)metaData.scriptClass->getMethodExact("Internal_onConstantConfirmed", "")->getThunk();
 	}
 
-	void ScriptGUIFloatDistributionField::onClicked()
+	void ScriptGUIFloatDistributionField::onClicked(int32_t p0)
 	{
-		MonoUtil::invokeThunk(onClickedThunk, getManagedInstance());
+		MonoUtil::invokeThunk(onClickedThunk, getManagedInstance(), p0);
 	}
 
 	void ScriptGUIFloatDistributionField::onConstantModified()

+ 2 - 2
Source/Scripting/SBansheeEditor/Generated/BsScriptGUIFloatDistributionField.generated.h

@@ -18,11 +18,11 @@ namespace bs
 		ScriptGUIFloatDistributionField(MonoObject* managedInstance, GUIFloatDistributionField* value);
 
 	private:
-		void onClicked();
+		void onClicked(int32_t p0);
 		void onConstantModified();
 		void onConstantConfirmed();
 
-		typedef void(BS_THUNKCALL *onClickedThunkDef) (MonoObject*, MonoException**);
+		typedef void(BS_THUNKCALL *onClickedThunkDef) (MonoObject*, int32_t p0, MonoException**);
 		static onClickedThunkDef onClickedThunk;
 		typedef void(BS_THUNKCALL *onConstantModifiedThunkDef) (MonoObject*, MonoException**);
 		static onConstantModifiedThunkDef onConstantModifiedThunk;

+ 137 - 0
Source/Scripting/SBansheeEditor/Generated/BsScriptGUIVector2DistributionField.generated.cpp

@@ -0,0 +1,137 @@
+#include "BsScriptGUIVector2DistributionField.generated.h"
+#include "BsMonoMethod.h"
+#include "BsMonoClass.h"
+#include "BsMonoUtil.h"
+#include "../../../EditorCore/GUI/BsGUIFloatDistributionField.h"
+#include "BsScriptTDistribution.generated.h"
+#include "BsScriptGUIContent.generated.h"
+#include "../../../EditorCore/GUI/BsGUIFloatDistributionField.h"
+#include "BsScriptHString.generated.h"
+
+namespace bs
+{
+	ScriptGUIVector2DistributionField::onClickedThunkDef ScriptGUIVector2DistributionField::onClickedThunk; 
+	ScriptGUIVector2DistributionField::onConstantModifiedThunkDef ScriptGUIVector2DistributionField::onConstantModifiedThunk; 
+	ScriptGUIVector2DistributionField::onConstantConfirmedThunkDef ScriptGUIVector2DistributionField::onConstantConfirmedThunk; 
+
+	ScriptGUIVector2DistributionField::ScriptGUIVector2DistributionField(MonoObject* managedInstance, GUIVector2DistributionField* value)
+		:TScriptGUIElement(managedInstance, value)
+	{
+		value->onClicked.connect(std::bind(&ScriptGUIVector2DistributionField::onClicked, this, std::placeholders::_1));
+		value->onConstantModified.connect(std::bind(&ScriptGUIVector2DistributionField::onConstantModified, this));
+		value->onConstantConfirmed.connect(std::bind(&ScriptGUIVector2DistributionField::onConstantConfirmed, this));
+	}
+
+	void ScriptGUIVector2DistributionField::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_getValue", (void*)&ScriptGUIVector2DistributionField::Internal_getValue);
+		metaData.scriptClass->addInternalCall("Internal_setValue", (void*)&ScriptGUIVector2DistributionField::Internal_setValue);
+		metaData.scriptClass->addInternalCall("Internal_hasInputFocus", (void*)&ScriptGUIVector2DistributionField::Internal_hasInputFocus);
+		metaData.scriptClass->addInternalCall("Internal_create", (void*)&ScriptGUIVector2DistributionField::Internal_create);
+		metaData.scriptClass->addInternalCall("Internal_create0", (void*)&ScriptGUIVector2DistributionField::Internal_create0);
+		metaData.scriptClass->addInternalCall("Internal_create1", (void*)&ScriptGUIVector2DistributionField::Internal_create1);
+		metaData.scriptClass->addInternalCall("Internal_create2", (void*)&ScriptGUIVector2DistributionField::Internal_create2);
+		metaData.scriptClass->addInternalCall("Internal_create3", (void*)&ScriptGUIVector2DistributionField::Internal_create3);
+
+		onClickedThunk = (onClickedThunkDef)metaData.scriptClass->getMethodExact("Internal_onClicked", "int")->getThunk();
+		onConstantModifiedThunk = (onConstantModifiedThunkDef)metaData.scriptClass->getMethodExact("Internal_onConstantModified", "")->getThunk();
+		onConstantConfirmedThunk = (onConstantConfirmedThunkDef)metaData.scriptClass->getMethodExact("Internal_onConstantConfirmed", "")->getThunk();
+	}
+
+	void ScriptGUIVector2DistributionField::onClicked(int32_t p0)
+	{
+		MonoUtil::invokeThunk(onClickedThunk, getManagedInstance(), p0);
+	}
+
+	void ScriptGUIVector2DistributionField::onConstantModified()
+	{
+		MonoUtil::invokeThunk(onConstantModifiedThunk, getManagedInstance());
+	}
+
+	void ScriptGUIVector2DistributionField::onConstantConfirmed()
+	{
+		MonoUtil::invokeThunk(onConstantConfirmedThunk, getManagedInstance());
+	}
+	MonoObject* ScriptGUIVector2DistributionField::Internal_getValue(ScriptGUIVector2DistributionField* thisPtr)
+	{
+		SPtr<TDistribution<Vector2>> tmp__output = bs_shared_ptr_new<TDistribution<Vector2>>();
+		*tmp__output = static_cast<GUIVector2DistributionField*>(thisPtr->getGUIElement())->getValue();
+
+		MonoObject* __output;
+		__output = ScriptTDistributionVector2::create(tmp__output);
+
+		return __output;
+	}
+
+	void ScriptGUIVector2DistributionField::Internal_setValue(ScriptGUIVector2DistributionField* thisPtr, MonoObject* value)
+	{
+		SPtr<TDistribution<Vector2>> tmpvalue;
+		ScriptTDistributionVector2* scriptvalue;
+		scriptvalue = ScriptTDistributionVector2::toNative(value);
+		tmpvalue = scriptvalue->getInternal();
+		static_cast<GUIVector2DistributionField*>(thisPtr->getGUIElement())->setValue(*tmpvalue);
+	}
+
+	bool ScriptGUIVector2DistributionField::Internal_hasInputFocus(ScriptGUIVector2DistributionField* thisPtr)
+	{
+		bool tmp__output;
+		tmp__output = static_cast<GUIVector2DistributionField*>(thisPtr->getGUIElement())->hasInputFocus();
+
+		bool __output;
+		__output = tmp__output;
+
+		return __output;
+	}
+
+	void ScriptGUIVector2DistributionField::Internal_create(MonoObject* managedInstance, __GUIContentInterop* labelContent, uint32_t labelWidth, MonoString* style)
+	{
+		GUIContent tmplabelContent;
+		tmplabelContent = ScriptGUIContent::fromInterop(*labelContent);
+		String tmpstyle;
+		tmpstyle = MonoUtil::monoToString(style);
+		GUIVector2DistributionField* instance = GUIVector2DistributionField::create(tmplabelContent, labelWidth, tmpstyle);
+		new (bs_alloc<ScriptGUIVector2DistributionField>())ScriptGUIVector2DistributionField(managedInstance, instance);
+	}
+
+	void ScriptGUIVector2DistributionField::Internal_create0(MonoObject* managedInstance, __GUIContentInterop* labelContent, MonoString* style)
+	{
+		GUIContent tmplabelContent;
+		tmplabelContent = ScriptGUIContent::fromInterop(*labelContent);
+		String tmpstyle;
+		tmpstyle = MonoUtil::monoToString(style);
+		GUIVector2DistributionField* instance = GUIVector2DistributionField::create(tmplabelContent, tmpstyle);
+		new (bs_alloc<ScriptGUIVector2DistributionField>())ScriptGUIVector2DistributionField(managedInstance, instance);
+	}
+
+	void ScriptGUIVector2DistributionField::Internal_create1(MonoObject* managedInstance, MonoObject* labelText, uint32_t labelWidth, MonoString* style)
+	{
+		SPtr<HString> tmplabelText;
+		ScriptHString* scriptlabelText;
+		scriptlabelText = ScriptHString::toNative(labelText);
+		tmplabelText = scriptlabelText->getInternal();
+		String tmpstyle;
+		tmpstyle = MonoUtil::monoToString(style);
+		GUIVector2DistributionField* instance = GUIVector2DistributionField::create(*tmplabelText, labelWidth, tmpstyle);
+		new (bs_alloc<ScriptGUIVector2DistributionField>())ScriptGUIVector2DistributionField(managedInstance, instance);
+	}
+
+	void ScriptGUIVector2DistributionField::Internal_create2(MonoObject* managedInstance, MonoObject* labelText, MonoString* style)
+	{
+		SPtr<HString> tmplabelText;
+		ScriptHString* scriptlabelText;
+		scriptlabelText = ScriptHString::toNative(labelText);
+		tmplabelText = scriptlabelText->getInternal();
+		String tmpstyle;
+		tmpstyle = MonoUtil::monoToString(style);
+		GUIVector2DistributionField* instance = GUIVector2DistributionField::create(*tmplabelText, tmpstyle);
+		new (bs_alloc<ScriptGUIVector2DistributionField>())ScriptGUIVector2DistributionField(managedInstance, instance);
+	}
+
+	void ScriptGUIVector2DistributionField::Internal_create3(MonoObject* managedInstance, MonoString* style)
+	{
+		String tmpstyle;
+		tmpstyle = MonoUtil::monoToString(style);
+		GUIVector2DistributionField* instance = GUIVector2DistributionField::create(tmpstyle);
+		new (bs_alloc<ScriptGUIVector2DistributionField>())ScriptGUIVector2DistributionField(managedInstance, instance);
+	}
+}

+ 41 - 0
Source/Scripting/SBansheeEditor/Generated/BsScriptGUIVector2DistributionField.generated.h

@@ -0,0 +1,41 @@
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "Wrappers/GUI/BsScriptGUIElement.h"
+#include "../../../bsf/Source/Foundation/bsfCore/Particles/BsParticleDistribution.h"
+#include "../../../bsf/Source/Foundation/bsfCore/Localization/BsHString.h"
+
+namespace bs
+{
+	class GUIVector2DistributionField;
+	struct __GUIContentInterop;
+
+	class BS_SCR_BED_EXPORT ScriptGUIVector2DistributionField : public TScriptGUIElement<ScriptGUIVector2DistributionField>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "GUIVector2DistributionField")
+
+		ScriptGUIVector2DistributionField(MonoObject* managedInstance, GUIVector2DistributionField* value);
+
+	private:
+		void onClicked(int32_t p0);
+		void onConstantModified();
+		void onConstantConfirmed();
+
+		typedef void(BS_THUNKCALL *onClickedThunkDef) (MonoObject*, int32_t p0, MonoException**);
+		static onClickedThunkDef onClickedThunk;
+		typedef void(BS_THUNKCALL *onConstantModifiedThunkDef) (MonoObject*, MonoException**);
+		static onConstantModifiedThunkDef onConstantModifiedThunk;
+		typedef void(BS_THUNKCALL *onConstantConfirmedThunkDef) (MonoObject*, MonoException**);
+		static onConstantConfirmedThunkDef onConstantConfirmedThunk;
+
+		static MonoObject* Internal_getValue(ScriptGUIVector2DistributionField* thisPtr);
+		static void Internal_setValue(ScriptGUIVector2DistributionField* thisPtr, MonoObject* value);
+		static bool Internal_hasInputFocus(ScriptGUIVector2DistributionField* thisPtr);
+		static void Internal_create(MonoObject* managedInstance, __GUIContentInterop* labelContent, uint32_t labelWidth, MonoString* style);
+		static void Internal_create0(MonoObject* managedInstance, __GUIContentInterop* labelContent, MonoString* style);
+		static void Internal_create1(MonoObject* managedInstance, MonoObject* labelText, uint32_t labelWidth, MonoString* style);
+		static void Internal_create2(MonoObject* managedInstance, MonoObject* labelText, MonoString* style);
+		static void Internal_create3(MonoObject* managedInstance, MonoString* style);
+	};
+}

+ 137 - 0
Source/Scripting/SBansheeEditor/Generated/BsScriptGUIVector3DistributionField.generated.cpp

@@ -0,0 +1,137 @@
+#include "BsScriptGUIVector3DistributionField.generated.h"
+#include "BsMonoMethod.h"
+#include "BsMonoClass.h"
+#include "BsMonoUtil.h"
+#include "../../../EditorCore/GUI/BsGUIFloatDistributionField.h"
+#include "BsScriptGUIContent.generated.h"
+#include "BsScriptTDistribution.generated.h"
+#include "BsScriptHString.generated.h"
+#include "../../../EditorCore/GUI/BsGUIFloatDistributionField.h"
+
+namespace bs
+{
+	ScriptGUIVector3DistributionField::onClickedThunkDef ScriptGUIVector3DistributionField::onClickedThunk; 
+	ScriptGUIVector3DistributionField::onConstantModifiedThunkDef ScriptGUIVector3DistributionField::onConstantModifiedThunk; 
+	ScriptGUIVector3DistributionField::onConstantConfirmedThunkDef ScriptGUIVector3DistributionField::onConstantConfirmedThunk; 
+
+	ScriptGUIVector3DistributionField::ScriptGUIVector3DistributionField(MonoObject* managedInstance, GUIVector3DistributionField* value)
+		:TScriptGUIElement(managedInstance, value)
+	{
+		value->onClicked.connect(std::bind(&ScriptGUIVector3DistributionField::onClicked, this, std::placeholders::_1));
+		value->onConstantModified.connect(std::bind(&ScriptGUIVector3DistributionField::onConstantModified, this));
+		value->onConstantConfirmed.connect(std::bind(&ScriptGUIVector3DistributionField::onConstantConfirmed, this));
+	}
+
+	void ScriptGUIVector3DistributionField::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_getValue", (void*)&ScriptGUIVector3DistributionField::Internal_getValue);
+		metaData.scriptClass->addInternalCall("Internal_setValue", (void*)&ScriptGUIVector3DistributionField::Internal_setValue);
+		metaData.scriptClass->addInternalCall("Internal_hasInputFocus", (void*)&ScriptGUIVector3DistributionField::Internal_hasInputFocus);
+		metaData.scriptClass->addInternalCall("Internal_create", (void*)&ScriptGUIVector3DistributionField::Internal_create);
+		metaData.scriptClass->addInternalCall("Internal_create0", (void*)&ScriptGUIVector3DistributionField::Internal_create0);
+		metaData.scriptClass->addInternalCall("Internal_create1", (void*)&ScriptGUIVector3DistributionField::Internal_create1);
+		metaData.scriptClass->addInternalCall("Internal_create2", (void*)&ScriptGUIVector3DistributionField::Internal_create2);
+		metaData.scriptClass->addInternalCall("Internal_create3", (void*)&ScriptGUIVector3DistributionField::Internal_create3);
+
+		onClickedThunk = (onClickedThunkDef)metaData.scriptClass->getMethodExact("Internal_onClicked", "int")->getThunk();
+		onConstantModifiedThunk = (onConstantModifiedThunkDef)metaData.scriptClass->getMethodExact("Internal_onConstantModified", "")->getThunk();
+		onConstantConfirmedThunk = (onConstantConfirmedThunkDef)metaData.scriptClass->getMethodExact("Internal_onConstantConfirmed", "")->getThunk();
+	}
+
+	void ScriptGUIVector3DistributionField::onClicked(int32_t p0)
+	{
+		MonoUtil::invokeThunk(onClickedThunk, getManagedInstance(), p0);
+	}
+
+	void ScriptGUIVector3DistributionField::onConstantModified()
+	{
+		MonoUtil::invokeThunk(onConstantModifiedThunk, getManagedInstance());
+	}
+
+	void ScriptGUIVector3DistributionField::onConstantConfirmed()
+	{
+		MonoUtil::invokeThunk(onConstantConfirmedThunk, getManagedInstance());
+	}
+	MonoObject* ScriptGUIVector3DistributionField::Internal_getValue(ScriptGUIVector3DistributionField* thisPtr)
+	{
+		SPtr<TDistribution<Vector3>> tmp__output = bs_shared_ptr_new<TDistribution<Vector3>>();
+		*tmp__output = static_cast<GUIVector3DistributionField*>(thisPtr->getGUIElement())->getValue();
+
+		MonoObject* __output;
+		__output = ScriptTDistributionVector3::create(tmp__output);
+
+		return __output;
+	}
+
+	void ScriptGUIVector3DistributionField::Internal_setValue(ScriptGUIVector3DistributionField* thisPtr, MonoObject* value)
+	{
+		SPtr<TDistribution<Vector3>> tmpvalue;
+		ScriptTDistributionVector3* scriptvalue;
+		scriptvalue = ScriptTDistributionVector3::toNative(value);
+		tmpvalue = scriptvalue->getInternal();
+		static_cast<GUIVector3DistributionField*>(thisPtr->getGUIElement())->setValue(*tmpvalue);
+	}
+
+	bool ScriptGUIVector3DistributionField::Internal_hasInputFocus(ScriptGUIVector3DistributionField* thisPtr)
+	{
+		bool tmp__output;
+		tmp__output = static_cast<GUIVector3DistributionField*>(thisPtr->getGUIElement())->hasInputFocus();
+
+		bool __output;
+		__output = tmp__output;
+
+		return __output;
+	}
+
+	void ScriptGUIVector3DistributionField::Internal_create(MonoObject* managedInstance, __GUIContentInterop* labelContent, uint32_t labelWidth, MonoString* style)
+	{
+		GUIContent tmplabelContent;
+		tmplabelContent = ScriptGUIContent::fromInterop(*labelContent);
+		String tmpstyle;
+		tmpstyle = MonoUtil::monoToString(style);
+		GUIVector3DistributionField* instance = GUIVector3DistributionField::create(tmplabelContent, labelWidth, tmpstyle);
+		new (bs_alloc<ScriptGUIVector3DistributionField>())ScriptGUIVector3DistributionField(managedInstance, instance);
+	}
+
+	void ScriptGUIVector3DistributionField::Internal_create0(MonoObject* managedInstance, __GUIContentInterop* labelContent, MonoString* style)
+	{
+		GUIContent tmplabelContent;
+		tmplabelContent = ScriptGUIContent::fromInterop(*labelContent);
+		String tmpstyle;
+		tmpstyle = MonoUtil::monoToString(style);
+		GUIVector3DistributionField* instance = GUIVector3DistributionField::create(tmplabelContent, tmpstyle);
+		new (bs_alloc<ScriptGUIVector3DistributionField>())ScriptGUIVector3DistributionField(managedInstance, instance);
+	}
+
+	void ScriptGUIVector3DistributionField::Internal_create1(MonoObject* managedInstance, MonoObject* labelText, uint32_t labelWidth, MonoString* style)
+	{
+		SPtr<HString> tmplabelText;
+		ScriptHString* scriptlabelText;
+		scriptlabelText = ScriptHString::toNative(labelText);
+		tmplabelText = scriptlabelText->getInternal();
+		String tmpstyle;
+		tmpstyle = MonoUtil::monoToString(style);
+		GUIVector3DistributionField* instance = GUIVector3DistributionField::create(*tmplabelText, labelWidth, tmpstyle);
+		new (bs_alloc<ScriptGUIVector3DistributionField>())ScriptGUIVector3DistributionField(managedInstance, instance);
+	}
+
+	void ScriptGUIVector3DistributionField::Internal_create2(MonoObject* managedInstance, MonoObject* labelText, MonoString* style)
+	{
+		SPtr<HString> tmplabelText;
+		ScriptHString* scriptlabelText;
+		scriptlabelText = ScriptHString::toNative(labelText);
+		tmplabelText = scriptlabelText->getInternal();
+		String tmpstyle;
+		tmpstyle = MonoUtil::monoToString(style);
+		GUIVector3DistributionField* instance = GUIVector3DistributionField::create(*tmplabelText, tmpstyle);
+		new (bs_alloc<ScriptGUIVector3DistributionField>())ScriptGUIVector3DistributionField(managedInstance, instance);
+	}
+
+	void ScriptGUIVector3DistributionField::Internal_create3(MonoObject* managedInstance, MonoString* style)
+	{
+		String tmpstyle;
+		tmpstyle = MonoUtil::monoToString(style);
+		GUIVector3DistributionField* instance = GUIVector3DistributionField::create(tmpstyle);
+		new (bs_alloc<ScriptGUIVector3DistributionField>())ScriptGUIVector3DistributionField(managedInstance, instance);
+	}
+}

+ 41 - 0
Source/Scripting/SBansheeEditor/Generated/BsScriptGUIVector3DistributionField.generated.h

@@ -0,0 +1,41 @@
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "Wrappers/GUI/BsScriptGUIElement.h"
+#include "../../../bsf/Source/Foundation/bsfCore/Particles/BsParticleDistribution.h"
+#include "../../../bsf/Source/Foundation/bsfCore/Localization/BsHString.h"
+
+namespace bs
+{
+	class GUIVector3DistributionField;
+	struct __GUIContentInterop;
+
+	class BS_SCR_BED_EXPORT ScriptGUIVector3DistributionField : public TScriptGUIElement<ScriptGUIVector3DistributionField>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "GUIVector3DistributionField")
+
+		ScriptGUIVector3DistributionField(MonoObject* managedInstance, GUIVector3DistributionField* value);
+
+	private:
+		void onClicked(int32_t p0);
+		void onConstantModified();
+		void onConstantConfirmed();
+
+		typedef void(BS_THUNKCALL *onClickedThunkDef) (MonoObject*, int32_t p0, MonoException**);
+		static onClickedThunkDef onClickedThunk;
+		typedef void(BS_THUNKCALL *onConstantModifiedThunkDef) (MonoObject*, MonoException**);
+		static onConstantModifiedThunkDef onConstantModifiedThunk;
+		typedef void(BS_THUNKCALL *onConstantConfirmedThunkDef) (MonoObject*, MonoException**);
+		static onConstantConfirmedThunkDef onConstantConfirmedThunk;
+
+		static MonoObject* Internal_getValue(ScriptGUIVector3DistributionField* thisPtr);
+		static void Internal_setValue(ScriptGUIVector3DistributionField* thisPtr, MonoObject* value);
+		static bool Internal_hasInputFocus(ScriptGUIVector3DistributionField* thisPtr);
+		static void Internal_create(MonoObject* managedInstance, __GUIContentInterop* labelContent, uint32_t labelWidth, MonoString* style);
+		static void Internal_create0(MonoObject* managedInstance, __GUIContentInterop* labelContent, MonoString* style);
+		static void Internal_create1(MonoObject* managedInstance, MonoObject* labelText, uint32_t labelWidth, MonoString* style);
+		static void Internal_create2(MonoObject* managedInstance, MonoObject* labelText, MonoString* style);
+		static void Internal_create3(MonoObject* managedInstance, MonoString* style);
+	};
+}

+ 54 - 6
Source/Scripting/SBansheeEngine/Generated/BsScriptAnimationUtility.generated.cpp

@@ -6,6 +6,7 @@
 #include "BsScriptTAnimationCurve.generated.h"
 #include "BsScriptTAnimationCurve.generated.h"
 #include "BsScriptTAnimationCurve.generated.h"
+#include "BsScriptTAnimationCurve.generated.h"
 
 namespace bs
 {
@@ -18,8 +19,10 @@ namespace bs
 	{
 		metaData.scriptClass->addInternalCall("Internal_eulerToQuaternionCurve", (void*)&ScriptAnimationUtility::Internal_eulerToQuaternionCurve);
 		metaData.scriptClass->addInternalCall("Internal_quaternionToEulerCurve", (void*)&ScriptAnimationUtility::Internal_quaternionToEulerCurve);
-		metaData.scriptClass->addInternalCall("Internal_splitCurve", (void*)&ScriptAnimationUtility::Internal_splitCurve);
-		metaData.scriptClass->addInternalCall("Internal_combineCurve", (void*)&ScriptAnimationUtility::Internal_combineCurve);
+		metaData.scriptClass->addInternalCall("Internal_splitCurve3D", (void*)&ScriptAnimationUtility::Internal_splitCurve3D);
+		metaData.scriptClass->addInternalCall("Internal_combineCurve3D", (void*)&ScriptAnimationUtility::Internal_combineCurve3D);
+		metaData.scriptClass->addInternalCall("Internal_splitCurve2D", (void*)&ScriptAnimationUtility::Internal_splitCurve2D);
+		metaData.scriptClass->addInternalCall("Internal_combineCurve2D", (void*)&ScriptAnimationUtility::Internal_combineCurve2D);
 		metaData.scriptClass->addInternalCall("Internal_calculateRange", (void*)&ScriptAnimationUtility::Internal_calculateRange);
 
 	}
@@ -65,14 +68,14 @@ namespace bs
 		return __output;
 	}
 
-	MonoArray* ScriptAnimationUtility::Internal_splitCurve(MonoObject* compoundCurve)
+	MonoArray* ScriptAnimationUtility::Internal_splitCurve3D(MonoObject* compoundCurve)
 	{
 		Vector<SPtr<TAnimationCurve<float>>> vec__output;
 		SPtr<TAnimationCurve<Vector3>> tmpcompoundCurve;
 		ScriptTAnimationCurveVector3* scriptcompoundCurve;
 		scriptcompoundCurve = ScriptTAnimationCurveVector3::toNative(compoundCurve);
 		tmpcompoundCurve = scriptcompoundCurve->getInternal();
-		vec__output = AnimationUtility::splitCurve(tmpcompoundCurve);
+		vec__output = AnimationUtility::splitCurve3D(tmpcompoundCurve);
 
 		MonoArray* __output;
 		int arraySize__output = (int)vec__output.size();
@@ -86,7 +89,7 @@ namespace bs
 		return __output;
 	}
 
-	MonoObject* ScriptAnimationUtility::Internal_combineCurve(MonoArray* curveComponents)
+	MonoObject* ScriptAnimationUtility::Internal_combineCurve3D(MonoArray* curveComponents)
 	{
 		SPtr<TAnimationCurve<Vector3>> tmp__output;
 		Vector<SPtr<TAnimationCurve<float>>> veccurveComponents;
@@ -102,7 +105,7 @@ namespace bs
 					veccurveComponents[i] = scriptcurveComponents->getInternal();
 			}
 		}
-		tmp__output = AnimationUtility::combineCurve(veccurveComponents);
+		tmp__output = AnimationUtility::combineCurve3D(veccurveComponents);
 
 		MonoObject* __output;
 		__output = ScriptTAnimationCurveVector3::create(tmp__output);
@@ -110,6 +113,51 @@ namespace bs
 		return __output;
 	}
 
+	MonoArray* ScriptAnimationUtility::Internal_splitCurve2D(MonoObject* compoundCurve)
+	{
+		Vector<SPtr<TAnimationCurve<float>>> vec__output;
+		SPtr<TAnimationCurve<Vector2>> tmpcompoundCurve;
+		ScriptTAnimationCurveVector2* scriptcompoundCurve;
+		scriptcompoundCurve = ScriptTAnimationCurveVector2::toNative(compoundCurve);
+		tmpcompoundCurve = scriptcompoundCurve->getInternal();
+		vec__output = AnimationUtility::splitCurve2D(tmpcompoundCurve);
+
+		MonoArray* __output;
+		int arraySize__output = (int)vec__output.size();
+		ScriptArray array__output = ScriptArray::create<ScriptTAnimationCurvefloat>(arraySize__output);
+		for(int i = 0; i < arraySize__output; i++)
+		{
+			array__output.set(i, ScriptTAnimationCurvefloat::create(vec__output[i]));
+		}
+		__output = array__output.getInternal();
+
+		return __output;
+	}
+
+	MonoObject* ScriptAnimationUtility::Internal_combineCurve2D(MonoArray* curveComponents)
+	{
+		SPtr<TAnimationCurve<Vector2>> tmp__output;
+		Vector<SPtr<TAnimationCurve<float>>> veccurveComponents;
+		if(curveComponents != nullptr)
+		{
+			ScriptArray arraycurveComponents(curveComponents);
+			veccurveComponents.resize(arraycurveComponents.size());
+			for(int i = 0; i < (int)arraycurveComponents.size(); i++)
+			{
+				ScriptTAnimationCurvefloat* scriptcurveComponents;
+				scriptcurveComponents = ScriptTAnimationCurvefloat::toNative(arraycurveComponents.get<MonoObject*>(i));
+				if(scriptcurveComponents != nullptr)
+					veccurveComponents[i] = scriptcurveComponents->getInternal();
+			}
+		}
+		tmp__output = AnimationUtility::combineCurve2D(veccurveComponents);
+
+		MonoObject* __output;
+		__output = ScriptTAnimationCurveVector2::create(tmp__output);
+
+		return __output;
+	}
+
 	void ScriptAnimationUtility::Internal_calculateRange(MonoArray* curves, float* xMin, float* xMax, float* yMin, float* yMax)
 	{
 		Vector<SPtr<TAnimationCurve<float>>> veccurves;

+ 4 - 2
Source/Scripting/SBansheeEngine/Generated/BsScriptAnimationUtility.generated.h

@@ -22,8 +22,10 @@ namespace bs
 
 		static MonoObject* Internal_eulerToQuaternionCurve(MonoObject* eulerCurve);
 		static MonoObject* Internal_quaternionToEulerCurve(MonoObject* quatCurve);
-		static MonoArray* Internal_splitCurve(MonoObject* compoundCurve);
-		static MonoObject* Internal_combineCurve(MonoArray* curveComponents);
+		static MonoArray* Internal_splitCurve3D(MonoObject* compoundCurve);
+		static MonoObject* Internal_combineCurve3D(MonoArray* curveComponents);
+		static MonoArray* Internal_splitCurve2D(MonoObject* compoundCurve);
+		static MonoObject* Internal_combineCurve2D(MonoArray* curveComponents);
 		static void Internal_calculateRange(MonoArray* curves, float* xMin, float* xMax, float* yMin, float* yMax);
 	};
 }