Jelajahi Sumber

More work on improving documentation for doxygen generation

BearishSun 10 tahun lalu
induk
melakukan
82fef4f0ff
66 mengubah file dengan 9626 tambahan dan 9612 penghapusan
  1. 21 10
      Doxyfile
  2. 154 154
      Source/BansheeCore/Include/BsCollider.h
  3. 301 301
      Source/BansheeCore/Include/BsGpuParam.h
  4. 1 1
      Source/BansheeCore/Include/BsGpuParams.h
  5. 208 208
      Source/BansheeCore/Include/BsPass.h
  6. 487 487
      Source/BansheeCore/Include/BsShader.h
  7. 696 698
      Source/BansheeCore/Source/Win32/BsWin32FolderMonitor.cpp
  8. 197 197
      Source/BansheeEditor/Include/BsEditorPrerequisites.h
  9. 159 159
      Source/BansheeEditor/Include/BsEditorSettings.h
  10. 5 5
      Source/BansheeEditor/Include/BsEditorWidget.h
  11. 64 64
      Source/BansheeEditor/Include/BsEditorWindow.h
  12. 90 90
      Source/BansheeEditor/Include/BsEditorWindowBase.h
  13. 226 226
      Source/BansheeEditor/Include/BsGUIResourceTreeView.h
  14. 203 203
      Source/BansheeEditor/Include/BsGUISceneTreeView.h
  15. 3 3
      Source/BansheeEditor/Include/BsGUITreeView.h
  16. 3 2
      Source/BansheeEditor/Include/BsGizmoManager.h
  17. 384 384
      Source/BansheeEditor/Include/BsProjectLibrary.h
  18. 344 344
      Source/BansheeEngine/Include/BsBuiltinResources.h
  19. 91 91
      Source/BansheeEngine/Include/BsCRenderable.h
  20. 119 119
      Source/BansheeEngine/Include/BsCursor.h
  21. 124 124
      Source/BansheeEngine/Include/BsDragAndDropManager.h
  22. 58 58
      Source/BansheeEngine/Include/BsGUICommandEvent.h
  23. 40 38
      Source/BansheeEngine/Include/BsGUIContextMenu.h
  24. 77 77
      Source/BansheeEngine/Include/BsGUIDropDownHitBox.h
  25. 4 4
      Source/BansheeEngine/Include/BsGUIElement.h
  26. 146 146
      Source/BansheeEngine/Include/BsGUIInputTool.h
  27. 7 7
      Source/BansheeEngine/Include/BsGUIManager.h
  28. 178 178
      Source/BansheeEngine/Include/BsGUIMenu.h
  29. 1 1
      Source/BansheeEngine/Include/BsGUIScrollBar.h
  30. 1 1
      Source/BansheeEngine/Include/BsGUISkin.h
  31. 105 105
      Source/BansheeEngine/Include/BsGUISpace.h
  32. 63 63
      Source/BansheeEngine/Include/BsImageSprite.h
  33. 58 58
      Source/BansheeEngine/Include/BsPaths.h
  34. 2 2
      Source/BansheeEngine/Include/BsPrerequisites.h
  35. 54 54
      Source/BansheeEngine/Include/BsRendererMaterialManager.h
  36. 58 58
      Source/BansheeEngine/Include/BsScriptManager.h
  37. 44 44
      Source/BansheeEngine/Include/BsShortcutKey.h
  38. 104 104
      Source/BansheeEngine/Include/BsSpriteTexture.h
  39. 139 139
      Source/BansheeEngine/Include/BsTextSprite.h
  40. 137 137
      Source/BansheeEngine/Include/BsVirtualInput.h
  41. 95 95
      Source/BansheeEngine/Source/BsDragAndDropManager.cpp
  42. 88 87
      Source/BansheeMono/Include/BsMonoField.h
  43. 1049 1049
      Source/BansheeUtility/Include/BsRTTIType.h
  44. 65 65
      Source/MBansheeEditor/BrowseDialog.cs
  45. 515 515
      Source/MBansheeEditor/BuildManager.cs
  46. 175 175
      Source/MBansheeEditor/EditorInput.cs
  47. 2 2
      Source/MBansheeEditor/Library/LibraryGUIEntry.cs
  48. 69 69
      Source/MBansheeEditor/MenuItem.cs
  49. 574 574
      Source/MBansheeEditor/ProjectLibrary.cs
  50. 67 67
      Source/MBansheeEditor/ToolbarItem.cs
  51. 130 130
      Source/MBansheeEngine/ContextMenu.cs
  52. 200 200
      Source/MBansheeEngine/Font.cs
  53. 656 656
      Source/MBansheeEngine/Input.cs
  54. 83 83
      Source/MBansheeEngine/LocString.cs
  55. 8 8
      Source/MBansheeEngine/Physics/D6Joint.cs
  56. 172 171
      Source/MBansheeEngine/Physics/HingeJoint.cs
  57. 2 2
      Source/MBansheeEngine/Physics/Joint.cs
  58. 87 87
      Source/MBansheeEngine/Physics/PhysicsMaterial.cs
  59. 3 3
      Source/MBansheeEngine/Physics/Rigidbody.cs
  60. 48 48
      Source/MBansheeEngine/Prefab.cs
  61. 112 112
      Source/MBansheeEngine/Resources.cs
  62. 122 122
      Source/MBansheeEngine/SpriteTexture.cs
  63. 141 141
      Source/MBansheeEngine/VirtualInput.cs
  64. 2 2
      Source/SBansheeEditor/Include/BsScriptDragDropManager.h
  65. 3 3
      Source/SBansheeEngine/Include/BsManagedSerializableObjectInfo.h
  66. 2 2
      Source/SBansheeEngine/Include/BsScriptEnginePrerequisites.h

+ 21 - 10
Doxyfile

@@ -775,13 +775,25 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = C:\Projects\BansheeEngineDev\BansheeEngine\BansheeUtility\Include \
-                         C:\Projects\BansheeEngineDev\BansheeEngine\BansheeUtility\Source \
-                         BansheeCore/Include \
-                         BansheeCore/Source \
-                         BansheeEngine/Include \
-                         BansheeEngine/Source \
-                         Documentation/Manuals/Native
+INPUT                  = Documentation/Manuals/Native \
+                         Source/BansheeCore/Include \
+                         Source/BansheeD3D9RenderAPI/Include \
+                         Source/BansheeD3D11RenderAPI/Include \
+                         Source/BansheeEditor/Include \
+                         Source/BansheeEngine/Include \
+                         Source/BansheeFBXImporter/Include \
+                         Source/BansheeFontImporter/Include \
+                         Source/BansheeFreeImgImporter/Include \
+                         Source/BansheeGLRenderAPI/Include \
+                         Source/BansheeMono/Include \
+                         Source/BansheeOISInput/Include \
+                         Source/BansheePhysX/Include \
+                         Source/BansheeSL/Include \
+                         Source/BansheeUtility/Include \
+                         Source/RenderBeast/Include \
+                         Source/SBansheeEditor/Include \
+                         Source/SBansheeEngine/Include \
+                         Source/BansheeGLRenderAPI/Source/GLSL/include
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -862,8 +874,7 @@ RECURSIVE              = YES
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 
-EXCLUDE                = C:\Projects\BansheeEngineDev\BansheeEngine\BansheeUtility\Include\ThirdParty \
-                         C:\Projects\BansheeEngineDev\BansheeEngine\BansheeUtility\Source\ThirdParty
+EXCLUDE                = Source/BansheeUtility/Include/ThirdParty
 
 # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
 # directories that are symbolic links (a Unix file system feature) are excluded
@@ -890,7 +901,7 @@ EXCLUDE_PATTERNS       =
 # Note that the wildcards are matched against the file with absolute path, so to
 # exclude all test directories use the pattern */test/*
 
-EXCLUDE_SYMBOLS        = _*
+EXCLUDE_SYMBOLS        = 
 
 # The EXAMPLE_PATH tag can be used to specify one or more files or directories
 # that contain example code fragments that are included (see the \include

+ 154 - 154
Source/BansheeCore/Include/BsCollider.h

@@ -1,155 +1,155 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsPhysicsCommon.h"
-#include "BsVector3.h"
-#include "BsQuaternion.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Physics
-	 *  @{
-	 */
-
-	/** 
-	 * Collider represents physics geometry that can be in multiple states:
-	 *  - Default: Static geometry that physics objects can collide with.
-	 *  - Trigger: Static geometry that can't be collided with but will report touch events.
-	 *  - Dynamic: Dynamic geometry that is a part of a Rigidbody. A set of colliders defines the shape of the parent 
-	 *		       rigidbody.
-	 */
-	class BS_CORE_EXPORT Collider
-	{
-	public:
-		virtual ~Collider() { }
-
-		/** @copydoc FCollider::getPosition */
-		inline Vector3 getPosition() const;
-
-		/** @copydoc FCollider::getRotation */
-		inline Quaternion getRotation() const;
-
-		/** @copydoc FCollider::setTransform */
-		inline void setTransform(const Vector3& pos, const Quaternion& rot);
-
-		/** @copydoc FCollider::setScale */
-		virtual void setScale(const Vector3& scale);
-
-		/** @copydoc FCollider::getScale */
-		inline Vector3 getScale() const;
-
-		/** @copydoc FCollider::setIsTrigger */
-		inline void setIsTrigger(bool value);
-
-		/** @copydoc FCollider::getIsTrigger */
-		inline bool getIsTrigger() const;
-
-		/** @copydoc FCollider::setRigidbody */
-		inline void setRigidbody(Rigidbody* value);
-
-		/** @copydoc FCollider::getRigidbody */
-		Rigidbody* getRigidbody() const { return mRigidbody; }
-
-		/** @copydoc FCollider::setMass */
-		inline void setMass(float mass);
-
-		/** @copydoc FCollider::getMass */
-		inline float getMass() const;
-
-		/** @copydoc FCollider::setMaterial */
-		inline void setMaterial(const HPhysicsMaterial& material);
-
-		/** @copydoc FCollider::getMaterial */
-		inline HPhysicsMaterial getMaterial() const;
-
-		/** @copydoc FCollider::setContactOffset */
-		inline void setContactOffset(float value);
-
-		/** @copydoc FCollider::getContactOffset */
-		inline float getContactOffset();
-
-		/** @copydoc FCollider::setRestOffset */
-		inline void setRestOffset(float value);
-
-		/** @copydoc FCollider::getRestOffset */
-		inline float getRestOffset();
-
-		/** @copydoc FCollider::setLayer */
-		inline void setLayer(UINT64 layer);
-
-		/** @copydoc FCollider::getLayer */
-		inline UINT64 getLayer() const;
-
-		/** Sets a value that determines which (if any) collision events are reported. */
-		inline void setCollisionReportMode(CollisionReportMode mode);
-
-		/** Gets a value that determines which (if any) collision events are reported. */
-		inline CollisionReportMode getCollisionReportMode() const;
-
-		/** 
-		 * Checks does the ray hit this collider. 
-		 *
-		 * @param[in]	ray		Ray to check.
-		 * @param[out]	hit		Information about the hit. Valid only if the method returns true.
-		 * @param[in]	maxDist	Maximum distance from the ray origin to search for hits.
-		 * @return				True if the ray has hit the collider.
-		 */
-		inline bool rayCast(const Ray& ray, PhysicsQueryHit& hit, float maxDist = FLT_MAX) const;
-
-		/** 
-		 * Checks does the ray hit this collider. 
-		 *
-		 * @param[in]	origin	Origin of the ray to check.
-		 * @param[in]	unitDir	Unit direction of the ray to check.
-		 * @param[out]	hit		Information about the hit. Valid only if the method returns true.
-		 * @param[in]	maxDist	Maximum distance from the ray origin to search for hits.
-		 * @return				True if the ray has hit the collider.
-		 */
-		inline bool rayCast(const Vector3& origin, const Vector3& unitDir, PhysicsQueryHit& hit,
-			float maxDist = FLT_MAX) const;
-
-		/** 
-		 * Triggered when some object starts interacting with the collider. Only triggered if proper collision report mode
-		 * is turned on. 
-		 */
-		Event<void(const CollisionData&)> onCollisionBegin;
-		/** 
-		 * Triggered for every frame that an object remains interacting with a collider. Only triggered if proper collision
-		 * report mode is turned on. 
-		 */
-		Event<void(const CollisionData&)> onCollisionStay;
-		/**
-		 * Triggered when some object stops interacting with the collider. Only triggered if proper collision report mode
-		 * is turned on. 
-		 */
-		Event<void(const CollisionData&)> onCollisionEnd;
-
-		/** @cond INTERNAL */
-
-		/** Returns the object containing common collider code. */
-		FCollider* _getInternal() const { return mInternal; }
-
-		/** 
-		 * Sets the object that owns this physics object, if any. Used for high level systems so they can easily map their
-		 * high level physics objects from the low level ones returned by various queries and events.
-		 */
-		void _setOwner(PhysicsOwnerType type, void* owner) { mOwner.type = type; mOwner.ownerData = owner; }
-
-		/** 
-		 * Gets the object that owns this physics object, if any. Used for high level systems so they can easily map their
-		 * high level physics objects from the low level ones returned by various queries and events.
-		 */
-		void* _getOwner(PhysicsOwnerType type) const { return mOwner.type == type ? mOwner.ownerData : nullptr; }
-
-		/** @endcond */
-	protected:
-		FCollider* mInternal = nullptr;
-		PhysicsObjectOwner mOwner;
-		Rigidbody* mRigidbody = nullptr;
-		Vector3 mScale = Vector3::ONE;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsPhysicsCommon.h"
+#include "BsVector3.h"
+#include "BsQuaternion.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Physics
+	 *  @{
+	 */
+
+	/** 
+	 * Collider represents physics geometry that can be in multiple states:
+	 *  - Default: Static geometry that physics objects can collide with.
+	 *  - Trigger: Static geometry that can't be collided with but will report touch events.
+	 *  - Dynamic: Dynamic geometry that is a part of a Rigidbody. A set of colliders defines the shape of the parent 
+	 *		       rigidbody.
+	 */
+	class BS_CORE_EXPORT Collider
+	{
+	public:
+		virtual ~Collider() { }
+
+		/** @copydoc FCollider::getPosition */
+		inline Vector3 getPosition() const;
+
+		/** @copydoc FCollider::getRotation */
+		inline Quaternion getRotation() const;
+
+		/** @copydoc FCollider::setTransform */
+		inline void setTransform(const Vector3& pos, const Quaternion& rot);
+
+		/** @copydoc FCollider::setScale */
+		virtual void setScale(const Vector3& scale);
+
+		/** @copydoc FCollider::getScale */
+		inline Vector3 getScale() const;
+
+		/** @copydoc FCollider::setIsTrigger */
+		inline void setIsTrigger(bool value);
+
+		/** @copydoc FCollider::getIsTrigger */
+		inline bool getIsTrigger() const;
+
+		/** @copydoc FCollider::setRigidbody */
+		inline void setRigidbody(Rigidbody* value);
+
+		/** Returns the rigidbody this collider is attached to, if any. */
+		Rigidbody* getRigidbody() const { return mRigidbody; }
+
+		/** @copydoc FCollider::setMass */
+		inline void setMass(float mass);
+
+		/** @copydoc FCollider::getMass */
+		inline float getMass() const;
+
+		/** @copydoc FCollider::setMaterial */
+		inline void setMaterial(const HPhysicsMaterial& material);
+
+		/** @copydoc FCollider::getMaterial */
+		inline HPhysicsMaterial getMaterial() const;
+
+		/** @copydoc FCollider::setContactOffset */
+		inline void setContactOffset(float value);
+
+		/** @copydoc FCollider::getContactOffset */
+		inline float getContactOffset();
+
+		/** @copydoc FCollider::setRestOffset */
+		inline void setRestOffset(float value);
+
+		/** @copydoc FCollider::getRestOffset */
+		inline float getRestOffset();
+
+		/** @copydoc FCollider::setLayer */
+		inline void setLayer(UINT64 layer);
+
+		/** @copydoc FCollider::getLayer */
+		inline UINT64 getLayer() const;
+
+		/** Sets a value that determines which (if any) collision events are reported. */
+		inline void setCollisionReportMode(CollisionReportMode mode);
+
+		/** Gets a value that determines which (if any) collision events are reported. */
+		inline CollisionReportMode getCollisionReportMode() const;
+
+		/** 
+		 * Checks does the ray hit this collider. 
+		 *
+		 * @param[in]	ray		Ray to check.
+		 * @param[out]	hit		Information about the hit. Valid only if the method returns true.
+		 * @param[in]	maxDist	Maximum distance from the ray origin to search for hits.
+		 * @return				True if the ray has hit the collider.
+		 */
+		inline bool rayCast(const Ray& ray, PhysicsQueryHit& hit, float maxDist = FLT_MAX) const;
+
+		/** 
+		 * Checks does the ray hit this collider. 
+		 *
+		 * @param[in]	origin	Origin of the ray to check.
+		 * @param[in]	unitDir	Unit direction of the ray to check.
+		 * @param[out]	hit		Information about the hit. Valid only if the method returns true.
+		 * @param[in]	maxDist	Maximum distance from the ray origin to search for hits.
+		 * @return				True if the ray has hit the collider.
+		 */
+		inline bool rayCast(const Vector3& origin, const Vector3& unitDir, PhysicsQueryHit& hit,
+			float maxDist = FLT_MAX) const;
+
+		/** 
+		 * Triggered when some object starts interacting with the collider. Only triggered if proper collision report mode
+		 * is turned on. 
+		 */
+		Event<void(const CollisionData&)> onCollisionBegin;
+		/** 
+		 * Triggered for every frame that an object remains interacting with a collider. Only triggered if proper collision
+		 * report mode is turned on. 
+		 */
+		Event<void(const CollisionData&)> onCollisionStay;
+		/**
+		 * Triggered when some object stops interacting with the collider. Only triggered if proper collision report mode
+		 * is turned on. 
+		 */
+		Event<void(const CollisionData&)> onCollisionEnd;
+
+		/** @cond INTERNAL */
+
+		/** Returns the object containing common collider code. */
+		FCollider* _getInternal() const { return mInternal; }
+
+		/** 
+		 * Sets the object that owns this physics object, if any. Used for high level systems so they can easily map their
+		 * high level physics objects from the low level ones returned by various queries and events.
+		 */
+		void _setOwner(PhysicsOwnerType type, void* owner) { mOwner.type = type; mOwner.ownerData = owner; }
+
+		/** 
+		 * Gets the object that owns this physics object, if any. Used for high level systems so they can easily map their
+		 * high level physics objects from the low level ones returned by various queries and events.
+		 */
+		void* _getOwner(PhysicsOwnerType type) const { return mOwner.type == type ? mOwner.ownerData : nullptr; }
+
+		/** @endcond */
+	protected:
+		FCollider* mInternal = nullptr;
+		PhysicsObjectOwner mOwner;
+		Rigidbody* mRigidbody = nullptr;
+		Vector3 mScale = Vector3::ONE;
+	};
+
+	/** @} */
 }

+ 301 - 301
Source/BansheeCore/Include/BsGpuParam.h

@@ -1,302 +1,302 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsVector2.h"
-#include "BsVector3.h"
-#include "BsVector4.h"
-#include "BsMatrix3.h"
-#include "BsMatrix4.h"
-#include "BsMatrixNxM.h"
-#include "BsVectorNI.h"
-#include "BsColor.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Implementation
-	 *  @{
-	 */
-
-	template<bool Core> struct TGpuParamsPtrType { };
-	template<> struct TGpuParamsPtrType<false> { typedef SPtr<GpuParams> Type; };
-	template<> struct TGpuParamsPtrType<true> { typedef SPtr<GpuParamsCore> Type; };
-
-	template<bool Core> struct TGpuParamTextureType { };
-	template<> struct TGpuParamTextureType < false > { typedef HTexture Type; };
-	template<> struct TGpuParamTextureType < true > { typedef SPtr<TextureCore> Type; };
-
-	template<bool Core> struct TGpuParamSamplerStateType { };
-	template<> struct TGpuParamSamplerStateType < false > { typedef SamplerStatePtr Type; };
-	template<> struct TGpuParamSamplerStateType < true > { typedef SPtr<SamplerStateCore> Type; };
-
-	/**
-	 * A handle that allows you to set a GpuProgram parameter. Internally keeps a reference to the GPU parameter buffer and
-	 * the necessary offsets. You should specialize this type for specific parameter types. 
-	 *
-	 * Object of this type must be returned by a Material. Setting/Getting parameter values will internally access a GPU 
-	 * parameter buffer attached to the Material this parameter was created from. Anything rendered with that material will
-	 * then use those set values.
-	 * 			
-	 * @note	
-	 * Normally you can set a GpuProgram parameter by calling various set/get methods on a Material. This class primarily 
-	 * used an as optimization in performance critical bits of code where it is important to locate and set parameters 
-	 * quickly without any lookups (Mentioned set/get methods expect a parameter name). You just retrieve the handle once 
-	 * and then set the parameter value many times with minimal performance impact.
-	 * 
-	 * @see		Material
-	 */
-	template<class T, bool Core>
-	class BS_CORE_EXPORT TGpuDataParam
-	{
-	private:
-		template<bool Core> struct TGpuParamBufferType { };
-		template<> struct TGpuParamBufferType < false > { typedef SPtr<GpuParamBlockBuffer> Type; };
-		template<> struct TGpuParamBufferType < true > { typedef SPtr<GpuParamBlockBufferCore> Type; };
-
-		typedef typename TGpuParamBufferType<Core>::Type GpuParamBufferType;
-		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
-
-		/**
-		 * Policy class that allows us to re-use this template class for matrices which might need transposing, and other 
-		 * types which do not. Matrix needs to be transposed for certain render systems depending on how they store them 
-		 * in memory.
-		 */
-		template<class Type>
-		struct TransposePolicy
-		{
-			static Type transpose(const Type& value) { return value; }
-			static bool transposeEnabled(bool enabled) { return false; }
-		};
-
-		/** Transpose policy for 3x3 matrix. */
-		template<>
-		struct TransposePolicy<Matrix3>
-		{
-			static Matrix3 transpose(const Matrix3& value) { return value.transpose(); }
-			static bool transposeEnabled(bool enabled) { return enabled; }
-		};
-
-		/**	Transpose policy for 4x4 matrix. */
-		template<>
-		struct TransposePolicy<Matrix4>
-		{
-			static Matrix4 transpose(const Matrix4& value) { return value.transpose(); }
-			static bool transposeEnabled(bool enabled) { return enabled; }
-		};
-
-		/**	Transpose policy for NxM matrix. */
-		template<int N, int M>
-		struct TransposePolicy<MatrixNxM<N, M>>
-		{
-			static MatrixNxM<N, M> transpose(const MatrixNxM<N, M>& value) { return value.transpose(); }
-			static bool transposeEnabled(bool enabled) { return enabled; }
-		};
-
-	public:
-		TGpuDataParam();
-		TGpuDataParam(GpuParamDataDesc* paramDesc, const GpuParamsType& parent);
-
-		/**
-		 * Sets a parameter value at the specified array index. If parameter does not contain an array leave the index at 0.
-		 *
-		 * @note	
-		 * Like with all GPU parameters, the actual GPU buffer will not be updated until rendering with material this 
-		 * parameter was created from starts on the core thread.
-		 */
-		void set(const T& value, UINT32 arrayIdx = 0);
-
-		/**
-		 * Returns a value of a parameter at the specified array index. If parameter does not contain an array leave the 
-		 * index at 0.
-		 *
-		 * @note	No GPU reads are done. Data returned was cached when it was written. 
-		 */
-		T get(UINT32 arrayIdx = 0);
-
-		/** Checks if param is initialized. */
-		bool operator==(const nullptr_t &nullval) const
-		{
-			return mParamDesc == nullptr;
-		}
-
-	protected:
-		GpuParamsType mParent;
-		GpuParamDataDesc* mParamDesc;
-	};
-
-	/** @copydoc TGpuDataParam */
-	template<bool Core>
-	class BS_CORE_EXPORT TGpuParamStruct
-	{
-	public:
-		template<bool Core> struct TGpuParamBufferType { };
-		template<> struct TGpuParamBufferType < false > { typedef SPtr<GpuParamBlockBuffer> Type; };
-		template<> struct TGpuParamBufferType < true > { typedef SPtr<GpuParamBlockBufferCore> Type; };
-
-		typedef typename TGpuParamBufferType<Core>::Type GpuParamBufferType;
-		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
-
-		TGpuParamStruct();
-		TGpuParamStruct(GpuParamDataDesc* paramDesc, const GpuParamsType& parent);
-
-		/** @copydoc TGpuDataParam::set */
-		void set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
-
-		/** @copydoc TGpuDataParam::get */
-		void get(void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
-
-		/**	Returns the size of the struct in bytes. */
-		UINT32 getElementSize() const;
-
-		/**	Checks if param is initialized. */
-		bool operator==(const nullptr_t &nullval) const
-		{
-			return mParamDesc == nullptr;
-		}
-
-	protected:
-		GpuParamsType mParent;
-		GpuParamDataDesc* mParamDesc;
-	};
-
-	/** @copydoc TGpuObjectParam */
-	template<bool Core>
-	class BS_CORE_EXPORT TGpuParamTexture
-	{
-	private:
-		friend class GpuParams;
-		friend class GpuParamsCore;
-
-		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
-		typedef typename TGpuParamTextureType<Core>::Type TextureType;
-
-	public:
-		TGpuParamTexture();
-		TGpuParamTexture(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent);
-
-		/** @copydoc TGpuDataParam::set */
-		void set(const TextureType& texture);
-
-		/** @copydoc TGpuDataParam::get */
-		TextureType get();
-
-		/** Checks if param is initialized. */
-		bool operator==(const nullptr_t &nullval) const
-		{
-			return mParamDesc == nullptr;
-		}
-
-	protected:
-		GpuParamsType mParent;
-		GpuParamObjectDesc* mParamDesc;
-	};
-
-	/** @copydoc TGpuObjectParam */
-	template<bool Core>
-	class BS_CORE_EXPORT TGpuParamLoadStoreTexture
-	{
-	private:
-		friend class GpuParams;
-		friend class GpuParamsCore;
-
-		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
-		typedef typename TGpuParamTextureType<Core>::Type TextureType;
-
-	public:
-		TGpuParamLoadStoreTexture();
-		TGpuParamLoadStoreTexture(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent);
-
-		/** @copydoc TGpuDataParam::set */
-		void set(const TextureType& texture, const TextureSurface& surface);
-
-		/** @copydoc TGpuDataParam::get */
-		TextureType get();
-
-		/**	Checks if param is initialized. */
-		bool operator==(const nullptr_t &nullval) const
-		{
-			return mParamDesc == nullptr;
-		}
-
-	protected:
-		GpuParamsType mParent;
-		GpuParamObjectDesc* mParamDesc;
-	};
-
-	/** @copydoc TGpuObjectParam */
-	template<bool Core>
-	class BS_CORE_EXPORT TGpuParamSampState
-	{
-	private:
-		friend class GpuParams;
-		friend class GpuParamsCore;
-
-		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
-		typedef typename TGpuParamSamplerStateType<Core>::Type SamplerStateType;
-
-	public:
-		TGpuParamSampState();
-		TGpuParamSampState(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent);
-
-		/** @copydoc TGpuDataParam::set */
-		void set(const SamplerStateType& samplerState);
-
-		/** @copydoc TGpuDataParam::get */
-		SamplerStateType get();
-
-		/**	Checks if param is initialized. */
-		bool operator==(const nullptr_t &nullval) const
-		{
-			return mParamDesc == nullptr;
-		}
-
-	protected:
-		GpuParamsType mParent;
-		GpuParamObjectDesc* mParamDesc;
-	};
-
-	/** @} */
-
-	/** @addtogroup RenderAPI
-	 *  @{
-	 */
-
-	typedef TGpuDataParam<float, false> GpuParamFloat;
-	typedef TGpuDataParam<Vector2, false> GpuParamVec2;
-	typedef TGpuDataParam<Vector3, false> GpuParamVec3;
-	typedef TGpuDataParam<Vector4, false> GpuParamVec4;
-	typedef TGpuDataParam<int, false> GpuParamInt;
-	typedef TGpuDataParam<Vector2I, false> GpuParamVec2I;
-	typedef TGpuDataParam<Vector3I, false> GpuParamVec3I;
-	typedef TGpuDataParam<Vector4I, false> GpuParamVec4I;
-	typedef TGpuDataParam<Matrix3, false> GpuParamMat3;
-	typedef TGpuDataParam<Matrix4, false> GpuParamMat4;
-	typedef TGpuDataParam<Color, false> GpuParamColor;
-
-	typedef TGpuDataParam<float, true> GpuParamFloatCore;
-	typedef TGpuDataParam<Vector2, true> GpuParamVec2Core;
-	typedef TGpuDataParam<Vector3, true> GpuParamVec3Core;
-	typedef TGpuDataParam<Vector4, true> GpuParamVec4Core;
-	typedef TGpuDataParam<int, true> GpuParamIntCore;
-	typedef TGpuDataParam<Vector2I, true> GpuParamVec2ICore;
-	typedef TGpuDataParam<Vector3I, true> GpuParamVec3ICore;
-	typedef TGpuDataParam<Vector4I, true> GpuParamVec4ICore;
-	typedef TGpuDataParam<Matrix3, true> GpuParamMat3Core;
-	typedef TGpuDataParam<Matrix4, true> GpuParamMat4Core;
-	typedef TGpuDataParam<Color, true> GpuParamColorCore;
-
-	typedef TGpuParamStruct<false> GpuParamStruct;
-	typedef TGpuParamStruct<true> GpuParamStructCore;
-
-	typedef TGpuParamTexture<false> GpuParamTexture;
-	typedef TGpuParamTexture<true> GpuParamTextureCore;
-
-	typedef TGpuParamSampState<false> GpuParamSampState;
-	typedef TGpuParamSampState<true> GpuParamSampStateCore;
-
-	typedef TGpuParamLoadStoreTexture<false> GpuParamLoadStoreTexture;
-	typedef TGpuParamLoadStoreTexture<true> GpuParamLoadStoreTextureCore;
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsVector2.h"
+#include "BsVector3.h"
+#include "BsVector4.h"
+#include "BsMatrix3.h"
+#include "BsMatrix4.h"
+#include "BsMatrixNxM.h"
+#include "BsVectorNI.h"
+#include "BsColor.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Implementation
+	 *  @{
+	 */
+
+	template<bool Core> struct TGpuParamsPtrType { };
+	template<> struct TGpuParamsPtrType<false> { typedef SPtr<GpuParams> Type; };
+	template<> struct TGpuParamsPtrType<true> { typedef SPtr<GpuParamsCore> Type; };
+
+	template<bool Core> struct TGpuParamTextureType { };
+	template<> struct TGpuParamTextureType < false > { typedef HTexture Type; };
+	template<> struct TGpuParamTextureType < true > { typedef SPtr<TextureCore> Type; };
+
+	template<bool Core> struct TGpuParamSamplerStateType { };
+	template<> struct TGpuParamSamplerStateType < false > { typedef SamplerStatePtr Type; };
+	template<> struct TGpuParamSamplerStateType < true > { typedef SPtr<SamplerStateCore> Type; };
+
+	/**
+	 * A handle that allows you to set a GpuProgram parameter. Internally keeps a reference to the GPU parameter buffer and
+	 * the necessary offsets. You should specialize this type for specific parameter types. 
+	 *
+	 * Object of this type must be returned by a Material. Setting/Getting parameter values will internally access a GPU 
+	 * parameter buffer attached to the Material this parameter was created from. Anything rendered with that material will
+	 * then use those set values.
+	 * 			
+	 * @note	
+	 * Normally you can set a GpuProgram parameter by calling various set/get methods on a Material. This class primarily 
+	 * used an as optimization in performance critical bits of code where it is important to locate and set parameters 
+	 * quickly without any lookups (Mentioned set/get methods expect a parameter name). You just retrieve the handle once 
+	 * and then set the parameter value many times with minimal performance impact.
+	 * 
+	 * @see		Material
+	 */
+	template<class T, bool Core>
+	class BS_CORE_EXPORT TGpuDataParam
+	{
+	private:
+		template<bool Core> struct TGpuParamBufferType { };
+		template<> struct TGpuParamBufferType < false > { typedef SPtr<GpuParamBlockBuffer> Type; };
+		template<> struct TGpuParamBufferType < true > { typedef SPtr<GpuParamBlockBufferCore> Type; };
+
+		typedef typename TGpuParamBufferType<Core>::Type GpuParamBufferType;
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+
+		/**
+		 * Policy class that allows us to re-use this template class for matrices which might need transposing, and other 
+		 * types which do not. Matrix needs to be transposed for certain render systems depending on how they store them 
+		 * in memory.
+		 */
+		template<class Type>
+		struct TransposePolicy
+		{
+			static Type transpose(const Type& value) { return value; }
+			static bool transposeEnabled(bool enabled) { return false; }
+		};
+
+		/** Transpose policy for 3x3 matrix. */
+		template<>
+		struct TransposePolicy<Matrix3>
+		{
+			static Matrix3 transpose(const Matrix3& value) { return value.transpose(); }
+			static bool transposeEnabled(bool enabled) { return enabled; }
+		};
+
+		/**	Transpose policy for 4x4 matrix. */
+		template<>
+		struct TransposePolicy<Matrix4>
+		{
+			static Matrix4 transpose(const Matrix4& value) { return value.transpose(); }
+			static bool transposeEnabled(bool enabled) { return enabled; }
+		};
+
+		/**	Transpose policy for NxM matrix. */
+		template<int N, int M>
+		struct TransposePolicy<MatrixNxM<N, M>>
+		{
+			static MatrixNxM<N, M> transpose(const MatrixNxM<N, M>& value) { return value.transpose(); }
+			static bool transposeEnabled(bool enabled) { return enabled; }
+		};
+
+	public:
+		TGpuDataParam();
+		TGpuDataParam(GpuParamDataDesc* paramDesc, const GpuParamsType& parent);
+
+		/**
+		 * Sets a parameter value at the specified array index. If parameter does not contain an array leave the index at 0.
+		 *
+		 * @note	
+		 * Like with all GPU parameters, the actual GPU buffer will not be updated until rendering with material this 
+		 * parameter was created from starts on the core thread.
+		 */
+		void set(const T& value, UINT32 arrayIdx = 0);
+
+		/**
+		 * Returns a value of a parameter at the specified array index. If parameter does not contain an array leave the 
+		 * index at 0.
+		 *
+		 * @note	No GPU reads are done. Data returned was cached when it was written. 
+		 */
+		T get(UINT32 arrayIdx = 0);
+
+		/** Checks if param is initialized. */
+		bool operator==(const nullptr_t &nullval) const
+		{
+			return mParamDesc == nullptr;
+		}
+
+	protected:
+		GpuParamsType mParent;
+		GpuParamDataDesc* mParamDesc;
+	};
+
+	/** @copydoc TGpuDataParam */
+	template<bool Core>
+	class BS_CORE_EXPORT TGpuParamStruct
+	{
+	public:
+		template<bool Core> struct TGpuParamBufferType { };
+		template<> struct TGpuParamBufferType < false > { typedef SPtr<GpuParamBlockBuffer> Type; };
+		template<> struct TGpuParamBufferType < true > { typedef SPtr<GpuParamBlockBufferCore> Type; };
+
+		typedef typename TGpuParamBufferType<Core>::Type GpuParamBufferType;
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+
+		TGpuParamStruct();
+		TGpuParamStruct(GpuParamDataDesc* paramDesc, const GpuParamsType& parent);
+
+		/** @copydoc TGpuDataParam::set */
+		void set(const void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
+
+		/** @copydoc TGpuDataParam::get */
+		void get(void* value, UINT32 sizeBytes, UINT32 arrayIdx = 0);
+
+		/**	Returns the size of the struct in bytes. */
+		UINT32 getElementSize() const;
+
+		/**	Checks if param is initialized. */
+		bool operator==(const nullptr_t &nullval) const
+		{
+			return mParamDesc == nullptr;
+		}
+
+	protected:
+		GpuParamsType mParent;
+		GpuParamDataDesc* mParamDesc;
+	};
+
+	/** @copydoc TGpuDataParam */
+	template<bool Core>
+	class BS_CORE_EXPORT TGpuParamTexture
+	{
+	private:
+		friend class GpuParams;
+		friend class GpuParamsCore;
+
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+		typedef typename TGpuParamTextureType<Core>::Type TextureType;
+
+	public:
+		TGpuParamTexture();
+		TGpuParamTexture(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent);
+
+		/** @copydoc TGpuDataParam::set */
+		void set(const TextureType& texture);
+
+		/** @copydoc TGpuDataParam::get */
+		TextureType get();
+
+		/** Checks if param is initialized. */
+		bool operator==(const nullptr_t &nullval) const
+		{
+			return mParamDesc == nullptr;
+		}
+
+	protected:
+		GpuParamsType mParent;
+		GpuParamObjectDesc* mParamDesc;
+	};
+
+	/** @copydoc TGpuDataParam */
+	template<bool Core>
+	class BS_CORE_EXPORT TGpuParamLoadStoreTexture
+	{
+	private:
+		friend class GpuParams;
+		friend class GpuParamsCore;
+
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+		typedef typename TGpuParamTextureType<Core>::Type TextureType;
+
+	public:
+		TGpuParamLoadStoreTexture();
+		TGpuParamLoadStoreTexture(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent);
+
+		/** @copydoc TGpuDataParam::set */
+		void set(const TextureType& texture, const TextureSurface& surface);
+
+		/** @copydoc TGpuDataParam::get */
+		TextureType get();
+
+		/**	Checks if param is initialized. */
+		bool operator==(const nullptr_t &nullval) const
+		{
+			return mParamDesc == nullptr;
+		}
+
+	protected:
+		GpuParamsType mParent;
+		GpuParamObjectDesc* mParamDesc;
+	};
+
+	/** @copydoc TGpuDataParam */
+	template<bool Core>
+	class BS_CORE_EXPORT TGpuParamSampState
+	{
+	private:
+		friend class GpuParams;
+		friend class GpuParamsCore;
+
+		typedef typename TGpuParamsPtrType<Core>::Type GpuParamsType;
+		typedef typename TGpuParamSamplerStateType<Core>::Type SamplerStateType;
+
+	public:
+		TGpuParamSampState();
+		TGpuParamSampState(GpuParamObjectDesc* paramDesc, const GpuParamsType& parent);
+
+		/** @copydoc TGpuDataParam::set */
+		void set(const SamplerStateType& samplerState);
+
+		/** @copydoc TGpuDataParam::get */
+		SamplerStateType get();
+
+		/**	Checks if param is initialized. */
+		bool operator==(const nullptr_t &nullval) const
+		{
+			return mParamDesc == nullptr;
+		}
+
+	protected:
+		GpuParamsType mParent;
+		GpuParamObjectDesc* mParamDesc;
+	};
+
+	/** @} */
+
+	/** @addtogroup RenderAPI
+	 *  @{
+	 */
+
+	typedef TGpuDataParam<float, false> GpuParamFloat;
+	typedef TGpuDataParam<Vector2, false> GpuParamVec2;
+	typedef TGpuDataParam<Vector3, false> GpuParamVec3;
+	typedef TGpuDataParam<Vector4, false> GpuParamVec4;
+	typedef TGpuDataParam<int, false> GpuParamInt;
+	typedef TGpuDataParam<Vector2I, false> GpuParamVec2I;
+	typedef TGpuDataParam<Vector3I, false> GpuParamVec3I;
+	typedef TGpuDataParam<Vector4I, false> GpuParamVec4I;
+	typedef TGpuDataParam<Matrix3, false> GpuParamMat3;
+	typedef TGpuDataParam<Matrix4, false> GpuParamMat4;
+	typedef TGpuDataParam<Color, false> GpuParamColor;
+
+	typedef TGpuDataParam<float, true> GpuParamFloatCore;
+	typedef TGpuDataParam<Vector2, true> GpuParamVec2Core;
+	typedef TGpuDataParam<Vector3, true> GpuParamVec3Core;
+	typedef TGpuDataParam<Vector4, true> GpuParamVec4Core;
+	typedef TGpuDataParam<int, true> GpuParamIntCore;
+	typedef TGpuDataParam<Vector2I, true> GpuParamVec2ICore;
+	typedef TGpuDataParam<Vector3I, true> GpuParamVec3ICore;
+	typedef TGpuDataParam<Vector4I, true> GpuParamVec4ICore;
+	typedef TGpuDataParam<Matrix3, true> GpuParamMat3Core;
+	typedef TGpuDataParam<Matrix4, true> GpuParamMat4Core;
+	typedef TGpuDataParam<Color, true> GpuParamColorCore;
+
+	typedef TGpuParamStruct<false> GpuParamStruct;
+	typedef TGpuParamStruct<true> GpuParamStructCore;
+
+	typedef TGpuParamTexture<false> GpuParamTexture;
+	typedef TGpuParamTexture<true> GpuParamTextureCore;
+
+	typedef TGpuParamSampState<false> GpuParamSampState;
+	typedef TGpuParamSampState<true> GpuParamSampStateCore;
+
+	typedef TGpuParamLoadStoreTexture<false> GpuParamLoadStoreTexture;
+	typedef TGpuParamLoadStoreTexture<true> GpuParamLoadStoreTextureCore;
+
+	/** @} */
 }

+ 1 - 1
Source/BansheeCore/Include/BsGpuParams.h

@@ -118,7 +118,7 @@ namespace BansheeEngine
 		virtual void _markCoreDirty() { }
 
 		/**
-		 * @copydoc	IResourceListener::markResourcesDirty
+		 * @copydoc	IResourceListener::markListenerResourcesDirty
 		 *
 		 * @note	Internal method.
 		 */

+ 208 - 208
Source/BansheeCore/Include/BsPass.h

@@ -1,209 +1,209 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsColor.h"
-#include "BsIReflectable.h"
-#include "BsCoreObject.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Material
-	 *  @{
-	 */
-
-	/** Descriptor structure used for initializing a shader pass. */
-	struct PASS_DESC
-	{
-		BlendStatePtr blendState;
-		RasterizerStatePtr rasterizerState;
-		DepthStencilStatePtr depthStencilState;
-		UINT32 stencilRefValue;
-
-		GpuProgramPtr vertexProgram;
-		GpuProgramPtr fragmentProgram;
-		GpuProgramPtr geometryProgram;
-		GpuProgramPtr hullProgram;
-		GpuProgramPtr domainProgram;
-		GpuProgramPtr computeProgram;
-	};
-
-	/** @cond INTERNAL */
-
-	/** Descriptor structure used for initializing a core thread variant of a shader pass. */
-	struct PASS_DESC_CORE
-	{
-		SPtr<BlendStateCore> blendState;
-		SPtr<RasterizerStateCore> rasterizerState;
-		SPtr<DepthStencilStateCore> depthStencilState;
-		UINT32 stencilRefValue;
-
-		SPtr<GpuProgramCore> vertexProgram;
-		SPtr<GpuProgramCore> fragmentProgram;
-		SPtr<GpuProgramCore> geometryProgram;
-		SPtr<GpuProgramCore> hullProgram;
-		SPtr<GpuProgramCore> domainProgram;
-		SPtr<GpuProgramCore> computeProgram;
-	};
-
-	/** @endcond */
-	/** @} */
-
-	/** @addtogroup Implementation
-	 *  @{
-	 */
-
-	/** Contains all data used by a pass, templated so it may contain both core and sim thread data. */
-	template<bool Core>
-	struct TPassTypes
-	{ };
-
-	template<>
-	struct TPassTypes < false >
-	{
-		typedef BlendStatePtr BlendStateType;
-		typedef RasterizerStatePtr RasterizerStateType;
-		typedef DepthStencilStatePtr DepthStencilStateType;
-		typedef GpuProgramPtr GpuProgramType;
-		typedef PASS_DESC PassDescType;
-	};
-
-	template<>
-	struct TPassTypes < true >
-	{
-		typedef SPtr<BlendStateCore> BlendStateType;
-		typedef SPtr<RasterizerStateCore> RasterizerStateType;
-		typedef SPtr<DepthStencilStateCore> DepthStencilStateType;
-		typedef SPtr<GpuProgramCore> GpuProgramType;
-		typedef PASS_DESC_CORE PassDescType;
-	};
-
-	/**
-	 * Class defining a single pass of a technique (of a material), i.e. a single rendering call.
-	 *
-	 * Pass may contain multiple GPU programs (vertex, fragment, geometry, etc.), and a set of pipeline states (blend, 
-	 * rasterizer, etc.).
-	 *
-	 * @note	Templated so it can be used for both core and non-core versions of a pass.
-	 */
-	template<bool Core>
-	class BS_CORE_EXPORT TPass
-    {
-    public:
-		typedef typename TPassTypes<Core>::BlendStateType BlendStateType;
-		typedef typename TPassTypes<Core>::RasterizerStateType RasterizerStateType;
-		typedef typename TPassTypes<Core>::DepthStencilStateType DepthStencilStateType;
-		typedef typename TPassTypes<Core>::GpuProgramType GpuProgramType;
-		typedef typename TPassTypes<Core>::PassDescType PassDescType;
-
-		virtual ~TPass() { }
-
-        bool hasVertexProgram() const { return mData.vertexProgram != nullptr; }
-		bool hasFragmentProgram() const { return mData.fragmentProgram != nullptr; }
-		bool hasGeometryProgram() const { return mData.geometryProgram != nullptr; }
-		bool hasHullProgram() const { return mData.hullProgram != nullptr; }
-		bool hasDomainProgram() const { return mData.domainProgram != nullptr; }
-		bool hasComputeProgram() const { return mData.computeProgram != nullptr; }
-
-		/**	Returns true if this pass has some element of transparency. */
-		bool hasBlending() const;
-
-		BlendStateType getBlendState() const { return mData.blendState; }
-		RasterizerStateType getRasterizerState() const { return mData.rasterizerState; }
-		DepthStencilStateType getDepthStencilState() const { return mData.depthStencilState; }
-
-		/** Gets the stencil reference value that is used when performing operations using the stencil buffer. */
-		UINT32 getStencilRefValue() const { return mData.stencilRefValue; }
-
-		const GpuProgramType& getVertexProgram() const { return mData.vertexProgram; }
-		const GpuProgramType& getFragmentProgram() const { return mData.fragmentProgram; }
-		const GpuProgramType& getGeometryProgram() const { return mData.geometryProgram; }
-		const GpuProgramType& getHullProgram(void) const { return mData.hullProgram; }
-		const GpuProgramType& getDomainProgram(void) const { return mData.domainProgram; }
-		const GpuProgramType& getComputeProgram(void) const { return mData.computeProgram; }
-
-	protected:
-		TPass();
-		TPass(const PassDescType& desc);
-
-		PassDescType mData;
-    };
-
-	/** @} */
-
-	/** @addtogroup Material
-	 *  @{
-	 */
-	/** @cond INTERNAL */
-
-	/**
-	 * @copydoc	PassBase
-	 *
-	 * @note	Core thread.
-	 */
-	class BS_CORE_EXPORT PassCore : public CoreObjectCore, public TPass<true>
-    {
-    public:
-		virtual ~PassCore() { }
-
-		/**	Creates a new empty pass. */
-		static SPtr<PassCore> create(const PASS_DESC_CORE& desc);
-
-	protected:
-		friend class Pass;
-		friend class TechniqueCore;
-
-		PassCore() { }
-		PassCore(const PASS_DESC_CORE& desc);
-
-		/** @copydoc CoreObjectCore::syncToCore */
-		void syncToCore(const CoreSyncData& data) override;
-    };
-	/** @endcond */
-
-	/**
-	 * @copydoc	PassBase
-	 *
-	 * @note	Sim thread.
-	 */
-	class BS_CORE_EXPORT Pass : public IReflectable, public CoreObject, public TPass<false>
-    {
-    public:
-		virtual ~Pass() { }
-
-		/** Retrieves an implementation of a pass usable only from the core thread. */
-		SPtr<PassCore> getCore() const;
-
-		/**	Creates a new empty pass. */
-		static PassPtr create(const PASS_DESC& desc);
-
-	protected:
-		friend class Technique;
-
-		Pass() { }
-		Pass(const PASS_DESC& desc);
-
-		/** @copydoc CoreObject::syncToCore */
-		CoreSyncData syncToCore(FrameAlloc* allocator) override;
-
-		/** @copydoc CoreObject::createCore */
-		SPtr<CoreObjectCore> createCore() const override;
-
-		/** @copydoc CoreObject::syncToCore */
-		void getCoreDependencies(Vector<CoreObject*>& dependencies) override;
-
-		/**	Creates a new empty pass but doesn't initialize it. */
-		static PassPtr createEmpty();
-
-		/************************************************************************/
-		/* 								RTTI		                     		*/
-		/************************************************************************/
-	public:
-		friend class PassRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-    };
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsColor.h"
+#include "BsIReflectable.h"
+#include "BsCoreObject.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Material
+	 *  @{
+	 */
+
+	/** Descriptor structure used for initializing a shader pass. */
+	struct PASS_DESC
+	{
+		BlendStatePtr blendState;
+		RasterizerStatePtr rasterizerState;
+		DepthStencilStatePtr depthStencilState;
+		UINT32 stencilRefValue;
+
+		GpuProgramPtr vertexProgram;
+		GpuProgramPtr fragmentProgram;
+		GpuProgramPtr geometryProgram;
+		GpuProgramPtr hullProgram;
+		GpuProgramPtr domainProgram;
+		GpuProgramPtr computeProgram;
+	};
+
+	/** @cond INTERNAL */
+
+	/** Descriptor structure used for initializing a core thread variant of a shader pass. */
+	struct PASS_DESC_CORE
+	{
+		SPtr<BlendStateCore> blendState;
+		SPtr<RasterizerStateCore> rasterizerState;
+		SPtr<DepthStencilStateCore> depthStencilState;
+		UINT32 stencilRefValue;
+
+		SPtr<GpuProgramCore> vertexProgram;
+		SPtr<GpuProgramCore> fragmentProgram;
+		SPtr<GpuProgramCore> geometryProgram;
+		SPtr<GpuProgramCore> hullProgram;
+		SPtr<GpuProgramCore> domainProgram;
+		SPtr<GpuProgramCore> computeProgram;
+	};
+
+	/** @endcond */
+	/** @} */
+
+	/** @addtogroup Implementation
+	 *  @{
+	 */
+
+	/** Contains all data used by a pass, templated so it may contain both core and sim thread data. */
+	template<bool Core>
+	struct TPassTypes
+	{ };
+
+	template<>
+	struct TPassTypes < false >
+	{
+		typedef BlendStatePtr BlendStateType;
+		typedef RasterizerStatePtr RasterizerStateType;
+		typedef DepthStencilStatePtr DepthStencilStateType;
+		typedef GpuProgramPtr GpuProgramType;
+		typedef PASS_DESC PassDescType;
+	};
+
+	template<>
+	struct TPassTypes < true >
+	{
+		typedef SPtr<BlendStateCore> BlendStateType;
+		typedef SPtr<RasterizerStateCore> RasterizerStateType;
+		typedef SPtr<DepthStencilStateCore> DepthStencilStateType;
+		typedef SPtr<GpuProgramCore> GpuProgramType;
+		typedef PASS_DESC_CORE PassDescType;
+	};
+
+	/**
+	 * Class defining a single pass of a technique (of a material), i.e. a single rendering call.
+	 *
+	 * Pass may contain multiple GPU programs (vertex, fragment, geometry, etc.), and a set of pipeline states (blend, 
+	 * rasterizer, etc.).
+	 *
+	 * @note	Templated so it can be used for both core and non-core versions of a pass.
+	 */
+	template<bool Core>
+	class BS_CORE_EXPORT TPass
+    {
+    public:
+		typedef typename TPassTypes<Core>::BlendStateType BlendStateType;
+		typedef typename TPassTypes<Core>::RasterizerStateType RasterizerStateType;
+		typedef typename TPassTypes<Core>::DepthStencilStateType DepthStencilStateType;
+		typedef typename TPassTypes<Core>::GpuProgramType GpuProgramType;
+		typedef typename TPassTypes<Core>::PassDescType PassDescType;
+
+		virtual ~TPass() { }
+
+        bool hasVertexProgram() const { return mData.vertexProgram != nullptr; }
+		bool hasFragmentProgram() const { return mData.fragmentProgram != nullptr; }
+		bool hasGeometryProgram() const { return mData.geometryProgram != nullptr; }
+		bool hasHullProgram() const { return mData.hullProgram != nullptr; }
+		bool hasDomainProgram() const { return mData.domainProgram != nullptr; }
+		bool hasComputeProgram() const { return mData.computeProgram != nullptr; }
+
+		/**	Returns true if this pass has some element of transparency. */
+		bool hasBlending() const;
+
+		BlendStateType getBlendState() const { return mData.blendState; }
+		RasterizerStateType getRasterizerState() const { return mData.rasterizerState; }
+		DepthStencilStateType getDepthStencilState() const { return mData.depthStencilState; }
+
+		/** Gets the stencil reference value that is used when performing operations using the stencil buffer. */
+		UINT32 getStencilRefValue() const { return mData.stencilRefValue; }
+
+		const GpuProgramType& getVertexProgram() const { return mData.vertexProgram; }
+		const GpuProgramType& getFragmentProgram() const { return mData.fragmentProgram; }
+		const GpuProgramType& getGeometryProgram() const { return mData.geometryProgram; }
+		const GpuProgramType& getHullProgram(void) const { return mData.hullProgram; }
+		const GpuProgramType& getDomainProgram(void) const { return mData.domainProgram; }
+		const GpuProgramType& getComputeProgram(void) const { return mData.computeProgram; }
+
+	protected:
+		TPass();
+		TPass(const PassDescType& desc);
+
+		PassDescType mData;
+    };
+
+	/** @} */
+
+	/** @addtogroup Material
+	 *  @{
+	 */
+	/** @cond INTERNAL */
+
+	/**
+	 * @copydoc	TPass
+	 *
+	 * @note	Core thread.
+	 */
+	class BS_CORE_EXPORT PassCore : public CoreObjectCore, public TPass<true>
+    {
+    public:
+		virtual ~PassCore() { }
+
+		/**	Creates a new empty pass. */
+		static SPtr<PassCore> create(const PASS_DESC_CORE& desc);
+
+	protected:
+		friend class Pass;
+		friend class TechniqueCore;
+
+		PassCore() { }
+		PassCore(const PASS_DESC_CORE& desc);
+
+		/** @copydoc CoreObjectCore::syncToCore */
+		void syncToCore(const CoreSyncData& data) override;
+    };
+	/** @endcond */
+
+	/**
+	 * @copydoc	TPass
+	 *
+	 * @note	Sim thread.
+	 */
+	class BS_CORE_EXPORT Pass : public IReflectable, public CoreObject, public TPass<false>
+    {
+    public:
+		virtual ~Pass() { }
+
+		/** Retrieves an implementation of a pass usable only from the core thread. */
+		SPtr<PassCore> getCore() const;
+
+		/**	Creates a new empty pass. */
+		static PassPtr create(const PASS_DESC& desc);
+
+	protected:
+		friend class Technique;
+
+		Pass() { }
+		Pass(const PASS_DESC& desc);
+
+		/** @copydoc CoreObject::syncToCore */
+		CoreSyncData syncToCore(FrameAlloc* allocator) override;
+
+		/** @copydoc CoreObject::createCore */
+		SPtr<CoreObjectCore> createCore() const override;
+
+		/** @copydoc CoreObject::syncToCore */
+		void getCoreDependencies(Vector<CoreObject*>& dependencies) override;
+
+		/**	Creates a new empty pass but doesn't initialize it. */
+		static PassPtr createEmpty();
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class PassRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
+    };
+
+	/** @} */
 }

+ 487 - 487
Source/BansheeCore/Include/BsShader.h

@@ -1,488 +1,488 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsResource.h"
-#include "BsStringID.h"
-#include "BsResourceMetaData.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Material
-	 *  @{
-	 */
-
-	/**
-	 * Describes a single data (int, Vector2, etc.) shader parameter.
-	 *
-	 * @see	Shader::addParameter().
-	 */
-	struct SHADER_DATA_PARAM_DESC
-	{
-		String name;
-		String gpuVariableName;
-		GpuParamDataType type;
-		StringID rendererSemantic;
-		UINT32 arraySize;
-		UINT32 elementSize;
-		UINT32 defaultValueIdx;
-	};
-
-	/**
-	 * Describes a single object (texture, sampler state, etc.) shader parameter.
-	 *
-	 * @see	Shader::addParameter().
-	 */
-	struct SHADER_OBJECT_PARAM_DESC
-	{
-		String name;
-		Vector<String> gpuVariableNames;
-		StringID rendererSemantic;
-		GpuParamObjectType type;
-		UINT32 defaultValueIdx;
-	};
-
-	/** Describes a shader parameter block. */
-	struct SHADER_PARAM_BLOCK_DESC
-	{
-		String name;
-		bool shared;
-		StringID rendererSemantic;
-		GpuParamBlockUsage usage;
-	};
-
-	/** @} */
-
-	/** @addtogroup Implementation
-	 *  @{
-	 */
-
-	/** Structure used for initializing a shader. */
-	template<bool Core>
-	struct BS_CORE_EXPORT TSHADER_DESC
-	{
-		template<bool Core> struct TTextureType {};
-		template<> struct TTextureType < false > { typedef HTexture Type; };
-		template<> struct TTextureType < true > { typedef SPtr<TextureCore> Type; };
-
-		template<bool Core> struct TSamplerStateType {};
-		template<> struct TSamplerStateType < false > { typedef SamplerStatePtr Type; };
-		template<> struct TSamplerStateType < true > { typedef SPtr<SamplerStateCore> Type; };
-
-		typedef typename TTextureType<Core>::Type TextureType;
-		typedef typename TSamplerStateType<Core>::Type SamplerStateType;
-
-		TSHADER_DESC();
-
-		/**
-		 * Registers a new data (int, Vector2, etc.) parameter you that you may then use via Material by providing the 
-		 * parameter name. All parameters internally map to variables defined in GPU programs.
-		 *
-		 * @param[in]	name		   		The name of the parameter. Name must be unique between all data and object parameters.
-		 * @param[in]	gpuVariableName		Name of the GPU variable in the GpuProgram that the parameter corresponds with.
-		 * @param[in]	type		   		The type of the parameter, must be the same as the type in GpuProgram.
-		 * @param[in]	rendererSemantic	(optional) Semantic that allows you to specify the use of this parameter in the 
-		 *									renderer. The actual value of the semantic depends on the current Renderer and
-		 *									its supported list of semantics. Elements with renderer semantics should not be
-		 *									updated by the user, and will be updated by the renderer. These semantics will 
-		 *									also be used to determine if a shader is compatible with a specific renderer 
-		 *									or not. Value of 0 signifies the parameter is not used by the renderer.
-		 * @param[in]	arraySize	   		(optional) If the parameter is an array, the number of elements in the array. 
-		 *									Size of 1 means its not an array.
-		 * @param[in]	elementSize	   		(optional) Size of an individual element in the array, in bytes. You only need 
-		 *									to set this if you are setting variable length parameters, like structs.
-		 * @param[in]	defaultValue		(optional) Pointer to the buffer containing the default value for this parameter
-		 *									(initial value that will be set when a material is initialized with this shader). 
-		 *									The provided buffer must be of the correct size (depending on the element type 
-		 *									and array size).
-		 *
-		 * @note	If multiple parameters are given with the same name but different types behavior is undefined.
-		 */
-		void addParameter(const String& name, const String& gpuVariableName, GpuParamDataType type, StringID rendererSemantic = StringID::NONE,
-			UINT32 arraySize = 1, UINT32 elementSize = 0, UINT8* defaultValue = nullptr);
-
-		/**
-		 * Registers a new object (texture, sampler state, etc.) parameter you that you may then use via Material by 
-		 * providing the parameter name. All parameters internally map to variables defined in GPU programs. Multiple GPU 
-		 * variables may be mapped to a single parameter in which case the first variable actually found in the program will
-		 * be used while others will be ignored.
-		 *
-		 * @param[in]	name				The name of the parameter. Name must be unique between all data and object parameters.
-		 * @param[in]	gpuVariableName		Name of the GPU variable in the GpuProgram that the parameter corresponds with.
-		 * @param[in]	type		   		The type of the parameter, must be the same as the type in GpuProgram.
-		 * @param[in]	rendererSemantic	(optional) Semantic that allows you to specify the use of this parameter in the 
-		 *									renderer. The actual value of the semantic depends on the current Renderer and 
-		 *									its supported list of semantics. Elements with renderer semantics should not be 
-		 *									updated by the user, and will be updated by the renderer. These semantics will 
-		 *									also be used to determine if a shader is compatible with a specific renderer or 
-		 *									not. Value of 0 signifies the parameter is not used by the renderer.
-		 *
-		 * @note	
-		 * If multiple parameters are given with the same name but different types behavior is undefined. You are allowed 
-		 * to call this method multiple times in order to map multiple GPU variable names to a single parameter, but the 
-		 * default value (if any) will only be recognized on the first call. Mapping multiple GPU variables to a single 
-		 * parameter is useful when you are defining a shader that supports techniques across different render systems 
-		 * where GPU variable names for the same parameters might differ.
-		 */
-		void addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, StringID rendererSemantic = StringID::NONE);
-
-		/**
-		 * @see	SHADER_DESC::addParameter(const String&, const String&, GpuParamObjectType, StringID)
-		 *
-		 * @note	
-		 * Specialized version of addParameter that accepts a default sampler value that will be used for initializing the 
-		 * object parameter upon Material creation. Default sampler value is only valid if the object type is one of the 
-		 * sampler types.
-		 */
-		void addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, 
-			const SamplerStateType& defaultValue, StringID rendererSemantic = StringID::NONE);
-
-		/**
-		 * @see	SHADER_DESC::addParameter(const String&, const String&, GpuParamObjectType, StringID)
-		 *
-		 * @note	
-		 * Specialized version of addParameter that accepts a default texture value that will be used for initializing the 
-		 * object parameter upon Material creation. Default texture value is only valid if the object type is one of the 
-		 * texture types.
-		 */
-		void addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, 
-			const TextureType& defaultValue, StringID rendererSemantic = StringID::NONE);
-
-		/**
-		 * Changes parameters of a parameter block with the specified name.
-		 *
-		 * @param[in]	name				Name of the parameter block. This should correspond with the name specified in 
-		 *									the GPU program code.
-		 * @param[in]	shared				If parameter block is marked as shared it will not be automatically created by 
-		 *									the Material. You will need to create it elsewhere and then assign it manually.
-		 * @param[in]	usage				Specified how often do we plan on modifying the buffer, which determines how is 
-		 *									the buffer internally stored for best performance.
-		 * @param[in]	rendererSemantic	(optional) Semantic that allows you to specify the use of this parameter block 
-		 *									in the renderer. The actual value of the semantic depends on the current 
-		 *									Renderer and its supported list of semantics. Elements with a renderer semantic
-		 *									will not have their parameter block automatically created (similar to "shared" 
-		 *									argument), but instead a Renderer will create an assign it instead. Be aware 
-		 *									that renderers have strict policies on what and how are parameters stored in the 
-		 *									buffer and you will need to respect them. If you don't respect them your shader 
-		 *									will be deemed incompatible and won't be used. Value of 0 signifies the parameter
-		 *									block is not used by the renderer.
-		 */
-		void setParamBlockAttribs(const String& name, bool shared, GpuParamBlockUsage usage, StringID rendererSemantic = StringID::NONE);
-
-		/**
-		 * Sorting type to use when performing sort in the render queue. Default value is sort front to back which causes
-		 * least overdraw and is preferable. Transparent objects need to be sorted back to front. You may also specify no 
-		 * sorting and the elements will be rendered in the order they were added to the render queue.
-		 */
-		QueueSortType queueSortType;
-
-		/**
-		 * Priority that allows you to control in what order are your shaders rendered. See QueuePriority for a list of 
-		 * initial values. Shaders with higher priority will be rendered before shaders with lower priority, and 
-		 * additionally render queue will only sort elements within the same priority group.
-		 *
-		 * @note	
-		 * This is useful when you want all your opaque objects to be rendered before you start drawing your transparent 
-		 * ones. Or to render your overlays after everything else. Values provided in QueuePriority are just for general 
-		 * guidance and feel free to increase them or decrease them for finer tuning. (e.g. QueuePriority::Opaque + 1).
-		 */
-		INT32 queuePriority;
-
-		/**
-		 * Enables or disables separable passes. When separable passes are disabled all shader passes will be executed in a
-		 * sequence one after another. If it is disabled the renderer is free to mix and match passes from different 
-		 * objects to achieve best performance. (They will still be executed in sequence, but some other object may be 
-		 * rendered in-between passes)
-		 *
-		 * @note	Shaders with transparency generally can't be separable, while opaque can.
-		 */
-		bool separablePasses;
-
-		/** Flags that let the renderer know how should it interpret the shader. */
-		UINT32 flags;
-
-		Map<String, SHADER_DATA_PARAM_DESC> dataParams;
-		Map<String, SHADER_OBJECT_PARAM_DESC> textureParams;
-		Map<String, SHADER_OBJECT_PARAM_DESC> bufferParams;
-		Map<String, SHADER_OBJECT_PARAM_DESC> samplerParams;
-		Map<String, SHADER_PARAM_BLOCK_DESC> paramBlocks;
-
-		Vector<UINT8> dataDefaultValues;
-		Vector<SamplerStateType> samplerDefaultValues;
-		Vector<TextureType> textureDefaultValues;
-
-	private:
-		/**
-		 * @copydoc	addParameter(const String&, const String&, GpuParamObjectType, StringID)
-		 *
-		 * @note	Common method shared by different addParameter overloads.
-		 */
-		void addParameterInternal(const String& name, const String& gpuVariableName, GpuParamObjectType type, StringID rendererSemantic, UINT32 defaultValueIdx);
-	};
-
-	/**
-	 * Shader represents a collection of techniques. They are used in Materials, which can be considered as instances of a 
-	 * Shader. Multiple materials may share the same shader but provide different parameters to it.
-	 *
-	 * Shader will always choose the first supported technique based on the current render system, render manager and other
-	 * properties. So make sure to add most important techniques first so you make sure they are used if they are supported.
-	 *
-	 * @note	Templated version of Shader used for implementing both sim and core thread variants.
-	 */
-	template<bool Core>
-	class BS_CORE_EXPORT TShader
-	{
-	public:
-		template<bool Core> struct TTechniqueType {};
-		template<> struct TTechniqueType < false > { typedef Technique Type; };
-		template<> struct TTechniqueType < true > { typedef TechniqueCore Type; };
-
-		typedef typename TTechniqueType<Core>::Type TechniqueType;
-		typedef typename TSHADER_DESC<Core>::TextureType TextureType;
-		typedef typename TSHADER_DESC<Core>::SamplerStateType SamplerStateType;
-
-		TShader() { }
-		TShader(const String& name, const TSHADER_DESC<Core>& desc, const Vector<SPtr<TechniqueType>>& techniques, UINT32 id);
-		virtual ~TShader();
-	
-		/** Returns the total number of techniques in this shader. */
-		UINT32 getNumTechniques() const { return (UINT32)mTechniques.size(); }
-
-		/**
-		 * Gets the best supported technique based on current render and other systems. Returns null if not a single 
-		 * technique is supported.
-		 */
-		SPtr<TechniqueType> getBestTechnique() const;
-
-		/**
-		 * Returns currently active queue sort type.
-		 *
-		 * @see		SHADER_DESC::queueSortType
-		 */
-		QueueSortType getQueueSortType() const { return mDesc.queueSortType; }
-
-		/**
-		 * Returns currently active queue priority.
-		 *
-		 * @see		SHADER_DESC::queuePriority
-		 */
-		INT32 getQueuePriority() const { return mDesc.queuePriority; }
-
-		/**
-		 * Returns if separable passes are allowed.
-		 *
-		 * @see		SHADER_DESC::separablePasses
-		 */
-		bool getAllowSeparablePasses() const { return mDesc.separablePasses; }
-
-		/**
-		 * Returns flags that control how the renderer interprets the shader. Actual interpretation of the flags depends on 
-		 * the active renderer.
-		 */
-		UINT32 getFlags() const { return mDesc.flags; }
-
-		/** Returns type of the parameter with the specified name. Throws exception if the parameter doesn't exist. */
-		GpuParamType getParamType(const String& name) const;
-
-		/**
-		 * Returns description for a data parameter with the specified name. Throws exception if the parameter doesn't exist.
-		 */
-		const SHADER_DATA_PARAM_DESC& getDataParamDesc(const String& name) const;
-
-		/**
-		 * Returns description for a texture parameter with the specified name. Throws exception if the parameter doesn't 
-		 * exist.
-		 */
-		const SHADER_OBJECT_PARAM_DESC& getTextureParamDesc(const String& name) const;
-
-		/**
-		 * Returns description for a sampler parameter with the specified name. Throws exception if the parameter doesn't 
-		 * exist.
-		 */
-		const SHADER_OBJECT_PARAM_DESC& getSamplerParamDesc(const String& name) const;
-
-		/**
-		 * Returns description for a buffer parameter with the specified name. Throws exception if the parameter doesn't 
-		 * exist.
-		 */
-		const SHADER_OBJECT_PARAM_DESC& getBufferParamDesc(const String& name) const;
-
-		/** Checks if the parameter with the specified name exists, and is a data parameter. */
-		bool hasDataParam(const String& name) const;
-
-		/**	Checks if the parameter with the specified name exists, and is a texture parameter. */
-		bool hasTextureParam(const String& name) const;
-
-		/** Checks if the parameter with the specified name exists, and is a sampler parameter. */
-		bool hasSamplerParam(const String& name) const;
-
-		/** Checks if the parameter with the specified name exists, and is a buffer parameter. */
-		bool hasBufferParam(const String& name) const;
-
-		/**	Returns a map of all data parameters in the shader. */
-		const Map<String, SHADER_DATA_PARAM_DESC>& getDataParams() const { return mDesc.dataParams; }
-
-		/**	Returns a map of all texture parameters in the shader. */
-		const Map<String, SHADER_OBJECT_PARAM_DESC>& getTextureParams() const { return mDesc.textureParams; }
-
-		/**	Returns a map of all buffer parameters in the shader. */
-		const Map<String, SHADER_OBJECT_PARAM_DESC>& getBufferParams() const { return mDesc.bufferParams; }
-
-		/** Returns a map of all sampler parameters in the shader. */
-		const Map<String, SHADER_OBJECT_PARAM_DESC>& getSamplerParams() const { return mDesc.samplerParams; }
-
-		/** Returns a map of all parameter blocks. */
-		const Map<String, SHADER_PARAM_BLOCK_DESC>& getParamBlocks() const { return mDesc.paramBlocks; }
-
-		/**
-		 * Returns a default texture for a parameter that has the specified default value index (retrieved from the 
-		 * parameters descriptor).
-		 */
-		TextureType getDefaultTexture(UINT32 index) const;
-
-		/**
-		 * Returns a default sampler state for a parameter that has the specified default value index (retrieved from the 
-		 * parameters descriptor).
-		 */
-		SamplerStateType getDefaultSampler(UINT32 index) const;
-
-		/**
-		 * Returns a pointer to the internal buffer containing the default value for a data parameter that has the
-		 * specified default value index (retrieved from the parameters descriptor).
-		 */
-		UINT8* getDefaultValue(UINT32 index) const;
-
-		/** Returns the unique shader ID. */
-		UINT32 getId() const { return mId; }
-
-	protected:
-		String mName;
-		TSHADER_DESC<Core> mDesc;
-		Vector<SPtr<TechniqueType>> mTechniques;
-		UINT32 mId;
-	};
-
-	/** @} */
-
-	/** @addtogroup Material
-	 *  @{
-	 */
-
-	/** @cond INTERNAL */
-
-	typedef TSHADER_DESC<true> SHADER_DESC_CORE;
-	
-	/** @copydoc ShaderBase */
-	class BS_CORE_EXPORT ShaderCore : public CoreObjectCore, public TShader<true>
-	{
-	public:
-		/** @copydoc Shader::create */
-		static SPtr<ShaderCore> create(const String& name, const SHADER_DESC_CORE& desc, const Vector<SPtr<TechniqueCore>>& techniques);
-
-	protected:
-		friend class Shader;
-
-		ShaderCore(const String& name, const SHADER_DESC_CORE& desc, const Vector<SPtr<TechniqueCore>>& techniques, UINT32 id);
-
-		static std::atomic<UINT32> mNextShaderId;
-	};
-
-	/** @endcond */
-
-	typedef TSHADER_DESC<false> SHADER_DESC;
-
-	/** @copydoc ShaderBase */
-	class BS_CORE_EXPORT Shader : public Resource, public TShader<false>
-	{
-	public:
-		/** Retrieves an implementation of a shader usable only from the core thread. */
-		SPtr<ShaderCore> getCore() const;
-
-		/**
-		 * Sets a list include file paths that are referenced by this shader.
-		 *
-		 * @note	
-		 * This is not used directly by the shader as includes are expected to be processed during GPU program and state 
-		 * creation, but it may be referenced by higher layers for various purposes.
-		 */
-		void setIncludeFiles(const Vector<String>& includes);
-
-		/**	Checks is the provided object type a sampler. */
-		static bool isSampler(GpuParamObjectType type);
-
-		/**	Checks is the provided object type a texture. */
-		static bool isTexture(GpuParamObjectType type);
-
-		/** Checks is the provided object type a buffer. */
-		static bool isBuffer(GpuParamObjectType type);
-
-		/**
-		 * Returns the size in bytes for a specific data type.
-		 *
-		 * @note	Returns 0 for variable size types like structures.
-		 */
-		static UINT32 getDataParamSize(GpuParamDataType type);
-
-		/**	Creates a new shader resource using the provided descriptor and techniques. */
-		static HShader create(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques);
-
-		/**	Returns a shader object but doesn't initialize it. */
-		static ShaderPtr createEmpty();
-
-	public: // ***** INTERNAL ******
-		/** @cond INTERNAL */
-
-		/**
-		 * Creates a new shader object using the provided descriptor and techniques.
-		 *
-		 * @note	Internal method.
-		 */
-		static ShaderPtr _createPtr(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques);
-
-		/** @endcond */
-
-	private:
-		Shader(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques, UINT32 id);
-
-		/** @copydoc CoreObject::getCoreDependencies */
-		void getCoreDependencies(Vector<CoreObject*>& dependencies) override;
-
-		/** @copydoc CoreObject::createCore */
-		SPtr<CoreObjectCore> createCore() const override;
-
-		/** Converts a sim thread version of the shader descriptor to a core thread version. */
-		SHADER_DESC_CORE convertDesc(const SHADER_DESC& desc) const;
-
-	private:
-		/************************************************************************/
-		/* 								RTTI		                     		*/
-		/************************************************************************/
-		Shader() { }
-
-	public:
-		friend class ShaderRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	/** @cond INTERNAL */
-
-	/** Shader specific resource meta-data containing information about referenced include files. */
-	class BS_CORE_EXPORT ShaderMetaData : public ResourceMetaData
-	{
-	public:
-		Vector<String> includes;
-
-		/************************************************************************/
-		/* 								SERIALIZATION                      		*/
-		/************************************************************************/
-	public:
-		friend class ShaderMetaDataRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	/** @endcond */
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsResource.h"
+#include "BsStringID.h"
+#include "BsResourceMetaData.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Material
+	 *  @{
+	 */
+
+	/**
+	 * Describes a single data (int, Vector2, etc.) shader parameter.
+	 *
+	 * @see	Shader::addParameter().
+	 */
+	struct SHADER_DATA_PARAM_DESC
+	{
+		String name;
+		String gpuVariableName;
+		GpuParamDataType type;
+		StringID rendererSemantic;
+		UINT32 arraySize;
+		UINT32 elementSize;
+		UINT32 defaultValueIdx;
+	};
+
+	/**
+	 * Describes a single object (texture, sampler state, etc.) shader parameter.
+	 *
+	 * @see	Shader::addParameter().
+	 */
+	struct SHADER_OBJECT_PARAM_DESC
+	{
+		String name;
+		Vector<String> gpuVariableNames;
+		StringID rendererSemantic;
+		GpuParamObjectType type;
+		UINT32 defaultValueIdx;
+	};
+
+	/** Describes a shader parameter block. */
+	struct SHADER_PARAM_BLOCK_DESC
+	{
+		String name;
+		bool shared;
+		StringID rendererSemantic;
+		GpuParamBlockUsage usage;
+	};
+
+	/** @} */
+
+	/** @addtogroup Implementation
+	 *  @{
+	 */
+
+	/** Structure used for initializing a shader. */
+	template<bool Core>
+	struct BS_CORE_EXPORT TSHADER_DESC
+	{
+		template<bool Core> struct TTextureType {};
+		template<> struct TTextureType < false > { typedef HTexture Type; };
+		template<> struct TTextureType < true > { typedef SPtr<TextureCore> Type; };
+
+		template<bool Core> struct TSamplerStateType {};
+		template<> struct TSamplerStateType < false > { typedef SamplerStatePtr Type; };
+		template<> struct TSamplerStateType < true > { typedef SPtr<SamplerStateCore> Type; };
+
+		typedef typename TTextureType<Core>::Type TextureType;
+		typedef typename TSamplerStateType<Core>::Type SamplerStateType;
+
+		TSHADER_DESC();
+
+		/**
+		 * Registers a new data (int, Vector2, etc.) parameter you that you may then use via Material by providing the 
+		 * parameter name. All parameters internally map to variables defined in GPU programs.
+		 *
+		 * @param[in]	name		   		The name of the parameter. Name must be unique between all data and object parameters.
+		 * @param[in]	gpuVariableName		Name of the GPU variable in the GpuProgram that the parameter corresponds with.
+		 * @param[in]	type		   		The type of the parameter, must be the same as the type in GpuProgram.
+		 * @param[in]	rendererSemantic	(optional) Semantic that allows you to specify the use of this parameter in the 
+		 *									renderer. The actual value of the semantic depends on the current Renderer and
+		 *									its supported list of semantics. Elements with renderer semantics should not be
+		 *									updated by the user, and will be updated by the renderer. These semantics will 
+		 *									also be used to determine if a shader is compatible with a specific renderer 
+		 *									or not. Value of 0 signifies the parameter is not used by the renderer.
+		 * @param[in]	arraySize	   		(optional) If the parameter is an array, the number of elements in the array. 
+		 *									Size of 1 means its not an array.
+		 * @param[in]	elementSize	   		(optional) Size of an individual element in the array, in bytes. You only need 
+		 *									to set this if you are setting variable length parameters, like structs.
+		 * @param[in]	defaultValue		(optional) Pointer to the buffer containing the default value for this parameter
+		 *									(initial value that will be set when a material is initialized with this shader). 
+		 *									The provided buffer must be of the correct size (depending on the element type 
+		 *									and array size).
+		 *
+		 * @note	If multiple parameters are given with the same name but different types behavior is undefined.
+		 */
+		void addParameter(const String& name, const String& gpuVariableName, GpuParamDataType type, StringID rendererSemantic = StringID::NONE,
+			UINT32 arraySize = 1, UINT32 elementSize = 0, UINT8* defaultValue = nullptr);
+
+		/**
+		 * Registers a new object (texture, sampler state, etc.) parameter you that you may then use via Material by 
+		 * providing the parameter name. All parameters internally map to variables defined in GPU programs. Multiple GPU 
+		 * variables may be mapped to a single parameter in which case the first variable actually found in the program will
+		 * be used while others will be ignored.
+		 *
+		 * @param[in]	name				The name of the parameter. Name must be unique between all data and object parameters.
+		 * @param[in]	gpuVariableName		Name of the GPU variable in the GpuProgram that the parameter corresponds with.
+		 * @param[in]	type		   		The type of the parameter, must be the same as the type in GpuProgram.
+		 * @param[in]	rendererSemantic	(optional) Semantic that allows you to specify the use of this parameter in the 
+		 *									renderer. The actual value of the semantic depends on the current Renderer and 
+		 *									its supported list of semantics. Elements with renderer semantics should not be 
+		 *									updated by the user, and will be updated by the renderer. These semantics will 
+		 *									also be used to determine if a shader is compatible with a specific renderer or 
+		 *									not. Value of 0 signifies the parameter is not used by the renderer.
+		 *
+		 * @note	
+		 * If multiple parameters are given with the same name but different types behavior is undefined. You are allowed 
+		 * to call this method multiple times in order to map multiple GPU variable names to a single parameter, but the 
+		 * default value (if any) will only be recognized on the first call. Mapping multiple GPU variables to a single 
+		 * parameter is useful when you are defining a shader that supports techniques across different render systems 
+		 * where GPU variable names for the same parameters might differ.
+		 */
+		void addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, StringID rendererSemantic = StringID::NONE);
+
+		/**
+		 * @see	SHADER_DESC::addParameter(const String&, const String&, GpuParamObjectType, StringID)
+		 *
+		 * @note	
+		 * Specialized version of addParameter that accepts a default sampler value that will be used for initializing the 
+		 * object parameter upon Material creation. Default sampler value is only valid if the object type is one of the 
+		 * sampler types.
+		 */
+		void addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, 
+			const SamplerStateType& defaultValue, StringID rendererSemantic = StringID::NONE);
+
+		/**
+		 * @see	SHADER_DESC::addParameter(const String&, const String&, GpuParamObjectType, StringID)
+		 *
+		 * @note	
+		 * Specialized version of addParameter that accepts a default texture value that will be used for initializing the 
+		 * object parameter upon Material creation. Default texture value is only valid if the object type is one of the 
+		 * texture types.
+		 */
+		void addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, 
+			const TextureType& defaultValue, StringID rendererSemantic = StringID::NONE);
+
+		/**
+		 * Changes parameters of a parameter block with the specified name.
+		 *
+		 * @param[in]	name				Name of the parameter block. This should correspond with the name specified in 
+		 *									the GPU program code.
+		 * @param[in]	shared				If parameter block is marked as shared it will not be automatically created by 
+		 *									the Material. You will need to create it elsewhere and then assign it manually.
+		 * @param[in]	usage				Specified how often do we plan on modifying the buffer, which determines how is 
+		 *									the buffer internally stored for best performance.
+		 * @param[in]	rendererSemantic	(optional) Semantic that allows you to specify the use of this parameter block 
+		 *									in the renderer. The actual value of the semantic depends on the current 
+		 *									Renderer and its supported list of semantics. Elements with a renderer semantic
+		 *									will not have their parameter block automatically created (similar to "shared" 
+		 *									argument), but instead a Renderer will create an assign it instead. Be aware 
+		 *									that renderers have strict policies on what and how are parameters stored in the 
+		 *									buffer and you will need to respect them. If you don't respect them your shader 
+		 *									will be deemed incompatible and won't be used. Value of 0 signifies the parameter
+		 *									block is not used by the renderer.
+		 */
+		void setParamBlockAttribs(const String& name, bool shared, GpuParamBlockUsage usage, StringID rendererSemantic = StringID::NONE);
+
+		/**
+		 * Sorting type to use when performing sort in the render queue. Default value is sort front to back which causes
+		 * least overdraw and is preferable. Transparent objects need to be sorted back to front. You may also specify no 
+		 * sorting and the elements will be rendered in the order they were added to the render queue.
+		 */
+		QueueSortType queueSortType;
+
+		/**
+		 * Priority that allows you to control in what order are your shaders rendered. See QueuePriority for a list of 
+		 * initial values. Shaders with higher priority will be rendered before shaders with lower priority, and 
+		 * additionally render queue will only sort elements within the same priority group.
+		 *
+		 * @note	
+		 * This is useful when you want all your opaque objects to be rendered before you start drawing your transparent 
+		 * ones. Or to render your overlays after everything else. Values provided in QueuePriority are just for general 
+		 * guidance and feel free to increase them or decrease them for finer tuning. (e.g. QueuePriority::Opaque + 1).
+		 */
+		INT32 queuePriority;
+
+		/**
+		 * Enables or disables separable passes. When separable passes are disabled all shader passes will be executed in a
+		 * sequence one after another. If it is disabled the renderer is free to mix and match passes from different 
+		 * objects to achieve best performance. (They will still be executed in sequence, but some other object may be 
+		 * rendered in-between passes)
+		 *
+		 * @note	Shaders with transparency generally can't be separable, while opaque can.
+		 */
+		bool separablePasses;
+
+		/** Flags that let the renderer know how should it interpret the shader. */
+		UINT32 flags;
+
+		Map<String, SHADER_DATA_PARAM_DESC> dataParams;
+		Map<String, SHADER_OBJECT_PARAM_DESC> textureParams;
+		Map<String, SHADER_OBJECT_PARAM_DESC> bufferParams;
+		Map<String, SHADER_OBJECT_PARAM_DESC> samplerParams;
+		Map<String, SHADER_PARAM_BLOCK_DESC> paramBlocks;
+
+		Vector<UINT8> dataDefaultValues;
+		Vector<SamplerStateType> samplerDefaultValues;
+		Vector<TextureType> textureDefaultValues;
+
+	private:
+		/**
+		 * @copydoc	addParameter(const String&, const String&, GpuParamObjectType, StringID)
+		 *
+		 * @note	Common method shared by different addParameter overloads.
+		 */
+		void addParameterInternal(const String& name, const String& gpuVariableName, GpuParamObjectType type, StringID rendererSemantic, UINT32 defaultValueIdx);
+	};
+
+	/**
+	 * Shader represents a collection of techniques. They are used in Materials, which can be considered as instances of a 
+	 * Shader. Multiple materials may share the same shader but provide different parameters to it.
+	 *
+	 * Shader will always choose the first supported technique based on the current render system, render manager and other
+	 * properties. So make sure to add most important techniques first so you make sure they are used if they are supported.
+	 *
+	 * @note	Templated version of Shader used for implementing both sim and core thread variants.
+	 */
+	template<bool Core>
+	class BS_CORE_EXPORT TShader
+	{
+	public:
+		template<bool Core> struct TTechniqueType {};
+		template<> struct TTechniqueType < false > { typedef Technique Type; };
+		template<> struct TTechniqueType < true > { typedef TechniqueCore Type; };
+
+		typedef typename TTechniqueType<Core>::Type TechniqueType;
+		typedef typename TSHADER_DESC<Core>::TextureType TextureType;
+		typedef typename TSHADER_DESC<Core>::SamplerStateType SamplerStateType;
+
+		TShader() { }
+		TShader(const String& name, const TSHADER_DESC<Core>& desc, const Vector<SPtr<TechniqueType>>& techniques, UINT32 id);
+		virtual ~TShader();
+	
+		/** Returns the total number of techniques in this shader. */
+		UINT32 getNumTechniques() const { return (UINT32)mTechniques.size(); }
+
+		/**
+		 * Gets the best supported technique based on current render and other systems. Returns null if not a single 
+		 * technique is supported.
+		 */
+		SPtr<TechniqueType> getBestTechnique() const;
+
+		/**
+		 * Returns currently active queue sort type.
+		 *
+		 * @see		SHADER_DESC::queueSortType
+		 */
+		QueueSortType getQueueSortType() const { return mDesc.queueSortType; }
+
+		/**
+		 * Returns currently active queue priority.
+		 *
+		 * @see		SHADER_DESC::queuePriority
+		 */
+		INT32 getQueuePriority() const { return mDesc.queuePriority; }
+
+		/**
+		 * Returns if separable passes are allowed.
+		 *
+		 * @see		SHADER_DESC::separablePasses
+		 */
+		bool getAllowSeparablePasses() const { return mDesc.separablePasses; }
+
+		/**
+		 * Returns flags that control how the renderer interprets the shader. Actual interpretation of the flags depends on 
+		 * the active renderer.
+		 */
+		UINT32 getFlags() const { return mDesc.flags; }
+
+		/** Returns type of the parameter with the specified name. Throws exception if the parameter doesn't exist. */
+		GpuParamType getParamType(const String& name) const;
+
+		/**
+		 * Returns description for a data parameter with the specified name. Throws exception if the parameter doesn't exist.
+		 */
+		const SHADER_DATA_PARAM_DESC& getDataParamDesc(const String& name) const;
+
+		/**
+		 * Returns description for a texture parameter with the specified name. Throws exception if the parameter doesn't 
+		 * exist.
+		 */
+		const SHADER_OBJECT_PARAM_DESC& getTextureParamDesc(const String& name) const;
+
+		/**
+		 * Returns description for a sampler parameter with the specified name. Throws exception if the parameter doesn't 
+		 * exist.
+		 */
+		const SHADER_OBJECT_PARAM_DESC& getSamplerParamDesc(const String& name) const;
+
+		/**
+		 * Returns description for a buffer parameter with the specified name. Throws exception if the parameter doesn't 
+		 * exist.
+		 */
+		const SHADER_OBJECT_PARAM_DESC& getBufferParamDesc(const String& name) const;
+
+		/** Checks if the parameter with the specified name exists, and is a data parameter. */
+		bool hasDataParam(const String& name) const;
+
+		/**	Checks if the parameter with the specified name exists, and is a texture parameter. */
+		bool hasTextureParam(const String& name) const;
+
+		/** Checks if the parameter with the specified name exists, and is a sampler parameter. */
+		bool hasSamplerParam(const String& name) const;
+
+		/** Checks if the parameter with the specified name exists, and is a buffer parameter. */
+		bool hasBufferParam(const String& name) const;
+
+		/**	Returns a map of all data parameters in the shader. */
+		const Map<String, SHADER_DATA_PARAM_DESC>& getDataParams() const { return mDesc.dataParams; }
+
+		/**	Returns a map of all texture parameters in the shader. */
+		const Map<String, SHADER_OBJECT_PARAM_DESC>& getTextureParams() const { return mDesc.textureParams; }
+
+		/**	Returns a map of all buffer parameters in the shader. */
+		const Map<String, SHADER_OBJECT_PARAM_DESC>& getBufferParams() const { return mDesc.bufferParams; }
+
+		/** Returns a map of all sampler parameters in the shader. */
+		const Map<String, SHADER_OBJECT_PARAM_DESC>& getSamplerParams() const { return mDesc.samplerParams; }
+
+		/** Returns a map of all parameter blocks. */
+		const Map<String, SHADER_PARAM_BLOCK_DESC>& getParamBlocks() const { return mDesc.paramBlocks; }
+
+		/**
+		 * Returns a default texture for a parameter that has the specified default value index (retrieved from the 
+		 * parameters descriptor).
+		 */
+		TextureType getDefaultTexture(UINT32 index) const;
+
+		/**
+		 * Returns a default sampler state for a parameter that has the specified default value index (retrieved from the 
+		 * parameters descriptor).
+		 */
+		SamplerStateType getDefaultSampler(UINT32 index) const;
+
+		/**
+		 * Returns a pointer to the internal buffer containing the default value for a data parameter that has the
+		 * specified default value index (retrieved from the parameters descriptor).
+		 */
+		UINT8* getDefaultValue(UINT32 index) const;
+
+		/** Returns the unique shader ID. */
+		UINT32 getId() const { return mId; }
+
+	protected:
+		String mName;
+		TSHADER_DESC<Core> mDesc;
+		Vector<SPtr<TechniqueType>> mTechniques;
+		UINT32 mId;
+	};
+
+	/** @} */
+
+	/** @addtogroup Material
+	 *  @{
+	 */
+
+	/** @cond INTERNAL */
+
+	typedef TSHADER_DESC<true> SHADER_DESC_CORE;
+	
+	/** @copydoc TShader */
+	class BS_CORE_EXPORT ShaderCore : public CoreObjectCore, public TShader<true>
+	{
+	public:
+		/** @copydoc Shader::create */
+		static SPtr<ShaderCore> create(const String& name, const SHADER_DESC_CORE& desc, const Vector<SPtr<TechniqueCore>>& techniques);
+
+	protected:
+		friend class Shader;
+
+		ShaderCore(const String& name, const SHADER_DESC_CORE& desc, const Vector<SPtr<TechniqueCore>>& techniques, UINT32 id);
+
+		static std::atomic<UINT32> mNextShaderId;
+	};
+
+	/** @endcond */
+
+	typedef TSHADER_DESC<false> SHADER_DESC;
+
+	/** @copydoc TShader */
+	class BS_CORE_EXPORT Shader : public Resource, public TShader<false>
+	{
+	public:
+		/** Retrieves an implementation of a shader usable only from the core thread. */
+		SPtr<ShaderCore> getCore() const;
+
+		/**
+		 * Sets a list include file paths that are referenced by this shader.
+		 *
+		 * @note	
+		 * This is not used directly by the shader as includes are expected to be processed during GPU program and state 
+		 * creation, but it may be referenced by higher layers for various purposes.
+		 */
+		void setIncludeFiles(const Vector<String>& includes);
+
+		/**	Checks is the provided object type a sampler. */
+		static bool isSampler(GpuParamObjectType type);
+
+		/**	Checks is the provided object type a texture. */
+		static bool isTexture(GpuParamObjectType type);
+
+		/** Checks is the provided object type a buffer. */
+		static bool isBuffer(GpuParamObjectType type);
+
+		/**
+		 * Returns the size in bytes for a specific data type.
+		 *
+		 * @note	Returns 0 for variable size types like structures.
+		 */
+		static UINT32 getDataParamSize(GpuParamDataType type);
+
+		/**	Creates a new shader resource using the provided descriptor and techniques. */
+		static HShader create(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques);
+
+		/**	Returns a shader object but doesn't initialize it. */
+		static ShaderPtr createEmpty();
+
+	public: // ***** INTERNAL ******
+		/** @cond INTERNAL */
+
+		/**
+		 * Creates a new shader object using the provided descriptor and techniques.
+		 *
+		 * @note	Internal method.
+		 */
+		static ShaderPtr _createPtr(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques);
+
+		/** @endcond */
+
+	private:
+		Shader(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques, UINT32 id);
+
+		/** @copydoc CoreObject::getCoreDependencies */
+		void getCoreDependencies(Vector<CoreObject*>& dependencies) override;
+
+		/** @copydoc CoreObject::createCore */
+		SPtr<CoreObjectCore> createCore() const override;
+
+		/** Converts a sim thread version of the shader descriptor to a core thread version. */
+		SHADER_DESC_CORE convertDesc(const SHADER_DESC& desc) const;
+
+	private:
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+		Shader() { }
+
+	public:
+		friend class ShaderRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
+	};
+
+	/** @cond INTERNAL */
+
+	/** Shader specific resource meta-data containing information about referenced include files. */
+	class BS_CORE_EXPORT ShaderMetaData : public ResourceMetaData
+	{
+	public:
+		Vector<String> includes;
+
+		/************************************************************************/
+		/* 								SERIALIZATION                      		*/
+		/************************************************************************/
+	public:
+		friend class ShaderMetaDataRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
+	};
+
+	/** @endcond */
+	/** @} */
 }

+ 696 - 698
Source/BansheeCore/Source/Win32/BsWin32FolderMonitor.cpp

@@ -1,699 +1,697 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "Win32/BsWin32FolderMonitor.h"
-#include "BsFileSystem.h"
-#include "BsException.h"
-
-#include "BsDebug.h"
-
-#include <windows.h>
-
-namespace BansheeEngine
-{
-	enum class MonitorState
-	{
-		Inactive,
-		Starting,
-		Monitoring,
-		Shutdown,
-		Shutdown2
-	};
-
-	class WorkerFunc
-	{
-	public:
-		WorkerFunc(FolderMonitor* owner);
-
-		void operator()();
-
-	private:
-		FolderMonitor* mOwner;
-	};
-
-	struct FolderMonitor::FolderWatchInfo
-	{
-		FolderWatchInfo(const Path& folderToMonitor, HANDLE dirHandle, bool monitorSubdirectories, DWORD monitorFlags);
-		~FolderWatchInfo();
-
-		void startMonitor(HANDLE compPortHandle);
-		void stopMonitor(HANDLE compPortHandle);
-
-		static const UINT32 READ_BUFFER_SIZE = 65536;
-
-		Path mFolderToMonitor;
-		HANDLE mDirHandle;
-		OVERLAPPED mOverlapped;
-		MonitorState mState;
-		UINT8 mBuffer[READ_BUFFER_SIZE];
-		DWORD mBufferSize;
-		bool mMonitorSubdirectories;
-		DWORD mMonitorFlags;
-		DWORD mReadError;
-
-		WString mCachedOldFileName; // Used during rename notifications as they are handled in two steps
-
-		BS_MUTEX(mStatusMutex)
-		BS_THREAD_SYNCHRONISER(mStartStopEvent)
-	};
-
-	FolderMonitor::FolderWatchInfo::FolderWatchInfo(const Path& folderToMonitor, HANDLE dirHandle, bool monitorSubdirectories, DWORD monitorFlags)
-		:mFolderToMonitor(folderToMonitor), mDirHandle(dirHandle), mState(MonitorState::Inactive), mBufferSize(0),
-		mMonitorSubdirectories(monitorSubdirectories), mMonitorFlags(monitorFlags), mReadError(0)
-	{
-		memset(&mOverlapped, 0, sizeof(mOverlapped));
-	}
-
-	FolderMonitor::FolderWatchInfo::~FolderWatchInfo()
-	{
-		assert(mState == MonitorState::Inactive);
-
-		stopMonitor(0);
-	}
-
-	void FolderMonitor::FolderWatchInfo::startMonitor(HANDLE compPortHandle)
-	{
-		if(mState != MonitorState::Inactive)
-			return; // Already monitoring
-
-		{
-			BS_LOCK_MUTEX_NAMED(mStatusMutex, lock);
-
-			mState = MonitorState::Starting;
-			PostQueuedCompletionStatus(compPortHandle, sizeof(this), (ULONG_PTR)this, &mOverlapped);
-
-			while(mState != MonitorState::Monitoring)
-				BS_THREAD_WAIT(mStartStopEvent, mStatusMutex, lock);
-		}
-
-		if(mReadError != ERROR_SUCCESS)
-		{
-			{
-				BS_LOCK_MUTEX(mStatusMutex);
-				mState = MonitorState::Inactive;
-			}
-
-			BS_EXCEPT(InternalErrorException, "Failed to start folder monitor on folder \"" + 
-				mFolderToMonitor.toString() + "\" because ReadDirectoryChangesW failed.");
-		}
-	}
-
-	void FolderMonitor::FolderWatchInfo::stopMonitor(HANDLE compPortHandle)
-	{
-		if(mState != MonitorState::Inactive)
-		{
-			BS_LOCK_MUTEX_NAMED(mStatusMutex, lock);
-
-			mState = MonitorState::Shutdown;
-			PostQueuedCompletionStatus(compPortHandle, sizeof(this), (ULONG_PTR)this, &mOverlapped);
-
-			while(mState != MonitorState::Inactive)
-				BS_THREAD_WAIT(mStartStopEvent, mStatusMutex, lock);
-		}
-
-		if(mDirHandle != INVALID_HANDLE_VALUE)
-		{			
-			CloseHandle(mDirHandle);
-			mDirHandle = INVALID_HANDLE_VALUE;
-		}
-	}
-
-	class FolderMonitor::FileNotifyInfo
-	{
-	public:
-		FileNotifyInfo(UINT8* notifyBuffer, DWORD bufferSize)
-		:mBuffer(notifyBuffer), mBufferSize(bufferSize)
-		{
-			mCurrentRecord = (PFILE_NOTIFY_INFORMATION)mBuffer;
-		}
-
-		bool getNext();
-	
-		DWORD	getAction() const;
-		WString getFileName() const;
-		WString getFileNameWithPath(const Path& rootPath) const;
-
-	protected:
-		UINT8* mBuffer;
-		DWORD mBufferSize;
-		PFILE_NOTIFY_INFORMATION mCurrentRecord;
-	};
-
-	bool FolderMonitor::FileNotifyInfo::getNext()
-	{
-		if(mCurrentRecord && mCurrentRecord->NextEntryOffset != 0)
-		{
-			PFILE_NOTIFY_INFORMATION oldRecord = mCurrentRecord;
-			mCurrentRecord = (PFILE_NOTIFY_INFORMATION) ((UINT8*)mCurrentRecord + mCurrentRecord->NextEntryOffset);
-
-			if((DWORD)((UINT8*)mCurrentRecord - mBuffer) > mBufferSize)
-			{
-				// Gone out of range, something bad happened
-				assert(false);
-
-				mCurrentRecord = oldRecord;
-			}
-					
-			return (mCurrentRecord != oldRecord);
-		}
-
-		return false;
-	}
-
-	DWORD FolderMonitor::FileNotifyInfo::getAction() const
-	{ 
-		assert(mCurrentRecord != nullptr);
-
-		if(mCurrentRecord)
-			return mCurrentRecord->Action;
-
-		return 0;
-	}
-
-	WString FolderMonitor::FileNotifyInfo::getFileName() const
-	{
-		if(mCurrentRecord)
-		{
-			wchar_t fileNameBuffer[32768 + 1] = {0};
-
-			memcpy(fileNameBuffer, mCurrentRecord->FileName, 
-					std::min(DWORD(32768 * sizeof(wchar_t)), mCurrentRecord->FileNameLength));
-		
-			return WString(fileNameBuffer);
-		}
-
-		return WString();
-	}		
-
-	WString FolderMonitor::FileNotifyInfo::getFileNameWithPath(const Path& rootPath) const
-	{
-		Path fullPath = rootPath;
-		return fullPath.append(getFileName()).toWString();
-	}
-
-	enum class FileActionType
-	{
-		Added,
-		Removed,
-		Modified,
-		Renamed
-	};
-
-	struct FileAction
-	{
-		static FileAction* createAdded(const WString& fileName)
-		{
-			UINT8* bytes = (UINT8*)bs_alloc((UINT32)(sizeof(FileAction) + (fileName.size() + 1) * sizeof(WString::value_type)));
-
-			FileAction* action = (FileAction*)bytes;
-			bytes += sizeof(FileAction);
-
-			action->oldName = nullptr;
-			action->newName = (WString::value_type*)bytes;
-			action->type = FileActionType::Added;
-
-			memcpy(action->newName, fileName.data(), fileName.size() * sizeof(WString::value_type));
-			action->newName[fileName.size()] = L'\0';
-			action->lastSize = 0;
-			action->checkForWriteStarted = false;
-
-			return action;
-		}
-
-		static FileAction* createRemoved(const WString& fileName)
-		{
-			UINT8* bytes = (UINT8*)bs_alloc((UINT32)(sizeof(FileAction) + (fileName.size() + 1) * sizeof(WString::value_type)));
-
-			FileAction* action = (FileAction*)bytes;
-			bytes += sizeof(FileAction);
-
-			action->oldName = nullptr;
-			action->newName = (WString::value_type*)bytes;
-			action->type = FileActionType::Removed;
-
-			memcpy(action->newName, fileName.data(), fileName.size() * sizeof(WString::value_type));
-			action->newName[fileName.size()] = L'\0';
-			action->lastSize = 0;
-			action->checkForWriteStarted = false;
-
-			return action;
-		}
-
-		static FileAction* createModified(const WString& fileName)
-		{
-			UINT8* bytes = (UINT8*)bs_alloc((UINT32)(sizeof(FileAction) + (fileName.size() + 1) * sizeof(WString::value_type)));
-
-			FileAction* action = (FileAction*)bytes;
-			bytes += sizeof(FileAction);
-
-			action->oldName = nullptr;
-			action->newName = (WString::value_type*)bytes;
-			action->type = FileActionType::Modified;
-
-			memcpy(action->newName, fileName.data(), fileName.size() * sizeof(WString::value_type));
-			action->newName[fileName.size()] = L'\0';
-			action->lastSize = 0;
-			action->checkForWriteStarted = false;
-
-			return action;
-		}
-
-		static FileAction* createRenamed(const WString& oldFilename, const WString& newfileName)
-		{
-			UINT8* bytes = (UINT8*)bs_alloc((UINT32)(sizeof(FileAction) + 
-				(oldFilename.size() + newfileName.size() + 2) * sizeof(WString::value_type)));
-
-			FileAction* action = (FileAction*)bytes;
-			bytes += sizeof(FileAction);
-
-			action->oldName = (WString::value_type*)bytes;
-			bytes += (oldFilename.size() + 1) * sizeof(WString::value_type);
-
-			action->newName = (WString::value_type*)bytes;
-			action->type = FileActionType::Modified;
-
-			memcpy(action->oldName, oldFilename.data(), oldFilename.size() * sizeof(WString::value_type));
-			action->oldName[oldFilename.size()] = L'\0';
-
-			memcpy(action->newName, newfileName.data(), newfileName.size() * sizeof(WString::value_type));
-			action->newName[newfileName.size()] = L'\0';
-			action->lastSize = 0;
-			action->checkForWriteStarted = false;
-
-			return action;
-		}
-
-		static void destroy(FileAction* action)
-		{
-			bs_free(action);
-		}
-
-		WString::value_type* oldName;
-		WString::value_type* newName;
-		FileActionType type;
-
-		UINT64 lastSize;
-		bool checkForWriteStarted;
-	};
-
-	struct FolderMonitor::Pimpl
-	{
-		Vector<FolderWatchInfo*> mFoldersToWatch;
-		HANDLE mCompPortHandle;
-
-		Queue<FileAction*> mFileActions;
-		List<FileAction*> mActiveFileActions;
-
-		BS_MUTEX(mMainMutex);
-		BS_THREAD_TYPE* mWorkerThread;
-	};
-
-	FolderMonitor::FolderMonitor()
-	{
-		mPimpl = bs_new<Pimpl>();
-		mPimpl->mWorkerThread = nullptr;
-		mPimpl->mCompPortHandle = nullptr;
-	}
-
-	FolderMonitor::~FolderMonitor()
-	{
-		stopMonitorAll();
-
-		// No need for mutex since we know worker thread is shut down by now
-		while(!mPimpl->mFileActions.empty())
-		{
-			FileAction* action = mPimpl->mFileActions.front();
-			mPimpl->mFileActions.pop();
-
-			FileAction::destroy(action);
-		}
-
-		bs_delete(mPimpl);
-	}
-
-	void FolderMonitor::startMonitor(const Path& folderPath, bool subdirectories, FolderChange changeFilter)
-	{
-		if(!FileSystem::isDirectory(folderPath))
-		{
-			BS_EXCEPT(InvalidParametersException, "Provided path \"" + folderPath.toString() + "\" is not a directory");
-		}
-
-		WString extendedFolderPath = L"\\\\?\\" + folderPath.toWString(Path::PathType::Windows);
-		HANDLE dirHandle = CreateFileW(extendedFolderPath.c_str(), FILE_LIST_DIRECTORY,
-			FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING,
-			FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr);
-
-		if(dirHandle == INVALID_HANDLE_VALUE)
-		{
-			BS_EXCEPT(InternalErrorException, "Failed to open folder \"" + folderPath.toString() + "\" for monitoring. Error code: " + toString((UINT64)GetLastError()));
-		}
-
-		DWORD filterFlags = 0;
-
-		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::FileName) != 0)
-			filterFlags |= FILE_NOTIFY_CHANGE_FILE_NAME;
-
-		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::DirName) != 0)
-			filterFlags |= FILE_NOTIFY_CHANGE_DIR_NAME;
-
-		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::Attributes) != 0)
-			filterFlags |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
-
-		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::Size) != 0)
-			filterFlags |= FILE_NOTIFY_CHANGE_SIZE;
-
-		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::LastWrite) != 0)
-			filterFlags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
-
-		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::LastAccess) != 0)
-			filterFlags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
-
-		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::Creation) != 0)
-			filterFlags |= FILE_NOTIFY_CHANGE_CREATION;
-
-		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::Security) != 0)
-			filterFlags |= FILE_NOTIFY_CHANGE_SECURITY;
-
-		mPimpl->mFoldersToWatch.push_back(bs_new<FolderWatchInfo>(folderPath, dirHandle, subdirectories, filterFlags));
-		FolderWatchInfo* watchInfo = mPimpl->mFoldersToWatch.back();
-
-		mPimpl->mCompPortHandle = CreateIoCompletionPort(dirHandle, mPimpl->mCompPortHandle, (ULONG_PTR)watchInfo, 0);
-
-		if(mPimpl->mCompPortHandle == nullptr)
-		{
-			mPimpl->mFoldersToWatch.erase(mPimpl->mFoldersToWatch.end() - 1);
-			bs_delete(watchInfo);
-			BS_EXCEPT(InternalErrorException, "Failed to open completition port for folder monitoring. Error code: " + toString((UINT64)GetLastError()));
-		}
-
-		if(mPimpl->mWorkerThread == nullptr)
-		{
-			BS_THREAD_CREATE(t, (std::bind(&FolderMonitor::workerThreadMain, this)));
-			mPimpl->mWorkerThread = t;
-
-			if(mPimpl->mWorkerThread == nullptr)
-			{
-				mPimpl->mFoldersToWatch.erase(mPimpl->mFoldersToWatch.end() - 1);
-				bs_delete(watchInfo);
-				BS_EXCEPT(InternalErrorException, "Failed to create a new worker thread for folder monitoring");
-			}
-		}
-
-		if(mPimpl->mWorkerThread != nullptr)
-		{
-			try
-			{
-				watchInfo->startMonitor(mPimpl->mCompPortHandle);
-			}
-			catch (Exception* e)
-			{
-				mPimpl->mFoldersToWatch.erase(mPimpl->mFoldersToWatch.end() - 1);
-				bs_delete(watchInfo);
-				throw(e);
-			}
-		}
-		else
-		{
-			mPimpl->mFoldersToWatch.erase(mPimpl->mFoldersToWatch.end() - 1);
-			bs_delete(watchInfo);
-			BS_EXCEPT(InternalErrorException, "Failed to create a new worker thread for folder monitoring");
-		}
-	}
-
-	void FolderMonitor::stopMonitor(const Path& folderPath)
-	{
-		auto findIter = std::find_if(mPimpl->mFoldersToWatch.begin(), mPimpl->mFoldersToWatch.end(), 
-			[&](const FolderWatchInfo* x) { return x->mFolderToMonitor == folderPath; });
-
-		if(findIter != mPimpl->mFoldersToWatch.end())
-		{
-			FolderWatchInfo* watchInfo = *findIter;
-
-			watchInfo->stopMonitor(mPimpl->mCompPortHandle);
-			bs_delete(watchInfo);
-
-			mPimpl->mFoldersToWatch.erase(findIter);
-		}
-
-		if(mPimpl->mFoldersToWatch.size() == 0)
-			stopMonitorAll();
-	}
-
-	void FolderMonitor::stopMonitorAll()
-	{
-		for(auto& watchInfo : mPimpl->mFoldersToWatch)
-		{
-			watchInfo->stopMonitor(mPimpl->mCompPortHandle);
-
-			{
-				// Note: Need this mutex to ensure worker thread is done with watchInfo.
-				// Even though we wait for a condition variable from the worker thread in stopMonitor,
-				// that doesn't mean the worker thread is done with the condition variable
-				// (which is stored inside watchInfo)
-				BS_LOCK_MUTEX(mPimpl->mMainMutex); 
-				bs_delete(watchInfo);
-			}
-		}
-
-		mPimpl->mFoldersToWatch.clear();
-
-		if(mPimpl->mWorkerThread != nullptr)
-		{
-			PostQueuedCompletionStatus(mPimpl->mCompPortHandle, 0, 0, nullptr);
-
-			mPimpl->mWorkerThread->join();
-			BS_THREAD_DESTROY(mPimpl->mWorkerThread);
-			mPimpl->mWorkerThread = nullptr;
-		}
-
-		if(mPimpl->mCompPortHandle != nullptr)
-		{
-			CloseHandle(mPimpl->mCompPortHandle);
-			mPimpl->mCompPortHandle = nullptr;
-		}
-	}
-
-	void FolderMonitor::workerThreadMain()
-	{
-		FolderWatchInfo* watchInfo = nullptr;
-
-		do 
-		{
-			DWORD numBytes;
-			LPOVERLAPPED overlapped;
-
-			if(!GetQueuedCompletionStatus(mPimpl->mCompPortHandle, &numBytes, (PULONG_PTR) &watchInfo, &overlapped, INFINITE))
-			{
-				assert(false);
-				// TODO: Folder handle was lost most likely. Not sure how to deal with that. Shutdown watch on this folder and cleanup?
-			}
-
-			if(watchInfo != nullptr)
-			{
-				MonitorState state;
-
-				{
-					BS_LOCK_MUTEX(watchInfo->mStatusMutex);
-					state = watchInfo->mState;
-				}
-
-				switch(state)
-				{
-				case MonitorState::Starting:
-					if(!ReadDirectoryChangesW(watchInfo->mDirHandle, watchInfo->mBuffer, FolderWatchInfo::READ_BUFFER_SIZE,
-						watchInfo->mMonitorSubdirectories, watchInfo->mMonitorFlags, &watchInfo->mBufferSize, &watchInfo->mOverlapped, nullptr))
-					{
-						assert(false); // TODO - Possibly the buffer was too small?
-						watchInfo->mReadError = GetLastError();
-					}
-					else
-					{
-						watchInfo->mReadError = ERROR_SUCCESS;
-
-						{
-							BS_LOCK_MUTEX(watchInfo->mStatusMutex);
-							watchInfo->mState = MonitorState::Monitoring;
-						}
-					}
-
-					BS_THREAD_NOTIFY_ONE(watchInfo->mStartStopEvent);
-
-					break;
-				case MonitorState::Monitoring:
-					{
-						FileNotifyInfo info(watchInfo->mBuffer, FolderWatchInfo::READ_BUFFER_SIZE);
-						handleNotifications(info, *watchInfo);
-
-						if(!ReadDirectoryChangesW(watchInfo->mDirHandle, watchInfo->mBuffer, FolderWatchInfo::READ_BUFFER_SIZE,
-							watchInfo->mMonitorSubdirectories, watchInfo->mMonitorFlags, &watchInfo->mBufferSize, &watchInfo->mOverlapped, nullptr))
-						{
-							assert(false); // TODO: Failed during normal operation, possibly the buffer was too small. Shutdown watch on this folder and cleanup?
-							watchInfo->mReadError = GetLastError();
-						}
-						else
-						{
-							watchInfo->mReadError = ERROR_SUCCESS;
-						}
-					}
-					break;
-				case MonitorState::Shutdown:
-					if(watchInfo->mDirHandle != INVALID_HANDLE_VALUE)
-					{
-						CloseHandle(watchInfo->mDirHandle);
-						watchInfo->mDirHandle = INVALID_HANDLE_VALUE;
-
-						{
-							BS_LOCK_MUTEX(watchInfo->mStatusMutex);
-							watchInfo->mState = MonitorState::Shutdown2;
-						}
-					}
-					else
-					{
-						{
-							BS_LOCK_MUTEX(watchInfo->mStatusMutex);
-							watchInfo->mState = MonitorState::Inactive;
-						}
-
-						{
-							BS_LOCK_MUTEX(mPimpl->mMainMutex); // Ensures that we don't delete "watchInfo" before this thread is done with mStartStopEvent
-							BS_THREAD_NOTIFY_ONE(watchInfo->mStartStopEvent);
-						}
-					}
-
-					break;
-				case MonitorState::Shutdown2:
-					if(watchInfo->mDirHandle != INVALID_HANDLE_VALUE)
-					{
-						// Handle is still open? Try again.
-						CloseHandle(watchInfo->mDirHandle);
-						watchInfo->mDirHandle = INVALID_HANDLE_VALUE;
-					}
-					else
-					{
-						{
-							BS_LOCK_MUTEX(watchInfo->mStatusMutex);
-							watchInfo->mState = MonitorState::Inactive;
-						}
-
-						{
-							BS_LOCK_MUTEX(mPimpl->mMainMutex); // Ensures that we don't delete "watchInfo" before this thread is done with mStartStopEvent
-							BS_THREAD_NOTIFY_ONE(watchInfo->mStartStopEvent);
-						}
-					}
-
-					break;
-				}
-			}
-
-		} while (watchInfo != nullptr);
-	}
-
-	void FolderMonitor::handleNotifications(FileNotifyInfo& notifyInfo, FolderWatchInfo& watchInfo)
-	{
-		Vector<FileAction*> mActions;
-
-		do
-		{
-			WString fullPath = notifyInfo.getFileNameWithPath(watchInfo.mFolderToMonitor);
-
-			// Ignore notifications about hidden files
-			if ((GetFileAttributesW(fullPath.c_str()) & FILE_ATTRIBUTE_HIDDEN) != 0)
-				continue;
-
-			switch(notifyInfo.getAction())
-			{
-			case FILE_ACTION_ADDED:
-					mActions.push_back(FileAction::createAdded(fullPath));
-				break;
-			case FILE_ACTION_REMOVED:
-					mActions.push_back(FileAction::createRemoved(fullPath));
-				break;
-			case FILE_ACTION_MODIFIED:
-					mActions.push_back(FileAction::createModified(fullPath));
-				break;
-			case FILE_ACTION_RENAMED_OLD_NAME:
-					watchInfo.mCachedOldFileName = fullPath;
-				break;
-			case FILE_ACTION_RENAMED_NEW_NAME:
-					mActions.push_back(FileAction::createRenamed(watchInfo.mCachedOldFileName, fullPath));
-				break;
-			}
-    
-		} while(notifyInfo.getNext());
-
-		{
-			BS_LOCK_MUTEX(mPimpl->mMainMutex);
-
-			for(auto& action : mActions)
-				mPimpl->mFileActions.push(action);
-		}
-	}
-
-	void FolderMonitor::_update()
-	{
-		{
-			BS_LOCK_MUTEX(mPimpl->mMainMutex);
-
-			while (!mPimpl->mFileActions.empty())
-			{
-				FileAction* action = mPimpl->mFileActions.front();
-				mPimpl->mFileActions.pop();
-
-				mPimpl->mActiveFileActions.push_back(action);
-			}
-		}
-
-		for (auto iter = mPimpl->mActiveFileActions.begin(); iter != mPimpl->mActiveFileActions.end();)
-		{
-			FileAction* action = *iter;
-			
-			// Reported file actions might still be in progress (i.e. something might still be writing to those files).
-			// Sadly there doesn't seem to be a way to properly determine when those files are done being written, so instead
-			// we check for at least a couple of frames if the file's size hasn't changed before reporting a file action.
-			// This takes care of most of the issues and avoids reporting partially written files in almost all cases.
-			if (FileSystem::exists(action->newName))
-			{
-				UINT64 size = FileSystem::getFileSize(action->newName);
-				if (!action->checkForWriteStarted)
-				{
-					action->checkForWriteStarted = true;
-					action->lastSize = size;
-
-					++iter;
-					continue;
-				}
-				else
-				{
-					if (action->lastSize != size)
-					{
-						action->lastSize = size;
-						++iter;
-						continue;
-					}
-				}
-			}
-
-			switch (action->type)
-			{
-			case FileActionType::Added:
-				if (!onAdded.empty())
-					onAdded(Path(action->newName));
-				break;
-			case FileActionType::Removed:
-				if (!onRemoved.empty())
-					onRemoved(Path(action->newName));
-				break;
-			case FileActionType::Modified:
-				if (!onModified.empty())
-					onModified(Path(action->newName));
-				break;
-			case FileActionType::Renamed:
-				if (!onRenamed.empty())
-					onRenamed(Path(action->oldName), Path(action->newName));
-				break;
-			}
-
-			mPimpl->mActiveFileActions.erase(iter++);
-			FileAction::destroy(action);
-		}
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "Win32/BsWin32FolderMonitor.h"
+#include "BsFileSystem.h"
+#include "BsException.h"
+
+#include <windows.h>
+
+namespace BansheeEngine
+{
+	enum class MonitorState
+	{
+		Inactive,
+		Starting,
+		Monitoring,
+		Shutdown,
+		Shutdown2
+	};
+
+	class WorkerFunc
+	{
+	public:
+		WorkerFunc(FolderMonitor* owner);
+
+		void operator()();
+
+	private:
+		FolderMonitor* mOwner;
+	};
+
+	struct FolderMonitor::FolderWatchInfo
+	{
+		FolderWatchInfo(const Path& folderToMonitor, HANDLE dirHandle, bool monitorSubdirectories, DWORD monitorFlags);
+		~FolderWatchInfo();
+
+		void startMonitor(HANDLE compPortHandle);
+		void stopMonitor(HANDLE compPortHandle);
+
+		static const UINT32 READ_BUFFER_SIZE = 65536;
+
+		Path mFolderToMonitor;
+		HANDLE mDirHandle;
+		OVERLAPPED mOverlapped;
+		MonitorState mState;
+		UINT8 mBuffer[READ_BUFFER_SIZE];
+		DWORD mBufferSize;
+		bool mMonitorSubdirectories;
+		DWORD mMonitorFlags;
+		DWORD mReadError;
+
+		WString mCachedOldFileName; // Used during rename notifications as they are handled in two steps
+
+		BS_MUTEX(mStatusMutex)
+		BS_THREAD_SYNCHRONISER(mStartStopEvent)
+	};
+
+	FolderMonitor::FolderWatchInfo::FolderWatchInfo(const Path& folderToMonitor, HANDLE dirHandle, bool monitorSubdirectories, DWORD monitorFlags)
+		:mFolderToMonitor(folderToMonitor), mDirHandle(dirHandle), mState(MonitorState::Inactive), mBufferSize(0),
+		mMonitorSubdirectories(monitorSubdirectories), mMonitorFlags(monitorFlags), mReadError(0)
+	{
+		memset(&mOverlapped, 0, sizeof(mOverlapped));
+	}
+
+	FolderMonitor::FolderWatchInfo::~FolderWatchInfo()
+	{
+		assert(mState == MonitorState::Inactive);
+
+		stopMonitor(0);
+	}
+
+	void FolderMonitor::FolderWatchInfo::startMonitor(HANDLE compPortHandle)
+	{
+		if(mState != MonitorState::Inactive)
+			return; // Already monitoring
+
+		{
+			BS_LOCK_MUTEX_NAMED(mStatusMutex, lock);
+
+			mState = MonitorState::Starting;
+			PostQueuedCompletionStatus(compPortHandle, sizeof(this), (ULONG_PTR)this, &mOverlapped);
+
+			while(mState != MonitorState::Monitoring)
+				BS_THREAD_WAIT(mStartStopEvent, mStatusMutex, lock);
+		}
+
+		if(mReadError != ERROR_SUCCESS)
+		{
+			{
+				BS_LOCK_MUTEX(mStatusMutex);
+				mState = MonitorState::Inactive;
+			}
+
+			BS_EXCEPT(InternalErrorException, "Failed to start folder monitor on folder \"" + 
+				mFolderToMonitor.toString() + "\" because ReadDirectoryChangesW failed.");
+		}
+	}
+
+	void FolderMonitor::FolderWatchInfo::stopMonitor(HANDLE compPortHandle)
+	{
+		if(mState != MonitorState::Inactive)
+		{
+			BS_LOCK_MUTEX_NAMED(mStatusMutex, lock);
+
+			mState = MonitorState::Shutdown;
+			PostQueuedCompletionStatus(compPortHandle, sizeof(this), (ULONG_PTR)this, &mOverlapped);
+
+			while(mState != MonitorState::Inactive)
+				BS_THREAD_WAIT(mStartStopEvent, mStatusMutex, lock);
+		}
+
+		if(mDirHandle != INVALID_HANDLE_VALUE)
+		{			
+			CloseHandle(mDirHandle);
+			mDirHandle = INVALID_HANDLE_VALUE;
+		}
+	}
+
+	class FolderMonitor::FileNotifyInfo
+	{
+	public:
+		FileNotifyInfo(UINT8* notifyBuffer, DWORD bufferSize)
+		:mBuffer(notifyBuffer), mBufferSize(bufferSize)
+		{
+			mCurrentRecord = (PFILE_NOTIFY_INFORMATION)mBuffer;
+		}
+
+		bool getNext();
+	
+		DWORD	getAction() const;
+		WString getFileName() const;
+		WString getFileNameWithPath(const Path& rootPath) const;
+
+	protected:
+		UINT8* mBuffer;
+		DWORD mBufferSize;
+		PFILE_NOTIFY_INFORMATION mCurrentRecord;
+	};
+
+	bool FolderMonitor::FileNotifyInfo::getNext()
+	{
+		if(mCurrentRecord && mCurrentRecord->NextEntryOffset != 0)
+		{
+			PFILE_NOTIFY_INFORMATION oldRecord = mCurrentRecord;
+			mCurrentRecord = (PFILE_NOTIFY_INFORMATION) ((UINT8*)mCurrentRecord + mCurrentRecord->NextEntryOffset);
+
+			if((DWORD)((UINT8*)mCurrentRecord - mBuffer) > mBufferSize)
+			{
+				// Gone out of range, something bad happened
+				assert(false);
+
+				mCurrentRecord = oldRecord;
+			}
+					
+			return (mCurrentRecord != oldRecord);
+		}
+
+		return false;
+	}
+
+	DWORD FolderMonitor::FileNotifyInfo::getAction() const
+	{ 
+		assert(mCurrentRecord != nullptr);
+
+		if(mCurrentRecord)
+			return mCurrentRecord->Action;
+
+		return 0;
+	}
+
+	WString FolderMonitor::FileNotifyInfo::getFileName() const
+	{
+		if(mCurrentRecord)
+		{
+			wchar_t fileNameBuffer[32768 + 1] = {0};
+
+			memcpy(fileNameBuffer, mCurrentRecord->FileName, 
+					std::min(DWORD(32768 * sizeof(wchar_t)), mCurrentRecord->FileNameLength));
+		
+			return WString(fileNameBuffer);
+		}
+
+		return WString();
+	}		
+
+	WString FolderMonitor::FileNotifyInfo::getFileNameWithPath(const Path& rootPath) const
+	{
+		Path fullPath = rootPath;
+		return fullPath.append(getFileName()).toWString();
+	}
+
+	enum class FileActionType
+	{
+		Added,
+		Removed,
+		Modified,
+		Renamed
+	};
+
+	struct FileAction
+	{
+		static FileAction* createAdded(const WString& fileName)
+		{
+			UINT8* bytes = (UINT8*)bs_alloc((UINT32)(sizeof(FileAction) + (fileName.size() + 1) * sizeof(WString::value_type)));
+
+			FileAction* action = (FileAction*)bytes;
+			bytes += sizeof(FileAction);
+
+			action->oldName = nullptr;
+			action->newName = (WString::value_type*)bytes;
+			action->type = FileActionType::Added;
+
+			memcpy(action->newName, fileName.data(), fileName.size() * sizeof(WString::value_type));
+			action->newName[fileName.size()] = L'\0';
+			action->lastSize = 0;
+			action->checkForWriteStarted = false;
+
+			return action;
+		}
+
+		static FileAction* createRemoved(const WString& fileName)
+		{
+			UINT8* bytes = (UINT8*)bs_alloc((UINT32)(sizeof(FileAction) + (fileName.size() + 1) * sizeof(WString::value_type)));
+
+			FileAction* action = (FileAction*)bytes;
+			bytes += sizeof(FileAction);
+
+			action->oldName = nullptr;
+			action->newName = (WString::value_type*)bytes;
+			action->type = FileActionType::Removed;
+
+			memcpy(action->newName, fileName.data(), fileName.size() * sizeof(WString::value_type));
+			action->newName[fileName.size()] = L'\0';
+			action->lastSize = 0;
+			action->checkForWriteStarted = false;
+
+			return action;
+		}
+
+		static FileAction* createModified(const WString& fileName)
+		{
+			UINT8* bytes = (UINT8*)bs_alloc((UINT32)(sizeof(FileAction) + (fileName.size() + 1) * sizeof(WString::value_type)));
+
+			FileAction* action = (FileAction*)bytes;
+			bytes += sizeof(FileAction);
+
+			action->oldName = nullptr;
+			action->newName = (WString::value_type*)bytes;
+			action->type = FileActionType::Modified;
+
+			memcpy(action->newName, fileName.data(), fileName.size() * sizeof(WString::value_type));
+			action->newName[fileName.size()] = L'\0';
+			action->lastSize = 0;
+			action->checkForWriteStarted = false;
+
+			return action;
+		}
+
+		static FileAction* createRenamed(const WString& oldFilename, const WString& newfileName)
+		{
+			UINT8* bytes = (UINT8*)bs_alloc((UINT32)(sizeof(FileAction) + 
+				(oldFilename.size() + newfileName.size() + 2) * sizeof(WString::value_type)));
+
+			FileAction* action = (FileAction*)bytes;
+			bytes += sizeof(FileAction);
+
+			action->oldName = (WString::value_type*)bytes;
+			bytes += (oldFilename.size() + 1) * sizeof(WString::value_type);
+
+			action->newName = (WString::value_type*)bytes;
+			action->type = FileActionType::Modified;
+
+			memcpy(action->oldName, oldFilename.data(), oldFilename.size() * sizeof(WString::value_type));
+			action->oldName[oldFilename.size()] = L'\0';
+
+			memcpy(action->newName, newfileName.data(), newfileName.size() * sizeof(WString::value_type));
+			action->newName[newfileName.size()] = L'\0';
+			action->lastSize = 0;
+			action->checkForWriteStarted = false;
+
+			return action;
+		}
+
+		static void destroy(FileAction* action)
+		{
+			bs_free(action);
+		}
+
+		WString::value_type* oldName;
+		WString::value_type* newName;
+		FileActionType type;
+
+		UINT64 lastSize;
+		bool checkForWriteStarted;
+	};
+
+	struct FolderMonitor::Pimpl
+	{
+		Vector<FolderWatchInfo*> mFoldersToWatch;
+		HANDLE mCompPortHandle;
+
+		Queue<FileAction*> mFileActions;
+		List<FileAction*> mActiveFileActions;
+
+		BS_MUTEX(mMainMutex);
+		BS_THREAD_TYPE* mWorkerThread;
+	};
+
+	FolderMonitor::FolderMonitor()
+	{
+		mPimpl = bs_new<Pimpl>();
+		mPimpl->mWorkerThread = nullptr;
+		mPimpl->mCompPortHandle = nullptr;
+	}
+
+	FolderMonitor::~FolderMonitor()
+	{
+		stopMonitorAll();
+
+		// No need for mutex since we know worker thread is shut down by now
+		while(!mPimpl->mFileActions.empty())
+		{
+			FileAction* action = mPimpl->mFileActions.front();
+			mPimpl->mFileActions.pop();
+
+			FileAction::destroy(action);
+		}
+
+		bs_delete(mPimpl);
+	}
+
+	void FolderMonitor::startMonitor(const Path& folderPath, bool subdirectories, FolderChange changeFilter)
+	{
+		if(!FileSystem::isDirectory(folderPath))
+		{
+			BS_EXCEPT(InvalidParametersException, "Provided path \"" + folderPath.toString() + "\" is not a directory");
+		}
+
+		WString extendedFolderPath = L"\\\\?\\" + folderPath.toWString(Path::PathType::Windows);
+		HANDLE dirHandle = CreateFileW(extendedFolderPath.c_str(), FILE_LIST_DIRECTORY,
+			FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING,
+			FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr);
+
+		if(dirHandle == INVALID_HANDLE_VALUE)
+		{
+			BS_EXCEPT(InternalErrorException, "Failed to open folder \"" + folderPath.toString() + "\" for monitoring. Error code: " + toString((UINT64)GetLastError()));
+		}
+
+		DWORD filterFlags = 0;
+
+		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::FileName) != 0)
+			filterFlags |= FILE_NOTIFY_CHANGE_FILE_NAME;
+
+		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::DirName) != 0)
+			filterFlags |= FILE_NOTIFY_CHANGE_DIR_NAME;
+
+		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::Attributes) != 0)
+			filterFlags |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
+
+		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::Size) != 0)
+			filterFlags |= FILE_NOTIFY_CHANGE_SIZE;
+
+		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::LastWrite) != 0)
+			filterFlags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
+
+		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::LastAccess) != 0)
+			filterFlags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
+
+		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::Creation) != 0)
+			filterFlags |= FILE_NOTIFY_CHANGE_CREATION;
+
+		if((((UINT32)changeFilter) & (UINT32)BansheeEngine::FolderChange::Security) != 0)
+			filterFlags |= FILE_NOTIFY_CHANGE_SECURITY;
+
+		mPimpl->mFoldersToWatch.push_back(bs_new<FolderWatchInfo>(folderPath, dirHandle, subdirectories, filterFlags));
+		FolderWatchInfo* watchInfo = mPimpl->mFoldersToWatch.back();
+
+		mPimpl->mCompPortHandle = CreateIoCompletionPort(dirHandle, mPimpl->mCompPortHandle, (ULONG_PTR)watchInfo, 0);
+
+		if(mPimpl->mCompPortHandle == nullptr)
+		{
+			mPimpl->mFoldersToWatch.erase(mPimpl->mFoldersToWatch.end() - 1);
+			bs_delete(watchInfo);
+			BS_EXCEPT(InternalErrorException, "Failed to open completition port for folder monitoring. Error code: " + toString((UINT64)GetLastError()));
+		}
+
+		if(mPimpl->mWorkerThread == nullptr)
+		{
+			BS_THREAD_CREATE(t, (std::bind(&FolderMonitor::workerThreadMain, this)));
+			mPimpl->mWorkerThread = t;
+
+			if(mPimpl->mWorkerThread == nullptr)
+			{
+				mPimpl->mFoldersToWatch.erase(mPimpl->mFoldersToWatch.end() - 1);
+				bs_delete(watchInfo);
+				BS_EXCEPT(InternalErrorException, "Failed to create a new worker thread for folder monitoring");
+			}
+		}
+
+		if(mPimpl->mWorkerThread != nullptr)
+		{
+			try
+			{
+				watchInfo->startMonitor(mPimpl->mCompPortHandle);
+			}
+			catch (Exception* e)
+			{
+				mPimpl->mFoldersToWatch.erase(mPimpl->mFoldersToWatch.end() - 1);
+				bs_delete(watchInfo);
+				throw(e);
+			}
+		}
+		else
+		{
+			mPimpl->mFoldersToWatch.erase(mPimpl->mFoldersToWatch.end() - 1);
+			bs_delete(watchInfo);
+			BS_EXCEPT(InternalErrorException, "Failed to create a new worker thread for folder monitoring");
+		}
+	}
+
+	void FolderMonitor::stopMonitor(const Path& folderPath)
+	{
+		auto findIter = std::find_if(mPimpl->mFoldersToWatch.begin(), mPimpl->mFoldersToWatch.end(), 
+			[&](const FolderWatchInfo* x) { return x->mFolderToMonitor == folderPath; });
+
+		if(findIter != mPimpl->mFoldersToWatch.end())
+		{
+			FolderWatchInfo* watchInfo = *findIter;
+
+			watchInfo->stopMonitor(mPimpl->mCompPortHandle);
+			bs_delete(watchInfo);
+
+			mPimpl->mFoldersToWatch.erase(findIter);
+		}
+
+		if(mPimpl->mFoldersToWatch.size() == 0)
+			stopMonitorAll();
+	}
+
+	void FolderMonitor::stopMonitorAll()
+	{
+		for(auto& watchInfo : mPimpl->mFoldersToWatch)
+		{
+			watchInfo->stopMonitor(mPimpl->mCompPortHandle);
+
+			{
+				// Note: Need this mutex to ensure worker thread is done with watchInfo.
+				// Even though we wait for a condition variable from the worker thread in stopMonitor,
+				// that doesn't mean the worker thread is done with the condition variable
+				// (which is stored inside watchInfo)
+				BS_LOCK_MUTEX(mPimpl->mMainMutex); 
+				bs_delete(watchInfo);
+			}
+		}
+
+		mPimpl->mFoldersToWatch.clear();
+
+		if(mPimpl->mWorkerThread != nullptr)
+		{
+			PostQueuedCompletionStatus(mPimpl->mCompPortHandle, 0, 0, nullptr);
+
+			mPimpl->mWorkerThread->join();
+			BS_THREAD_DESTROY(mPimpl->mWorkerThread);
+			mPimpl->mWorkerThread = nullptr;
+		}
+
+		if(mPimpl->mCompPortHandle != nullptr)
+		{
+			CloseHandle(mPimpl->mCompPortHandle);
+			mPimpl->mCompPortHandle = nullptr;
+		}
+	}
+
+	void FolderMonitor::workerThreadMain()
+	{
+		FolderWatchInfo* watchInfo = nullptr;
+
+		do 
+		{
+			DWORD numBytes;
+			LPOVERLAPPED overlapped;
+
+			if(!GetQueuedCompletionStatus(mPimpl->mCompPortHandle, &numBytes, (PULONG_PTR) &watchInfo, &overlapped, INFINITE))
+			{
+				assert(false);
+				// TODO: Folder handle was lost most likely. Not sure how to deal with that. Shutdown watch on this folder and cleanup?
+			}
+
+			if(watchInfo != nullptr)
+			{
+				MonitorState state;
+
+				{
+					BS_LOCK_MUTEX(watchInfo->mStatusMutex);
+					state = watchInfo->mState;
+				}
+
+				switch(state)
+				{
+				case MonitorState::Starting:
+					if(!ReadDirectoryChangesW(watchInfo->mDirHandle, watchInfo->mBuffer, FolderWatchInfo::READ_BUFFER_SIZE,
+						watchInfo->mMonitorSubdirectories, watchInfo->mMonitorFlags, &watchInfo->mBufferSize, &watchInfo->mOverlapped, nullptr))
+					{
+						assert(false); // TODO - Possibly the buffer was too small?
+						watchInfo->mReadError = GetLastError();
+					}
+					else
+					{
+						watchInfo->mReadError = ERROR_SUCCESS;
+
+						{
+							BS_LOCK_MUTEX(watchInfo->mStatusMutex);
+							watchInfo->mState = MonitorState::Monitoring;
+						}
+					}
+
+					BS_THREAD_NOTIFY_ONE(watchInfo->mStartStopEvent);
+
+					break;
+				case MonitorState::Monitoring:
+					{
+						FileNotifyInfo info(watchInfo->mBuffer, FolderWatchInfo::READ_BUFFER_SIZE);
+						handleNotifications(info, *watchInfo);
+
+						if(!ReadDirectoryChangesW(watchInfo->mDirHandle, watchInfo->mBuffer, FolderWatchInfo::READ_BUFFER_SIZE,
+							watchInfo->mMonitorSubdirectories, watchInfo->mMonitorFlags, &watchInfo->mBufferSize, &watchInfo->mOverlapped, nullptr))
+						{
+							assert(false); // TODO: Failed during normal operation, possibly the buffer was too small. Shutdown watch on this folder and cleanup?
+							watchInfo->mReadError = GetLastError();
+						}
+						else
+						{
+							watchInfo->mReadError = ERROR_SUCCESS;
+						}
+					}
+					break;
+				case MonitorState::Shutdown:
+					if(watchInfo->mDirHandle != INVALID_HANDLE_VALUE)
+					{
+						CloseHandle(watchInfo->mDirHandle);
+						watchInfo->mDirHandle = INVALID_HANDLE_VALUE;
+
+						{
+							BS_LOCK_MUTEX(watchInfo->mStatusMutex);
+							watchInfo->mState = MonitorState::Shutdown2;
+						}
+					}
+					else
+					{
+						{
+							BS_LOCK_MUTEX(watchInfo->mStatusMutex);
+							watchInfo->mState = MonitorState::Inactive;
+						}
+
+						{
+							BS_LOCK_MUTEX(mPimpl->mMainMutex); // Ensures that we don't delete "watchInfo" before this thread is done with mStartStopEvent
+							BS_THREAD_NOTIFY_ONE(watchInfo->mStartStopEvent);
+						}
+					}
+
+					break;
+				case MonitorState::Shutdown2:
+					if(watchInfo->mDirHandle != INVALID_HANDLE_VALUE)
+					{
+						// Handle is still open? Try again.
+						CloseHandle(watchInfo->mDirHandle);
+						watchInfo->mDirHandle = INVALID_HANDLE_VALUE;
+					}
+					else
+					{
+						{
+							BS_LOCK_MUTEX(watchInfo->mStatusMutex);
+							watchInfo->mState = MonitorState::Inactive;
+						}
+
+						{
+							BS_LOCK_MUTEX(mPimpl->mMainMutex); // Ensures that we don't delete "watchInfo" before this thread is done with mStartStopEvent
+							BS_THREAD_NOTIFY_ONE(watchInfo->mStartStopEvent);
+						}
+					}
+
+					break;
+				}
+			}
+
+		} while (watchInfo != nullptr);
+	}
+
+	void FolderMonitor::handleNotifications(FileNotifyInfo& notifyInfo, FolderWatchInfo& watchInfo)
+	{
+		Vector<FileAction*> mActions;
+
+		do
+		{
+			WString fullPath = notifyInfo.getFileNameWithPath(watchInfo.mFolderToMonitor);
+
+			// Ignore notifications about hidden files
+			if ((GetFileAttributesW(fullPath.c_str()) & FILE_ATTRIBUTE_HIDDEN) != 0)
+				continue;
+
+			switch(notifyInfo.getAction())
+			{
+			case FILE_ACTION_ADDED:
+					mActions.push_back(FileAction::createAdded(fullPath));
+				break;
+			case FILE_ACTION_REMOVED:
+					mActions.push_back(FileAction::createRemoved(fullPath));
+				break;
+			case FILE_ACTION_MODIFIED:
+					mActions.push_back(FileAction::createModified(fullPath));
+				break;
+			case FILE_ACTION_RENAMED_OLD_NAME:
+					watchInfo.mCachedOldFileName = fullPath;
+				break;
+			case FILE_ACTION_RENAMED_NEW_NAME:
+					mActions.push_back(FileAction::createRenamed(watchInfo.mCachedOldFileName, fullPath));
+				break;
+			}
+    
+		} while(notifyInfo.getNext());
+
+		{
+			BS_LOCK_MUTEX(mPimpl->mMainMutex);
+
+			for(auto& action : mActions)
+				mPimpl->mFileActions.push(action);
+		}
+	}
+
+	void FolderMonitor::_update()
+	{
+		{
+			BS_LOCK_MUTEX(mPimpl->mMainMutex);
+
+			while (!mPimpl->mFileActions.empty())
+			{
+				FileAction* action = mPimpl->mFileActions.front();
+				mPimpl->mFileActions.pop();
+
+				mPimpl->mActiveFileActions.push_back(action);
+			}
+		}
+
+		for (auto iter = mPimpl->mActiveFileActions.begin(); iter != mPimpl->mActiveFileActions.end();)
+		{
+			FileAction* action = *iter;
+			
+			// Reported file actions might still be in progress (i.e. something might still be writing to those files).
+			// Sadly there doesn't seem to be a way to properly determine when those files are done being written, so instead
+			// we check for at least a couple of frames if the file's size hasn't changed before reporting a file action.
+			// This takes care of most of the issues and avoids reporting partially written files in almost all cases.
+			if (FileSystem::exists(action->newName))
+			{
+				UINT64 size = FileSystem::getFileSize(action->newName);
+				if (!action->checkForWriteStarted)
+				{
+					action->checkForWriteStarted = true;
+					action->lastSize = size;
+
+					++iter;
+					continue;
+				}
+				else
+				{
+					if (action->lastSize != size)
+					{
+						action->lastSize = size;
+						++iter;
+						continue;
+					}
+				}
+			}
+
+			switch (action->type)
+			{
+			case FileActionType::Added:
+				if (!onAdded.empty())
+					onAdded(Path(action->newName));
+				break;
+			case FileActionType::Removed:
+				if (!onRemoved.empty())
+					onRemoved(Path(action->newName));
+				break;
+			case FileActionType::Modified:
+				if (!onModified.empty())
+					onModified(Path(action->newName));
+				break;
+			case FileActionType::Renamed:
+				if (!onRenamed.empty())
+					onRenamed(Path(action->oldName), Path(action->newName));
+				break;
+			}
+
+			mPimpl->mActiveFileActions.erase(iter++);
+			FileAction::destroy(action);
+		}
+	}
 }

+ 197 - 197
Source/BansheeEditor/Include/BsEditorPrerequisites.h

@@ -1,197 +1,197 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-
-/** @defgroup Editor Editor
- *	Provides functionality specific to the Banshee Editor.
- *  @{
- */
-
-/** @defgroup EditorWindow EditorWindow
- *  Functionality for creating, managing and interacting with editor windows.
- */
-
-/** @defgroup Utility-Editor Utility
- *  Various utility methods and types used by the editor layer.
- */
-
-/** @defgroup GUI-Editor GUI
-  *	Editor specific GUI elements.
-  */
-
-/** @defgroup Build Build
-  *	Functionality for building (publishing) the game from within the editor.
-  */
-
-/** @defgroup CodeEditor CodeEditor
-  *	Functionality for integrating the Banshee Editor with external code editors (e.g. Visual Studio).
-  */
-
-/** @defgroup Handles Handles
-  *	Functionality creating and interacting with handles (e.g. move/rotate/scale and custom tools).
-  */
-
-/** @defgroup Library Library
-  *	Management of all resources (assets) within a project.
-  */
-
-/** @defgroup RTTI-Impl-Editor RTTI types
- *  Types containing RTTI for specific classes.
- */
-
-/** @defgroup Scene-Editor Scene
-  *	Functionality for rendering/interacting with the scene view in editor.
-  */
-
-/** @defgroup Settings Settings
-  *	Persistent settings for editor and project.
-  */
-
-/** @defgroup Testing-Editor Testing
- *  Contains editor unit tests.
- */
-
-/** @defgroup UndoRedo UndoRedo
- *  Provides functionality for undoing and redoing actions within the editor.
- */
-
-/** @defgroup Application-Editor Application
- *  Entry point into the editor application.
- */
-
-/** @} */
-
-#if (BS_PLATFORM == BS_PLATFORM_WIN32) && !defined(__MINGW32__)
-#	ifdef BS_ED_EXPORTS
-#		define BS_ED_EXPORT __declspec(dllexport)
-#	else
-#       if defined( __MINGW32__ )
-#           define BS_ED_EXPORT
-#       else
-#    		define BS_ED_EXPORT __declspec(dllimport)
-#       endif
-#	endif
-#elif defined ( BS_GCC_VISIBILITY )
-#    define BS_ED_EXPORT  __attribute__ ((visibility("default")))
-#else
-#    define BS_ED_EXPORT
-#endif
-
-namespace BansheeEngine
-{
-	class EditorWindowBase;
-	class EditorWindow;
-	class EditorWidgetBase;
-	class EditorWidgetContainer;
-	class EditorWidgetManager;
-	class EditorWidgetLayout;
-	class ModalWindow;
-	class GUITabbedTitleBar;
-	class GUITabButton;
-	class GUIWindowFrame;
-	class GUIIntField;
-	class GUIFloatField;
-	class GUITextField;
-	class GUIToggleField;
-	class GUIVector2Field;
-	class GUIVector3Field;
-	class GUIVector4Field;
-	class GUIColorField;
-	class GUIListBoxField;
-	class GUISliderField;
-	class GUIColor;
-	class GUIStatusBar;
-	class GUIDropButton;
-	class GUIHoverHitBox;
-	class EditorWindowManager;
-	class DockManager;
-	class DockManagerLayout;
-	class MainEditorWindow;
-	class WindowFrameWidget;
-	class GUIMenuBar;
-	class GUIDockSlider;
-	class GUISceneTreeView;
-	class GUIResourceTreeView;
-	class GUITreeViewEditBox;
-	class EditorCommand;
-	class ProjectFileMeta;
-	class ProjectResourceMeta;
-	class SceneGrid;
-	class HandleSlider;
-	class HandleSliderLine;
-	class HandleSliderPlane;
-	class HandleSliderDisc;
-	class HandleSliderManager;
-	class HandleDrawManager;
-	class SceneCameraController;
-	class EditorSettings;
-	class SceneViewHandler;
-	class SelectionRenderer;
-	class DropDownWindow;
-	class ProjectSettings;
-
-	typedef std::shared_ptr<ProjectFileMeta> ProjectFileMetaPtr;
-	typedef std::shared_ptr<ProjectResourceMeta> ProjectResourceMetaPtr;
-	typedef std::shared_ptr<DockManagerLayout> DockManagerLayoutPtr;
-	typedef std::shared_ptr<EditorWidgetLayout> EditorWidgetLayoutPtr;
-	typedef std::shared_ptr<EditorSettings> EditorSettingsPtr;
-	typedef std::shared_ptr<ProjectSettings> ProjectSettingsPtr;
-
-	static const char* EDITOR_ASSEMBLY = "MBansheeEditor";
-	static const char* SCRIPT_EDITOR_ASSEMBLY = "MScriptEditor";
-	static const Path PROJECT_INTERNAL_DIR = L"Internal\\";
-	static const Path INTERNAL_ASSEMBLY_PATH = PROJECT_INTERNAL_DIR + "Assemblies\\";
-
-	/** Types of drag and drop operations. Different types specify different types of dragged data. */
-	enum class DragAndDropType
-	{
-		EditorWidget = 10000,
-		SceneObject = 10001,
-		Resources = 10002
-	};
-
-	/**
-	 * Recognized types of external code editors.
-	 *
-	 * @see		CodeEditorManager
-	 */
-	enum class CodeEditorType
-	{
-		VS2008,
-		VS2010,
-		VS2012,
-		VS2013,
-		VS2015,
-		None
-	};
-
-	/**	Type IDs used by the RTTI system for the editor library. */
-	enum TypeID_BansheeEditor
-	{
-		TID_ProjectFileMeta = 40000,
-		TID_ProjectLibraryEntries = 40001,
-		TID_ProjectLibraryResEntry = 40002,
-		TID_ProjectLibraryDirEntry = 40003,
-		TID_DockManagerLayout = 40004,
-		TID_DockManagerLayoutEntry = 40005,
-		TID_EditorWidgetLayout = 40006,
-		TID_EditorWidgetLayoutEntry = 40007,
-		TID_TestComponentA = 40008,
-		TID_TestComponentB = 40009,
-		TID_PlatformInfo = 40010,
-		TID_WinPlatformInfo = 40011,
-		TID_BuildData = 40012,
-		TID_TestObjectA = 40013,
-		TID_TestObjectB = 40014,
-		TID_TestComponentC = 40015,
-		TID_TestComponentD = 40016,
-		TID_EditorSettings = 40017,
-		TID_RecentProject = 40018,
-		TID_Settings = 40019,
-		TID_ProjectSettings = 40020,
-		TID_WindowFrameWidget = 40021,
-		TID_ProjectResourceMeta = 40022
-	};
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+
+/** @defgroup Editor Editor
+ *	Provides functionality specific to the Banshee Editor.
+ *  @{
+ */
+
+/** @defgroup EditorWindow EditorWindow
+ *  Functionality for creating, managing and interacting with editor windows.
+ */
+
+/** @defgroup Utility-Editor Utility
+ *  Various utility methods and types used by the editor layer.
+ */
+
+/** @defgroup GUI-Editor GUI
+  *	Editor specific GUI elements.
+  */
+
+/** @defgroup Build Build
+  *	Functionality for building (publishing) the game from within the editor.
+  */
+
+/** @defgroup CodeEditor CodeEditor
+  *	Functionality for integrating the Banshee Editor with external code editors (for example Visual Studio).
+  */
+
+/** @defgroup Handles Handles
+  *	Functionality creating and interacting with handles (for example move/rotate/scale and custom tools).
+  */
+
+/** @defgroup Library Library
+  *	Management of all resources (assets) within a project.
+  */
+
+/** @defgroup RTTI-Impl-Editor RTTI types
+ *  Types containing RTTI for specific classes.
+ */
+
+/** @defgroup Scene-Editor Scene
+  *	Functionality for rendering/interacting with the scene view in editor.
+  */
+
+/** @defgroup Settings Settings
+  *	Persistent settings for editor and project.
+  */
+
+/** @defgroup Testing-Editor Testing
+ *  Contains editor unit tests.
+ */
+
+/** @defgroup UndoRedo UndoRedo
+ *  Provides functionality for undoing and redoing actions within the editor.
+ */
+
+/** @defgroup Application-Editor Application
+ *  Entry point into the editor application.
+ */
+
+/** @} */
+
+#if (BS_PLATFORM == BS_PLATFORM_WIN32) && !defined(__MINGW32__)
+#	ifdef BS_ED_EXPORTS
+#		define BS_ED_EXPORT __declspec(dllexport)
+#	else
+#       if defined( __MINGW32__ )
+#           define BS_ED_EXPORT
+#       else
+#    		define BS_ED_EXPORT __declspec(dllimport)
+#       endif
+#	endif
+#elif defined ( BS_GCC_VISIBILITY )
+#    define BS_ED_EXPORT  __attribute__ ((visibility("default")))
+#else
+#    define BS_ED_EXPORT
+#endif
+
+namespace BansheeEngine
+{
+	class EditorWindowBase;
+	class EditorWindow;
+	class EditorWidgetBase;
+	class EditorWidgetContainer;
+	class EditorWidgetManager;
+	class EditorWidgetLayout;
+	class ModalWindow;
+	class GUITabbedTitleBar;
+	class GUITabButton;
+	class GUIWindowFrame;
+	class GUIIntField;
+	class GUIFloatField;
+	class GUITextField;
+	class GUIToggleField;
+	class GUIVector2Field;
+	class GUIVector3Field;
+	class GUIVector4Field;
+	class GUIColorField;
+	class GUIListBoxField;
+	class GUISliderField;
+	class GUIColor;
+	class GUIStatusBar;
+	class GUIDropButton;
+	class GUIHoverHitBox;
+	class EditorWindowManager;
+	class DockManager;
+	class DockManagerLayout;
+	class MainEditorWindow;
+	class WindowFrameWidget;
+	class GUIMenuBar;
+	class GUIDockSlider;
+	class GUISceneTreeView;
+	class GUIResourceTreeView;
+	class GUITreeViewEditBox;
+	class EditorCommand;
+	class ProjectFileMeta;
+	class ProjectResourceMeta;
+	class SceneGrid;
+	class HandleSlider;
+	class HandleSliderLine;
+	class HandleSliderPlane;
+	class HandleSliderDisc;
+	class HandleSliderManager;
+	class HandleDrawManager;
+	class SceneCameraController;
+	class EditorSettings;
+	class SceneViewHandler;
+	class SelectionRenderer;
+	class DropDownWindow;
+	class ProjectSettings;
+
+	typedef std::shared_ptr<ProjectFileMeta> ProjectFileMetaPtr;
+	typedef std::shared_ptr<ProjectResourceMeta> ProjectResourceMetaPtr;
+	typedef std::shared_ptr<DockManagerLayout> DockManagerLayoutPtr;
+	typedef std::shared_ptr<EditorWidgetLayout> EditorWidgetLayoutPtr;
+	typedef std::shared_ptr<EditorSettings> EditorSettingsPtr;
+	typedef std::shared_ptr<ProjectSettings> ProjectSettingsPtr;
+
+	static const char* EDITOR_ASSEMBLY = "MBansheeEditor";
+	static const char* SCRIPT_EDITOR_ASSEMBLY = "MScriptEditor";
+	static const Path PROJECT_INTERNAL_DIR = L"Internal\\";
+	static const Path INTERNAL_ASSEMBLY_PATH = PROJECT_INTERNAL_DIR + "Assemblies\\";
+
+	/** Types of drag and drop operations. Different types specify different types of dragged data. */
+	enum class DragAndDropType
+	{
+		EditorWidget = 10000,
+		SceneObject = 10001,
+		Resources = 10002
+	};
+
+	/**
+	 * Recognized types of external code editors.
+	 *
+	 * @see		CodeEditorManager
+	 */
+	enum class CodeEditorType
+	{
+		VS2008,
+		VS2010,
+		VS2012,
+		VS2013,
+		VS2015,
+		None
+	};
+
+	/**	Type IDs used by the RTTI system for the editor library. */
+	enum TypeID_BansheeEditor
+	{
+		TID_ProjectFileMeta = 40000,
+		TID_ProjectLibraryEntries = 40001,
+		TID_ProjectLibraryResEntry = 40002,
+		TID_ProjectLibraryDirEntry = 40003,
+		TID_DockManagerLayout = 40004,
+		TID_DockManagerLayoutEntry = 40005,
+		TID_EditorWidgetLayout = 40006,
+		TID_EditorWidgetLayoutEntry = 40007,
+		TID_TestComponentA = 40008,
+		TID_TestComponentB = 40009,
+		TID_PlatformInfo = 40010,
+		TID_WinPlatformInfo = 40011,
+		TID_BuildData = 40012,
+		TID_TestObjectA = 40013,
+		TID_TestObjectB = 40014,
+		TID_TestComponentC = 40015,
+		TID_TestComponentD = 40016,
+		TID_EditorSettings = 40017,
+		TID_RecentProject = 40018,
+		TID_Settings = 40019,
+		TID_ProjectSettings = 40020,
+		TID_WindowFrameWidget = 40021,
+		TID_ProjectResourceMeta = 40022
+	};
+}

+ 159 - 159
Source/BansheeEditor/Include/BsEditorSettings.h

@@ -1,160 +1,160 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsEditorPrerequisites.h"
-#include "BsSettings.h"
-#include "BsDegree.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Settings
-	 *  @{
-	 */
-
-	struct RecentProject;
-
-	/**	Contains various globally accessible editor preferences. */
-	class BS_ED_EXPORT EditorSettings : public Settings
-	{
-	public:
-		EditorSettings();
-
-		/**	Checks is snapping enabled for move handles in scene view. */
-		bool getMoveHandleSnapActive() const { return mMoveSnapActive; }
-
-		/**	Checks is angle snapping enabled for rotate handles in scene view. */
-		bool getRotateHandleSnapActive() const { return mRotateSnapActive; }
-
-		/**	Gets the snap amount if move snapping is enabled. All move handles will move in multiples of this amount. */
-		float getMoveHandleSnap() const { return mMoveSnap; }
-
-		/**
-		 * Gets the snap amount if rotate snapping is enabled. All rotate handles will rotate in multiples of this amount.
-		 */
-		Degree getRotationHandleSnap() const { return mRotationSnap; }
-
-		/**	Returns the size that determines to total size of the scene view grid (its width and height). */
-		UINT32 getGridSize() const { return mGridSize; }
-
-		/**	Returns the distance between scene view grid lines. */
-		float getGridSpacing() const { return mGridAxisSpacing; }
-
-		/**	Gets the default size of all scene view handles. */
-		float getHandleSize() const { return mHandleSize; }
-
-		/**	Returns the currently active scene view tool (e.g. move, rotate, etc.). */
-		UINT32 getActiveSceneTool() const { return mActiveSceneTool; }
-
-		/**	Returns the currently active coordinate mode for scene view (e.g. global/local). */
-		UINT32 getActiveCoordinateMode() const { return mActiveCoordinateMode; }
-
-		/**	Returns the currently active pivot mode for scene view (e.g. pivot/center). */
-		UINT32 getActivePivotMode() const { return mActivePivotMode; }
-
-		/**	Retrieves the path to the last project open in the editor. */
-		Path getLastOpenProject() const { return mLastOpenProject; }
-
-		/** Retrieves whether the last open project should be automatically loaded on editor start up. */
-		bool getAutoLoadLastProject() const { return mAutoLoadLastProject; }
-
-		/**	Retrieves a list of most recently loaded project paths and their last access times. */
-		const Vector<RecentProject>& getRecentProjects() const { return mRecentProjects; }
-
-		/** Retrieves the maximum number of frames per second the editor is allowed to execute. Zero means infinite. */
-		UINT32 getFPSLimit() const { return mFPSLimit; }
-
-		/** 
-		 * Retrieves a value that controls sensitivity of mouse movements. This doesn't apply to mouse cursor. 
-		 * Default value is 1.0f.
-		 */
-		float getMouseSensitivity() const { return mMouseSensitivity; }
-
-		/**	Enables/disables snapping for move handles in scene view. */
-		void setMoveHandleSnapActive(bool snapActive) { mMoveSnapActive = snapActive; markAsDirty(); }
-
-		/**	Enables/disables angle snapping for rotate handles in scene view. */
-		void setRotateHandleSnapActive(bool snapActive) { mRotateSnapActive = snapActive; markAsDirty(); }
-
-		/**	Sets the move snap amount. All move handles will move in multiples of this amount. */
-		void setMoveHandleSnap(float value) { mMoveSnap = value; markAsDirty(); }
-
-		/**	Sets the rotate snap amount. All rotate handles will rotate in multiples of this amount. */
-		void setRotationHandleSnap(Degree value) { mRotationSnap = value; markAsDirty(); }
-
-		/**	Sets the size that determines to total size of the scene view grid (its width and height). */
-		void setGridSize(UINT32 value) { mGridSize = value; markAsDirty(); }
-
-		/**	Sets the distance between scene view grid lines. */
-		void setGridSpacing(float value) { mGridAxisSpacing = value; markAsDirty(); }
-
-		/**	Sets the default size of all scene view handles. */
-		void setHandleSize(float value) { mHandleSize = value; markAsDirty(); }
-
-		/**	Changes the currently active scene view tool (e.g. move, rotate, etc.). */
-		void setActiveSceneTool(UINT32 value) { mActiveSceneTool = value; markAsDirty(); }
-
-		/**	Changes the currently active coordinate mode for scene view (e.g. global/local). */
-		void setActiveCoordinateMode(UINT32 value) { mActiveCoordinateMode = value; markAsDirty(); }
-
-		/**	Changes the currently active pivot mode for scene view (e.g. pivot/center). */
-		void setActivePivotMode(UINT32 value) { mActivePivotMode = value; markAsDirty(); }
-
-		/**	Sets the path to the last project open in the editor. */
-		void setLastOpenProject(const Path& value) { mLastOpenProject = value; markAsDirty(); }
-
-		/** Sets whether the last open project should be automatically loaded on editor start up. */
-		void setAutoLoadLastProject(bool value) { mAutoLoadLastProject = value; markAsDirty(); }
-
-		/**	Sets a list of most recently loaded project paths and their last access times. */
-		void setRecentProjects(const Vector<RecentProject>& value) { mRecentProjects = value; markAsDirty(); }
-
-		/** Sets the maximum number of frames per second the editor is allowed to execute. Zero means infinite. */
-		void setFPSLimit(UINT32 limit) { mFPSLimit = limit; markAsDirty(); }
-
-		/** 
-		 * Sets a value that controls sensitivity of mouse movements. This doesn't apply to mouse cursor. 
-		 * Default value is 1.0f.
-		 */
-		void setMouseSensitivity(float value) { mMouseSensitivity = value; markAsDirty(); }
-
-	private:
-		bool mMoveSnapActive;
-		bool mRotateSnapActive;
-
-		float mMoveSnap;
-		Degree mRotationSnap;
-
-		UINT32 mGridSize;
-		float mGridAxisSpacing;
-
-		UINT32 mActiveSceneTool;
-		UINT32 mActiveCoordinateMode;
-		UINT32 mActivePivotMode;
-
-		float mHandleSize;
-		UINT32 mFPSLimit;
-		float mMouseSensitivity;
-
-		Path mLastOpenProject;
-		bool mAutoLoadLastProject;
-		Vector<RecentProject> mRecentProjects;
-
-		/************************************************************************/
-		/* 								RTTI		                     		*/
-		/************************************************************************/
-	public:
-		friend class EditorSettingsRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	/**	Data about a recently loaded project. */
-	struct RecentProject
-	{
-		Path path;
-		UINT64 accessTimestamp;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsSettings.h"
+#include "BsDegree.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Settings
+	 *  @{
+	 */
+
+	struct RecentProject;
+
+	/**	Contains various globally accessible editor preferences. */
+	class BS_ED_EXPORT EditorSettings : public Settings
+	{
+	public:
+		EditorSettings();
+
+		/**	Checks is snapping enabled for move handles in scene view. */
+		bool getMoveHandleSnapActive() const { return mMoveSnapActive; }
+
+		/**	Checks is angle snapping enabled for rotate handles in scene view. */
+		bool getRotateHandleSnapActive() const { return mRotateSnapActive; }
+
+		/**	Gets the snap amount if move snapping is enabled. All move handles will move in multiples of this amount. */
+		float getMoveHandleSnap() const { return mMoveSnap; }
+
+		/**
+		 * Gets the snap amount if rotate snapping is enabled. All rotate handles will rotate in multiples of this amount.
+		 */
+		Degree getRotationHandleSnap() const { return mRotationSnap; }
+
+		/**	Returns the size that determines to total size of the scene view grid (its width and height). */
+		UINT32 getGridSize() const { return mGridSize; }
+
+		/**	Returns the distance between scene view grid lines. */
+		float getGridSpacing() const { return mGridAxisSpacing; }
+
+		/**	Gets the default size of all scene view handles. */
+		float getHandleSize() const { return mHandleSize; }
+
+		/**	Returns the currently active scene view tool (for example move, rotate, etc.). */
+		UINT32 getActiveSceneTool() const { return mActiveSceneTool; }
+
+		/**	Returns the currently active coordinate mode for scene view (for example global/local). */
+		UINT32 getActiveCoordinateMode() const { return mActiveCoordinateMode; }
+
+		/**	Returns the currently active pivot mode for scene view (for example pivot/center). */
+		UINT32 getActivePivotMode() const { return mActivePivotMode; }
+
+		/**	Retrieves the path to the last project open in the editor. */
+		Path getLastOpenProject() const { return mLastOpenProject; }
+
+		/** Retrieves whether the last open project should be automatically loaded on editor start up. */
+		bool getAutoLoadLastProject() const { return mAutoLoadLastProject; }
+
+		/**	Retrieves a list of most recently loaded project paths and their last access times. */
+		const Vector<RecentProject>& getRecentProjects() const { return mRecentProjects; }
+
+		/** Retrieves the maximum number of frames per second the editor is allowed to execute. Zero means infinite. */
+		UINT32 getFPSLimit() const { return mFPSLimit; }
+
+		/** 
+		 * Retrieves a value that controls sensitivity of mouse movements. This doesn't apply to mouse cursor. 
+		 * Default value is 1.0f.
+		 */
+		float getMouseSensitivity() const { return mMouseSensitivity; }
+
+		/**	Enables/disables snapping for move handles in scene view. */
+		void setMoveHandleSnapActive(bool snapActive) { mMoveSnapActive = snapActive; markAsDirty(); }
+
+		/**	Enables/disables angle snapping for rotate handles in scene view. */
+		void setRotateHandleSnapActive(bool snapActive) { mRotateSnapActive = snapActive; markAsDirty(); }
+
+		/**	Sets the move snap amount. All move handles will move in multiples of this amount. */
+		void setMoveHandleSnap(float value) { mMoveSnap = value; markAsDirty(); }
+
+		/**	Sets the rotate snap amount. All rotate handles will rotate in multiples of this amount. */
+		void setRotationHandleSnap(Degree value) { mRotationSnap = value; markAsDirty(); }
+
+		/**	Sets the size that determines to total size of the scene view grid (its width and height). */
+		void setGridSize(UINT32 value) { mGridSize = value; markAsDirty(); }
+
+		/**	Sets the distance between scene view grid lines. */
+		void setGridSpacing(float value) { mGridAxisSpacing = value; markAsDirty(); }
+
+		/**	Sets the default size of all scene view handles. */
+		void setHandleSize(float value) { mHandleSize = value; markAsDirty(); }
+
+		/**	Changes the currently active scene view tool (for example move, rotate, etc.). */
+		void setActiveSceneTool(UINT32 value) { mActiveSceneTool = value; markAsDirty(); }
+
+		/**	Changes the currently active coordinate mode for scene view (for example global/local). */
+		void setActiveCoordinateMode(UINT32 value) { mActiveCoordinateMode = value; markAsDirty(); }
+
+		/**	Changes the currently active pivot mode for scene view (for example pivot/center). */
+		void setActivePivotMode(UINT32 value) { mActivePivotMode = value; markAsDirty(); }
+
+		/**	Sets the path to the last project open in the editor. */
+		void setLastOpenProject(const Path& value) { mLastOpenProject = value; markAsDirty(); }
+
+		/** Sets whether the last open project should be automatically loaded on editor start up. */
+		void setAutoLoadLastProject(bool value) { mAutoLoadLastProject = value; markAsDirty(); }
+
+		/**	Sets a list of most recently loaded project paths and their last access times. */
+		void setRecentProjects(const Vector<RecentProject>& value) { mRecentProjects = value; markAsDirty(); }
+
+		/** Sets the maximum number of frames per second the editor is allowed to execute. Zero means infinite. */
+		void setFPSLimit(UINT32 limit) { mFPSLimit = limit; markAsDirty(); }
+
+		/** 
+		 * Sets a value that controls sensitivity of mouse movements. This doesn't apply to mouse cursor. 
+		 * Default value is 1.0f.
+		 */
+		void setMouseSensitivity(float value) { mMouseSensitivity = value; markAsDirty(); }
+
+	private:
+		bool mMoveSnapActive;
+		bool mRotateSnapActive;
+
+		float mMoveSnap;
+		Degree mRotationSnap;
+
+		UINT32 mGridSize;
+		float mGridAxisSpacing;
+
+		UINT32 mActiveSceneTool;
+		UINT32 mActiveCoordinateMode;
+		UINT32 mActivePivotMode;
+
+		float mHandleSize;
+		UINT32 mFPSLimit;
+		float mMouseSensitivity;
+
+		Path mLastOpenProject;
+		bool mAutoLoadLastProject;
+		Vector<RecentProject> mRecentProjects;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class EditorSettingsRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
+	};
+
+	/**	Data about a recently loaded project. */
+	struct RecentProject
+	{
+		Path path;
+		UINT64 accessTimestamp;
+	};
+
+	/** @} */
 }

+ 5 - 5
Source/BansheeEditor/Include/BsEditorWidget.h

@@ -63,13 +63,13 @@ namespace BansheeEngine
 		bool isActive() const { return mIsActive; }
 
 		/**
-		 * Gets the parent editor window this widget is docked in. Can be null (e.g. when widget is in the process of
+		 * Gets the parent editor window this widget is docked in. Can be null (for example when widget is in the process of
 		 * dragging and not visible).
 		 */
 		EditorWindowBase* getParentWindow() const;
 
 		/**
-		 * Returns the parent widget container. Can be null (e.g. when widget is in the process of dragging and not 
+		 * Returns the parent widget container. Can be null (for example when widget is in the process of dragging and not 
 		 * visible). 
 		 */
 		EditorWidgetContainer* _getParent() const { return mParent; }
@@ -83,7 +83,7 @@ namespace BansheeEngine
 		/**	Closes the widget, undocking it from its container and freeing any resources related to it. */
 		void close();
 
-		/** Internal method. Called once per frame.	 */
+		/** Internal method. Called once per frame.	*/
 		virtual void update() { }
 
 		Event<void(UINT32, UINT32)> onResized; /**< Triggered whenever widget size changes. */
@@ -100,8 +100,8 @@ namespace BansheeEngine
 		void _setPosition(INT32 x, INT32 y);
 
 		/**
-		 * Changes the parent container of the widget (e.g. when re-docking or moving a widget to another window). Parent
-		 * can be null (e.g. when widget is in the process of dragging and not visible).
+		 * Changes the parent container of the widget (for example when re-docking or moving a widget to another window). 
+		 * Parent can be null (for example when widget is in the process of dragging and not visible).
 		 */
 		void _changeParent(EditorWidgetContainer* parent);
 

+ 64 - 64
Source/BansheeEditor/Include/BsEditorWindow.h

@@ -1,65 +1,65 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsEditorPrerequisites.h"
-#include "BsEditorWindowBase.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup EditorWindow
-	 *  @{
-	 */
-
-	/**	A draggable and resizeable window that has a single widget container you may use for docking editor widgets in. */
-	class BS_ED_EXPORT EditorWindow : public EditorWindowBase
-	{
-	public:
-		virtual ~EditorWindow();
-
-		/**	Returns the widget container for this window. */
-		EditorWidgetContainer& widgets() const { return *mWidgets; }
-
-		/** @copydoc EditorWindowBase::update  */
-		virtual void update() override;
-
-		/**	Creates a new empty editor window. */
-		static EditorWindow* create();
-
-	protected:
-		friend class EditorWindowManager;
-		EditorWindow();
-
-		/** @copydoc EditorWindowBase::resized  */
-		virtual void resized() override;
-	private:
-		EditorWidgetContainer* mWidgets;
-
-		/**
-		 * Updates the sizes of the child widget container and OS non-client areas (like drag and resize). Call when window
-		 * size changes.
-		 */
-		void updateSize();
-
-		/**	Called when a widget is added to the widget container. */
-		void widgetAdded();
-
-		/**	Called when a widget is removed from the widget container. */
-		void widgetRemoved();
-
-		/**	Triggered when the maximize button on the title bar is clicked. */
-		void maximizeClicked();
-
-		/**
-		 * A callback that triggers when a drag and drop operation originated from this window ends. 
-		 *
-		 * @note	
-		 * This is a workaround to get around the problem that closing the window when the drag operation starts (e.g. if
-		 * the last widget is dragged from the window) will cause the application to lose mouse capture and will not receive
-		 * mouse events. Therefore we delay the window closing until the drag ends.
-		 */
-		void closeWindowDelayed();
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsEditorWindowBase.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup EditorWindow
+	 *  @{
+	 */
+
+	/**	A draggable and resizeable window that has a single widget container you may use for docking editor widgets in. */
+	class BS_ED_EXPORT EditorWindow : public EditorWindowBase
+	{
+	public:
+		virtual ~EditorWindow();
+
+		/**	Returns the widget container for this window. */
+		EditorWidgetContainer& widgets() const { return *mWidgets; }
+
+		/** @copydoc EditorWindowBase::update  */
+		virtual void update() override;
+
+		/**	Creates a new empty editor window. */
+		static EditorWindow* create();
+
+	protected:
+		friend class EditorWindowManager;
+		EditorWindow();
+
+		/** @copydoc EditorWindowBase::resized  */
+		virtual void resized() override;
+	private:
+		EditorWidgetContainer* mWidgets;
+
+		/**
+		 * Updates the sizes of the child widget container and OS non-client areas (like drag and resize). Call when window
+		 * size changes.
+		 */
+		void updateSize();
+
+		/**	Called when a widget is added to the widget container. */
+		void widgetAdded();
+
+		/**	Called when a widget is removed from the widget container. */
+		void widgetRemoved();
+
+		/**	Triggered when the maximize button on the title bar is clicked. */
+		void maximizeClicked();
+
+		/**
+		 * A callback that triggers when a drag and drop operation originated from this window ends. 
+		 *
+		 * @note	
+		 * This is a workaround to get around the problem that closing the window when the drag operation starts (for 
+		 * example if the last widget is dragged from the window) will cause the application to lose mouse capture and will
+		 * not receive mouse events. Therefore we delay the window closing until the drag ends.
+		 */
+		void closeWindowDelayed();
+	};
+
+	/** @} */
 }

+ 90 - 90
Source/BansheeEditor/Include/BsEditorWindowBase.h

@@ -1,91 +1,91 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsEditorPrerequisites.h"
-#include "BsEvent.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Implementation
-	 *  @{
-	 */
-
-	/**
-	 * A base class for all editor window. Each editor window is backed by a render window (e.g. the OS "window"), and also
-	 * provides a GUI widget for child elements to use. On top of that it also provides basic GUI like window background
-	 * and frame, as well as setting up the OS-specific areas for resize/move operations.
-	 */
-	class BS_ED_EXPORT EditorWindowBase
-	{
-	public:
-		virtual ~EditorWindowBase();
-
-		/**	Moves the window on the desktop. Coordinates are in screen space. */
-		virtual void setPosition(INT32 x, INT32 y);
-
-		/**	Resizes the window. */
-		virtual void setSize(UINT32 width, UINT32 height);
-
-		/**	Returns the X position of the window in screen coordinates. */
-		INT32 getLeft() const;
-
-		/**	Returns the X position of the window in screen coordinates. */
-		INT32 getTop() const;
-
-		/**	Returns the width of the window in pixels. */
-		UINT32 getWidth() const;
-
-		/**	Returns the height of the window in pixels. */
-		UINT32 getHeight() const;
-
-		/**	Closes and destroys the window. */
-		virtual void close();
-
-		/**	Hides the window without closing it. */
-		void hide();
-
-		/**	Return true if this is the main editor window. */
-		virtual bool isMain() const { return false; }
-
-		/**	Called once every frame. Internal method. */
-		virtual void update() { }
-
-		/**	Returns the render window that this editor window is being rendered to. */
-		RenderWindowPtr getRenderWindow() const { return mRenderWindow; }
-
-		/**	Returns the GUI widget used for displaying all GUI contents in the window. */
-		HGUIWidget getGUIWidget() const { return mGUI; }
-
-		/**	Returns the camera used for rendering the window GUI contents. */	
-		HCamera getGUICamera() const { return mCamera; }
-
-		/**	Checks whether the window currently has keyboard focus. */	
-		bool hasFocus() const;
-
-	protected:
-		EditorWindowBase(bool isModal = false);
-		EditorWindowBase(const RenderWindowPtr& renderWindow);
-
-		/**	Common code for constructing the object to be called from all constructors. */
-		void construct(const RenderWindowPtr& renderWindow);
-
-		/**	Initializes elements that cannot be initialized in the constructor. Must be called right after construction. */
-		virtual void initialize();
-
-		/**	Callback that triggers whenever the underlying render window changes size. */
-		virtual void resized() { }
-
-		RenderWindowPtr mRenderWindow;
-		HSceneObject mSceneObject;
-		HGUIWidget mGUI;
-		HCamera mCamera;
-		GameObjectHandle<WindowFrameWidget> mWindowFrame;
-		bool mOwnsRenderWindow;
-		bool mIsModal;
-	private:
-		HEvent mResizedConn;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsEvent.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Implementation
+	 *  @{
+	 */
+
+	/**
+	 * A base class for all editor window. Each editor window is backed by a render window (for example the OS "window"), 
+	 * and also provides a GUI widget for child elements to use. On top of that it also provides basic GUI like window
+	 * background and frame, as well as setting up the OS-specific areas for resize/move operations.
+	 */
+	class BS_ED_EXPORT EditorWindowBase
+	{
+	public:
+		virtual ~EditorWindowBase();
+
+		/**	Moves the window on the desktop. Coordinates are in screen space. */
+		virtual void setPosition(INT32 x, INT32 y);
+
+		/**	Resizes the window. */
+		virtual void setSize(UINT32 width, UINT32 height);
+
+		/**	Returns the X position of the window in screen coordinates. */
+		INT32 getLeft() const;
+
+		/**	Returns the X position of the window in screen coordinates. */
+		INT32 getTop() const;
+
+		/**	Returns the width of the window in pixels. */
+		UINT32 getWidth() const;
+
+		/**	Returns the height of the window in pixels. */
+		UINT32 getHeight() const;
+
+		/**	Closes and destroys the window. */
+		virtual void close();
+
+		/**	Hides the window without closing it. */
+		void hide();
+
+		/**	Return true if this is the main editor window. */
+		virtual bool isMain() const { return false; }
+
+		/**	Called once every frame. Internal method. */
+		virtual void update() { }
+
+		/**	Returns the render window that this editor window is being rendered to. */
+		RenderWindowPtr getRenderWindow() const { return mRenderWindow; }
+
+		/**	Returns the GUI widget used for displaying all GUI contents in the window. */
+		HGUIWidget getGUIWidget() const { return mGUI; }
+
+		/**	Returns the camera used for rendering the window GUI contents. */	
+		HCamera getGUICamera() const { return mCamera; }
+
+		/**	Checks whether the window currently has keyboard focus. */	
+		bool hasFocus() const;
+
+	protected:
+		EditorWindowBase(bool isModal = false);
+		EditorWindowBase(const RenderWindowPtr& renderWindow);
+
+		/**	Common code for constructing the object to be called from all constructors. */
+		void construct(const RenderWindowPtr& renderWindow);
+
+		/**	Initializes elements that cannot be initialized in the constructor. Must be called right after construction. */
+		virtual void initialize();
+
+		/**	Callback that triggers whenever the underlying render window changes size. */
+		virtual void resized() { }
+
+		RenderWindowPtr mRenderWindow;
+		HSceneObject mSceneObject;
+		HGUIWidget mGUI;
+		HCamera mCamera;
+		GameObjectHandle<WindowFrameWidget> mWindowFrame;
+		bool mOwnsRenderWindow;
+		bool mIsModal;
+	private:
+		HEvent mResizedConn;
+	};
+
+	/** @} */
 }

+ 226 - 226
Source/BansheeEditor/Include/BsGUIResourceTreeView.h

@@ -1,227 +1,227 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsEditorPrerequisites.h"
-#include "BsServiceLocator.h"
-#include "BsGUITreeView.h"
-#include "BsProjectLibrary.h"
-#include "BsEvent.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup GUI-Editor
-	 *  @{
-	 */
-
-	/** Contains paths to resources currently involved in a drag and drop operation. */
-	struct DraggedResources
-	{
-		Vector<Path> resourcePaths;
-	};
-
-	/**	GUI element that displays all resources in the active project in a tree view. */
-	class GUIResourceTreeView : public GUITreeView
-	{
-		/**	Tree element with resource-specific data. */
-		struct ResourceTreeElement : public GUITreeView::TreeElement
-		{
-			Path mFullPath;
-			WString mElementName;
-		};
-
-		/** Contains paths to resources currently involved in a drag and drop operation initiated by this tree view. */
-		struct InternalDraggedResources
-		{
-			InternalDraggedResources(UINT32 numObjects);
-			~InternalDraggedResources();
-
-			UINT32 numObjects;
-			Path* resourcePaths;
-		};
-
-	public:
-		/** Returns type name of the GUI element used for finding GUI element styles. */
-		static const String& getGUITypeName();
-
-		/**
-		 * Creates a new resource tree view element.
-		 *
-		 * @param[in]	backgroundStyle				Name of the style for the tree view background.
-		 * @param[in]	elementBtnStyle				Name of the style for a normal tree view element.
-		 * @param[in]	foldoutBtnStyle				Name of the style for a foldout element (e.g. for a folder).
-		 * @param[in]	highlightBackgroundStyle	Name of the style for the background of highlighted elements.
-		 * @param[in]	selectionBackgroundStyle	Name of the style for the background of selected elements.
-		 * @param[in]	editBoxStyle				Name of the style for element that is being renamed.
-		 * @param[in]	dragHighlightStyle			Name of the style for the element being dragged over.
-		 * @param[in]	dragSepHighlightStyle		Name of the style for the separator displayed while dragging
-		 *											an element between two other elements.
-		 */	
-		static GUIResourceTreeView* create(
-			const String& backgroundStyle = StringUtil::BLANK, const String& elementBtnStyle = StringUtil::BLANK, 
-			const String& foldoutBtnStyle = StringUtil::BLANK, const String& highlightBackgroundStyle = StringUtil::BLANK,
-			const String& selectionBackgroundStyle = StringUtil::BLANK, const String& editBoxStyle = StringUtil::BLANK, 
-			const String& dragHighlightStyle = StringUtil::BLANK, const String& dragSepHighlightStyle = StringUtil::BLANK);
-
-		/**
-		 * Creates a new resource tree view element.
-		 *
-		 * @param[in]	options						Options that allow you to control how is the element positioned and 
-		 *											sized. This will override any similar options set by style.
-		 * @param[in]	backgroundStyle				Name of the style for the tree view background.
-		 * @param[in]	elementBtnStyle				Name of the style for a normal tree view element.
-		 * @param[in]	foldoutBtnStyle				Name of the style for a foldout element (e.g. for a folder).
-		 * @param[in]	highlightBackgroundStyle	Name of the style for the background of highlighted elements.
-		 * @param[in]	selectionBackgroundStyle	Name of the style for the background of selected elements.
-		 * @param[in]	editBoxStyle				Name of the style for element that is being renamed.
-		 * @param[in]	dragHighlightStyle			Name of the style for the element being dragged over.
-		 * @param[in]	dragSepHighlightStyle		Name of the style for the separator displayed while dragging an element
-		 *											between two other elements.
-		 */	
-		static GUIResourceTreeView* create(const GUIOptions& options, 
-			const String& backgroundStyle = StringUtil::BLANK, const String& elementBtnStyle = StringUtil::BLANK, 
-			const String& foldoutBtnStyle = StringUtil::BLANK, const String& highlightBackgroundStyle = StringUtil::BLANK, 
-			const String& selectionBackgroundStyle = StringUtil::BLANK, const String& editBoxStyle = StringUtil::BLANK, 
-			const String& dragHighlightStyle = StringUtil::BLANK, const String& dragSepHighlightStyle = StringUtil::BLANK);
-
-		/**
-		 * Returns a list of paths of currently selected resources (if any). Returned paths are relative to the project
-		 * folder.
-		 */	
-		Vector<Path> getSelection() const;
-
-		/** Changes the active selection to the provided resources. Paths can be absolute or relative. */	
-		void setSelection(const Vector<Path>& paths);
-
-		/** Triggered whenever the selection changes. Call getSelection() to retrieve the new selection. */
-		Event<void()> onSelectionChanged; 
-
-		static const MessageId SELECTION_CHANGED_MSG;
-
-	protected:
-		virtual ~GUIResourceTreeView();
-
-	protected:
-		InternalDraggedResources* mDraggedResources;
-		ResourceTreeElement mRootElement;
-		RenderWindow* mCurrentWindow;
-		OSDropTarget* mDropTarget;
-		bool mDropTargetDragActive;
-
-		HEvent mDropTargetEnterConn;
-		HEvent mDropTargetMoveConn;
-		HEvent mDropTargetLeaveConn;
-		HEvent mDropTargetDroppedConn;
-
-		GUIResourceTreeView(const String& backgroundStyle, const String& elementBtnStyle, const String& foldoutBtnStyle, 
-			const String& highlightBackgroundStyle, const String& selectionBackgroundStyle, const String& editBoxStyle,
-			const String& dragHighlightStyle, const String& dragSepHighlightStyle, const GUIDimensions& dimensions);
-
-		/** @copydoc GUITreeView::_updateLayoutInternal */	
-		virtual void _updateLayoutInternal(const GUILayoutData& data) override;
-
-		/** @copydoc GUITreeView::getRootElement */	
-		virtual TreeElement& getRootElement() override { return mRootElement; }
-
-		/** @copydoc GUITreeView::getRootElementConst */	
-		virtual const TreeElement& getRootElementConst() const override { return mRootElement; }
-
-		/** @copydoc GUITreeView::updateTreeElementHierarchy */	
-		virtual void updateTreeElementHierarchy() override;
-
-		/** @copydoc GUITreeView::renameTreeElement */	
-		virtual void renameTreeElement(TreeElement* element, const WString& name) override;
-
-		/** @copydoc GUITreeView::deleteTreeElement */	
-		virtual void deleteTreeElement(TreeElement* element) override;
-
-		/** @copydoc GUITreeView::acceptDragAndDrop */	
-		virtual bool acceptDragAndDrop() const override;
-
-		/** @copydoc GUITreeView::dragAndDropStart */	
-		virtual void dragAndDropStart() override;
-
-		/** @copydoc GUITreeView::dragAndDropEnded */	
-		virtual void dragAndDropEnded(TreeElement* overTreeElement) override;
-
-		/** @copydoc GUITreeView::_acceptDragAndDrop */	
-		virtual bool _acceptDragAndDrop(const Vector2I position, UINT32 typeId) const override;
-
-		/** @copydoc GUITreeView::selectionChanged */	
-		virtual void selectionChanged() override;
-
-		/** @copydoc GUITreeView::_changeParentWidget */	
-		void _changeParentWidget(GUIWidget* widget) override;
-
-		/**
-		 * Triggered when a drag and drop operation that was started by the tree view ends, regardless if it was processed
-		 * or not.
-		 */
-		void dragAndDropFinalize();
-
-		/**	Updates the contents of the provided tree entry with a project library entry. */
-		void updateFromProjectLibraryEntry(ResourceTreeElement* treeElement, const ProjectLibrary::LibraryEntry* libraryEntry);
-
-		/**
-		 * Creates a new tree view entry.
-		 *
-		 * @param[in]	parent		Parent tree view entry to create the new one for.
-		 * @param[in]	fullPath	Absolute path to the new tree entry.
-		 */
-		ResourceTreeElement* addTreeElement(ResourceTreeElement* parent, const Path& fullPath);
-
-		/**	Deletes the provided tree element. */
-		void deleteTreeElement(ResourceTreeElement* element);
-
-		/**	Sorts the children of the provided tree element by name. */
-		void sortTreeElement(ResourceTreeElement* element);
-
-		/** Attempts to find a tree element with the specified path. Returns null if one cannot be found. */
-		ResourceTreeElement* findTreeElement(const Path& fullPath);
-
-		/**	Called whenever a new entry is added to the project library. */
-		void entryAdded(const Path& path); 
-
-		/**	Called whenever an entry is removed from the project library. */
-		void entryRemoved(const Path& path);
-
-		/**
-		 * Sets an OS drag and drop target that allows this element to receive OS-specific drag and drop events originating
-		 * from other processes.
-		 */
-		void setDropTarget(RenderWindow* parentWindow, INT32 x, INT32 y, UINT32 width, UINT32 height);
-
-		/**	Removes the currently set OS drop target. */
-		void clearDropTarget();
-
-		/**
-		 * Triggered whenever the user drags the pointer over the set drop target, while OS drag and drop operation is
-		 * active.
-		 *
-		 * @param[in]	x	X coordinate of the pointer, relative to drop area.
-		 * @param[in]	y	Y coordinate of the pointer, relative to drop area.
-		 */
-		void dropTargetDragMove(INT32 x, INT32 y);
-
-		/** Triggered whenever pointer leaves the drop target, while OS drag and drop operation is active. */
-		void dropTargetDragLeave();
-
-		/**
-		 * Triggered whenever the user releases the pointer over the set drop target, while OS drag and drop operation is
-		 * active.
-		 *
-		 * @param[in]	x	X coordinate of the pointer, relative to drop area.
-		 * @param[in]	y	Y coordinate of the pointer, relative to drop area.
-		 */
-		void dropTargetDragDropped(INT32 x, INT32 y);
-
-		/**	Generates a unique path in the case that something already exists on the provided one. */
-		Path findUniquePath(const Path& path);
-	};
-
-	typedef ServiceLocator<GUIResourceTreeView> ResourceTreeViewLocator;
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsServiceLocator.h"
+#include "BsGUITreeView.h"
+#include "BsProjectLibrary.h"
+#include "BsEvent.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup GUI-Editor
+	 *  @{
+	 */
+
+	/** Contains paths to resources currently involved in a drag and drop operation. */
+	struct DraggedResources
+	{
+		Vector<Path> resourcePaths;
+	};
+
+	/**	GUI element that displays all resources in the active project in a tree view. */
+	class GUIResourceTreeView : public GUITreeView
+	{
+		/**	Tree element with resource-specific data. */
+		struct ResourceTreeElement : public GUITreeView::TreeElement
+		{
+			Path mFullPath;
+			WString mElementName;
+		};
+
+		/** Contains paths to resources currently involved in a drag and drop operation initiated by this tree view. */
+		struct InternalDraggedResources
+		{
+			InternalDraggedResources(UINT32 numObjects);
+			~InternalDraggedResources();
+
+			UINT32 numObjects;
+			Path* resourcePaths;
+		};
+
+	public:
+		/** Returns type name of the GUI element used for finding GUI element styles. */
+		static const String& getGUITypeName();
+
+		/**
+		 * Creates a new resource tree view element.
+		 *
+		 * @param[in]	backgroundStyle				Name of the style for the tree view background.
+		 * @param[in]	elementBtnStyle				Name of the style for a normal tree view element.
+		 * @param[in]	foldoutBtnStyle				Name of the style for a foldout element (for example for a folder).
+		 * @param[in]	highlightBackgroundStyle	Name of the style for the background of highlighted elements.
+		 * @param[in]	selectionBackgroundStyle	Name of the style for the background of selected elements.
+		 * @param[in]	editBoxStyle				Name of the style for element that is being renamed.
+		 * @param[in]	dragHighlightStyle			Name of the style for the element being dragged over.
+		 * @param[in]	dragSepHighlightStyle		Name of the style for the separator displayed while dragging
+		 *											an element between two other elements.
+		 */	
+		static GUIResourceTreeView* create(
+			const String& backgroundStyle = StringUtil::BLANK, const String& elementBtnStyle = StringUtil::BLANK, 
+			const String& foldoutBtnStyle = StringUtil::BLANK, const String& highlightBackgroundStyle = StringUtil::BLANK,
+			const String& selectionBackgroundStyle = StringUtil::BLANK, const String& editBoxStyle = StringUtil::BLANK, 
+			const String& dragHighlightStyle = StringUtil::BLANK, const String& dragSepHighlightStyle = StringUtil::BLANK);
+
+		/**
+		 * Creates a new resource tree view element.
+		 *
+		 * @param[in]	options						Options that allow you to control how is the element positioned and 
+		 *											sized. This will override any similar options set by style.
+		 * @param[in]	backgroundStyle				Name of the style for the tree view background.
+		 * @param[in]	elementBtnStyle				Name of the style for a normal tree view element.
+		 * @param[in]	foldoutBtnStyle				Name of the style for a foldout element (for example for a folder).
+		 * @param[in]	highlightBackgroundStyle	Name of the style for the background of highlighted elements.
+		 * @param[in]	selectionBackgroundStyle	Name of the style for the background of selected elements.
+		 * @param[in]	editBoxStyle				Name of the style for element that is being renamed.
+		 * @param[in]	dragHighlightStyle			Name of the style for the element being dragged over.
+		 * @param[in]	dragSepHighlightStyle		Name of the style for the separator displayed while dragging an element
+		 *											between two other elements.
+		 */	
+		static GUIResourceTreeView* create(const GUIOptions& options, 
+			const String& backgroundStyle = StringUtil::BLANK, const String& elementBtnStyle = StringUtil::BLANK, 
+			const String& foldoutBtnStyle = StringUtil::BLANK, const String& highlightBackgroundStyle = StringUtil::BLANK, 
+			const String& selectionBackgroundStyle = StringUtil::BLANK, const String& editBoxStyle = StringUtil::BLANK, 
+			const String& dragHighlightStyle = StringUtil::BLANK, const String& dragSepHighlightStyle = StringUtil::BLANK);
+
+		/**
+		 * Returns a list of paths of currently selected resources (if any). Returned paths are relative to the project
+		 * folder.
+		 */	
+		Vector<Path> getSelection() const;
+
+		/** Changes the active selection to the provided resources. Paths can be absolute or relative. */	
+		void setSelection(const Vector<Path>& paths);
+
+		/** Triggered whenever the selection changes. Call getSelection() to retrieve the new selection. */
+		Event<void()> onSelectionChanged; 
+
+		static const MessageId SELECTION_CHANGED_MSG;
+
+	protected:
+		virtual ~GUIResourceTreeView();
+
+	protected:
+		InternalDraggedResources* mDraggedResources;
+		ResourceTreeElement mRootElement;
+		RenderWindow* mCurrentWindow;
+		OSDropTarget* mDropTarget;
+		bool mDropTargetDragActive;
+
+		HEvent mDropTargetEnterConn;
+		HEvent mDropTargetMoveConn;
+		HEvent mDropTargetLeaveConn;
+		HEvent mDropTargetDroppedConn;
+
+		GUIResourceTreeView(const String& backgroundStyle, const String& elementBtnStyle, const String& foldoutBtnStyle, 
+			const String& highlightBackgroundStyle, const String& selectionBackgroundStyle, const String& editBoxStyle,
+			const String& dragHighlightStyle, const String& dragSepHighlightStyle, const GUIDimensions& dimensions);
+
+		/** @copydoc GUITreeView::_updateLayoutInternal */	
+		virtual void _updateLayoutInternal(const GUILayoutData& data) override;
+
+		/** @copydoc GUITreeView::getRootElement */	
+		virtual TreeElement& getRootElement() override { return mRootElement; }
+
+		/** @copydoc GUITreeView::getRootElementConst */	
+		virtual const TreeElement& getRootElementConst() const override { return mRootElement; }
+
+		/** @copydoc GUITreeView::updateTreeElementHierarchy */	
+		virtual void updateTreeElementHierarchy() override;
+
+		/** @copydoc GUITreeView::renameTreeElement */	
+		virtual void renameTreeElement(TreeElement* element, const WString& name) override;
+
+		/** @copydoc GUITreeView::deleteTreeElement */	
+		virtual void deleteTreeElement(TreeElement* element) override;
+
+		/** @copydoc GUITreeView::acceptDragAndDrop */	
+		virtual bool acceptDragAndDrop() const override;
+
+		/** @copydoc GUITreeView::dragAndDropStart */	
+		virtual void dragAndDropStart() override;
+
+		/** @copydoc GUITreeView::dragAndDropEnded */	
+		virtual void dragAndDropEnded(TreeElement* overTreeElement) override;
+
+		/** @copydoc GUITreeView::_acceptDragAndDrop */	
+		virtual bool _acceptDragAndDrop(const Vector2I position, UINT32 typeId) const override;
+
+		/** @copydoc GUITreeView::selectionChanged */	
+		virtual void selectionChanged() override;
+
+		/** @copydoc GUITreeView::_changeParentWidget */	
+		void _changeParentWidget(GUIWidget* widget) override;
+
+		/**
+		 * Triggered when a drag and drop operation that was started by the tree view ends, regardless if it was processed
+		 * or not.
+		 */
+		void dragAndDropFinalize();
+
+		/**	Updates the contents of the provided tree entry with a project library entry. */
+		void updateFromProjectLibraryEntry(ResourceTreeElement* treeElement, const ProjectLibrary::LibraryEntry* libraryEntry);
+
+		/**
+		 * Creates a new tree view entry.
+		 *
+		 * @param[in]	parent		Parent tree view entry to create the new one for.
+		 * @param[in]	fullPath	Absolute path to the new tree entry.
+		 */
+		ResourceTreeElement* addTreeElement(ResourceTreeElement* parent, const Path& fullPath);
+
+		/**	Deletes the provided tree element. */
+		void deleteTreeElement(ResourceTreeElement* element);
+
+		/**	Sorts the children of the provided tree element by name. */
+		void sortTreeElement(ResourceTreeElement* element);
+
+		/** Attempts to find a tree element with the specified path. Returns null if one cannot be found. */
+		ResourceTreeElement* findTreeElement(const Path& fullPath);
+
+		/**	Called whenever a new entry is added to the project library. */
+		void entryAdded(const Path& path); 
+
+		/**	Called whenever an entry is removed from the project library. */
+		void entryRemoved(const Path& path);
+
+		/**
+		 * Sets an OS drag and drop target that allows this element to receive OS-specific drag and drop events originating
+		 * from other processes.
+		 */
+		void setDropTarget(RenderWindow* parentWindow, INT32 x, INT32 y, UINT32 width, UINT32 height);
+
+		/**	Removes the currently set OS drop target. */
+		void clearDropTarget();
+
+		/**
+		 * Triggered whenever the user drags the pointer over the set drop target, while OS drag and drop operation is
+		 * active.
+		 *
+		 * @param[in]	x	X coordinate of the pointer, relative to drop area.
+		 * @param[in]	y	Y coordinate of the pointer, relative to drop area.
+		 */
+		void dropTargetDragMove(INT32 x, INT32 y);
+
+		/** Triggered whenever pointer leaves the drop target, while OS drag and drop operation is active. */
+		void dropTargetDragLeave();
+
+		/**
+		 * Triggered whenever the user releases the pointer over the set drop target, while OS drag and drop operation is
+		 * active.
+		 *
+		 * @param[in]	x	X coordinate of the pointer, relative to drop area.
+		 * @param[in]	y	Y coordinate of the pointer, relative to drop area.
+		 */
+		void dropTargetDragDropped(INT32 x, INT32 y);
+
+		/**	Generates a unique path in the case that something already exists on the provided one. */
+		Path findUniquePath(const Path& path);
+	};
+
+	typedef ServiceLocator<GUIResourceTreeView> ResourceTreeViewLocator;
+
+	/** @} */
+	/** @endcond */
 }

+ 203 - 203
Source/BansheeEditor/Include/BsGUISceneTreeView.h

@@ -1,204 +1,204 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsEditorPrerequisites.h"
-#include "BsGUITreeView.h"
-#include "BsEvent.h"
-#include "BsServiceLocator.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup GUI-Editor
-	 *  @{
-	 */
-
-	/** Contains SceneObject%s currently involved in a drag and drop operation. */
-	struct BS_ED_EXPORT DraggedSceneObjects
-	{
-		DraggedSceneObjects(UINT32 numObjects);
-		~DraggedSceneObjects();
-
-		UINT32 numObjects;
-		HSceneObject* objects;
-	};
-
-	/** GUI element that displays all SceneObject%s in the current scene in the active project in a tree view. */
-	class BS_ED_EXPORT GUISceneTreeView : public GUITreeView
-	{
-		/**	Tree element with SceneObject%-specific data. */
-		struct SceneTreeElement : public GUITreeView::TreeElement
-		{
-			SceneTreeElement()
-				:mId(0), mIsPrefabInstance(false)
-			{ }
-
-			HSceneObject mSceneObject;
-			UINT64 mId;
-			bool mIsPrefabInstance;
-		};
-
-	public:
-		/** Returns type name of the GUI element used for finding GUI element styles. */
-		static const String& getGUITypeName();
-
-		/**
-		 * Creates a new resource tree view element.
-		 *
-		 * @param[in]	backgroundStyle				Name of the style for the tree view background.
-		 * @param[in]	elementBtnStyle				Name of the style for a normal tree view element.
-		 * @param[in]	foldoutBtnStyle				Name of the style for a foldout element (e.g. for a folder).
-		 * @param[in]	selectionBackgroundStyle	Name of the style for the background of selected elements.
-		 * @param[in]	highlightBackgroundStyle	Name of the style for the background of highlighted elements.
-		 * @param[in]	editBoxStyle				Name of the style for element that is being renamed.
-		 * @param[in]	dragHighlightStyle			Name of the style for the element being dragged over.
-		 * @param[in]	dragSepHighlightStyle		Name of the style for the separator displayed while dragging an element
-		 *											between two other elements.
-		 */	
-		static GUISceneTreeView* create(
-			const String& backgroundStyle = StringUtil::BLANK, const String& elementBtnStyle = StringUtil::BLANK, 
-			const String& foldoutBtnStyle = StringUtil::BLANK, const String& highlightBackgroundStyle = StringUtil::BLANK, 
-			const String& selectionBackgroundStyle = StringUtil::BLANK, const String& editBoxStyle = StringUtil::BLANK, 
-			const String& dragHighlightStyle = StringUtil::BLANK, const String& dragSepHighlightStyle = StringUtil::BLANK);
-
-		/**
-		 * Creates a new resource tree view element.
-		 *
-		 * @param[in]	options						Options that allow you to control how is the element positioned and 
-		 *											sized. This will override any similar options set by style.
-		 * @param[in]	backgroundStyle				Name of the style for the tree view background.
-		 * @param[in]	elementBtnStyle				Name of the style for a normal tree view element.
-		 * @param[in]	foldoutBtnStyle				Name of the style for a foldout element (e.g. for a folder).
-		 * @param[in]	highlightBackgroundStyle	Name of the style for the background of highlighted elements.
-		 * @param[in]	selectionBackgroundStyle	Name of the style for the background of selected elements.
-		 * @param[in]	editBoxStyle				Name of the style for element that is being renamed.
-		 * @param[in]	dragHighlightStyle			Name of the style for the element being dragged over.
-		 * @param[in]	dragSepHighlightStyle		Name of the style for the separator displayed while dragging an element
-		 *											between two other elements.
-		 */	
-		static GUISceneTreeView* create(const GUIOptions& options, 
-			const String& backgroundStyle = StringUtil::BLANK, const String& elementBtnStyle = StringUtil::BLANK, 
-			const String& foldoutBtnStyle = StringUtil::BLANK, const String& highlightBackgroundStyle = StringUtil::BLANK,
-			const String& selectionBackgroundStyle = StringUtil::BLANK, const String& editBoxStyle = StringUtil::BLANK, 
-			const String& dragHighlightStyle = StringUtil::BLANK, const String& dragSepHighlightStyle = StringUtil::BLANK);
-
-		/**	Returns a list of SceneObject&s currently selected (if any). */	
-		Vector<HSceneObject> getSelection() const;
-
-		/**	Changes the active selection to the provided SceneObject%s. */	
-		void setSelection(const Vector<HSceneObject>& objects);
-
-		/**	Scrolls to and highlights the selected object (does not select it). */
-		void ping(const HSceneObject& object);
-
-		/** @copydoc GUITreeView::duplicateSelection */
-		void duplicateSelection() override;
-
-		/** @copydoc GUITreeView::copySelection */
-		void copySelection() override;
-		
-		/** @copydoc GUITreeView::cutSelection */
-		void cutSelection() override;
-
-		/** @copydoc GUITreeView::paste */
-		void paste() override;
-
-		/** Triggered whenever the selection changes. Call getSelection() to retrieve new selection. */
-		Event<void()> onSelectionChanged; 
-
-		/** 
-		 * Triggered whenever the scene is modified in any way from within the scene tree view (e.g. object is deleted, 
-		 * added, etc.).
-		 */
-		Event<void()> onModified; 
-
-		/**
-		 * Triggered when a resource drag and drop operation finishes over the scene tree view. Provided scene object
-		 * is the tree view element that the operation finished over (or null if none), and the list of paths is the list 
-		 * of relative paths of the resources that were dropped.
-		 */
-		Event<void(const HSceneObject&, const Vector<Path>&)> onResourceDropped;
-		
-		static const MessageId SELECTION_CHANGED_MSG;
-	protected:
-		virtual ~GUISceneTreeView();
-
-	protected:
-		SceneTreeElement mRootElement;
-
-		GUISceneTreeView(const String& backgroundStyle, const String& elementBtnStyle, 
-			const String& foldoutBtnStyle, const String& highlightBackgroundStyle, const String& selectionBackgroundStyle, 
-			const String& editBoxStyle, const String& dragHighlightStyle, const String& dragSepHighlightStyle, const GUIDimensions& dimensions);
-
-		/**
-		 * Checks it the SceneObject referenced by this tree element changed in any way and updates the tree element. This
-		 * can involve recursing all children and updating them as well.
-		 */
-		void updateTreeElement(SceneTreeElement* element);
-
-		/**
-		 * Triggered when a drag and drop operation that was started by the tree view ends, regardless if it was processed
-		 * or not.
-		 */
-		void dragAndDropFinalize();
-
-		/** @copydoc TreeView::getRootElement */
-		virtual TreeElement& getRootElement() override { return mRootElement; }
-
-		/** @copydoc TreeView::getRootElementConst */
-		virtual const TreeElement& getRootElementConst() const override { return mRootElement; }
-
-		/** @copydoc TreeView::updateTreeElementHierarchy */
-		virtual void updateTreeElementHierarchy() override;
-
-		/** @copydoc TreeView::renameTreeElement */
-		virtual void renameTreeElement(TreeElement* element, const WString& name) override;
-
-		/** @copydoc TreeView::deleteTreeElement */
-		virtual void deleteTreeElement(TreeElement* element) override;
-
-		/** @copydoc TreeView::acceptDragAndDrop */
-		virtual bool acceptDragAndDrop() const override;
-
-		/** @copydoc TreeView::dragAndDropStart */
-		virtual void dragAndDropStart() override;
-
-		/** @copydoc TreeView::dragAndDropEnded */
-		virtual void dragAndDropEnded(TreeElement* overTreeElement) override;
-
-		/** @copydoc TreeView::_acceptDragAndDrop */
-		virtual bool _acceptDragAndDrop(const Vector2I position, UINT32 typeId) const override;
-
-		/** @copydoc TreeView::selectionChanged */
-		virtual void selectionChanged() override;
-
-		/** Deletes the internal TreeElement representation without actually deleting the referenced SceneObject. */
-		void deleteTreeElementInternal(TreeElement* element);
-
-		/**	Attempts to find a tree element referencing the specified scene object. */
-		SceneTreeElement* findTreeElement(const HSceneObject& so);
-
-		/**	Creates a new scene object as a child of the currently selected object (if any). */
-		void createNewSO();
-
-		/**	Removes all elements from the list used for copy/cut operations. */
-		void clearCopyList();
-
-		/**
-		 * Cleans duplicate objects from the provided scene object list. This involves removing child elements if their
-		 * parents are already part of the list.
-		 */
-		static void cleanDuplicates(Vector<HSceneObject>& objects);
-
-		Vector<HSceneObject> mCopyList;
-		bool mCutFlag;
-
-		static const Color PREFAB_TINT;
-	};
-
-	typedef ServiceLocator<GUISceneTreeView> SceneTreeViewLocator;
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsGUITreeView.h"
+#include "BsEvent.h"
+#include "BsServiceLocator.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup GUI-Editor
+	 *  @{
+	 */
+
+	/** Contains SceneObject%s currently involved in a drag and drop operation. */
+	struct BS_ED_EXPORT DraggedSceneObjects
+	{
+		DraggedSceneObjects(UINT32 numObjects);
+		~DraggedSceneObjects();
+
+		UINT32 numObjects;
+		HSceneObject* objects;
+	};
+
+	/** GUI element that displays all SceneObject%s in the current scene in the active project in a tree view. */
+	class BS_ED_EXPORT GUISceneTreeView : public GUITreeView
+	{
+		/**	Tree element with SceneObject%-specific data. */
+		struct SceneTreeElement : public GUITreeView::TreeElement
+		{
+			SceneTreeElement()
+				:mId(0), mIsPrefabInstance(false)
+			{ }
+
+			HSceneObject mSceneObject;
+			UINT64 mId;
+			bool mIsPrefabInstance;
+		};
+
+	public:
+		/** Returns type name of the GUI element used for finding GUI element styles. */
+		static const String& getGUITypeName();
+
+		/**
+		 * Creates a new resource tree view element.
+		 *
+		 * @param[in]	backgroundStyle				Name of the style for the tree view background.
+		 * @param[in]	elementBtnStyle				Name of the style for a normal tree view element.
+		 * @param[in]	foldoutBtnStyle				Name of the style for a foldout element (for example for a folder).
+		 * @param[in]	selectionBackgroundStyle	Name of the style for the background of selected elements.
+		 * @param[in]	highlightBackgroundStyle	Name of the style for the background of highlighted elements.
+		 * @param[in]	editBoxStyle				Name of the style for element that is being renamed.
+		 * @param[in]	dragHighlightStyle			Name of the style for the element being dragged over.
+		 * @param[in]	dragSepHighlightStyle		Name of the style for the separator displayed while dragging an element
+		 *											between two other elements.
+		 */	
+		static GUISceneTreeView* create(
+			const String& backgroundStyle = StringUtil::BLANK, const String& elementBtnStyle = StringUtil::BLANK, 
+			const String& foldoutBtnStyle = StringUtil::BLANK, const String& highlightBackgroundStyle = StringUtil::BLANK, 
+			const String& selectionBackgroundStyle = StringUtil::BLANK, const String& editBoxStyle = StringUtil::BLANK, 
+			const String& dragHighlightStyle = StringUtil::BLANK, const String& dragSepHighlightStyle = StringUtil::BLANK);
+
+		/**
+		 * Creates a new resource tree view element.
+		 *
+		 * @param[in]	options						Options that allow you to control how is the element positioned and 
+		 *											sized. This will override any similar options set by style.
+		 * @param[in]	backgroundStyle				Name of the style for the tree view background.
+		 * @param[in]	elementBtnStyle				Name of the style for a normal tree view element.
+		 * @param[in]	foldoutBtnStyle				Name of the style for a foldout element (for example for a folder).
+		 * @param[in]	highlightBackgroundStyle	Name of the style for the background of highlighted elements.
+		 * @param[in]	selectionBackgroundStyle	Name of the style for the background of selected elements.
+		 * @param[in]	editBoxStyle				Name of the style for element that is being renamed.
+		 * @param[in]	dragHighlightStyle			Name of the style for the element being dragged over.
+		 * @param[in]	dragSepHighlightStyle		Name of the style for the separator displayed while dragging an element
+		 *											between two other elements.
+		 */	
+		static GUISceneTreeView* create(const GUIOptions& options, 
+			const String& backgroundStyle = StringUtil::BLANK, const String& elementBtnStyle = StringUtil::BLANK, 
+			const String& foldoutBtnStyle = StringUtil::BLANK, const String& highlightBackgroundStyle = StringUtil::BLANK,
+			const String& selectionBackgroundStyle = StringUtil::BLANK, const String& editBoxStyle = StringUtil::BLANK, 
+			const String& dragHighlightStyle = StringUtil::BLANK, const String& dragSepHighlightStyle = StringUtil::BLANK);
+
+		/**	Returns a list of SceneObject&s currently selected (if any). */	
+		Vector<HSceneObject> getSelection() const;
+
+		/**	Changes the active selection to the provided SceneObject%s. */	
+		void setSelection(const Vector<HSceneObject>& objects);
+
+		/**	Scrolls to and highlights the selected object (does not select it). */
+		void ping(const HSceneObject& object);
+
+		/** @copydoc GUITreeView::duplicateSelection */
+		void duplicateSelection() override;
+
+		/** @copydoc GUITreeView::copySelection */
+		void copySelection() override;
+		
+		/** @copydoc GUITreeView::cutSelection */
+		void cutSelection() override;
+
+		/** @copydoc GUITreeView::paste */
+		void paste() override;
+
+		/** Triggered whenever the selection changes. Call getSelection() to retrieve new selection. */
+		Event<void()> onSelectionChanged; 
+
+		/** 
+		 * Triggered whenever the scene is modified in any way from within the scene tree view (for example object is 
+		 * deleted, added, etc.).
+		 */
+		Event<void()> onModified; 
+
+		/**
+		 * Triggered when a resource drag and drop operation finishes over the scene tree view. Provided scene object
+		 * is the tree view element that the operation finished over (or null if none), and the list of paths is the list 
+		 * of relative paths of the resources that were dropped.
+		 */
+		Event<void(const HSceneObject&, const Vector<Path>&)> onResourceDropped;
+		
+		static const MessageId SELECTION_CHANGED_MSG;
+	protected:
+		virtual ~GUISceneTreeView();
+
+	protected:
+		SceneTreeElement mRootElement;
+
+		GUISceneTreeView(const String& backgroundStyle, const String& elementBtnStyle, 
+			const String& foldoutBtnStyle, const String& highlightBackgroundStyle, const String& selectionBackgroundStyle, 
+			const String& editBoxStyle, const String& dragHighlightStyle, const String& dragSepHighlightStyle, const GUIDimensions& dimensions);
+
+		/**
+		 * Checks it the SceneObject referenced by this tree element changed in any way and updates the tree element. This
+		 * can involve recursing all children and updating them as well.
+		 */
+		void updateTreeElement(SceneTreeElement* element);
+
+		/**
+		 * Triggered when a drag and drop operation that was started by the tree view ends, regardless if it was processed
+		 * or not.
+		 */
+		void dragAndDropFinalize();
+
+		/** @copydoc TreeView::getRootElement */
+		virtual TreeElement& getRootElement() override { return mRootElement; }
+
+		/** @copydoc TreeView::getRootElementConst */
+		virtual const TreeElement& getRootElementConst() const override { return mRootElement; }
+
+		/** @copydoc TreeView::updateTreeElementHierarchy */
+		virtual void updateTreeElementHierarchy() override;
+
+		/** @copydoc TreeView::renameTreeElement */
+		virtual void renameTreeElement(TreeElement* element, const WString& name) override;
+
+		/** @copydoc TreeView::deleteTreeElement */
+		virtual void deleteTreeElement(TreeElement* element) override;
+
+		/** @copydoc TreeView::acceptDragAndDrop */
+		virtual bool acceptDragAndDrop() const override;
+
+		/** @copydoc TreeView::dragAndDropStart */
+		virtual void dragAndDropStart() override;
+
+		/** @copydoc TreeView::dragAndDropEnded */
+		virtual void dragAndDropEnded(TreeElement* overTreeElement) override;
+
+		/** @copydoc TreeView::_acceptDragAndDrop */
+		virtual bool _acceptDragAndDrop(const Vector2I position, UINT32 typeId) const override;
+
+		/** @copydoc TreeView::selectionChanged */
+		virtual void selectionChanged() override;
+
+		/** Deletes the internal TreeElement representation without actually deleting the referenced SceneObject. */
+		void deleteTreeElementInternal(TreeElement* element);
+
+		/**	Attempts to find a tree element referencing the specified scene object. */
+		SceneTreeElement* findTreeElement(const HSceneObject& so);
+
+		/**	Creates a new scene object as a child of the currently selected object (if any). */
+		void createNewSO();
+
+		/**	Removes all elements from the list used for copy/cut operations. */
+		void clearCopyList();
+
+		/**
+		 * Cleans duplicate objects from the provided scene object list. This involves removing child elements if their
+		 * parents are already part of the list.
+		 */
+		static void cleanDuplicates(Vector<HSceneObject>& objects);
+
+		Vector<HSceneObject> mCopyList;
+		bool mCutFlag;
+
+		static const Color PREFAB_TINT;
+	};
+
+	typedef ServiceLocator<GUISceneTreeView> SceneTreeViewLocator;
+
+	/** @} */
+	/** @endcond */
 }

+ 3 - 3
Source/BansheeEditor/Include/BsGUITreeView.h

@@ -20,8 +20,8 @@ namespace BansheeEngine
 	 *
 	 * Elements may be selected, renamed, dragged and re-parented.
 	 *
-	 * This class is abstract and meant to be extended by an implementation specific to some content type (e.g. scene object
-	 * hierarchy). 
+	 * This class is abstract and meant to be extended by an implementation specific to some content type (for example scene
+	 * object hierarchy). 
 	 */
 	class BS_ED_EXPORT GUITreeView : public GUIElementContainer
 	{
@@ -38,7 +38,7 @@ namespace BansheeEngine
 
 		/**
 		 * Contains data about a single piece of content and all its children. This element may be visible and represented
-		 * by a GUI element, but might not (e.g. its parent is collapsed).
+		 * by a GUI element, but might not (for example its parent is collapsed).
 		 */
 		struct TreeElement
 		{

+ 3 - 2
Source/BansheeEditor/Include/BsGizmoManager.h

@@ -20,7 +20,7 @@ namespace BansheeEngine
 
 	/**
 	 * Handles the rendering and picking of gizmo elements. Gizmos are icons and 3D objects usually rendered in scene view
-	 * for various visualization purposes (e.g. a Camera component will have a gizmo that draws a Camera icon since
+	 * for various visualization purposes (for example a Camera component will have a gizmo that draws a Camera icon since
 	 * otherwise it has no visual representation). Aside from being rendered, gizmos can also be selected by the user as if
 	 * they were normal scene elements.
 	 */
@@ -358,7 +358,8 @@ namespace BansheeEngine
 		void limitIconSize(UINT32& width, UINT32& height);
 
 		/**
-		 * Calculates colors for an icon based on its position in the camera. e.g. icons too close to too far might be faded.
+		 * Calculates colors for an icon based on its position in the camera. For example icons too close to too far might
+		 * be faded.
 		 *
 		 * @param[in]	tint		Primary tint for the icon.
 		 * @param[in]	camera		Camera in which the icon will be rendered in.

+ 384 - 384
Source/BansheeEditor/Include/BsProjectLibrary.h

@@ -1,385 +1,385 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsEditorPrerequisites.h"
-#include "BsModule.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Library
-	 *  @{
-	 */
-
-	/**
-	 * Project library is the primary location for interacting with all the resources in the current project. A complete
-	 * hierarchy of resources is provided which can be interacted with by importing new ones, deleting them, moving,
-	 * renaming and similar.
-	 */
-	class BS_ED_EXPORT ProjectLibrary : public Module<ProjectLibrary>
-	{
-	public:
-		struct LibraryEntry;
-		struct FileEntry;
-		struct DirectoryEntry;
-
-		/** Types of elements in the library, either a file or a folder. */
-		enum class LibraryEntryType
-		{
-			File,
-			Directory
-		};
-
-		/**	A generic library entry that may be a file or a folder depending on its type. */
-		struct LibraryEntry
-		{
-			LibraryEntry();
-			LibraryEntry(const Path& path, const WString& name, DirectoryEntry* parent, LibraryEntryType type);
-
-			LibraryEntryType type; /**< Specific type of this entry. */
-			Path path; /**< Absolute path to the entry. */
-			WString elementName; /**< Name of the entry. */
-
-			DirectoryEntry* parent; /**< Folder this entry is located in. */
-		};
-
-		/**	A library entry representing a file. Each file can have one or multiple resources. */
-		struct FileEntry : public LibraryEntry
-		{
-			FileEntry();
-			FileEntry(const Path& path, const WString& name, DirectoryEntry* parent);
-
-			ProjectFileMetaPtr meta; /**< Meta file containing various information about the resource(s). */
-			std::time_t lastUpdateTime; /**< Timestamp of when we last imported the resource. */
-		};
-
-		/**	A library entry representing a folder that contains other entries. */
-		struct DirectoryEntry : public LibraryEntry
-		{
-			DirectoryEntry();
-			DirectoryEntry(const Path& path, const WString& name, DirectoryEntry* parent);
-
-			Vector<LibraryEntry*> mChildren; /**< Child files or folders. */
-		};
-
-	public:
-		ProjectLibrary();
-		~ProjectLibrary();
-
-		/**
-		 * Checks if any resources at the specified path have been modified, added or deleted, and updates the internal
-		 * hierarchy accordingly. Automatically imports dirty resources.
-		 *
-		 * @param[in]	path	Absolute path of the file or folder to check. If a folder is provided all its children will
-		 *						be checked recursively.
-		 */
-		void checkForModifications(const Path& path);
-
-		/**
-		 * Checks if any resources at the specified path have been modified, added or deleted, and updates the internal
-		 * hierarchy accordingly. 
-		 *
-		 * @param[in]	path			Absolute path of the file or folder to check. If a folder is provided all its 
-		 *								children will be checked recursively.
-		 * @param[in]	import			Should the dirty resources be automatically reimported.
-		 * @param[in]	dirtyResources	A list of resources that should be reimported.
-		 */
-		void checkForModifications(const Path& path, bool import, Vector<Path>& dirtyResources);
-
-		/**	Returns the root library entry that references the entire library hierarchy. */
-		const LibraryEntry* getRootEntry() const { return mRootEntry; }
-
-		/**
-		 * Attempts to a find a library entry at the specified path.
-		 *
-		 * @param[in]	path	Path to the entry, either absolute or relative to resources folder.
-		 * @return				Found entry, or null if not found. Value returned by this method is transient, it may be
-		 *						destroyed on any following ProjectLibrary call.
-		 */
-		LibraryEntry* findEntry(const Path& path) const;
-
-		/** 
-		 * Checks whether the provided path points to a sub-resource. Sub-resource is any resource that is not the primary
-		 * resource in the file.
-		 */
-		bool isSubresource(const Path& path) const;
-
-		/**
-		 * Attempts to a find a meta information for a resource at the specified path.
-		 *
-		 * @param[in]	path	Path to the entry, either absolute or relative to resources folder. If a sub-resource within
-		 *						a file is needed, append the name of the subresource to the path 
-		 *						(e.g. mymesh.fbx/my_animation).
-		 * @return				Found meta information for the resource, or null if not found. 
-		 */
-		ProjectResourceMetaPtr findResourceMeta(const Path& path) const;
-
-		/**
-		 * Searches the library for a pattern and returns all entries matching it.
-		 *
-		 * @param[in]	pattern	Pattern to search for. Use wildcard * to match any character(s).
-		 * @return		A list of entries matching the pattern. Values returned by this method are transient, they may be
-		 *				destroyed on any following ProjectLibrary call.
-		 */
-		Vector<LibraryEntry*> search(const WString& pattern);
-
-		/**
-		 * Searches the library for a pattern, but only among specific resource types.
-		 *
-		 * @param[in]	pattern	Pattern to search for. Use wildcard * to match any character(s).
-		 * @param[in]	typeIds	RTTI type IDs of the resource types we're interested in searching.
-		 * @return		A list of entries matching the pattern. Values returned by this method are transient, they may be
-		 *				destroyed on any following ProjectLibrary call.
-		 */
-		Vector<LibraryEntry*> search(const WString& pattern, const Vector<UINT32>& typeIds);
-
-		/**
-		 * Returns resource path based on its UUID.
-		 *
-		 * @param[in]	uuid	UUID of the resource to look for.
-		 * @return				Absolute path to the resource.
-		 */
-		Path uuidToPath(const String& uuid) const;
-
-		/**
-		 * Registers a new resource in the library.
-		 *
-		 * @param[in]	resource	Resource instance to add to the library. A copy of the resource will be saved at the
-		 *							provided path.
-		 * @param[in]	path		Path where where to store the resource. Absolute or relative to the resources folder.
-		 */
-		void createEntry(const HResource& resource, const Path& path);
-
-		/**
-		 * Creates a new folder in the library.
-		 *
-		 * @param[in]	path		Path where where to store the folder. Absolute or relative to the resources folder.
-		 */
-		void createFolderEntry(const Path& path);
-
-		/**	Updates a resource that is already in the library. */
-		void saveEntry(const HResource& resource);
-
-		/**
-		 * Moves a library entry from one path to another.
-		 *
-		 * @param[in]	oldPath		Source path of the entry, absolute or relative to resources folder.
-		 * @param[in]	newPath		Destination path of the entry, absolute or relative to resources folder.
-		 * @param[in]	overwrite	If an entry already exists at the destination path, should it be overwritten.
-		 */
-		void moveEntry(const Path& oldPath, const Path& newPath, bool overwrite = true);
-
-		/**
-		 * Copies a library entry from one path to another.
-		 *
-		 * @param[in]	oldPath		Source path of the entry, absolute or relative to resources folder.
-		 * @param[in]	newPath		Destination path of the entry, absolute or relative to resources folder.
-		 * @param[in]	overwrite	If an entry already exists at the destination path, should it be overwritten.
-		 */
-		void copyEntry(const Path& oldPath, const Path& newPath, bool overwrite = true);
-
-		/**
-		 * Deletes an entry from the library.
-		 *
-		 * @param[in]	path		Path of the entry, absolute or relative to resources folder.
-		 */
-		void deleteEntry(const Path& path);
-
-		/**
-		 * Triggers a reimport of a resource using the provided import options, if needed.
-		 *
-		 * @param[in]	path			Path to the resource to reimport, absolute or relative to resources folder.
-		 * @param[in]	importOptions	Optional import options to use when importing the resource. Caller must ensure the
-		 *								import options are of the correct type for the resource in question. If null is
-		 *								provided default import options are used.
-		 * @param[in]	forceReimport	Should the resource be reimported even if no changes are detected. This should be
-		 *								true if import options changed since last import.
-		 */
-		void reimport(const Path& path, const ImportOptionsPtr& importOptions = nullptr, bool forceReimport = false);
-
-		/**
-		 * Determines if this resource will always be included in the build, regardless if it's being referenced or not.
-		 *
-		 * @param[in]	path	Path to the resource to modify, absolute or relative to resources folder.
-		 * @param[in]	force	True if we want the resource to be included in the build, false otherwise.
-		 */
-		void setIncludeInBuild(const Path& path, bool force);
-
-		/**
-		 * Finds all top-level resource entries that should be included in a build. Values returned by this method are
-		 * transient, they may be destroyed on any following ProjectLibrary call.
-		 */
-		Vector<FileEntry*> getResourcesForBuild() const;
-
-		/**
-		 * Loads a resource at the specified path, synchronously.
-		 *
-		 * @param[in]	path	Path of the resource, absolute or relative to resources folder. If a sub-resource within
-		 *						a file is needed, append the name of the subresource to the path 
-		 *						(e.g. mymesh.fbx/my_animation).
-		 * @return				Loaded resource, or null handle if one is not found.
-		 */
-		HResource load(const Path& path);
-
-		/** Returns the path to the project's resource folder where all the assets are stored. */
-		const Path& getResourcesFolder() const { return mResourcesFolder; }
-
-		/**	Returns the resource manifest managed by the project library. */
-		const ResourceManifestPtr& _getManifest() const { return mResourceManifest; }
-
-		/**
-		 * Saves all the project library data so it may be restored later, at the default save location in the project
-		 * folder. Project must be loaded when calling this.
-		 */
-		void saveLibrary();
-
-		/**
-		 * Loads previously saved project library data from the default save location in the project folder. Nothing is
-		 * loaded if it doesn't exist.Project must be loaded when calling this.
-		 */
-		void loadLibrary();
-
-		/**	Clears all library data. */
-		void unloadLibrary();
-
-		/** Triggered whenever an entry is removed from the library. Path provided is absolute. */
-		Event<void(const Path&)> onEntryRemoved; 
-
-		/** Triggered whenever an entry is added to the library. Path provided is absolute. */
-		Event<void(const Path&)> onEntryAdded; 
-
-		/** Triggered when a resource is being (re)imported. Path provided is absolute. */
-		Event<void(const Path&)> onEntryImported; 
-
-		static const Path RESOURCES_DIR;
-		static const Path INTERNAL_RESOURCES_DIR;
-	private:
-		/**
-		 * Common code for adding a new resource entry to the library.
-		 *
-		 * @param[in]	parent			Parent of the new entry.
-		 * @param[in]	filePath		Absolute path to the resource.
-		 * @param[in]	importOptions	Optional import options to use when importing the resource. Caller must ensure the
-		 *								import options are of the correct type for the resource in question. If null is 
-		 *								provided default import options are used.
-		 * @param[in]	forceReimport	Should the resource be reimported even if we detect no changes. This should be true
-		 *								if import options changed since last import.
-		 * @return						Newly added resource entry.
-		 */
-		FileEntry* addResourceInternal(DirectoryEntry* parent, const Path& filePath, 
-			const ImportOptionsPtr& importOptions = nullptr, bool forceReimport = false);
-
-		/**
-		 * Common code for adding a new folder entry to the library.
-		 *
-		 * @param[in]	parent	Parent of the new entry.
-		 * @param[in]	dirPath	Absolute path to the directory.
-		 * @return		Newly added directory entry.
-		 */
-		DirectoryEntry* addDirectoryInternal(DirectoryEntry* parent, const Path& dirPath);
-
-		/**
-		 * Common code for deleting a resource from the library. This code only removes the library entry, not the actual
-		 * resource file.
-		 *
-		 * @param[in]	resource	Entry to delete.
-		 */
-		void deleteResourceInternal(FileEntry* resource);
-
-		/**
-		 * Common code for deleting a directory from the library. This code only removes the library entry, not the actual
-		 * directory.
-		 *
-		 * @param[in]	resource	Entry to delete.
-		 */
-		void deleteDirectoryInternal(DirectoryEntry* directory);
-
-		/**
-		 * Triggers a reimport of a resource using the provided import options, if needed. Doesn't import dependencies.
-		 *
-		 * @param[in]	path				Absolute Path to the resource to reimport.
-		 * @param[in]	importOptions		Optional import options to use when importing the resource. Caller must ensure 
-		 *									the import options are of the correct type for the resource in question. If null
-		 *									is provided default import options are used.
-		 * @param[in]	forceReimport		Should the resource be reimported even if we detect no changes. This should be 
-		 *									true if import options changed since last import.
-		 * @param[in]	pruneResourceMetas	Determines should resource meta data for resources that no longer exist within
-		 *									the file be deleted. Default behaviour is to keep these alive so that if their
-		 *									resources are eventually restored, references to them will remain valid. If you
-		 *									feel that you need to clear this data, set this to true but be aware that you
-		 *									might need to re-apply those references.
-		 */
-		void reimportResourceInternal(FileEntry* file, const ImportOptionsPtr& importOptions = nullptr, 
-			bool forceReimport = false, bool pruneResourceMetas = false);
-
-		/**
-		 * Creates a full hierarchy of directory entries up to the provided directory, if any are needed.
-		 *
-		 * @param[in]	fullPath			Absolute path to a directory we are creating the hierarchy to.
-		 * @param[in]	newHierarchyRoot	First directory entry that already existed in our hierarchy.
-		 * @param[in]	newHierarchyLeaf	Leaf entry corresponding to the exact entry at \p path.
-		 */
-		void createInternalParentHierarchy(const Path& fullPath, DirectoryEntry** newHierarchyRoot, DirectoryEntry** newHierarchyLeaf);
-
-		/**	Checks has a file been modified since the last import. */
-		bool isUpToDate(FileEntry* file) const;
-
-		/**	Checks is the resource a native engine resource that doesn't require importing. */
-		bool isNative(const Path& path) const;
-
-		/**
-		 * Returns a path to a .meta file based on the resource path.
-		 *
-		 * @param[in]	path	Absolute path to the resource.
-		 * @return				Path to the .meta file.
-		 */
-		Path getMetaPath(const Path& path) const;
-		
-		/**	Checks does the path represent a .meta file. */
-		bool isMeta(const Path& fullPath) const;
-
-		/**
-		 * Returns a set of resource paths that are dependent on the provided resource entry. (e.g. a shader file might be
-		 * dependent on shader include file).
-		 */
-		Vector<Path> getImportDependencies(const FileEntry* entry);
-
-		/**	Registers any import dependencies for the specified resource. */
-		void addDependencies(const FileEntry* entry);
-
-		/**	Removes any import dependencies for the specified resource. */
-		void removeDependencies(const FileEntry* entry);
-
-		/**	Finds dependants resource for the specified resource entry and reimports them. */
-		void reimportDependants(const Path& entryPath);
-
-		/**	Makes all library entry paths relative to the current resources folder. */
-		void makeEntriesRelative();
-
-		/**
-		 * Makes all library entry paths absolute by appending them to the current resources folder. Entries must have
-		 * previously been made relative by calling makeEntriesRelative().
-		 */
-		void makeEntriesAbsolute();
-
-		/** Deletes all library entries. */
-		void clearEntries();
-
-		static const WString LIBRARY_ENTRIES_FILENAME;
-		static const WString RESOURCE_MANIFEST_FILENAME;
-
-		ResourceManifestPtr mResourceManifest;
-		DirectoryEntry* mRootEntry;
-		Path mProjectFolder;
-		Path mResourcesFolder;
-		bool mIsLoaded;
-
-		UnorderedMap<Path, Vector<Path>> mDependencies;
-		UnorderedMap<String, Path> mUUIDToPath;
-	};
-
-	/**	Provides easy access to ProjectLibrary. */
-	BS_ED_EXPORT ProjectLibrary& gProjectLibrary();
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsModule.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Library
+	 *  @{
+	 */
+
+	/**
+	 * Project library is the primary location for interacting with all the resources in the current project. A complete
+	 * hierarchy of resources is provided which can be interacted with by importing new ones, deleting them, moving,
+	 * renaming and similar.
+	 */
+	class BS_ED_EXPORT ProjectLibrary : public Module<ProjectLibrary>
+	{
+	public:
+		struct LibraryEntry;
+		struct FileEntry;
+		struct DirectoryEntry;
+
+		/** Types of elements in the library, either a file or a folder. */
+		enum class LibraryEntryType
+		{
+			File,
+			Directory
+		};
+
+		/**	A generic library entry that may be a file or a folder depending on its type. */
+		struct LibraryEntry
+		{
+			LibraryEntry();
+			LibraryEntry(const Path& path, const WString& name, DirectoryEntry* parent, LibraryEntryType type);
+
+			LibraryEntryType type; /**< Specific type of this entry. */
+			Path path; /**< Absolute path to the entry. */
+			WString elementName; /**< Name of the entry. */
+
+			DirectoryEntry* parent; /**< Folder this entry is located in. */
+		};
+
+		/**	A library entry representing a file. Each file can have one or multiple resources. */
+		struct FileEntry : public LibraryEntry
+		{
+			FileEntry();
+			FileEntry(const Path& path, const WString& name, DirectoryEntry* parent);
+
+			ProjectFileMetaPtr meta; /**< Meta file containing various information about the resource(s). */
+			std::time_t lastUpdateTime; /**< Timestamp of when we last imported the resource. */
+		};
+
+		/**	A library entry representing a folder that contains other entries. */
+		struct DirectoryEntry : public LibraryEntry
+		{
+			DirectoryEntry();
+			DirectoryEntry(const Path& path, const WString& name, DirectoryEntry* parent);
+
+			Vector<LibraryEntry*> mChildren; /**< Child files or folders. */
+		};
+
+	public:
+		ProjectLibrary();
+		~ProjectLibrary();
+
+		/**
+		 * Checks if any resources at the specified path have been modified, added or deleted, and updates the internal
+		 * hierarchy accordingly. Automatically imports dirty resources.
+		 *
+		 * @param[in]	path	Absolute path of the file or folder to check. If a folder is provided all its children will
+		 *						be checked recursively.
+		 */
+		void checkForModifications(const Path& path);
+
+		/**
+		 * Checks if any resources at the specified path have been modified, added or deleted, and updates the internal
+		 * hierarchy accordingly. 
+		 *
+		 * @param[in]	path			Absolute path of the file or folder to check. If a folder is provided all its 
+		 *								children will be checked recursively.
+		 * @param[in]	import			Should the dirty resources be automatically reimported.
+		 * @param[in]	dirtyResources	A list of resources that should be reimported.
+		 */
+		void checkForModifications(const Path& path, bool import, Vector<Path>& dirtyResources);
+
+		/**	Returns the root library entry that references the entire library hierarchy. */
+		const LibraryEntry* getRootEntry() const { return mRootEntry; }
+
+		/**
+		 * Attempts to a find a library entry at the specified path.
+		 *
+		 * @param[in]	path	Path to the entry, either absolute or relative to resources folder.
+		 * @return				Found entry, or null if not found. Value returned by this method is transient, it may be
+		 *						destroyed on any following ProjectLibrary call.
+		 */
+		LibraryEntry* findEntry(const Path& path) const;
+
+		/** 
+		 * Checks whether the provided path points to a sub-resource. Sub-resource is any resource that is not the primary
+		 * resource in the file.
+		 */
+		bool isSubresource(const Path& path) const;
+
+		/**
+		 * Attempts to a find a meta information for a resource at the specified path.
+		 *
+		 * @param[in]	path	Path to the entry, either absolute or relative to resources folder. If a sub-resource within
+		 *						a file is needed, append the name of the subresource to the path 
+		 *						(for example mymesh.fbx/my_animation).
+		 * @return				Found meta information for the resource, or null if not found. 
+		 */
+		ProjectResourceMetaPtr findResourceMeta(const Path& path) const;
+
+		/**
+		 * Searches the library for a pattern and returns all entries matching it.
+		 *
+		 * @param[in]	pattern	Pattern to search for. Use wildcard * to match any character(s).
+		 * @return		A list of entries matching the pattern. Values returned by this method are transient, they may be
+		 *				destroyed on any following ProjectLibrary call.
+		 */
+		Vector<LibraryEntry*> search(const WString& pattern);
+
+		/**
+		 * Searches the library for a pattern, but only among specific resource types.
+		 *
+		 * @param[in]	pattern	Pattern to search for. Use wildcard * to match any character(s).
+		 * @param[in]	typeIds	RTTI type IDs of the resource types we're interested in searching.
+		 * @return		A list of entries matching the pattern. Values returned by this method are transient, they may be
+		 *				destroyed on any following ProjectLibrary call.
+		 */
+		Vector<LibraryEntry*> search(const WString& pattern, const Vector<UINT32>& typeIds);
+
+		/**
+		 * Returns resource path based on its UUID.
+		 *
+		 * @param[in]	uuid	UUID of the resource to look for.
+		 * @return				Absolute path to the resource.
+		 */
+		Path uuidToPath(const String& uuid) const;
+
+		/**
+		 * Registers a new resource in the library.
+		 *
+		 * @param[in]	resource	Resource instance to add to the library. A copy of the resource will be saved at the
+		 *							provided path.
+		 * @param[in]	path		Path where where to store the resource. Absolute or relative to the resources folder.
+		 */
+		void createEntry(const HResource& resource, const Path& path);
+
+		/**
+		 * Creates a new folder in the library.
+		 *
+		 * @param[in]	path		Path where where to store the folder. Absolute or relative to the resources folder.
+		 */
+		void createFolderEntry(const Path& path);
+
+		/**	Updates a resource that is already in the library. */
+		void saveEntry(const HResource& resource);
+
+		/**
+		 * Moves a library entry from one path to another.
+		 *
+		 * @param[in]	oldPath		Source path of the entry, absolute or relative to resources folder.
+		 * @param[in]	newPath		Destination path of the entry, absolute or relative to resources folder.
+		 * @param[in]	overwrite	If an entry already exists at the destination path, should it be overwritten.
+		 */
+		void moveEntry(const Path& oldPath, const Path& newPath, bool overwrite = true);
+
+		/**
+		 * Copies a library entry from one path to another.
+		 *
+		 * @param[in]	oldPath		Source path of the entry, absolute or relative to resources folder.
+		 * @param[in]	newPath		Destination path of the entry, absolute or relative to resources folder.
+		 * @param[in]	overwrite	If an entry already exists at the destination path, should it be overwritten.
+		 */
+		void copyEntry(const Path& oldPath, const Path& newPath, bool overwrite = true);
+
+		/**
+		 * Deletes an entry from the library.
+		 *
+		 * @param[in]	path		Path of the entry, absolute or relative to resources folder.
+		 */
+		void deleteEntry(const Path& path);
+
+		/**
+		 * Triggers a reimport of a resource using the provided import options, if needed.
+		 *
+		 * @param[in]	path			Path to the resource to reimport, absolute or relative to resources folder.
+		 * @param[in]	importOptions	Optional import options to use when importing the resource. Caller must ensure the
+		 *								import options are of the correct type for the resource in question. If null is
+		 *								provided default import options are used.
+		 * @param[in]	forceReimport	Should the resource be reimported even if no changes are detected. This should be
+		 *								true if import options changed since last import.
+		 */
+		void reimport(const Path& path, const ImportOptionsPtr& importOptions = nullptr, bool forceReimport = false);
+
+		/**
+		 * Determines if this resource will always be included in the build, regardless if it's being referenced or not.
+		 *
+		 * @param[in]	path	Path to the resource to modify, absolute or relative to resources folder.
+		 * @param[in]	force	True if we want the resource to be included in the build, false otherwise.
+		 */
+		void setIncludeInBuild(const Path& path, bool force);
+
+		/**
+		 * Finds all top-level resource entries that should be included in a build. Values returned by this method are
+		 * transient, they may be destroyed on any following ProjectLibrary call.
+		 */
+		Vector<FileEntry*> getResourcesForBuild() const;
+
+		/**
+		 * Loads a resource at the specified path, synchronously.
+		 *
+		 * @param[in]	path	Path of the resource, absolute or relative to resources folder. If a sub-resource within
+		 *						a file is needed, append the name of the subresource to the path 
+		 *						(for example mymesh.fbx/my_animation).
+		 * @return				Loaded resource, or null handle if one is not found.
+		 */
+		HResource load(const Path& path);
+
+		/** Returns the path to the project's resource folder where all the assets are stored. */
+		const Path& getResourcesFolder() const { return mResourcesFolder; }
+
+		/**	Returns the resource manifest managed by the project library. */
+		const ResourceManifestPtr& _getManifest() const { return mResourceManifest; }
+
+		/**
+		 * Saves all the project library data so it may be restored later, at the default save location in the project
+		 * folder. Project must be loaded when calling this.
+		 */
+		void saveLibrary();
+
+		/**
+		 * Loads previously saved project library data from the default save location in the project folder. Nothing is
+		 * loaded if it doesn't exist.Project must be loaded when calling this.
+		 */
+		void loadLibrary();
+
+		/**	Clears all library data. */
+		void unloadLibrary();
+
+		/** Triggered whenever an entry is removed from the library. Path provided is absolute. */
+		Event<void(const Path&)> onEntryRemoved; 
+
+		/** Triggered whenever an entry is added to the library. Path provided is absolute. */
+		Event<void(const Path&)> onEntryAdded; 
+
+		/** Triggered when a resource is being (re)imported. Path provided is absolute. */
+		Event<void(const Path&)> onEntryImported; 
+
+		static const Path RESOURCES_DIR;
+		static const Path INTERNAL_RESOURCES_DIR;
+	private:
+		/**
+		 * Common code for adding a new resource entry to the library.
+		 *
+		 * @param[in]	parent			Parent of the new entry.
+		 * @param[in]	filePath		Absolute path to the resource.
+		 * @param[in]	importOptions	Optional import options to use when importing the resource. Caller must ensure the
+		 *								import options are of the correct type for the resource in question. If null is 
+		 *								provided default import options are used.
+		 * @param[in]	forceReimport	Should the resource be reimported even if we detect no changes. This should be true
+		 *								if import options changed since last import.
+		 * @return						Newly added resource entry.
+		 */
+		FileEntry* addResourceInternal(DirectoryEntry* parent, const Path& filePath, 
+			const ImportOptionsPtr& importOptions = nullptr, bool forceReimport = false);
+
+		/**
+		 * Common code for adding a new folder entry to the library.
+		 *
+		 * @param[in]	parent	Parent of the new entry.
+		 * @param[in]	dirPath	Absolute path to the directory.
+		 * @return		Newly added directory entry.
+		 */
+		DirectoryEntry* addDirectoryInternal(DirectoryEntry* parent, const Path& dirPath);
+
+		/**
+		 * Common code for deleting a resource from the library. This code only removes the library entry, not the actual
+		 * resource file.
+		 *
+		 * @param[in]	resource	Entry to delete.
+		 */
+		void deleteResourceInternal(FileEntry* resource);
+
+		/**
+		 * Common code for deleting a directory from the library. This code only removes the library entry, not the actual
+		 * directory.
+		 *
+		 * @param[in]	resource	Entry to delete.
+		 */
+		void deleteDirectoryInternal(DirectoryEntry* directory);
+
+		/**
+		 * Triggers a reimport of a resource using the provided import options, if needed. Doesn't import dependencies.
+		 *
+		 * @param[in]	path				Absolute Path to the resource to reimport.
+		 * @param[in]	importOptions		Optional import options to use when importing the resource. Caller must ensure 
+		 *									the import options are of the correct type for the resource in question. If null
+		 *									is provided default import options are used.
+		 * @param[in]	forceReimport		Should the resource be reimported even if we detect no changes. This should be 
+		 *									true if import options changed since last import.
+		 * @param[in]	pruneResourceMetas	Determines should resource meta data for resources that no longer exist within
+		 *									the file be deleted. Default behaviour is to keep these alive so that if their
+		 *									resources are eventually restored, references to them will remain valid. If you
+		 *									feel that you need to clear this data, set this to true but be aware that you
+		 *									might need to re-apply those references.
+		 */
+		void reimportResourceInternal(FileEntry* file, const ImportOptionsPtr& importOptions = nullptr, 
+			bool forceReimport = false, bool pruneResourceMetas = false);
+
+		/**
+		 * Creates a full hierarchy of directory entries up to the provided directory, if any are needed.
+		 *
+		 * @param[in]	fullPath			Absolute path to a directory we are creating the hierarchy to.
+		 * @param[in]	newHierarchyRoot	First directory entry that already existed in our hierarchy.
+		 * @param[in]	newHierarchyLeaf	Leaf entry corresponding to the exact entry at \p path.
+		 */
+		void createInternalParentHierarchy(const Path& fullPath, DirectoryEntry** newHierarchyRoot, DirectoryEntry** newHierarchyLeaf);
+
+		/**	Checks has a file been modified since the last import. */
+		bool isUpToDate(FileEntry* file) const;
+
+		/**	Checks is the resource a native engine resource that doesn't require importing. */
+		bool isNative(const Path& path) const;
+
+		/**
+		 * Returns a path to a .meta file based on the resource path.
+		 *
+		 * @param[in]	path	Absolute path to the resource.
+		 * @return				Path to the .meta file.
+		 */
+		Path getMetaPath(const Path& path) const;
+		
+		/**	Checks does the path represent a .meta file. */
+		bool isMeta(const Path& fullPath) const;
+
+		/**
+		 * Returns a set of resource paths that are dependent on the provided resource entry. (for example a shader file
+		 * might be dependent on shader include file).
+		 */
+		Vector<Path> getImportDependencies(const FileEntry* entry);
+
+		/**	Registers any import dependencies for the specified resource. */
+		void addDependencies(const FileEntry* entry);
+
+		/**	Removes any import dependencies for the specified resource. */
+		void removeDependencies(const FileEntry* entry);
+
+		/**	Finds dependants resource for the specified resource entry and reimports them. */
+		void reimportDependants(const Path& entryPath);
+
+		/**	Makes all library entry paths relative to the current resources folder. */
+		void makeEntriesRelative();
+
+		/**
+		 * Makes all library entry paths absolute by appending them to the current resources folder. Entries must have
+		 * previously been made relative by calling makeEntriesRelative().
+		 */
+		void makeEntriesAbsolute();
+
+		/** Deletes all library entries. */
+		void clearEntries();
+
+		static const WString LIBRARY_ENTRIES_FILENAME;
+		static const WString RESOURCE_MANIFEST_FILENAME;
+
+		ResourceManifestPtr mResourceManifest;
+		DirectoryEntry* mRootEntry;
+		Path mProjectFolder;
+		Path mResourcesFolder;
+		bool mIsLoaded;
+
+		UnorderedMap<Path, Vector<Path>> mDependencies;
+		UnorderedMap<String, Path> mUUIDToPath;
+	};
+
+	/**	Provides easy access to ProjectLibrary. */
+	BS_ED_EXPORT ProjectLibrary& gProjectLibrary();
+
+	/** @} */
 }

+ 344 - 344
Source/BansheeEngine/Include/BsBuiltinResources.h

@@ -1,345 +1,345 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsGUISkin.h"
-#include "BsModule.h"
-#include "BsVector2I.h"
-#include "BsApplication.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Resources-Engine
-	 *  @{
-	 */
-
-	/**	Types of builtin meshes that are always available in the engine. */
-	enum class BuiltinMesh
-	{
-		Box, Sphere, Cone, Quad, Disc
-	};
-
-	/**	Types of builtin textures that are always available in the engine. */
-	enum class BuiltinTexture
-	{
-		White, Black, Normal
-	};
-
-	/**	Holds references to built-in resources used by the core engine. */
-	class BS_EXPORT BuiltinResources : public BansheeEngine::Module<BuiltinResources>
-	{
-	public:
-		BuiltinResources();
-		~BuiltinResources();
-
-		/**	Returns the default skin used by engine GUI elements. */
-		const HGUISkin& getGUISkin() const { return mSkin; }
-
-		/**	Returns an empty skin used to be used when no other is available. */
-		const HGUISkin& getEmptyGUISkin() const { return mEmptySkin; }
-
-		/**	Returns a small entirely white texture. */
-		const HSpriteTexture& getWhiteSpriteTexture() const { return mWhiteSpriteTexture; }
-
-		/**	Returns a 2x2 sprite texture that can be used when no other is available. */
-		const HSpriteTexture& getDummySpriteTexture() const { return mDummySpriteTexture; }
-
-		/**	Returns a dummy 2x2 texture that may be used when no other is available. Don't modify the returned texture. */
-		const HTexture& getDummyTexture() const { return mDummyTexture; }
-
-		/**	Returns image data for an arrow cursor, along with its hotspot. */
-		const PixelData& getCursorArrow(Vector2I& hotSpot);
-
-		/**	Returns image data for an arrow with dragged object cursor, along with its hotspot. */
-		const PixelData& getCursorArrowDrag(Vector2I& hotSpot);
-		
-		/**	Returns image data for a wait cursor, along with its hotspot. */
-		const PixelData& getCursorWait(Vector2I& hotSpot);
-		
-		/**	Returns image data for an "I" beam cursor, along with its hotspot. */
-		const PixelData& getCursorIBeam(Vector2I& hotSpot);
-		
-		/**	Returns image data for a NESW resize cursor, along with its hotspot. */
-		const PixelData& getCursorSizeNESW(Vector2I& hotSpot);
-		
-		/**	Returns image data for a NS resize cursor, along with its hotspot. */
-		const PixelData& getCursorSizeNS(Vector2I& hotSpot);
-		
-		/**	Returns image data for a NWSE resize cursor, along with its hotspot. */
-		const PixelData& getCursorSizeNWSE(Vector2I& hotSpot);
-		
-		/**	Returns image data for a WE resize cursor, along with its hotspot. */
-		const PixelData& getCursorSizeWE(Vector2I& hotSpot);
-		
-		/**	Returns image data for a deny cursor, along with its hotspot. */
-		const PixelData& getCursorDeny(Vector2I& hotSpot);
-		
-		/**	Returns image data for a move left-right cursor, along with its hotspot. */
-		const PixelData& getCursorMoveLeftRight(Vector2I& hotSpot);
-
-		/**	Returns the default application icon. */
-		const PixelData& getBansheeIcon();
-
-		/**	Returns a shader used for rendering only a diffuse texture. */
-		HShader getDiffuseShader() const { return mShaderDiffuse; }
-
-		/**	Creates material used for textual sprite rendering (e.g. text in GUI). */
-		HMaterial createSpriteTextMaterial() const;
-
-		/**	Creates material used for image sprite rendering (e.g. images in GUI). */
-		HMaterial createSpriteImageMaterial() const;
-
-		/**	Creates material used for non-transparent image sprite rendering (e.g. images in GUI). */
-		HMaterial createSpriteNonAlphaImageMaterial() const;
-
-		/**	Retrieves one of the builtin meshes. */
-		HMesh getMesh(BuiltinMesh mesh) const;
-
-		/**
-		 * Loads a shader at the specified path.
-		 * 
-		 * @param[in]	Path relative to the default shader folder with no file extension.
-		 */
-		HShader getShader(const Path& path);
-
-		/**	Retrieves one of the builtin textures. */
-		static HTexture getTexture(BuiltinTexture type);
-
-		/**	Returns image data the Banshee Engine splash screen. */
-		static PixelDataPtr getSplashScreen();
-
-		/**	Returns path to the builtin shader include folder, relative to the working directory. */
-		static Path getShaderIncludeFolder();
-
-		/**	Returns path to the builtin icons folder, relative to the working directory. */
-		static Path getIconFolder();
-
-		static const WString IconTextureName;
-
-		static const String MultiLineLabelStyle;
-	private:
-		/**
-		 * Imports all necessary resources and converts them to engine-ready format.
-		 *
-		 * @note	
-		 * Normally you only want to use this during development phase and then ship with engine-ready format only.
-		 */
-		void preprocess();
-
-		/**	Generates the default engine skin and all GUI element styles. */
-		GUISkinPtr generateGUISkin();
-
-		/**	Generates the builtin meshes. */
-		void generateMeshes();
-
-		/**	Generates the builtin textures. */
-		void generateTextures();
-
-		/**	Loads a GUI skin texture with the specified filename. */
-		HSpriteTexture getSkinTexture(const WString& name);
-
-		/**	Loads a cursor texture with the specified filename. */
-		HTexture getCursorTexture(const WString& name);
-
-		HGUISkin mEmptySkin;
-		HGUISkin mSkin;
-
-		PixelDataPtr mCursorArrow;
-		PixelDataPtr mCursorArrowDrag;
-		PixelDataPtr mCursorArrowLeftRight;
-		PixelDataPtr mCursorIBeam;
-		PixelDataPtr mCursorDeny;
-		PixelDataPtr mCursorWait;
-		PixelDataPtr mCursorSizeNESW;
-		PixelDataPtr mCursorSizeNS;
-		PixelDataPtr mCursorSizeNWSE;
-		PixelDataPtr mCursorSizeWE;
-		PixelDataPtr mBansheeIcon;
-
-		HSpriteTexture mWhiteSpriteTexture;
-		HSpriteTexture mDummySpriteTexture;
-
-		HTexture mDummyTexture;
-
-		HShader mShaderSpriteText;
-		HShader mShaderSpriteImage;
-		HShader mShaderSpriteNonAlphaImage;
-		HShader mShaderDiffuse;
-
-		ResourceManifestPtr mResourceManifest;
-
-		Path mBuiltinRawDataFolder;
-		Path mEngineRawCursorFolder;
-		Path mEngineRawIconFolder;
-		Path mEngineRawShaderFolder;
-		Path mEngineRawShaderIncludeFolder;
-		Path mEngineRawSkinFolder;
-
-		Path mBuiltinDataFolder;
-		Path mEngineSkinFolder;
-		Path mEngineCursorFolder;
-		Path mEngineIconFolder;
-		Path mEngineShaderFolder;
-		Path mEngineShaderIncludeFolder;
-		Path mEngineMeshFolder;
-		Path mEngineTextureFolder;
-
-		Path ResourceManifestPath;
-
-		static const char* CursorFolder;
-		static const char* IconFolder;
-		static const char* ShaderFolder;
-		static const char* ShaderIncludeFolder;
-		static const char* SkinFolder;
-		static const char* MeshFolder;
-		static const char* TextureFolder;
-
-		static const WString DefaultFontFilename;
-		static const UINT32 DefaultFontSize;
-
-		static const Color TextNormalColor;
-		static const Color TextActiveColor;
-
-		static const WString GUISkinFile;
-		static const WString WhiteTex;
-		static const wchar_t* SplashScreenName;
-
-		static const WString ButtonNormalTex;
-		static const WString ButtonHoverTex;
-		static const WString ButtonActiveTex;
-
-		static const WString ToggleNormalTex;
-		static const WString ToggleHoverTex;
-		static const WString ToggleNormalOnTex;
-		static const WString ToggleHoverOnTex;
-
-		static const WString InputBoxNormalTex;
-		static const WString InputBoxHoverTex;
-		static const WString InputBoxFocusedTex;
-
-		static const WString ScrollBarUpNormalTex;
-		static const WString ScrollBarUpHoverTex;
-		static const WString ScrollBarUpActiveTex;
-
-		static const WString ScrollBarDownNormalTex;
-		static const WString ScrollBarDownHoverTex;
-		static const WString ScrollBarDownActiveTex;
-
-		static const WString ScrollBarLeftNormalTex;
-		static const WString ScrollBarLeftHoverTex;
-		static const WString ScrollBarLeftActiveTex;
-
-		static const WString ScrollBarRightNormalTex;
-		static const WString ScrollBarRightHoverTex;
-		static const WString ScrollBarRightActiveTex;
-
-		static const WString ScrollBarHandleHorzNormalTex;
-		static const WString ScrollBarHandleHorzHoverTex;
-		static const WString ScrollBarHandleHorzActiveTex;
-
-		static const WString ScrollBarHandleVertNormalTex;
-		static const WString ScrollBarHandleVertHoverTex;
-		static const WString ScrollBarHandleVertActiveTex;
-
-		static const WString ScrollBarHBgTex;
-		static const WString ScrollBarVBgTex;
-
-		static const WString DropDownBtnNormalTex;
-		static const WString DropDownBtnHoverTex;
-		static const WString DropDownBtnActiveTex;
-
-		static const WString DropDownBoxBgTex;
-		static const WString DropDownBoxSideBgTex;
-		static const WString DropDownBoxHandleTex;
-
-		static const WString DropDownBoxEntryNormalTex;
-		static const WString DropDownBoxEntryHoverTex;
-
-		static const WString DropDownBoxBtnUpNormalTex;
-		static const WString DropDownBoxBtnUpHoverTex;
-
-		static const WString DropDownBoxBtnDownNormalTex;
-		static const WString DropDownBoxBtnDownHoverTex;
-
-		static const WString DropDownBoxEntryExpNormalTex;
-		static const WString DropDownBoxEntryExpHoverTex;
-
-		static const WString DropDownSeparatorTex;
-
-		static const WString CursorArrowTex;
-		static const WString CursorArrowDragTex;
-		static const WString CursorArrowLeftRightTex;
-		static const WString CursorIBeamTex;
-		static const WString CursorDenyTex;
-		static const WString CursorWaitTex;
-		static const WString CursorSizeNESWTex;
-		static const WString CursorSizeNSTex;
-		static const WString CursorSizeNWSETex;
-		static const WString CursorSizeWETex;
-
-		static const Vector2I CursorArrowHotspot;
-		static const Vector2I CursorArrowDragHotspot;
-		static const Vector2I CursorArrowLeftRightHotspot;
-		static const Vector2I CursorIBeamHotspot;
-		static const Vector2I CursorDenyHotspot;
-		static const Vector2I CursorWaitHotspot;
-		static const Vector2I CursorSizeNESWHotspot;
-		static const Vector2I CursorSizeNSHotspot;
-		static const Vector2I CursorSizeNWSEHotspot;
-		static const Vector2I CursorSizeWEHotspot;
-
-		static const WString ShaderSpriteTextFile;
-		static const WString ShaderSpriteImageAlphaFile;
-		static const WString ShaderSpriteImageNoAlphaFile;
-		static const WString ShaderDiffuseFile;
-
-		static const WString MeshSphereFile;
-		static const WString MeshBoxFile;
-		static const WString MeshConeFile;
-		static const WString MeshQuadFile;
-		static const WString MeshDiscFile;
-
-		static const WString TextureWhiteFile;
-		static const WString TextureBlackFile;
-		static const WString TextureNormalFile;
-	};
-
-	/** @cond INTERNAL */
-
-	/**	Provides various methods commonly used for managing builtin resources. */
-	class BS_EXPORT BuiltinResourcesHelper
-	{
-	public:
-		/**
-		 * Imports all recognized assets in the specified folder and saves them to the specified output folder. All saved
-		 * resources are registered in the provided resource manifest.
-		 */
-		static void importAssets(const Path& inputFolder, const Path& outputFolder, const ResourceManifestPtr& manifest);
-
-		/**
-		 * Imports a font from the specified file. Imported font assets are saved in the output folder. All saved resources
-		 * are registered in the provided resource manifest.
-		 */
-		static void importFont(const Path& inputFile, const WString& outputName, const Path& outputFolder, 
-			const Vector<UINT32>& fontSizes, bool antialiasing, const ResourceManifestPtr& manifest);
-
-		/**
-		 * Generates sprite textures for all texture assets in the specified folder. Results are written in the same folder
-		 * with a "sprite_" prefix. All saved resources are registered in the provided resource manifest.
-		 */
-		static void generateSpriteTextures(const Path& folder, const ResourceManifestPtr& manifest);
-
-		/** Writes a timestamp with the current date and time in the specified file. */
-		static void writeTimestamp(const Path& file);
-
-		/**
-		 * Checks all files in the specified folder for modifications compared to the time stored in the timestamp file. 
-		 * Timestamp file must have been saved using writeTimestamp().
-		 */
-		static bool checkForModifications(const Path& folder, const Path& timeStampFile);
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsGUISkin.h"
+#include "BsModule.h"
+#include "BsVector2I.h"
+#include "BsApplication.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Resources-Engine
+	 *  @{
+	 */
+
+	/**	Types of builtin meshes that are always available in the engine. */
+	enum class BuiltinMesh
+	{
+		Box, Sphere, Cone, Quad, Disc
+	};
+
+	/**	Types of builtin textures that are always available in the engine. */
+	enum class BuiltinTexture
+	{
+		White, Black, Normal
+	};
+
+	/**	Holds references to built-in resources used by the core engine. */
+	class BS_EXPORT BuiltinResources : public BansheeEngine::Module<BuiltinResources>
+	{
+	public:
+		BuiltinResources();
+		~BuiltinResources();
+
+		/**	Returns the default skin used by engine GUI elements. */
+		const HGUISkin& getGUISkin() const { return mSkin; }
+
+		/**	Returns an empty skin used to be used when no other is available. */
+		const HGUISkin& getEmptyGUISkin() const { return mEmptySkin; }
+
+		/**	Returns a small entirely white texture. */
+		const HSpriteTexture& getWhiteSpriteTexture() const { return mWhiteSpriteTexture; }
+
+		/**	Returns a 2x2 sprite texture that can be used when no other is available. */
+		const HSpriteTexture& getDummySpriteTexture() const { return mDummySpriteTexture; }
+
+		/**	Returns a dummy 2x2 texture that may be used when no other is available. Don't modify the returned texture. */
+		const HTexture& getDummyTexture() const { return mDummyTexture; }
+
+		/**	Returns image data for an arrow cursor, along with its hotspot. */
+		const PixelData& getCursorArrow(Vector2I& hotSpot);
+
+		/**	Returns image data for an arrow with dragged object cursor, along with its hotspot. */
+		const PixelData& getCursorArrowDrag(Vector2I& hotSpot);
+		
+		/**	Returns image data for a wait cursor, along with its hotspot. */
+		const PixelData& getCursorWait(Vector2I& hotSpot);
+		
+		/**	Returns image data for an "I" beam cursor, along with its hotspot. */
+		const PixelData& getCursorIBeam(Vector2I& hotSpot);
+		
+		/**	Returns image data for a NESW resize cursor, along with its hotspot. */
+		const PixelData& getCursorSizeNESW(Vector2I& hotSpot);
+		
+		/**	Returns image data for a NS resize cursor, along with its hotspot. */
+		const PixelData& getCursorSizeNS(Vector2I& hotSpot);
+		
+		/**	Returns image data for a NWSE resize cursor, along with its hotspot. */
+		const PixelData& getCursorSizeNWSE(Vector2I& hotSpot);
+		
+		/**	Returns image data for a WE resize cursor, along with its hotspot. */
+		const PixelData& getCursorSizeWE(Vector2I& hotSpot);
+		
+		/**	Returns image data for a deny cursor, along with its hotspot. */
+		const PixelData& getCursorDeny(Vector2I& hotSpot);
+		
+		/**	Returns image data for a move left-right cursor, along with its hotspot. */
+		const PixelData& getCursorMoveLeftRight(Vector2I& hotSpot);
+
+		/**	Returns the default application icon. */
+		const PixelData& getBansheeIcon();
+
+		/**	Returns a shader used for rendering only a diffuse texture. */
+		HShader getDiffuseShader() const { return mShaderDiffuse; }
+
+		/**	Creates material used for textual sprite rendering (for example text in GUI). */
+		HMaterial createSpriteTextMaterial() const;
+
+		/**	Creates material used for image sprite rendering (for example images in GUI). */
+		HMaterial createSpriteImageMaterial() const;
+
+		/**	Creates material used for non-transparent image sprite rendering (for example images in GUI). */
+		HMaterial createSpriteNonAlphaImageMaterial() const;
+
+		/**	Retrieves one of the builtin meshes. */
+		HMesh getMesh(BuiltinMesh mesh) const;
+
+		/**
+		 * Loads a shader at the specified path.
+		 * 
+		 * @param[in]	Path relative to the default shader folder with no file extension.
+		 */
+		HShader getShader(const Path& path);
+
+		/**	Retrieves one of the builtin textures. */
+		static HTexture getTexture(BuiltinTexture type);
+
+		/**	Returns image data the Banshee Engine splash screen. */
+		static PixelDataPtr getSplashScreen();
+
+		/**	Returns path to the builtin shader include folder, relative to the working directory. */
+		static Path getShaderIncludeFolder();
+
+		/**	Returns path to the builtin icons folder, relative to the working directory. */
+		static Path getIconFolder();
+
+		static const WString IconTextureName;
+
+		static const String MultiLineLabelStyle;
+	private:
+		/**
+		 * Imports all necessary resources and converts them to engine-ready format.
+		 *
+		 * @note	
+		 * Normally you only want to use this during development phase and then ship with engine-ready format only.
+		 */
+		void preprocess();
+
+		/**	Generates the default engine skin and all GUI element styles. */
+		GUISkinPtr generateGUISkin();
+
+		/**	Generates the builtin meshes. */
+		void generateMeshes();
+
+		/**	Generates the builtin textures. */
+		void generateTextures();
+
+		/**	Loads a GUI skin texture with the specified filename. */
+		HSpriteTexture getSkinTexture(const WString& name);
+
+		/**	Loads a cursor texture with the specified filename. */
+		HTexture getCursorTexture(const WString& name);
+
+		HGUISkin mEmptySkin;
+		HGUISkin mSkin;
+
+		PixelDataPtr mCursorArrow;
+		PixelDataPtr mCursorArrowDrag;
+		PixelDataPtr mCursorArrowLeftRight;
+		PixelDataPtr mCursorIBeam;
+		PixelDataPtr mCursorDeny;
+		PixelDataPtr mCursorWait;
+		PixelDataPtr mCursorSizeNESW;
+		PixelDataPtr mCursorSizeNS;
+		PixelDataPtr mCursorSizeNWSE;
+		PixelDataPtr mCursorSizeWE;
+		PixelDataPtr mBansheeIcon;
+
+		HSpriteTexture mWhiteSpriteTexture;
+		HSpriteTexture mDummySpriteTexture;
+
+		HTexture mDummyTexture;
+
+		HShader mShaderSpriteText;
+		HShader mShaderSpriteImage;
+		HShader mShaderSpriteNonAlphaImage;
+		HShader mShaderDiffuse;
+
+		ResourceManifestPtr mResourceManifest;
+
+		Path mBuiltinRawDataFolder;
+		Path mEngineRawCursorFolder;
+		Path mEngineRawIconFolder;
+		Path mEngineRawShaderFolder;
+		Path mEngineRawShaderIncludeFolder;
+		Path mEngineRawSkinFolder;
+
+		Path mBuiltinDataFolder;
+		Path mEngineSkinFolder;
+		Path mEngineCursorFolder;
+		Path mEngineIconFolder;
+		Path mEngineShaderFolder;
+		Path mEngineShaderIncludeFolder;
+		Path mEngineMeshFolder;
+		Path mEngineTextureFolder;
+
+		Path ResourceManifestPath;
+
+		static const char* CursorFolder;
+		static const char* IconFolder;
+		static const char* ShaderFolder;
+		static const char* ShaderIncludeFolder;
+		static const char* SkinFolder;
+		static const char* MeshFolder;
+		static const char* TextureFolder;
+
+		static const WString DefaultFontFilename;
+		static const UINT32 DefaultFontSize;
+
+		static const Color TextNormalColor;
+		static const Color TextActiveColor;
+
+		static const WString GUISkinFile;
+		static const WString WhiteTex;
+		static const wchar_t* SplashScreenName;
+
+		static const WString ButtonNormalTex;
+		static const WString ButtonHoverTex;
+		static const WString ButtonActiveTex;
+
+		static const WString ToggleNormalTex;
+		static const WString ToggleHoverTex;
+		static const WString ToggleNormalOnTex;
+		static const WString ToggleHoverOnTex;
+
+		static const WString InputBoxNormalTex;
+		static const WString InputBoxHoverTex;
+		static const WString InputBoxFocusedTex;
+
+		static const WString ScrollBarUpNormalTex;
+		static const WString ScrollBarUpHoverTex;
+		static const WString ScrollBarUpActiveTex;
+
+		static const WString ScrollBarDownNormalTex;
+		static const WString ScrollBarDownHoverTex;
+		static const WString ScrollBarDownActiveTex;
+
+		static const WString ScrollBarLeftNormalTex;
+		static const WString ScrollBarLeftHoverTex;
+		static const WString ScrollBarLeftActiveTex;
+
+		static const WString ScrollBarRightNormalTex;
+		static const WString ScrollBarRightHoverTex;
+		static const WString ScrollBarRightActiveTex;
+
+		static const WString ScrollBarHandleHorzNormalTex;
+		static const WString ScrollBarHandleHorzHoverTex;
+		static const WString ScrollBarHandleHorzActiveTex;
+
+		static const WString ScrollBarHandleVertNormalTex;
+		static const WString ScrollBarHandleVertHoverTex;
+		static const WString ScrollBarHandleVertActiveTex;
+
+		static const WString ScrollBarHBgTex;
+		static const WString ScrollBarVBgTex;
+
+		static const WString DropDownBtnNormalTex;
+		static const WString DropDownBtnHoverTex;
+		static const WString DropDownBtnActiveTex;
+
+		static const WString DropDownBoxBgTex;
+		static const WString DropDownBoxSideBgTex;
+		static const WString DropDownBoxHandleTex;
+
+		static const WString DropDownBoxEntryNormalTex;
+		static const WString DropDownBoxEntryHoverTex;
+
+		static const WString DropDownBoxBtnUpNormalTex;
+		static const WString DropDownBoxBtnUpHoverTex;
+
+		static const WString DropDownBoxBtnDownNormalTex;
+		static const WString DropDownBoxBtnDownHoverTex;
+
+		static const WString DropDownBoxEntryExpNormalTex;
+		static const WString DropDownBoxEntryExpHoverTex;
+
+		static const WString DropDownSeparatorTex;
+
+		static const WString CursorArrowTex;
+		static const WString CursorArrowDragTex;
+		static const WString CursorArrowLeftRightTex;
+		static const WString CursorIBeamTex;
+		static const WString CursorDenyTex;
+		static const WString CursorWaitTex;
+		static const WString CursorSizeNESWTex;
+		static const WString CursorSizeNSTex;
+		static const WString CursorSizeNWSETex;
+		static const WString CursorSizeWETex;
+
+		static const Vector2I CursorArrowHotspot;
+		static const Vector2I CursorArrowDragHotspot;
+		static const Vector2I CursorArrowLeftRightHotspot;
+		static const Vector2I CursorIBeamHotspot;
+		static const Vector2I CursorDenyHotspot;
+		static const Vector2I CursorWaitHotspot;
+		static const Vector2I CursorSizeNESWHotspot;
+		static const Vector2I CursorSizeNSHotspot;
+		static const Vector2I CursorSizeNWSEHotspot;
+		static const Vector2I CursorSizeWEHotspot;
+
+		static const WString ShaderSpriteTextFile;
+		static const WString ShaderSpriteImageAlphaFile;
+		static const WString ShaderSpriteImageNoAlphaFile;
+		static const WString ShaderDiffuseFile;
+
+		static const WString MeshSphereFile;
+		static const WString MeshBoxFile;
+		static const WString MeshConeFile;
+		static const WString MeshQuadFile;
+		static const WString MeshDiscFile;
+
+		static const WString TextureWhiteFile;
+		static const WString TextureBlackFile;
+		static const WString TextureNormalFile;
+	};
+
+	/** @cond INTERNAL */
+
+	/**	Provides various methods commonly used for managing builtin resources. */
+	class BS_EXPORT BuiltinResourcesHelper
+	{
+	public:
+		/**
+		 * Imports all recognized assets in the specified folder and saves them to the specified output folder. All saved
+		 * resources are registered in the provided resource manifest.
+		 */
+		static void importAssets(const Path& inputFolder, const Path& outputFolder, const ResourceManifestPtr& manifest);
+
+		/**
+		 * Imports a font from the specified file. Imported font assets are saved in the output folder. All saved resources
+		 * are registered in the provided resource manifest.
+		 */
+		static void importFont(const Path& inputFile, const WString& outputName, const Path& outputFolder, 
+			const Vector<UINT32>& fontSizes, bool antialiasing, const ResourceManifestPtr& manifest);
+
+		/**
+		 * Generates sprite textures for all texture assets in the specified folder. Results are written in the same folder
+		 * with a "sprite_" prefix. All saved resources are registered in the provided resource manifest.
+		 */
+		static void generateSpriteTextures(const Path& folder, const ResourceManifestPtr& manifest);
+
+		/** Writes a timestamp with the current date and time in the specified file. */
+		static void writeTimestamp(const Path& file);
+
+		/**
+		 * Checks all files in the specified folder for modifications compared to the time stored in the timestamp file. 
+		 * Timestamp file must have been saved using writeTimestamp().
+		 */
+		static bool checkForModifications(const Path& folder, const Path& timeStampFile);
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 91 - 91
Source/BansheeEngine/Include/BsCRenderable.h

@@ -1,92 +1,92 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsRenderable.h"
-#include "BsBounds.h"
-#include "BsComponent.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Components
-	 *  @{
-	 */
-
-	/**
-	 * @copydoc	Renderable
-	 * 			
-	 * Wraps a Renderable as a Component.
-	 */
-	class BS_EXPORT CRenderable : public Component
-	{
-	public:
-		/** @copydoc Renderable::setMesh */
-		void setMesh(HMesh mesh) { mInternal->setMesh(mesh); }
-
-		/** @copydoc Renderable::setMaterial */
-		void setMaterial(UINT32 idx, HMaterial material) { mInternal->setMaterial(idx, material); }
-
-		/** @copydoc Renderable::setMaterial */
-		void setMaterial(HMaterial material) { mInternal->setMaterial(material); }
-
-		/** @copydoc Renderable::setLayer */
-		void setLayer(UINT64 layer) { mInternal->setLayer(layer); }
-
-		/** @copydoc Renderable::getLayer */
-		UINT64 getLayer() const { return mInternal->getLayer(); }
-
-		/** @copydoc Renderable::getMesh */
-		HMesh getMesh() const { return mInternal->getMesh(); }
-
-		/** @copydoc Renderable::getMaterial */
-		HMaterial getMaterial(UINT32 idx) const { return mInternal->getMaterial(idx); }
-
-		/**	Gets world bounds of the mesh rendered by this object. */
-		Bounds getBounds() const;
-
-		/** @copydoc Component::calculateBounds */
-		bool calculateBounds(Bounds& bounds) override;
-
-		/** Returns the internal renderable that is used for majority of operations by this component. */
-		RenderablePtr _getRenderable() const { return mInternal; }
-
-	private:
-		/**	Updates the world transform if the SceneObject transform changed. */
-		void updateTransform() const;
-
-		mutable RenderablePtr mInternal;
-
-		/************************************************************************/
-		/* 							COMPONENT OVERRIDES                    		*/
-		/************************************************************************/
-
-	protected:
-		friend class SceneObject;
-
-		CRenderable(const HSceneObject& parent);
-
-		/** @copydoc Component::onInitialized */
-		void onInitialized() override;
-
-		/** @copydoc Component::onDestroyed */
-		void onDestroyed() override;
-
-	public:
-		/** @copydoc Component::update */
-		virtual void update() override;
-
-		/************************************************************************/
-		/* 								RTTI		                     		*/
-		/************************************************************************/
-	public:
-		friend class CRenderableRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-
-	protected:
-		CRenderable() {} // Serialization only
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsRenderable.h"
+#include "BsBounds.h"
+#include "BsComponent.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Components
+	 *  @{
+	 */
+
+	/**
+	 * @copydoc	Renderable
+	 * 			
+	 * Wraps a TRenderable as a Component.
+	 */
+	class BS_EXPORT CRenderable : public Component
+	{
+	public:
+		/** @copydoc Renderable::setMesh */
+		void setMesh(HMesh mesh) { mInternal->setMesh(mesh); }
+
+		/** @copydoc Renderable::setMaterial */
+		void setMaterial(UINT32 idx, HMaterial material) { mInternal->setMaterial(idx, material); }
+
+		/** @copydoc Renderable::setMaterial */
+		void setMaterial(HMaterial material) { mInternal->setMaterial(material); }
+
+		/** @copydoc Renderable::setLayer */
+		void setLayer(UINT64 layer) { mInternal->setLayer(layer); }
+
+		/** @copydoc Renderable::getLayer */
+		UINT64 getLayer() const { return mInternal->getLayer(); }
+
+		/** @copydoc Renderable::getMesh */
+		HMesh getMesh() const { return mInternal->getMesh(); }
+
+		/** @copydoc Renderable::getMaterial */
+		HMaterial getMaterial(UINT32 idx) const { return mInternal->getMaterial(idx); }
+
+		/**	Gets world bounds of the mesh rendered by this object. */
+		Bounds getBounds() const;
+
+		/** @copydoc Component::calculateBounds */
+		bool calculateBounds(Bounds& bounds) override;
+
+		/** Returns the internal renderable that is used for majority of operations by this component. */
+		RenderablePtr _getRenderable() const { return mInternal; }
+
+	private:
+		/**	Updates the world transform if the SceneObject transform changed. */
+		void updateTransform() const;
+
+		mutable RenderablePtr mInternal;
+
+		/************************************************************************/
+		/* 							COMPONENT OVERRIDES                    		*/
+		/************************************************************************/
+
+	protected:
+		friend class SceneObject;
+
+		CRenderable(const HSceneObject& parent);
+
+		/** @copydoc Component::onInitialized */
+		void onInitialized() override;
+
+		/** @copydoc Component::onDestroyed */
+		void onDestroyed() override;
+
+	public:
+		/** @copydoc Component::update */
+		virtual void update() override;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+	public:
+		friend class CRenderableRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
+
+	protected:
+		CRenderable() {} // Serialization only
+	};
+
+	/** @} */
 }

+ 119 - 119
Source/BansheeEngine/Include/BsCursor.h

@@ -1,120 +1,120 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsModule.h"
-#include "BsPixelData.h"
-#include "BsVector2I.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Platform-Engine
-	 *  @{
-	 */
-
-	/**
-	 * Allows you to manipulate the platform cursor in various ways.
-	 * 			
-	 * @note	Thread safe.
-	 */
-	class BS_EXPORT Cursor : public Module<Cursor>
-	{
-		/**	Internal container for data about a single cursor icon. */
-		struct CustomIcon
-		{
-			CustomIcon() {}
-			CustomIcon(const PixelData& pixelData, const Vector2I& hotSpot)
-				:hotSpot(hotSpot), pixelData(pixelData)
-			{ }
-
-			Vector2I hotSpot;
-			PixelData pixelData;
-		};
-
-	public:
-		Cursor();
-
-		/**	Moves the cursor to the specified screen position. */
-		void setScreenPosition(const Vector2I& screenPos);
-
-		/**	Retrieves the cursor position in screen coordinates. */
-		Vector2I getScreenPosition();
-
-		/**	Hides the cursor. */
-		void hide();
-
-		/**	Shows the cursor. */
-		void show();
-
-		/**	Limit cursor movement to the specified window. */
-		void clipToWindow(const RenderWindow& window);
-
-		/**	Limit cursor movement to specific area on the screen. */
-		void clipToRect(const Rect2I& screenRect);
-
-		/**	Disables cursor clipping that was set using any of the clipTo* methods. */
-		void clipDisable();
-		
-		/**	Sets a cursor icon. Uses one of the built-in cursor types. */
-		void setCursor(CursorType type);
-
-		/**
-		 * Sets a cursor icon. Uses one of the manually registered icons.
-		 * 			
-		 * @param[in]	name		The name to identify the cursor, one set previously by calling setCursorIcon().
-		 */
-		void setCursor(const String& name);
-
-		/**
-		 * Registers a new custom cursor icon you can then set by calling "setCursor".
-		 *
-		 * @param[in]	name		The name to identify the cursor.
-		 * @param[in]	pixelData	Cursor image data.
-		 * @param[in]	hotSpot		Offset on the cursor image to where the actual input happens (e.g. tip of the Arrow 
-		 *							cursor).
-		 * 						
-		 * @note	
-		 * Stores an internal copy of the pixel data. Clear it by calling removeCursorIcon(). If a custom icon with the 
-		 * same name already exists it will be replaced.
-		 */
-		void setCursorIcon(const String& name, const PixelData& pixelData, const Vector2I& hotSpot);
-
-		/**
-		 * Registers a new custom cursor icon you can then set by calling setCursor().
-		 *
-		 * @param[in]	type		One of the built-in cursor types.
-		 * @param[in] 	pixelData	Cursor image data.
-		 * @param[in]	hotSpot		Offset on the cursor image to where the actual input happens (e.g. tip of the Arrow 
-		 *							cursor).
-		 * 						
-		 * @note	
-		 * Stores an internal copy of the pixel data. Clear it by calling removeCursorIcon(). If a custom icon with the
-		 * same type already exists it will be replaced.
-		 */
-		void setCursorIcon(CursorType type, const PixelData& pixelData, const Vector2I& hotSpot);
-
-		/**	Removes a custom cursor icon and releases any data associated with it. */
-		void clearCursorIcon(const String& name);
-
-		/**
-		 * Removes a custom cursor icon and releases any data associated with it. Restores original icon associated with
-		 * this cursor type.
-		 */
-		void clearCursorIcon(CursorType type);
-
-	private:
-		/**	Restores the default cursor icon for the specified cursor type. */
-		void restoreCursorIcon(CursorType type);
-
-		/**	Sends the cursor image to the OS, making it active. */
-		void updateCursorImage();
-
-		UnorderedMap<String, UINT32> mCustomIconNameToId;
-		UnorderedMap<UINT32, CustomIcon> mCustomIcons;
-		UINT32 mNextUniqueId;
-		INT32 mActiveCursorId;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsModule.h"
+#include "BsPixelData.h"
+#include "BsVector2I.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Platform-Engine
+	 *  @{
+	 */
+
+	/**
+	 * Allows you to manipulate the platform cursor in various ways.
+	 * 			
+	 * @note	Thread safe.
+	 */
+	class BS_EXPORT Cursor : public Module<Cursor>
+	{
+		/**	Internal container for data about a single cursor icon. */
+		struct CustomIcon
+		{
+			CustomIcon() {}
+			CustomIcon(const PixelData& pixelData, const Vector2I& hotSpot)
+				:hotSpot(hotSpot), pixelData(pixelData)
+			{ }
+
+			Vector2I hotSpot;
+			PixelData pixelData;
+		};
+
+	public:
+		Cursor();
+
+		/**	Moves the cursor to the specified screen position. */
+		void setScreenPosition(const Vector2I& screenPos);
+
+		/**	Retrieves the cursor position in screen coordinates. */
+		Vector2I getScreenPosition();
+
+		/**	Hides the cursor. */
+		void hide();
+
+		/**	Shows the cursor. */
+		void show();
+
+		/**	Limit cursor movement to the specified window. */
+		void clipToWindow(const RenderWindow& window);
+
+		/**	Limit cursor movement to specific area on the screen. */
+		void clipToRect(const Rect2I& screenRect);
+
+		/**	Disables cursor clipping that was set using any of the clipTo* methods. */
+		void clipDisable();
+		
+		/**	Sets a cursor icon. Uses one of the built-in cursor types. */
+		void setCursor(CursorType type);
+
+		/**
+		 * Sets a cursor icon. Uses one of the manually registered icons.
+		 * 			
+		 * @param[in]	name		The name to identify the cursor, one set previously by calling setCursorIcon().
+		 */
+		void setCursor(const String& name);
+
+		/**
+		 * Registers a new custom cursor icon you can then set by calling "setCursor".
+		 *
+		 * @param[in]	name		The name to identify the cursor.
+		 * @param[in]	pixelData	Cursor image data.
+		 * @param[in]	hotSpot		Offset on the cursor image to where the actual input happens (for example tip of the 
+		 *							Arrow cursor).
+		 * 						
+		 * @note	
+		 * Stores an internal copy of the pixel data. Clear it by calling removeCursorIcon(). If a custom icon with the 
+		 * same name already exists it will be replaced.
+		 */
+		void setCursorIcon(const String& name, const PixelData& pixelData, const Vector2I& hotSpot);
+
+		/**
+		 * Registers a new custom cursor icon you can then set by calling setCursor().
+		 *
+		 * @param[in]	type		One of the built-in cursor types.
+		 * @param[in] 	pixelData	Cursor image data.
+		 * @param[in]	hotSpot		Offset on the cursor image to where the actual input happens (for example tip of the 
+		 *							Arrow cursor).
+		 * 						
+		 * @note	
+		 * Stores an internal copy of the pixel data. Clear it by calling removeCursorIcon(). If a custom icon with the
+		 * same type already exists it will be replaced.
+		 */
+		void setCursorIcon(CursorType type, const PixelData& pixelData, const Vector2I& hotSpot);
+
+		/**	Removes a custom cursor icon and releases any data associated with it. */
+		void clearCursorIcon(const String& name);
+
+		/**
+		 * Removes a custom cursor icon and releases any data associated with it. Restores original icon associated with
+		 * this cursor type.
+		 */
+		void clearCursorIcon(CursorType type);
+
+	private:
+		/**	Restores the default cursor icon for the specified cursor type. */
+		void restoreCursorIcon(CursorType type);
+
+		/**	Sends the cursor image to the OS, making it active. */
+		void updateCursorImage();
+
+		UnorderedMap<String, UINT32> mCustomIconNameToId;
+		UnorderedMap<UINT32, CustomIcon> mCustomIcons;
+		UINT32 mNextUniqueId;
+		INT32 mActiveCursorId;
+	};
+
+	/** @} */
 }

+ 124 - 124
Source/BansheeEngine/Include/BsDragAndDropManager.h

@@ -1,125 +1,125 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsModule.h"
-#include "BsInput.h"
-#include "BsEvent.h"
-#include <atomic>
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup GUI
-	 *  @{
-	 */
-
-	/**	Holds data returned by DragAndDropManager callbacks. */
-	struct BS_EXPORT DragCallbackInfo
-	{
-		DragCallbackInfo()
-			:processed(false)
-		{ }
-
-		bool processed;
-	};
-
-	/**
-	 * Handles GUI drag and drop operations. When active GUI elements will be notified of any drag events and will be able
-	 * to retrieve dragged data.
-	 *
-	 * @note	Sim thread only.
-	 */
-	class BS_EXPORT DragAndDropManager : public Module<DragAndDropManager>
-	{
-	public:
-		DragAndDropManager();
-		~DragAndDropManager();
-
-		/**
-		 * Starts a drag operation of the specified type. This means GUI elements will start receiving drag and drop 
-		 * related events and they may choose to handle them.
-		 *
-		 * @param[in]	typeId					Type of the drag and drop operation that other objects may query and decide
-		 *										if they want to handle it. User defined.
-		 * @param[in] 	data					Some operation specific data that is just passed through to however needs it.
-		 * @param[in]	dropCallback			The drop callback that gets triggered whenever mouse button is released and
-		 *										drag operation ends. You should perform any cleanup here.
-		 * @param[in]	needsValidDropTarget	(optional) Determines whether the drop operation may happen anywhere or 
-		 *										does the GUI element need to specifically accept the drag of this type. 
-		 *										If false all GUI elements we mouse over will receive drag/drop events, 
-		 *										otherwise only those that specifically subscribe to the specified drag 
-		 *										operation of this typeId will.
-		 * 										Additionally this will determine the cursor displayed (whether or not it 
-		 *										can have a "denied" state).
-		 */
-		void startDrag(UINT32 typeId, void* data, std::function<void(bool)> dropCallback, bool needsValidDropTarget = false);
-
-		/**	Returns true if drag is currently in progress. */
-		bool isDragInProgress() const { return mIsDragInProgress; }
-
-		/**	Get type ID of drag currently in progress. Only valid if drag is in progress. */
-		UINT32 getDragTypeId() const { return mDragTypeId; }
-
-		/**	Gets drag specific data specified when the drag started. Only valid if drag is in progress. */
-		void* getDragData() const { return mData; }
-
-		/**
-		 * Determines whether the drop operation may happen anywhere or does the GUI element need to specifically accept the
-		 * drag of this type. If false all GUI elements we mouse over will receive drag/drop events, otherwise only those 
-		 * that specifically subscribe to the specified drag operation of this typeId will.
-		 * 									
-		 * Additionally this will determine the cursor displayed (whether or not it can have a "denied" state).
-		 */
-		bool needsValidDropTarget() const { return mNeedsValidDropTarget; }
-
-		/**
-		 * Registers a new callback that will be triggered when dragged item is dropped. Provided parameter specifies if 
-		 * the drop operation was handled by anyone or not.
-		 */
-		void addDropCallback(std::function<void(bool)> dropCallback);
-
-		/** Called once per frame. Checks if drag ended or if window loses focus. */
-		void _update();
-
-		/**
-		 * Triggers a callback when user releases the pointer and the drag operation ends. Provided parameters inform the
-		 * subscriber where the pointer was released, and allows the subscriber to note whether the drag operation was 
-		 * processed or not.
-		 *
-		 * @note	Internal event. You should use addDropCallback for normal use.
-		 */
-		Event<void(const PointerEvent&, DragCallbackInfo&)> onDragEnded;
-	private:
-
-		/**	Triggers any drop callbacks and clears callback data. */
-		void endDrag(bool processed);
-
-		/**
-		 * Called by the core thread whenever mouse capture state changes. This can happen when window loses focus 
-		 * (e.g. alt+tab). In that case we want to end the drag even if the user is still holding the dragged item.
-		 *
-		 * @note	Core thread.
-		 */
-		void mouseCaptureChanged();
-
-		/**	Called by the input system when pointer is released. */
-		void cursorReleased(const PointerEvent& event);
-
-	private:
-		UINT32 mDragTypeId;
-		void* mData;
-		Vector<std::function<void(bool)>> mDropCallbacks;
-		bool mIsDragInProgress;
-		bool mNeedsValidDropTarget;
-		HEvent mMouseCaptureChangedConn;
-
-		std::atomic<bool> mCaptureChanged;
-		std::atomic<int> mCaptureActive;
-		std::atomic<UINT64> mCaptureChangeFrame;
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsModule.h"
+#include "BsInput.h"
+#include "BsEvent.h"
+#include <atomic>
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup GUI
+	 *  @{
+	 */
+
+	/**	Holds data returned by DragAndDropManager callbacks. */
+	struct BS_EXPORT DragCallbackInfo
+	{
+		DragCallbackInfo()
+			:processed(false)
+		{ }
+
+		bool processed;
+	};
+
+	/**
+	 * Handles GUI drag and drop operations. When active GUI elements will be notified of any drag events and will be able
+	 * to retrieve dragged data.
+	 *
+	 * @note	Sim thread only.
+	 */
+	class BS_EXPORT DragAndDropManager : public Module<DragAndDropManager>
+	{
+	public:
+		DragAndDropManager();
+		~DragAndDropManager();
+
+		/**
+		 * Starts a drag operation of the specified type. This means GUI elements will start receiving drag and drop 
+		 * related events and they may choose to handle them.
+		 *
+		 * @param[in]	typeId					Type of the drag and drop operation that other objects may query and decide
+		 *										if they want to handle it. User defined.
+		 * @param[in] 	data					Some operation specific data that is just passed through to however needs it.
+		 * @param[in]	dropCallback			The drop callback that gets triggered whenever mouse button is released and
+		 *										drag operation ends. You should perform any cleanup here.
+		 * @param[in]	needsValidDropTarget	(optional) Determines whether the drop operation may happen anywhere or 
+		 *										does the GUI element need to specifically accept the drag of this type. 
+		 *										If false all GUI elements we mouse over will receive drag/drop events, 
+		 *										otherwise only those that specifically subscribe to the specified drag 
+		 *										operation of this typeId will.
+		 * 										Additionally this will determine the cursor displayed (whether or not it 
+		 *										can have a "denied" state).
+		 */
+		void startDrag(UINT32 typeId, void* data, std::function<void(bool)> dropCallback, bool needsValidDropTarget = false);
+
+		/**	Returns true if drag is currently in progress. */
+		bool isDragInProgress() const { return mIsDragInProgress; }
+
+		/**	Get type ID of drag currently in progress. Only valid if drag is in progress. */
+		UINT32 getDragTypeId() const { return mDragTypeId; }
+
+		/**	Gets drag specific data specified when the drag started. Only valid if drag is in progress. */
+		void* getDragData() const { return mData; }
+
+		/**
+		 * Determines whether the drop operation may happen anywhere or does the GUI element need to specifically accept the
+		 * drag of this type. If false all GUI elements we mouse over will receive drag/drop events, otherwise only those 
+		 * that specifically subscribe to the specified drag operation of this typeId will.
+		 * 									
+		 * Additionally this will determine the cursor displayed (whether or not it can have a "denied" state).
+		 */
+		bool needsValidDropTarget() const { return mNeedsValidDropTarget; }
+
+		/**
+		 * Registers a new callback that will be triggered when dragged item is dropped. Provided parameter specifies if 
+		 * the drop operation was handled by anyone or not.
+		 */
+		void addDropCallback(std::function<void(bool)> dropCallback);
+
+		/** Called once per frame. Checks if drag ended or if window loses focus. */
+		void _update();
+
+		/**
+		 * Triggers a callback when user releases the pointer and the drag operation ends. Provided parameters inform the
+		 * subscriber where the pointer was released, and allows the subscriber to note whether the drag operation was 
+		 * processed or not.
+		 *
+		 * @note	Internal event. You should use addDropCallback for normal use.
+		 */
+		Event<void(const PointerEvent&, DragCallbackInfo&)> onDragEnded;
+	private:
+
+		/**	Triggers any drop callbacks and clears callback data. */
+		void endDrag(bool processed);
+
+		/**
+		 * Called by the core thread whenever mouse capture state changes. This can happen when window loses focus 
+		 * (for example alt+tab). In that case we want to end the drag even if the user is still holding the dragged item.
+		 *
+		 * @note	Core thread.
+		 */
+		void mouseCaptureChanged();
+
+		/**	Called by the input system when pointer is released. */
+		void cursorReleased(const PointerEvent& event);
+
+	private:
+		UINT32 mDragTypeId;
+		void* mData;
+		Vector<std::function<void(bool)>> mDropCallbacks;
+		bool mIsDragInProgress;
+		bool mNeedsValidDropTarget;
+		HEvent mMouseCaptureChangedConn;
+
+		std::atomic<bool> mCaptureChanged;
+		std::atomic<int> mCaptureActive;
+		std::atomic<UINT64> mCaptureChangeFrame;
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 58 - 58
Source/BansheeEngine/Include/BsGUICommandEvent.h

@@ -1,59 +1,59 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup GUI
-	 *  @{
-	 */
-
-	/**	Type of valid command events. */
-	enum class GUICommandEventType
-	{
-		Redraw, /**< GUI system is forcing the GUI element to redraw itself. */
-		FocusLost, /**< GUI element lost input focus. */
-		FocusGained, /**< GUI element gained input focus. */
-		MoveLeft, /**< Input caret was moved left (e.g. for navigating an input box). */
-		MoveRight, /**< Input caret was moved right (e.g. for navigating an input box). */
-		MoveUp, /**< Input caret was moved up (e.g. for navigating an input box). */ 
-		MoveDown, /**< Input caret was moved down (e.g. for navigating an input box). */ 
-		SelectLeft, /**< Input Selection was moved left (e.g. for selecting text in an input box). */ 
-		SelectRight, /**< Input Selection was moved right (e.g. for selecting text in an input box). */ 
-		SelectUp, /**< Input Selection was moved up (e.g. for selecting text in an input box). */ 
-		SelectDown, /**< Input Selection was moved down (e.g. for selecting text in an input box). */ 
-		Escape, /**< Escape key was pressed. */
-		Delete, /**< Delete key was pressed. */
-		Backspace, /**< Backspace key was pressed. */
-		Return, /**< Shift + Enter was pressed. */
-		Confirm /**< Enter key was pressed. */
-	};
-
-	/**
-	 * Holds data about a GUI command event. Command events are special events with a more specific purpose than general
-	 * input events.
-	 */
-	class BS_EXPORT GUICommandEvent
-	{
-	public:
-		GUICommandEvent()
-			:mType(GUICommandEventType::Redraw)
-		{ }
-
-		/**	Returns type describing what kind of event this is. */
-		GUICommandEventType getType() const { return mType; }
-	private:
-		friend class GUIManager;
-
-		/**	Sets type describing what kind of event this is. */
-		void setType(GUICommandEventType type) { mType = type; }
-
-		GUICommandEventType mType;
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup GUI
+	 *  @{
+	 */
+
+	/**	Type of valid command events. */
+	enum class GUICommandEventType
+	{
+		Redraw, /**< GUI system is forcing the GUI element to redraw itself. */
+		FocusLost, /**< GUI element lost input focus. */
+		FocusGained, /**< GUI element gained input focus. */
+		MoveLeft, /**< Input caret was moved left (for example for navigating an input box). */
+		MoveRight, /**< Input caret was moved right (for example for navigating an input box). */
+		MoveUp, /**< Input caret was moved up (for example for navigating an input box). */ 
+		MoveDown, /**< Input caret was moved down (for example for navigating an input box). */ 
+		SelectLeft, /**< Input Selection was moved left (for example for selecting text in an input box). */ 
+		SelectRight, /**< Input Selection was moved right (for example for selecting text in an input box). */ 
+		SelectUp, /**< Input Selection was moved up (for example for selecting text in an input box). */ 
+		SelectDown, /**< Input Selection was moved down (for example for selecting text in an input box). */ 
+		Escape, /**< Escape key was pressed. */
+		Delete, /**< Delete key was pressed. */
+		Backspace, /**< Backspace key was pressed. */
+		Return, /**< Shift + Enter was pressed. */
+		Confirm /**< Enter key was pressed. */
+	};
+
+	/**
+	 * Holds data about a GUI command event. Command events are special events with a more specific purpose than general
+	 * input events.
+	 */
+	class BS_EXPORT GUICommandEvent
+	{
+	public:
+		GUICommandEvent()
+			:mType(GUICommandEventType::Redraw)
+		{ }
+
+		/**	Returns type describing what kind of event this is. */
+		GUICommandEventType getType() const { return mType; }
+	private:
+		friend class GUIManager;
+
+		/**	Sets type describing what kind of event this is. */
+		void setType(GUICommandEventType type) { mType = type; }
+
+		GUICommandEventType mType;
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 40 - 38
Source/BansheeEngine/Include/BsGUIContextMenu.h

@@ -1,39 +1,41 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsGUIMenu.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup GUI
-	 *  @{
-	 */
-
-	/**
-	 * Manages display and logic for a context menu. Context menus can be opened anywhere within the GUI and can contain a
-	 * hierarchy of menu items. 
-	 */
-	class BS_EXPORT GUIContextMenu : public GUIMenu
-	{
-	public:
-		GUIContextMenu();
-		~GUIContextMenu();
-
-		/** Opens a context menu at the specified position relative to the provided widget. */
-		void open(const Vector2I& position, GUIWidget& widget);
-
-	private:
-		/**	Closes the context menu if open. */
-		void close();
-
-		/**	Called when the context menu is closed externally (e.g. when user selects an item or clicks outside it). */
-		void onMenuClosed();
-
-	private:
-		bool mContextMenuOpen;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsGUIMenu.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup GUI
+	 *  @{
+	 */
+
+	/**
+	 * Manages display and logic for a context menu. Context menus can be opened anywhere within the GUI and can contain a
+	 * hierarchy of menu items. 
+	 */
+	class BS_EXPORT GUIContextMenu : public GUIMenu
+	{
+	public:
+		GUIContextMenu();
+		~GUIContextMenu();
+
+		/** Opens a context menu at the specified position relative to the provided widget. */
+		void open(const Vector2I& position, GUIWidget& widget);
+
+	private:
+		/**	Closes the context menu if open. */
+		void close();
+
+		/**	
+		 * Called when the context menu is closed externally (for example when user selects an item or clicks outside it). 
+		 */
+		void onMenuClosed();
+
+	private:
+		bool mContextMenuOpen;
+	};
+
+	/** @} */
 }

+ 77 - 77
Source/BansheeEngine/Include/BsGUIDropDownHitBox.h

@@ -1,78 +1,78 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsGUIElementContainer.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup GUI
-	 *  @{
-	 */
-
-	/** Helper class used for detecting when a certain area is in focus, and getting notified when that state changes. */
-	class BS_EXPORT GUIDropDownHitBox : public GUIElementContainer
-	{
-	public:
-		/** Returns type name of the GUI element used for finding GUI element styles.  */
-		static const String& getGUITypeName();
-
-		/**
-		 * Creates a new drop down hit box that will detect mouse input over certain area.
-		 * You must call setBounds() to define the area.
-		 *
-		 * @param[in]	captureMouseOver	If true mouse over/out/move events will be captured by this control and wont be
-		 *									passed to other GUI elements.
-		 * @param[in]	captureMousePresses	If true mouse clicks will be captured by this control and wont be passed
-		 *									to other GUI elements.
-		 */
-		static GUIDropDownHitBox* create(bool captureMouseOver, bool captureMousePresses);
-
-		/**
-		 * Creates a new drop down hit box that will detect mouse input over certain area. You must call setBounds() to 
-		 * define the area.
-		 *
-		 * @param[in]	captureMouseOver	If true mouse over/out/move events will be captured by this control and wont be
-		 *									passed to other GUI elements.
-		 * @param[in]	captureMousePresses	If true mouse clicks will be captured by this control and wont be passed to 
-		 *									other GUI elements.
-		 */
-		static GUIDropDownHitBox* create(bool captureMouseOver, bool captureMousePresses, const GUIOptions& options);
-
-		/** Sets a single rectangle bounds in which the hitbox will capture mouse events. */
-		void setBounds(const Rect2I& bounds);
-
-		/** Sets complex bounds consisting of multiple rectangles in which the hitbox will capture mouse events. */
-		void setBounds(const Vector<Rect2I>& bounds);
-
-		/** Triggered when hit box loses focus (e.g. user clicks outside of its bounds). */
-		Event<void()> onFocusLost;
-
-		/** Triggered when hit box gains focus (e.g. user clicks inside of its bounds). */
-		Event<void()> onFocusGained;
-
-	private:
-		GUIDropDownHitBox(bool captureMouseOver, bool captureMousePresses, const GUIDimensions& dimensions);
-
-		/** @copydoc GUIElementContainer::updateClippedBounds */
-		void updateClippedBounds() override;
-
-		/** @copydoc GUIElementContainer::_commandEvent */
-		virtual bool _commandEvent(const GUICommandEvent& ev) override;
-
-		/** @copydoc GUIElementContainer::_mouseEvent */
-		virtual bool _mouseEvent(const GUIMouseEvent& ev) override;
-
-		/** @copydoc GUIElementContainer::_isInBounds */
-		virtual bool _isInBounds(const Vector2I position) const override;
-
-		Vector<Rect2I> mBounds;
-		bool mCaptureMouseOver;
-		bool mCaptureMousePresses;
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsGUIElementContainer.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup GUI
+	 *  @{
+	 */
+
+	/** Helper class used for detecting when a certain area is in focus, and getting notified when that state changes. */
+	class BS_EXPORT GUIDropDownHitBox : public GUIElementContainer
+	{
+	public:
+		/** Returns type name of the GUI element used for finding GUI element styles.  */
+		static const String& getGUITypeName();
+
+		/**
+		 * Creates a new drop down hit box that will detect mouse input over certain area.
+		 * You must call setBounds() to define the area.
+		 *
+		 * @param[in]	captureMouseOver	If true mouse over/out/move events will be captured by this control and wont be
+		 *									passed to other GUI elements.
+		 * @param[in]	captureMousePresses	If true mouse clicks will be captured by this control and wont be passed
+		 *									to other GUI elements.
+		 */
+		static GUIDropDownHitBox* create(bool captureMouseOver, bool captureMousePresses);
+
+		/**
+		 * Creates a new drop down hit box that will detect mouse input over certain area. You must call setBounds() to 
+		 * define the area.
+		 *
+		 * @param[in]	captureMouseOver	If true mouse over/out/move events will be captured by this control and wont be
+		 *									passed to other GUI elements.
+		 * @param[in]	captureMousePresses	If true mouse clicks will be captured by this control and wont be passed to 
+		 *									other GUI elements.
+		 */
+		static GUIDropDownHitBox* create(bool captureMouseOver, bool captureMousePresses, const GUIOptions& options);
+
+		/** Sets a single rectangle bounds in which the hitbox will capture mouse events. */
+		void setBounds(const Rect2I& bounds);
+
+		/** Sets complex bounds consisting of multiple rectangles in which the hitbox will capture mouse events. */
+		void setBounds(const Vector<Rect2I>& bounds);
+
+		/** Triggered when hit box loses focus (for example user clicks outside of its bounds). */
+		Event<void()> onFocusLost;
+
+		/** Triggered when hit box gains focus (for example user clicks inside of its bounds). */
+		Event<void()> onFocusGained;
+
+	private:
+		GUIDropDownHitBox(bool captureMouseOver, bool captureMousePresses, const GUIDimensions& dimensions);
+
+		/** @copydoc GUIElementContainer::updateClippedBounds */
+		void updateClippedBounds() override;
+
+		/** @copydoc GUIElementContainer::_commandEvent */
+		virtual bool _commandEvent(const GUICommandEvent& ev) override;
+
+		/** @copydoc GUIElementContainer::_mouseEvent */
+		virtual bool _mouseEvent(const GUIMouseEvent& ev) override;
+
+		/** @copydoc GUIElementContainer::_isInBounds */
+		virtual bool _isInBounds(const Vector2I position) const override;
+
+		Vector<Rect2I> mBounds;
+		bool mCaptureMouseOver;
+		bool mCaptureMousePresses;
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 4 - 4
Source/BansheeEngine/Include/BsGUIElement.h

@@ -196,8 +196,8 @@ namespace BansheeEngine
 		 * Returns the range of depths that the child elements can be rendered it.
 		 *
 		 * @note	
-		 * e.g. if you are rendering a button with an image and a text you will want the text to be rendered in front of
-		 * the image at a different depth, which means the depth range is 2 (0 for text, 1 for background image).
+		 * For example if you are rendering a button with an image and a text you will want the text to be rendered in front
+		 * of the image at a different depth, which means the depth range is 2 (0 for text, 1 for background image).
 		 */
 		virtual UINT32 _getRenderElementDepthRange() const { return 1; }
 
@@ -256,8 +256,8 @@ namespace BansheeEngine
 		virtual void updateRenderElementsInternal();
 
 		/**
-		 * Called whenever element clipped bounds need to be recalculated. (e.g. when width, height or clip rectangles 
-		 * changes).
+		 * Called whenever element clipped bounds need to be recalculated. (for example when width, height or clip 
+		 * rectangles changes).
 		 */
 		virtual void updateClippedBounds();
 

+ 146 - 146
Source/BansheeEngine/Include/BsGUIInputTool.h

@@ -1,147 +1,147 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsTextSprite.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup GUI
-	 *  @{
-	 */
-
-	/**	Represents a single line of text used by the input tools. */
-	class BS_EXPORT GUIInputLineDesc
-	{
-	public:
-		/**
-		 * Constructs a new input line description.
-		 *
-		 * @param[in]	startChar		Index of the first character on the line.
-		 * @param[in]	endChar			Index of the last character on the line.
-		 * @param[in]	lineHeight		Height of the line in pixels.
-		 * @param[in]	lineYStart		Vertical offset from the top of the text to the start of this line (0 for first 
-		 *								line usually).
-		 * @param[in]	includesNewLine	True if the lines end character is a newline character.
-		 */
-		GUIInputLineDesc(UINT32 startChar, UINT32 endChar, UINT32 lineHeight, INT32 lineYStart, bool includesNewline);
-
-		/**
-		 * Returns index of the last character on the line. If lines contains a newline character it will be returned unless
-		 * you set @p includeNewLine to false, in which case the next end-most character is returned. (If newline is the 
-		 * only character on the line, its index will still be returned).
-		 */
-		UINT32 getEndChar(bool includeNewline = true) const;
-
-		/**	Returns index of the first character on the line. */
-		UINT32 getStartChar() const { return mStartChar; }
-
-		/**	Returns line height in pixels. */
-		UINT32 getLineHeight() const { return mLineHeight; }
-
-		/**	Returns vertical offset from the top of the text to the start of this line (0 for first line usually). */
-		INT32 getLineYStart() const { return mLineYStart; }
-
-		/**
-		 * Checks is the specified character index a newline. Character index is a global character index, not relative to
-		 * the start character index of this line. If the index is out of range of this line character indices, it will
-		 * always return false.
-		 */
-		bool isNewline(UINT32 charIdx) const;
-
-		/**	Returns true if the last character on this line is a newline. */
-		bool hasNewlineChar() const { return mIncludesNewline; }
-
-	private:
-		UINT32 mStartChar;
-		UINT32 mEndChar;
-		UINT32 mLineHeight;
-		INT32 mLineYStart;
-		bool mIncludesNewline;
-	};
-
-	/** Base class for input helper tools, like caret and text selection. */
-	class BS_EXPORT GUIInputTool
-	{
-	public:
-		GUIInputTool();
-		~GUIInputTool();
-
-		/**
-		 * Updates the input tool with new text descriptor and parent GUI element. These values will be used for all 
-		 * further calculations.
-		 */
-		void updateText(const GUIElement* element, const TEXT_SPRITE_DESC& textDesc);
-	protected:
-		/**	Returns text offset relative to parent widget. */
-		Vector2I getTextOffset() const;
-
-		/**	Returns number of lines in the current text string. */
-		UINT32 getNumLines() const { return (UINT32)mLineDescs.size(); }
-
-		/**	Returns descriptor for a line with the specified index. */
-		const GUIInputLineDesc& getLineDesc(UINT32 lineIdx) const { return mLineDescs.at(lineIdx); }
-
-		/**
-		 * Returns index of a line containing the specified character.
-		 *
-		 * @param[in]	charIdx					Index of the character to look for.
-		 * @param[in]	newlineCountsOnNextLine	If true, newline characters will return the next line and not the line
-		 *										they're actually on.
-		 */
-		UINT32 getLineForChar(UINT32 charIdx, bool newlineCountsOnNextLine = false) const;
-
-		/**
-		 * Returns a rectangle containing position and size of the character with the provided index, relative to parent
-		 * widget.
-		 */
-		Rect2I getCharRect(UINT32 charIdx) const;
-
-		/**
-		 * Returns a rectangle containing position and size of the character with the provided index, relative to parent 
-		 * element.
-		 */
-		Rect2I getLocalCharRect(UINT32 charIdx) const;
-
-		/** Returns character index nearest to the specified position. Position should be relative to parent widget. */
-		INT32 getCharIdxAtPos(const Vector2I& pos) const;
-
-		/**	Returns true if the currently set text desctiptor is valid (has any characters). */
-		bool isDescValid() const;
-
-		/**
-		 * Gets a character index after the input index. Input index represents the empty areas between the characters. 
-		 * Newline counts as a character. (e.g. 0 is before the first character, 1 is after the first character but before 
-		 * the second, etc.)
-		 * 			
-		 * @note	
-		 * This can return an out of range character index, in case the input index is specified after the last character.
-		 */
-		UINT32 getCharIdxAtInputIdx(UINT32 inputIdx) const;
-
-		/**	Checks is the specified character index a newline. */
-		bool isNewlineChar(UINT32 charIdx) const;
-
-		/**
-		 * Checks is the character after the specified input index a newline.
-		 *
-		 * @see		getCharIdxAtInputIdx
-		 */
-		bool isNewline(UINT32 inputIdx) const;
-
-	protected:
-		const GUIElement* mElement;
-
-		Vector2* mQuads;
-		UINT32 mNumQuads;
-
-		TEXT_SPRITE_DESC mTextDesc;
-
-		Vector<GUIInputLineDesc> mLineDescs;
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsTextSprite.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup GUI
+	 *  @{
+	 */
+
+	/**	Represents a single line of text used by the input tools. */
+	class BS_EXPORT GUIInputLineDesc
+	{
+	public:
+		/**
+		 * Constructs a new input line description.
+		 *
+		 * @param[in]	startChar		Index of the first character on the line.
+		 * @param[in]	endChar			Index of the last character on the line.
+		 * @param[in]	lineHeight		Height of the line in pixels.
+		 * @param[in]	lineYStart		Vertical offset from the top of the text to the start of this line (0 for first 
+		 *								line usually).
+		 * @param[in]	includesNewLine	True if the lines end character is a newline character.
+		 */
+		GUIInputLineDesc(UINT32 startChar, UINT32 endChar, UINT32 lineHeight, INT32 lineYStart, bool includesNewline);
+
+		/**
+		 * Returns index of the last character on the line. If lines contains a newline character it will be returned unless
+		 * you set @p includeNewLine to false, in which case the next end-most character is returned. (If newline is the 
+		 * only character on the line, its index will still be returned).
+		 */
+		UINT32 getEndChar(bool includeNewline = true) const;
+
+		/**	Returns index of the first character on the line. */
+		UINT32 getStartChar() const { return mStartChar; }
+
+		/**	Returns line height in pixels. */
+		UINT32 getLineHeight() const { return mLineHeight; }
+
+		/**	Returns vertical offset from the top of the text to the start of this line (0 for first line usually). */
+		INT32 getLineYStart() const { return mLineYStart; }
+
+		/**
+		 * Checks is the specified character index a newline. Character index is a global character index, not relative to
+		 * the start character index of this line. If the index is out of range of this line character indices, it will
+		 * always return false.
+		 */
+		bool isNewline(UINT32 charIdx) const;
+
+		/**	Returns true if the last character on this line is a newline. */
+		bool hasNewlineChar() const { return mIncludesNewline; }
+
+	private:
+		UINT32 mStartChar;
+		UINT32 mEndChar;
+		UINT32 mLineHeight;
+		INT32 mLineYStart;
+		bool mIncludesNewline;
+	};
+
+	/** Base class for input helper tools, like caret and text selection. */
+	class BS_EXPORT GUIInputTool
+	{
+	public:
+		GUIInputTool();
+		~GUIInputTool();
+
+		/**
+		 * Updates the input tool with new text descriptor and parent GUI element. These values will be used for all 
+		 * further calculations.
+		 */
+		void updateText(const GUIElement* element, const TEXT_SPRITE_DESC& textDesc);
+	protected:
+		/**	Returns text offset relative to parent widget. */
+		Vector2I getTextOffset() const;
+
+		/**	Returns number of lines in the current text string. */
+		UINT32 getNumLines() const { return (UINT32)mLineDescs.size(); }
+
+		/**	Returns descriptor for a line with the specified index. */
+		const GUIInputLineDesc& getLineDesc(UINT32 lineIdx) const { return mLineDescs.at(lineIdx); }
+
+		/**
+		 * Returns index of a line containing the specified character.
+		 *
+		 * @param[in]	charIdx					Index of the character to look for.
+		 * @param[in]	newlineCountsOnNextLine	If true, newline characters will return the next line and not the line
+		 *										they're actually on.
+		 */
+		UINT32 getLineForChar(UINT32 charIdx, bool newlineCountsOnNextLine = false) const;
+
+		/**
+		 * Returns a rectangle containing position and size of the character with the provided index, relative to parent
+		 * widget.
+		 */
+		Rect2I getCharRect(UINT32 charIdx) const;
+
+		/**
+		 * Returns a rectangle containing position and size of the character with the provided index, relative to parent 
+		 * element.
+		 */
+		Rect2I getLocalCharRect(UINT32 charIdx) const;
+
+		/** Returns character index nearest to the specified position. Position should be relative to parent widget. */
+		INT32 getCharIdxAtPos(const Vector2I& pos) const;
+
+		/**	Returns true if the currently set text desctiptor is valid (has any characters). */
+		bool isDescValid() const;
+
+		/**
+		 * Gets a character index after the input index. Input index represents the empty areas between the characters. 
+		 * Newline counts as a character. (for example 0 is before the first character, 1 is after the first character but
+		 * before the second, etc.)
+		 * 			
+		 * @note	
+		 * This can return an out of range character index, in case the input index is specified after the last character.
+		 */
+		UINT32 getCharIdxAtInputIdx(UINT32 inputIdx) const;
+
+		/**	Checks is the specified character index a newline. */
+		bool isNewlineChar(UINT32 charIdx) const;
+
+		/**
+		 * Checks is the character after the specified input index a newline.
+		 *
+		 * @see		getCharIdxAtInputIdx
+		 */
+		bool isNewline(UINT32 inputIdx) const;
+
+	protected:
+		const GUIElement* mElement;
+
+		Vector2* mQuads;
+		UINT32 mNumQuads;
+
+		TEXT_SPRITE_DESC mTextDesc;
+
+		Vector<GUIInputLineDesc> mLineDescs;
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 7 - 7
Source/BansheeEngine/Include/BsGUIManager.h

@@ -33,9 +33,9 @@ namespace BansheeEngine
 	 * @par
 	 * This ensures that GUIElements don't recursively modify GUIManager while GUIManager is still using that data.
 	 * @par
-	 * e.g. setFocus() usually gets called from within GUIElements, however we don't want elements in focus be modified 
-	 * immediately since that setFocus() call could have originated in sendCommandEvent and elements in focus array would
-	 * be modified while still being iterated upon.
+	 * for example setFocus() usually gets called from within GUIElements, however we don't want elements in focus be 
+	 * modified immediately since that setFocus() call could have originated in sendCommandEvent and elements in focus array
+	 * would be modified while still being iterated upon.
 	 * @note
 	 * Internal class. Unless modifying internal engine systems you should have no need to access this class.
 	 */
@@ -238,16 +238,16 @@ namespace BansheeEngine
 		 */
 		bool findElementUnderPointer(const Vector2I& screenMousePos, bool buttonStates[3], bool shift, bool control, bool alt);
 
-		/**	Called whenever a pointer (e.g. mouse cursor) is moved. */
+		/**	Called whenever a pointer (for example mouse cursor) is moved. */
 		void onPointerMoved(const PointerEvent& event);
 
-		/**	Called whenever a pointer button (e.g. mouse button) is released. */
+		/**	Called whenever a pointer button (for example mouse button) is released. */
 		void onPointerReleased(const PointerEvent& event);
 
-		/**	Called whenever a pointer button (e.g. mouse button) is pressed. */
+		/**	Called whenever a pointer button (for example mouse button) is pressed. */
 		void onPointerPressed(const PointerEvent& event);
 
-		/**	Called whenever a pointer button (e.g. mouse button) is double clicked. */
+		/**	Called whenever a pointer button (for example mouse button) is double clicked. */
 		void onPointerDoubleClick(const PointerEvent& event);
 
 		/**	Called whenever a text is input. */

+ 178 - 178
Source/BansheeEngine/Include/BsGUIMenu.h

@@ -1,179 +1,179 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsGUIDropDownMenu.h"
-#include "BsShortcutKey.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup GUI
-	 *  @{
-	 */
-
-	class GUIMenuItem;
-
-	/** Used for comparing GUI menu items in order to determine the order in which they are presented. */
-	struct GUIMenuItemComparer
-	{
-		bool operator() (const GUIMenuItem* const& a, const GUIMenuItem* const& b);
-	};
-
-	/** Holds information about a single element in a GUI menu. */
-	class BS_EXPORT GUIMenuItem
-	{
-	public:
-		/**
-		 * Constructs a new non-separator menu item.
-		 *
-		 * @param[in]	parent		Parent item, if any.
-		 * @param[in]	name		Name of the item to be displayed.
-		 * @param[in]	callback	Callback to be triggered when menu items is selected.
-		 * @param[in]	priority	Priority that determines the order of this element compared to its siblings.
-		 * @param[in]	seqIdx		Sequential index of the menu item that specifies in what order was it added to the menu
-		 * 							compared to other items.
-		 * @param[in]	key			Keyboard shortcut that can be used for triggering the menu item.
-		 */
-		GUIMenuItem(GUIMenuItem* parent, const WString& name, std::function<void()> callback, 
-			INT32 priority, UINT32 seqIdx, const ShortcutKey& key);
-
-		/**
-		 * Constructs a new separator menu item.
-		 *
-		 * @param[in]	parent		Parent item, if any.
-		 * @param[in]	priority	Priority that determines the order of this element compared to its siblings.
-		 * @param[in]	seqIdx		Sequential index of the menu item that specifies in what order was it added to the menu
-		 * 							compared to other items.
-		 */
-		GUIMenuItem(GUIMenuItem* parent, INT32 priority, UINT32 seqIdx);
-		~GUIMenuItem();
-
-		/**	Registers a new child with the item. */
-		void addChild(GUIMenuItem* child) { mChildren.insert(child); }
-
-		/**	Returns number of child menu items. */
-		UINT32 getNumChildren() const { return (UINT32)mChildren.size(); }
-
-		/**	Returns the parent menu item, or null if none. */
-		GUIMenuItem* getParent() const { return mParent; }
-
-		/**	Returns name of the menu item. Empty if separator. */
-		const WString& getName() const { return mName; }
-
-		/**	Returns callback that will trigger when menu item is selected. Null for separators. */
-		std::function<void()> getCallback() const { return mCallback; }
-
-		/**	Returns a keyboard shortcut that may be used for triggering the menu item callback. */
-		const ShortcutKey& getShortcut() const { return mShortcut; }
-
-		/**	Checks is the menu item a separator or a normal named menu item. */
-		bool isSeparator() const { return mIsSeparator; }
-
-		/** Attempts to find a child menu item with the specified name. Only direct descendants are searched. */
-		const GUIMenuItem* findChild(const WString& name) const;
-
-		/**	Removes the first child with the specified name. */
-		void removeChild(const WString& name);
-
-		/**	Removes the specified child. */
-		void removeChild(const GUIMenuItem* item);
-
-	private:
-		friend class GUIMenu;
-		friend struct GUIMenuItemComparer;
-
-		/** @copydoc GUIMenuitem::findChild(const WString& name) const */
-		GUIMenuItem* findChild(const WString& name);
-
-		GUIMenuItem* mParent;
-		bool mIsSeparator;
-		WString mName;
-		std::function<void()> mCallback;
-		INT32 mPriority;
-		ShortcutKey mShortcut;
-		UINT32 mSeqIdx;
-		Set<GUIMenuItem*, GUIMenuItemComparer> mChildren;
-	};
-
-	/**
-	 * Class that allows creation of menus with drop down functionality.
-	 * Menu consists out of a number of top level elements, each of which opens
-	 * a drop down menu which may internally hold a deeper hierarchy of menus.
-	 *
-	 * @note	
-	 * When specifying menu items you must provide a path. Path must be formated in a certain way. All path elements must
-	 * be separated by /, e.g. "View/Toolbars/Find". "View" would be the top level path element, "Toolbars" a child in its
-	 * menu that opens up its own submenu, and "Find" a child in the "Toolbars" sub-menu with an optional callback.
-	 * @note
-	 * This is an abstract class and you should provide specialized implementations for specific menu types.
-	 */
-	class BS_EXPORT GUIMenu
-	{
-	public:
-		GUIMenu();
-		virtual ~GUIMenu();
-
-		/**
-		 * Adds a new menu item with the specified callback. 
-		 *			
-		 * @param[in]	path		Path that determines where to add the element. See class information on how to specify
-		 *							paths. All sub-elements of a path will be added automatically.
-		 * @param[in]	callback	Callback that triggers when the path element is selected.
-		 * @param[in]	priority	Priority determines the position of the menu item relative to its siblings. Higher 
-		 *							priority means it will be placed earlier in the menu.
-		 * @param[in]	key			Keyboard shortcut that can be used for triggering the menu item.
-		 * @return					A menu item object that you may use for removing the menu item later. Its lifetime is
-		 *							managed internally.
-		 */
-		GUIMenuItem* addMenuItem(const WString& path, std::function<void()> callback, INT32 priority, const ShortcutKey& key = ShortcutKey::NONE);
-
-		/**
-		 * Adds a new separator menu item with the specified callback.
-		 *			
-		 * @param[in]	path		Path that determines where to add the element. See class information on how to specify 
-		 *							paths. All sub-elements of a path will be added automatically.
-		 * @param[in]	priority	Priority determines the position of the menu item relative to its siblings. Higher
-		 *							priority means it will be placed earlier in the menu.
-		 * @return					A menu item object that you may use for removing the menu item later. Its lifetime is
-		 *							managed internally.
-		 */
-		GUIMenuItem* addSeparator(const WString& path, INT32 priority);
-
-		/**	Returns a menu item at the specified path, or null if one is not found. */
-		GUIMenuItem* getMenuItem(const WString& path);
-
-		/**	Removes the specified menu item from the path. If the menu item has any sub-menus they will also be removed. */
-		void removeMenuItem(const GUIMenuItem* item);
-
-		/**
-		 * Normally menu items use values from their paths as their names. However path labels don't provide a way of
-		 * localizing the menu item. This method allows you to set specific names (different from path labels) to each menu
-		 * item. All the values are localized so they will also be updated according to the string table.
-		 *
-		 * @param[in]	menuItemLabel	The menu item label. (e.g. if you have a menu like "View/Toolbars/Find, this 
-		 *								parameter would be either "View", "Toolbars" or "Find" depending which entry you 
-		 *								want to localize)
-		 * @param[in]	localizedName	Localized string with the name.
-		 */
-		void setLocalizedName(const WString& menuItemLabel, const HString& localizedName);
-
-		/**	Returns data used for initializing a drop down list, for all elements. */
-		GUIDropDownData getDropDownData() const;
-	protected:
-		/**	Adds a menu item at the specified path, as a normal button or as a separator. */
-		GUIMenuItem* addMenuItemInternal(const WString& path, std::function<void()> callback, bool isSeparator, 
-			INT32 priority, const ShortcutKey& key);
-
-		/**	Return drop down data for the specified menu. */
-		GUIDropDownData getDropDownDataInternal(const GUIMenuItem& menu) const;
-
-		GUIMenuItem mRootElement;
-		UnorderedMap<WString, HString> mLocalizedEntryNames;
-		UINT32 mNextIdx;
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsGUIDropDownMenu.h"
+#include "BsShortcutKey.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup GUI
+	 *  @{
+	 */
+
+	class GUIMenuItem;
+
+	/** Used for comparing GUI menu items in order to determine the order in which they are presented. */
+	struct GUIMenuItemComparer
+	{
+		bool operator() (const GUIMenuItem* const& a, const GUIMenuItem* const& b);
+	};
+
+	/** Holds information about a single element in a GUI menu. */
+	class BS_EXPORT GUIMenuItem
+	{
+	public:
+		/**
+		 * Constructs a new non-separator menu item.
+		 *
+		 * @param[in]	parent		Parent item, if any.
+		 * @param[in]	name		Name of the item to be displayed.
+		 * @param[in]	callback	Callback to be triggered when menu items is selected.
+		 * @param[in]	priority	Priority that determines the order of this element compared to its siblings.
+		 * @param[in]	seqIdx		Sequential index of the menu item that specifies in what order was it added to the menu
+		 * 							compared to other items.
+		 * @param[in]	key			Keyboard shortcut that can be used for triggering the menu item.
+		 */
+		GUIMenuItem(GUIMenuItem* parent, const WString& name, std::function<void()> callback, 
+			INT32 priority, UINT32 seqIdx, const ShortcutKey& key);
+
+		/**
+		 * Constructs a new separator menu item.
+		 *
+		 * @param[in]	parent		Parent item, if any.
+		 * @param[in]	priority	Priority that determines the order of this element compared to its siblings.
+		 * @param[in]	seqIdx		Sequential index of the menu item that specifies in what order was it added to the menu
+		 * 							compared to other items.
+		 */
+		GUIMenuItem(GUIMenuItem* parent, INT32 priority, UINT32 seqIdx);
+		~GUIMenuItem();
+
+		/**	Registers a new child with the item. */
+		void addChild(GUIMenuItem* child) { mChildren.insert(child); }
+
+		/**	Returns number of child menu items. */
+		UINT32 getNumChildren() const { return (UINT32)mChildren.size(); }
+
+		/**	Returns the parent menu item, or null if none. */
+		GUIMenuItem* getParent() const { return mParent; }
+
+		/**	Returns name of the menu item. Empty if separator. */
+		const WString& getName() const { return mName; }
+
+		/**	Returns callback that will trigger when menu item is selected. Null for separators. */
+		std::function<void()> getCallback() const { return mCallback; }
+
+		/**	Returns a keyboard shortcut that may be used for triggering the menu item callback. */
+		const ShortcutKey& getShortcut() const { return mShortcut; }
+
+		/**	Checks is the menu item a separator or a normal named menu item. */
+		bool isSeparator() const { return mIsSeparator; }
+
+		/** Attempts to find a child menu item with the specified name. Only direct descendants are searched. */
+		const GUIMenuItem* findChild(const WString& name) const;
+
+		/**	Removes the first child with the specified name. */
+		void removeChild(const WString& name);
+
+		/**	Removes the specified child. */
+		void removeChild(const GUIMenuItem* item);
+
+	private:
+		friend class GUIMenu;
+		friend struct GUIMenuItemComparer;
+
+		/** @copydoc GUIMenuitem::findChild(const WString& name) const */
+		GUIMenuItem* findChild(const WString& name);
+
+		GUIMenuItem* mParent;
+		bool mIsSeparator;
+		WString mName;
+		std::function<void()> mCallback;
+		INT32 mPriority;
+		ShortcutKey mShortcut;
+		UINT32 mSeqIdx;
+		Set<GUIMenuItem*, GUIMenuItemComparer> mChildren;
+	};
+
+	/**
+	 * Class that allows creation of menus with drop down functionality.
+	 * Menu consists out of a number of top level elements, each of which opens
+	 * a drop down menu which may internally hold a deeper hierarchy of menus.
+	 *
+	 * @note	
+	 * When specifying menu items you must provide a path. Path must be formated in a certain way. All path elements must
+	 * be separated by /, for example "View/Toolbars/Find". "View" would be the top level path element, "Toolbars" a child
+	 * in its menu that opens up its own submenu, and "Find" a child in the "Toolbars" sub-menu with an optional callback.
+	 * @note
+	 * This is an abstract class and you should provide specialized implementations for specific menu types.
+	 */
+	class BS_EXPORT GUIMenu
+	{
+	public:
+		GUIMenu();
+		virtual ~GUIMenu();
+
+		/**
+		 * Adds a new menu item with the specified callback. 
+		 *			
+		 * @param[in]	path		Path that determines where to add the element. See class information on how to specify
+		 *							paths. All sub-elements of a path will be added automatically.
+		 * @param[in]	callback	Callback that triggers when the path element is selected.
+		 * @param[in]	priority	Priority determines the position of the menu item relative to its siblings. Higher 
+		 *							priority means it will be placed earlier in the menu.
+		 * @param[in]	key			Keyboard shortcut that can be used for triggering the menu item.
+		 * @return					A menu item object that you may use for removing the menu item later. Its lifetime is
+		 *							managed internally.
+		 */
+		GUIMenuItem* addMenuItem(const WString& path, std::function<void()> callback, INT32 priority, const ShortcutKey& key = ShortcutKey::NONE);
+
+		/**
+		 * Adds a new separator menu item with the specified callback.
+		 *			
+		 * @param[in]	path		Path that determines where to add the element. See class information on how to specify 
+		 *							paths. All sub-elements of a path will be added automatically.
+		 * @param[in]	priority	Priority determines the position of the menu item relative to its siblings. Higher
+		 *							priority means it will be placed earlier in the menu.
+		 * @return					A menu item object that you may use for removing the menu item later. Its lifetime is
+		 *							managed internally.
+		 */
+		GUIMenuItem* addSeparator(const WString& path, INT32 priority);
+
+		/**	Returns a menu item at the specified path, or null if one is not found. */
+		GUIMenuItem* getMenuItem(const WString& path);
+
+		/**	Removes the specified menu item from the path. If the menu item has any sub-menus they will also be removed. */
+		void removeMenuItem(const GUIMenuItem* item);
+
+		/**
+		 * Normally menu items use values from their paths as their names. However path labels don't provide a way of
+		 * localizing the menu item. This method allows you to set specific names (different from path labels) to each menu
+		 * item. All the values are localized so they will also be updated according to the string table.
+		 *
+		 * @param[in]	menuItemLabel	The menu item label. (for example if you have a menu like "View/Toolbars/Find, this 
+		 *								parameter would be either "View", "Toolbars" or "Find" depending which entry you 
+		 *								want to localize)
+		 * @param[in]	localizedName	Localized string with the name.
+		 */
+		void setLocalizedName(const WString& menuItemLabel, const HString& localizedName);
+
+		/**	Returns data used for initializing a drop down list, for all elements. */
+		GUIDropDownData getDropDownData() const;
+	protected:
+		/**	Adds a menu item at the specified path, as a normal button or as a separator. */
+		GUIMenuItem* addMenuItemInternal(const WString& path, std::function<void()> callback, bool isSeparator, 
+			INT32 priority, const ShortcutKey& key);
+
+		/**	Return drop down data for the specified menu. */
+		GUIDropDownData getDropDownDataInternal(const GUIMenuItem& menu) const;
+
+		GUIMenuItem mRootElement;
+		UnorderedMap<WString, HString> mLocalizedEntryNames;
+		UINT32 mNextIdx;
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 1 - 1
Source/BansheeEngine/Include/BsGUIScrollBar.h

@@ -28,7 +28,7 @@ namespace BansheeEngine
 		/**	Returns the maximum size of the scroll handle, in pixels. */
 		UINT32 getMaxHandleSize() const;
 
-		/**	Returns the maximum scrollable size the handle can move within (e.g. scroll bar length). */
+		/**	Returns the maximum scrollable size the handle can move within (for example scroll bar length). */
 		UINT32 getScrollableSize() const;
 
 		/** @copydoc GUIElement::setTint */

+ 1 - 1
Source/BansheeEngine/Include/BsGUISkin.h

@@ -62,7 +62,7 @@ namespace BansheeEngine
 		 */
 		static GUISkinPtr _createPtr();
 
-		/** @encond */
+		/** @endcond */
 	private:
 		GUISkin();
 		GUISkin(const GUISkin& skin); // Disable copying

+ 105 - 105
Source/BansheeEngine/Include/BsGUISpace.h

@@ -1,106 +1,106 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsGUIElementBase.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup GUI
-	 *  @{
-	 */
-
-	/** GUI element that may be inserted into layouts in order to make a space of a fixed size. */
-	class BS_EXPORT GUIFixedSpace : public GUIElementBase
-	{
-	public:
-		GUIFixedSpace(UINT32 size)
-			:mSize(size)
-		{ }
-
-		~GUIFixedSpace();
-
-		/**	Returns the size of the space in pixels. */
-		UINT32 getSize() const { return mSize; }
-
-		/**	Changes the size of the space to the specified value, in pixels. */
-		void setSize(UINT32 size) { if (mSize != size) { mSize = size; _markLayoutAsDirty(); } }
-
-		/**	Creates a new fixed space GUI element. */
-		static GUIFixedSpace* create(UINT32 size);
-
-		/**	Destroys the space and removes it from its parent. */
-		static void destroy(GUIFixedSpace* space);
-
-	public: // ***** INTERNAL ******
-		/** @cond INTERNAL */
-
-		/** @copydoc GUIElementBase::_getType */
-		Type _getType() const override { return GUIElementBase::Type::FixedSpace; }
-
-		/** @copydoc GUIElementBase::_getOptimalSize */
-		Vector2I _getOptimalSize() const override { return Vector2I(getSize(), getSize()); }
-
-		/** @copydoc GUIElementBase::_calculateLayoutSizeRange */
-		LayoutSizeRange _calculateLayoutSizeRange() const override;
-
-		/** @copydoc GUIElementBase::_getPadding */
-		const RectOffset& _getPadding() const override
-		{
-			static RectOffset padding;
-
-			return padding;
-		}
-
-		/** @endcond */
-	protected:
-		UINT32 mSize;
-	};
-
-	/**
-	 * GUI element that may be inserted into layouts to make a space of a flexible size. The space will expand only if 
-	 * there is room and other elements are not squished because of it. If multiple flexible spaces are in a layout, their
-	 * sizes will be shared equally.
-	 *
-	 * @note	
-	 * e.g. If you had a horizontal layout with a button, and you wanted to align that button to the right of the layout,
-	 * you would insert a flexible space before the button in the layout.
-	 */
-	class BS_EXPORT GUIFlexibleSpace : public GUIElementBase
-	{
-	public:
-		GUIFlexibleSpace() {}
-		~GUIFlexibleSpace();
-
-		/**	Creates a new flexible space GUI element. */
-		static GUIFlexibleSpace* create();
-
-		/**	Destroys the space and removes it from its parent. */
-		static void destroy(GUIFlexibleSpace* space);
-
-	public: // ***** INTERNAL ******
-		/** @cond INTERNAL */
-
-		/** @copydoc GUIElementBase::_getType */
-		Type _getType() const override { return GUIElementBase::Type::FlexibleSpace; }
-
-		/** @copydoc GUIElementBase::_getOptimalSize */
-		virtual Vector2I _getOptimalSize() const override { return Vector2I(0, 0); }
-
-		/** @copydoc GUIElementBase::_calculateLayoutSizeRange */
-		virtual LayoutSizeRange _calculateLayoutSizeRange() const override;
-
-		/** @copydoc GUIElementBase::_getPadding */
-		virtual const RectOffset& _getPadding() const override
-		{
-			static RectOffset padding;
-
-			return padding;
-		}
-
-		/** @endcond */
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsGUIElementBase.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup GUI
+	 *  @{
+	 */
+
+	/** GUI element that may be inserted into layouts in order to make a space of a fixed size. */
+	class BS_EXPORT GUIFixedSpace : public GUIElementBase
+	{
+	public:
+		GUIFixedSpace(UINT32 size)
+			:mSize(size)
+		{ }
+
+		~GUIFixedSpace();
+
+		/**	Returns the size of the space in pixels. */
+		UINT32 getSize() const { return mSize; }
+
+		/**	Changes the size of the space to the specified value, in pixels. */
+		void setSize(UINT32 size) { if (mSize != size) { mSize = size; _markLayoutAsDirty(); } }
+
+		/**	Creates a new fixed space GUI element. */
+		static GUIFixedSpace* create(UINT32 size);
+
+		/**	Destroys the space and removes it from its parent. */
+		static void destroy(GUIFixedSpace* space);
+
+	public: // ***** INTERNAL ******
+		/** @cond INTERNAL */
+
+		/** @copydoc GUIElementBase::_getType */
+		Type _getType() const override { return GUIElementBase::Type::FixedSpace; }
+
+		/** @copydoc GUIElementBase::_getOptimalSize */
+		Vector2I _getOptimalSize() const override { return Vector2I(getSize(), getSize()); }
+
+		/** @copydoc GUIElementBase::_calculateLayoutSizeRange */
+		LayoutSizeRange _calculateLayoutSizeRange() const override;
+
+		/** @copydoc GUIElementBase::_getPadding */
+		const RectOffset& _getPadding() const override
+		{
+			static RectOffset padding;
+
+			return padding;
+		}
+
+		/** @endcond */
+	protected:
+		UINT32 mSize;
+	};
+
+	/**
+	 * GUI element that may be inserted into layouts to make a space of a flexible size. The space will expand only if 
+	 * there is room and other elements are not squished because of it. If multiple flexible spaces are in a layout, their
+	 * sizes will be shared equally.
+	 *
+	 * @note	
+	 * For example if you had a horizontal layout with a button, and you wanted to align that button to the right of the
+	 * layout, you would insert a flexible space before the button in the layout.
+	 */
+	class BS_EXPORT GUIFlexibleSpace : public GUIElementBase
+	{
+	public:
+		GUIFlexibleSpace() {}
+		~GUIFlexibleSpace();
+
+		/**	Creates a new flexible space GUI element. */
+		static GUIFlexibleSpace* create();
+
+		/**	Destroys the space and removes it from its parent. */
+		static void destroy(GUIFlexibleSpace* space);
+
+	public: // ***** INTERNAL ******
+		/** @cond INTERNAL */
+
+		/** @copydoc GUIElementBase::_getType */
+		Type _getType() const override { return GUIElementBase::Type::FlexibleSpace; }
+
+		/** @copydoc GUIElementBase::_getOptimalSize */
+		virtual Vector2I _getOptimalSize() const override { return Vector2I(0, 0); }
+
+		/** @copydoc GUIElementBase::_calculateLayoutSizeRange */
+		virtual LayoutSizeRange _calculateLayoutSizeRange() const override;
+
+		/** @copydoc GUIElementBase::_getPadding */
+		virtual const RectOffset& _getPadding() const override
+		{
+			static RectOffset padding;
+
+			return padding;
+		}
+
+		/** @endcond */
+	};
+
+	/** @} */
 }

+ 63 - 63
Source/BansheeEngine/Include/BsImageSprite.h

@@ -1,64 +1,64 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsSprite.h"
-#include "BsVector2.h"
-#include "BsColor.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup 2D
-	 *  @{
-	 */
-
-	/**	Image sprite description structure used for initializing or updating an image sprite. */
-	struct IMAGE_SPRITE_DESC
-	{
-		IMAGE_SPRITE_DESC()
-			:width(0), height(0), anchor(SA_TopLeft), borderLeft(0), borderRight(0), 
-			borderTop(0), borderBottom(0), uvScale(1.0f, 1.0f), uvOffset(0.0f, 0.0f), transparent(true)
-		{ }
-
-		UINT32 width; /**< Width of the image in pixels. */
-		UINT32 height; /**< Height of the image in pixels. */
-		SpriteAnchor anchor; /**< Determines where in the provided bounds will the sprite be placed. */
-		Vector2 uvScale; /**< Scale applied to UV width/height used for rendering the sprite. */
-		Vector2 uvOffset; /**< Offset applied to UV coordinates when rendering the sprite. */
-		bool transparent; /**< Should the sprite be rendered with transparency. */
-
-		SpriteTexturePtr texture; /**< Texture to overlay on the sprite. */
-		Color color; /**< Color tint to apply to the sprite. */
-
-		/** Borders (in texels) that allow you to control how is the texture scaled. If borders are 0 the texture will be 
-		 * scaled uniformly. If they are not null only the area inside the borders will be scaled and the outside are will
-		 * remain the original size as in the texture. This allows you to implement "Scale9Grid" functionality.
-		 */
-		UINT32 borderLeft, borderRight, borderTop, borderBottom; 
-	};
-
-	/**	A sprite consisting of a single image represented by a sprite texture. */
-	class BS_EXPORT ImageSprite : public Sprite
-	{
-	public:
-		ImageSprite();
-		~ImageSprite();
-
-		/**
-		 * Recreates internal sprite data according the specified description structure.
-		 *
-		 * @param[in]	desc	Describes the geometry and material of the sprite.
-		 * @param[in]	groupId	Group identifier that forces different materials to be used for different groups (e.g. you
-		 *						don't want the sprites to share the same material if they use different world transform 
-		 *						matrices).
-		 */
-		void update(const IMAGE_SPRITE_DESC& desc, UINT64 groupId);
-
-	private:
-		/**	Clears internal geometry buffers. */
-		void clearMesh();
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsSprite.h"
+#include "BsVector2.h"
+#include "BsColor.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup 2D
+	 *  @{
+	 */
+
+	/**	Image sprite description structure used for initializing or updating an image sprite. */
+	struct IMAGE_SPRITE_DESC
+	{
+		IMAGE_SPRITE_DESC()
+			:width(0), height(0), anchor(SA_TopLeft), borderLeft(0), borderRight(0), 
+			borderTop(0), borderBottom(0), uvScale(1.0f, 1.0f), uvOffset(0.0f, 0.0f), transparent(true)
+		{ }
+
+		UINT32 width; /**< Width of the image in pixels. */
+		UINT32 height; /**< Height of the image in pixels. */
+		SpriteAnchor anchor; /**< Determines where in the provided bounds will the sprite be placed. */
+		Vector2 uvScale; /**< Scale applied to UV width/height used for rendering the sprite. */
+		Vector2 uvOffset; /**< Offset applied to UV coordinates when rendering the sprite. */
+		bool transparent; /**< Should the sprite be rendered with transparency. */
+
+		SpriteTexturePtr texture; /**< Texture to overlay on the sprite. */
+		Color color; /**< Color tint to apply to the sprite. */
+
+		/** Borders (in texels) that allow you to control how is the texture scaled. If borders are 0 the texture will be 
+		 * scaled uniformly. If they are not null only the area inside the borders will be scaled and the outside are will
+		 * remain the original size as in the texture. This allows you to implement "Scale9Grid" functionality.
+		 */
+		UINT32 borderLeft, borderRight, borderTop, borderBottom; 
+	};
+
+	/**	A sprite consisting of a single image represented by a sprite texture. */
+	class BS_EXPORT ImageSprite : public Sprite
+	{
+	public:
+		ImageSprite();
+		~ImageSprite();
+
+		/**
+		 * Recreates internal sprite data according the specified description structure.
+		 *
+		 * @param[in]	desc	Describes the geometry and material of the sprite.
+		 * @param[in]	groupId	Group identifier that forces different materials to be used for different groups (for 
+		 *						example you don't want the sprites to share the same material if they use different world
+		 *						transform matrices).
+		 */
+		void update(const IMAGE_SPRITE_DESC& desc, UINT64 groupId);
+
+	private:
+		/**	Clears internal geometry buffers. */
+		void clearMesh();
+	};
+
+	/** @} */
 }

+ 58 - 58
Source/BansheeEngine/Include/BsPaths.h

@@ -1,59 +1,59 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup Utility-Engine
-	 *  @{
-	 */
-
-	static const char* ENGINE_ASSEMBLY = "MBansheeEngine";
-	static const char* SCRIPT_GAME_ASSEMBLY = "MScriptGame";
-	static const char* GAME_RESOURCES_FOLDER_NAME = "Resources\\";
-	static const char* GAME_SETTINGS_NAME = "GameSettings.asset";
-	static const char* GAME_RESOURCE_MANIFEST_NAME = "ResourceManifest.asset";
-	static const char* GAME_RESOURCE_MAPPING_NAME = "ResourceMapping.asset";
-
-	/** Contains common engine paths. */
-	class BS_EXPORT Paths
-	{
-	public:
-		/**	Returns a path where the managed release assemblies are located. Relative to working directory. */
-		static const Path& getReleaseAssemblyPath();
-
-		/**	Returns a path where the managed debug assemblies are located. Relative to working directory. */
-		static const Path& getDebugAssemblyPath();
-
-		/**	Returns a path where the builtin assets are located. Relative to working directory. */
-		static const Path& getRuntimeDataPath();
-
-		/**	Returns a path where the builtin engine-specific assets are located. Relative to working directory. */
-		static const Path& getEngineDataPath();
-
-		/**	Returns a path to the game settings file used by editor-built executables. Relative to working directory. */
-		static const Path& getGameSettingsPath();
-
-		/**	Returns a path to the game resources folder used by editor-built executables. Relative to working directory. */
-		static const Path& getGameResourcesPath();
-
-		/**
-		 * Searches common locations for a specified path by querying if the file/directory exists and returns the found 
-		 * path.
-		 * 			
-		 * @param[in]	path	Relative path to search for (e.g. "Data\").				
-		 * @return				Path at which the relative path was found at. This path will be relative to the working 
-		 *						directory.
-		 */
-		static Path findPath(const Path& path);
-
-		static const Path RELEASE_ASSEMBLY_PATH;
-		static const Path DEBUG_ASSEMBLY_PATH;
-		static const Path RUNTIME_DATA_PATH;
-		static const Path ENGINE_DATA_PATH;
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Utility-Engine
+	 *  @{
+	 */
+
+	static const char* ENGINE_ASSEMBLY = "MBansheeEngine";
+	static const char* SCRIPT_GAME_ASSEMBLY = "MScriptGame";
+	static const char* GAME_RESOURCES_FOLDER_NAME = "Resources\\";
+	static const char* GAME_SETTINGS_NAME = "GameSettings.asset";
+	static const char* GAME_RESOURCE_MANIFEST_NAME = "ResourceManifest.asset";
+	static const char* GAME_RESOURCE_MAPPING_NAME = "ResourceMapping.asset";
+
+	/** Contains common engine paths. */
+	class BS_EXPORT Paths
+	{
+	public:
+		/**	Returns a path where the managed release assemblies are located. Relative to working directory. */
+		static const Path& getReleaseAssemblyPath();
+
+		/**	Returns a path where the managed debug assemblies are located. Relative to working directory. */
+		static const Path& getDebugAssemblyPath();
+
+		/**	Returns a path where the builtin assets are located. Relative to working directory. */
+		static const Path& getRuntimeDataPath();
+
+		/**	Returns a path where the builtin engine-specific assets are located. Relative to working directory. */
+		static const Path& getEngineDataPath();
+
+		/**	Returns a path to the game settings file used by editor-built executables. Relative to working directory. */
+		static const Path& getGameSettingsPath();
+
+		/**	Returns a path to the game resources folder used by editor-built executables. Relative to working directory. */
+		static const Path& getGameResourcesPath();
+
+		/**
+		 * Searches common locations for a specified path by querying if the file/directory exists and returns the found 
+		 * path.
+		 * 			
+		 * @param[in]	path	Relative path to search for (for example "Data\").				
+		 * @return				Path at which the relative path was found at. This path will be relative to the working 
+		 *						directory.
+		 */
+		static Path findPath(const Path& path);
+
+		static const Path RELEASE_ASSEMBLY_PATH;
+		static const Path DEBUG_ASSEMBLY_PATH;
+		static const Path RUNTIME_DATA_PATH;
+		static const Path ENGINE_DATA_PATH;
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 2 - 2
Source/BansheeEngine/Include/BsPrerequisites.h

@@ -12,8 +12,8 @@
  */
 
 /** @defgroup Renderer-Engine Renderer
-  *	Abstract interface and helper functionality for rendering scene objects and other geometry (e.g. GUI). Provides more
-  * specialized functionality than Renderer abstraction in BansheeCore.
+  *	Abstract interface and helper functionality for rendering scene objects and other geometry (for example GUI). Provides
+  * a more specialized functionality than Renderer abstraction in BansheeCore.
   */
 
 /** @defgroup 2D 2D

+ 54 - 54
Source/BansheeEngine/Include/BsRendererMaterialManager.h

@@ -1,55 +1,55 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsModule.h"
-#include "BsRendererMaterial.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup Renderer-Engine
-	 *  @{
-	 */
-
-	class RendererMaterialBase;
-	struct RendererMaterialMetaData;
-
-	/**	Initializes and handles all renderer materials. */
-	class BS_EXPORT RendererMaterialManager : public Module<RendererMaterialManager>
-	{
-		/**	Information used for initializing a renderer material managed by this module. */	
-		struct RendererMaterialData
-		{
-			RendererMaterialMetaData* metaData;
-			Path shaderPath;
-		};
-
-	public:
-		RendererMaterialManager();
-		~RendererMaterialManager();
-
-		/**	Registers a new material that should be initialized on module start-up. */
-		static void _registerMaterial(RendererMaterialMetaData* metaData, const Path& shaderPath);
-
-	private:
-		template<class T>
-		friend class RendererMaterial;
-
-		/**	Initializes all materials on the core thread. */
-		static void initOnCore(const Vector<SPtr<ShaderCore>>& shaders);
-
-		/**	Destroys all materials on the core thread. */
-		static void destroyOnCore();
-
-		/**	Returns a list in which are all materials managed by this module. */
-		static Vector<RendererMaterialData>& getMaterials();
-
-		/**	Returns a mutex used for inter-thread access to the materials list. */
-		static Mutex& getMutex();
-	};
-
-	/** @} */
-	/** @endgroup */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsModule.h"
+#include "BsRendererMaterial.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Renderer-Engine
+	 *  @{
+	 */
+
+	class RendererMaterialBase;
+	struct RendererMaterialMetaData;
+
+	/**	Initializes and handles all renderer materials. */
+	class BS_EXPORT RendererMaterialManager : public Module<RendererMaterialManager>
+	{
+		/**	Information used for initializing a renderer material managed by this module. */	
+		struct RendererMaterialData
+		{
+			RendererMaterialMetaData* metaData;
+			Path shaderPath;
+		};
+
+	public:
+		RendererMaterialManager();
+		~RendererMaterialManager();
+
+		/**	Registers a new material that should be initialized on module start-up. */
+		static void _registerMaterial(RendererMaterialMetaData* metaData, const Path& shaderPath);
+
+	private:
+		template<class T>
+		friend class RendererMaterial;
+
+		/**	Initializes all materials on the core thread. */
+		static void initOnCore(const Vector<SPtr<ShaderCore>>& shaders);
+
+		/**	Destroys all materials on the core thread. */
+		static void destroyOnCore();
+
+		/**	Returns a list in which are all materials managed by this module. */
+		static Vector<RendererMaterialData>& getMaterials();
+
+		/**	Returns a mutex used for inter-thread access to the materials list. */
+		static Mutex& getMutex();
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 58 - 58
Source/BansheeEngine/Include/BsScriptManager.h

@@ -1,59 +1,59 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsModule.h"
-
-namespace BansheeEngine 
-{
-	/** @cond INTERNAL */
-	/** @addtogroup Script
-	 *  @{
-	 */
-
-	/**	Abstraction that handles a specific set of script libraries. */
-	class BS_EXPORT ScriptLibrary
-	{
-	public:
-		virtual ~ScriptLibrary() { }
-
-		/**	Called when the script system is being activated. */
-		virtual void initialize() = 0;
-
-		/** Called when the script libraries should be reloaded (e.g. when they are recompiled). */
-		virtual void reload() = 0;
-
-		/**	Called when the script system is being destroyed. */
-		virtual void destroy() = 0;
-	};
-
-	/**	Handles initialization of a scripting system. */
-	class BS_EXPORT ScriptManager : public Module<ScriptManager>
-	{
-	public:
-		ScriptManager() { }
-		~ScriptManager() { }
-
-		/** Initializes the currently active script library loading the scripts contained within. */
-		void initialize();
-
-		/**
-		 * Reloads any scripts in the currently active library. Should be called after some change to the scripts was made
-		 * (e.g. project was changed, or scripts were recompiled).
-		 */
-		void reload();
-
-		/** Sets the active script library that controls what kind and which scripts are loaded. */
-		void _setScriptLibrary(const SPtr<ScriptLibrary>& library);
-
-	private:
-		/** @copydoc ScriptManager::onShutDown */
-		void onShutDown() override;
-
-		SPtr<ScriptLibrary> mScriptLibrary;
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsModule.h"
+
+namespace BansheeEngine 
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Script
+	 *  @{
+	 */
+
+	/**	Abstraction that handles a specific set of script libraries. */
+	class BS_EXPORT ScriptLibrary
+	{
+	public:
+		virtual ~ScriptLibrary() { }
+
+		/**	Called when the script system is being activated. */
+		virtual void initialize() = 0;
+
+		/** Called when the script libraries should be reloaded (for example when they are recompiled). */
+		virtual void reload() = 0;
+
+		/**	Called when the script system is being destroyed. */
+		virtual void destroy() = 0;
+	};
+
+	/**	Handles initialization of a scripting system. */
+	class BS_EXPORT ScriptManager : public Module<ScriptManager>
+	{
+	public:
+		ScriptManager() { }
+		~ScriptManager() { }
+
+		/** Initializes the currently active script library loading the scripts contained within. */
+		void initialize();
+
+		/**
+		 * Reloads any scripts in the currently active library. Should be called after some change to the scripts was made
+		 * (for example project was changed, or scripts were recompiled).
+		 */
+		void reload();
+
+		/** Sets the active script library that controls what kind and which scripts are loaded. */
+		void _setScriptLibrary(const SPtr<ScriptLibrary>& library);
+
+	private:
+		/** @copydoc ScriptManager::onShutDown */
+		void onShutDown() override;
+
+		SPtr<ScriptLibrary> mScriptLibrary;
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 44 - 44
Source/BansheeEngine/Include/BsShortcutKey.h

@@ -1,45 +1,45 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsInputFwd.h"
-
-namespace BansheeEngine
-{
-	/** @cond INTERNAL */
-	/** @addtogroup GUI
-	 *  @{
-	 */
-
-	/** A key combination that is used for triggering keyboard shortcuts. Contains a button code and an optional modifier. */
-	struct BS_EXPORT ShortcutKey
-	{
-		struct BS_EXPORT Hash
-		{
-			inline size_t operator()(const ShortcutKey& x) const;
-		};
-
-		struct BS_EXPORT Equals
-		{
-			inline bool operator()(const ShortcutKey& a, const ShortcutKey& b) const;
-		};
-
-		ShortcutKey();
-		ShortcutKey(ButtonModifier modifier, ButtonCode code);
-
-		/**	Checks is the shortcut button and modifier combination valid. */
-		bool isValid() const { return button != BC_UNASSIGNED; }
-
-		/**	Returns a readable name of the shortcut key (e.g. "Shift + F"). */
-		WString getName() const;
-
-		ButtonModifier modifier;
-		ButtonCode button;
-
-		static const ShortcutKey NONE;
-	};
-
-	/** @} */
-	/** @endcond */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsInputFwd.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup GUI
+	 *  @{
+	 */
+
+	/** A key combination that is used for triggering keyboard shortcuts. Contains a button code and an optional modifier. */
+	struct BS_EXPORT ShortcutKey
+	{
+		struct BS_EXPORT Hash
+		{
+			inline size_t operator()(const ShortcutKey& x) const;
+		};
+
+		struct BS_EXPORT Equals
+		{
+			inline bool operator()(const ShortcutKey& a, const ShortcutKey& b) const;
+		};
+
+		ShortcutKey();
+		ShortcutKey(ButtonModifier modifier, ButtonCode code);
+
+		/**	Checks is the shortcut button and modifier combination valid. */
+		bool isValid() const { return button != BC_UNASSIGNED; }
+
+		/**	Returns a readable name of the shortcut key (for example "Shift + F"). */
+		WString getName() const;
+
+		ButtonModifier modifier;
+		ButtonCode button;
+
+		static const ShortcutKey NONE;
+	};
+
+	/** @} */
+	/** @endcond */
 }

+ 104 - 104
Source/BansheeEngine/Include/BsSpriteTexture.h

@@ -1,105 +1,105 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsResource.h"
-#include "BsVector2.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup 2D
-	 *  @{
-	 */
-
-	/**
-	 * Texture interface that encapsulates underlying texture which allows us to create a sprite texture atlas (e.g. 
-	 * multiple SpriteTexture%s referencing different parts of a single Texture).
-	 */
-	class BS_EXPORT SpriteTexture : public Resource
-	{
-	public:
-		/**	Gets the internal texture that the sprite texture references. */
-		const HTexture& getTexture() const;
-
-		/**	Sets the internal texture that the sprite texture references. */
-		void setTexture(const HTexture& texture);
-
-		/**
-		 * Gets the offset into the referenced texture where the sprite starts.
-		 *
-		 * @return	Offset in UV coordinates, range [0, 1].
-		 */
-		Vector2 getOffset() const { return mUVOffset; }
-
-		/**
-		 * Sets the offset into the referenced texture where the sprite starts.
-		 *
-		 * @param	offset	Offset in UV coordinates, range [0, 1].
-		 */
-		void setOffset(const Vector2& offset) { mUVOffset = offset; }
-
-		/**
-		 * Gets the size of the sprite in the referenced texture.
-		 *
-		 * @return	Size in UV coordinates, range [0, 1].
-		 */
-		Vector2 getScale() const { return mUVScale; }
-
-		/**
-		 * Sets the size of the sprite in the referenced texture.
-		 *
-		 * @param	scale	Size in UV coordinates, range [0, 1].
-		 */
-		void setScale(const Vector2& scale) { mUVScale = scale; }
-
-		/** Transforms wanted UV coordinates into coordinates you can use for sampling the internal texture. */
-		Vector2 transformUV(const Vector2& uv) const;
-
-		/**	Returns a dummy sprite texture. */
-		static const HSpriteTexture& dummy();
-
-		/**	Returns width of the sprite texture in pixels. */
-		UINT32 getWidth() const;
-
-		/**	Returns height of the sprite texture in pixels. */
-		UINT32 getHeight() const;
-
-		/**	Creates a new sprite texture that references the entire area of the provided texture. */
-		static HSpriteTexture create(const HTexture& texture);
-
-		/**	Creates a new sprite texture that references a sub-area of the provided	texture. */
-		static HSpriteTexture create(const Vector2& uvOffset, const Vector2& uvScale, const HTexture& texture);
-
-		/**	Checks if the sprite texture and its internal texture have been loaded. */
-		static bool checkIsLoaded(const HSpriteTexture& tex);
-	private:
-		friend class SpriteTextureRTTI;
-
-		/** @copydoc create(const Vector2&, const Vector2&, const HTexture&) */
-		SpriteTexture(const Vector2& uvOffset, const Vector2& uvScale, const HTexture& texture);
-
-		/** @copydoc Resource::getResourceDependencies */
-		void getResourceDependencies(FrameVector<HResource>& dependencies) const override;
-
-		/** @copydoc CoreObject::getCoreDependencies */
-		void getCoreDependencies(Vector<CoreObject*>& dependencies) override;
-
-		HTexture mAtlasTexture;
-		Vector2 mUVOffset;
-		Vector2 mUVScale;
-
-		/************************************************************************/
-		/* 								RTTI		                     		*/
-		/************************************************************************/
-
-		/**	Creates a new empty and uninitialized sprite texture. To be used by factory methods. */
-		static SpriteTexturePtr createEmpty();
-	public:
-		friend class SpriteTextureRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsResource.h"
+#include "BsVector2.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup 2D
+	 *  @{
+	 */
+
+	/**
+	 * Texture interface that encapsulates underlying texture which allows us to create a sprite texture atlas (for example 
+	 * multiple SpriteTexture%s referencing different parts of a single Texture).
+	 */
+	class BS_EXPORT SpriteTexture : public Resource
+	{
+	public:
+		/**	Gets the internal texture that the sprite texture references. */
+		const HTexture& getTexture() const;
+
+		/**	Sets the internal texture that the sprite texture references. */
+		void setTexture(const HTexture& texture);
+
+		/**
+		 * Gets the offset into the referenced texture where the sprite starts.
+		 *
+		 * @return	Offset in UV coordinates, range [0, 1].
+		 */
+		Vector2 getOffset() const { return mUVOffset; }
+
+		/**
+		 * Sets the offset into the referenced texture where the sprite starts.
+		 *
+		 * @param	offset	Offset in UV coordinates, range [0, 1].
+		 */
+		void setOffset(const Vector2& offset) { mUVOffset = offset; }
+
+		/**
+		 * Gets the size of the sprite in the referenced texture.
+		 *
+		 * @return	Size in UV coordinates, range [0, 1].
+		 */
+		Vector2 getScale() const { return mUVScale; }
+
+		/**
+		 * Sets the size of the sprite in the referenced texture.
+		 *
+		 * @param	scale	Size in UV coordinates, range [0, 1].
+		 */
+		void setScale(const Vector2& scale) { mUVScale = scale; }
+
+		/** Transforms wanted UV coordinates into coordinates you can use for sampling the internal texture. */
+		Vector2 transformUV(const Vector2& uv) const;
+
+		/**	Returns a dummy sprite texture. */
+		static const HSpriteTexture& dummy();
+
+		/**	Returns width of the sprite texture in pixels. */
+		UINT32 getWidth() const;
+
+		/**	Returns height of the sprite texture in pixels. */
+		UINT32 getHeight() const;
+
+		/**	Creates a new sprite texture that references the entire area of the provided texture. */
+		static HSpriteTexture create(const HTexture& texture);
+
+		/**	Creates a new sprite texture that references a sub-area of the provided	texture. */
+		static HSpriteTexture create(const Vector2& uvOffset, const Vector2& uvScale, const HTexture& texture);
+
+		/**	Checks if the sprite texture and its internal texture have been loaded. */
+		static bool checkIsLoaded(const HSpriteTexture& tex);
+	private:
+		friend class SpriteTextureRTTI;
+
+		/** @copydoc create(const Vector2&, const Vector2&, const HTexture&) */
+		SpriteTexture(const Vector2& uvOffset, const Vector2& uvScale, const HTexture& texture);
+
+		/** @copydoc Resource::getResourceDependencies */
+		void getResourceDependencies(FrameVector<HResource>& dependencies) const override;
+
+		/** @copydoc CoreObject::getCoreDependencies */
+		void getCoreDependencies(Vector<CoreObject*>& dependencies) override;
+
+		HTexture mAtlasTexture;
+		Vector2 mUVOffset;
+		Vector2 mUVScale;
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+
+		/**	Creates a new empty and uninitialized sprite texture. To be used by factory methods. */
+		static SpriteTexturePtr createEmpty();
+	public:
+		friend class SpriteTextureRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
+	};
+
+	/** @} */
 }

+ 139 - 139
Source/BansheeEngine/Include/BsTextSprite.h

@@ -1,140 +1,140 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsSprite.h"
-#include "BsTextData.h"
-#include "BsColor.h"
-#include "BsVector2.h"
-#include "BsStaticAlloc.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup 2D
-	 *  @{
-	 */
-
-	/**	Specifies how is text horizontally aligned within its bounds. */
-	enum TextHorzAlign
-	{
-		THA_Left, THA_Center, THA_Right
-	};
-
-	/**	Specifies how is text vertically aligned within its bounds. */
-	enum TextVertAlign
-	{
-		TVA_Top, TVA_Center, TVA_Bottom
-	};
-
-	/**	Text sprite description structure used for initializing or updating a text sprite. */
-	struct TEXT_SPRITE_DESC
-	{
-		TEXT_SPRITE_DESC()
-			:width(0), height(0), anchor(SA_TopLeft), fontSize(0),
-			horzAlign(THA_Left), vertAlign(TVA_Top), wordWrap(false), wordBreak(true)
-		{ }
-
-		UINT32 width; /**< Width of the bounds to render the text within, in pixels. */
-		UINT32 height; /**< Height of the bounds to render the text within, in pixels. */
-		SpriteAnchor anchor; /**< Determines how to anchor the text within the bounds. */
-
-		WString text; /**< Text to generate geometry for. */
-		HFont font; /**< Font containing the data about character glyphs. */
-		UINT32 fontSize; /**< Size of the font to use when displaying the text. */
-		Color color; /**< Color tint of the text. */
-		TextHorzAlign horzAlign; /**< Specifies how is text horizontally aligned within its bounds. */
-		TextVertAlign vertAlign; /**< Specifies how is text vertically aligned within its bounds. */
-		bool wordWrap; /**< If true the text will word wrap when it doesn't fit, otherwise it will overflow. */
-		bool wordBreak; /**< If enabled together with word wrap it will allow words to be broken if they don't fit. */
-	};
-
-	/**	A sprite consisting of a quads representing a text string. */
-	class BS_EXPORT TextSprite : public Sprite
-	{
-	public:
-		TextSprite();
-		~TextSprite();
-
-		/**
-		 * Recreates internal sprite data according the specified description structure.
-		 *
-		 * @param[in]	desc	Describes the geometry and material of the sprite.
-		 * @param[in]	groupId	Group identifier that forces different materials to be used for different groups (e.g. you
-		 *						don't want the sprites to share the same group if they use different world transform
-		 *						matrices).
-		 */
-		void update(const TEXT_SPRITE_DESC& desc, UINT64 groupId);
-
-		/**
-		 * Calculates and returns offset for each individual text line. The offsets provide information on how much to 
-		 * offset the lines within provided bounds.
-		 *
-		 * @param[in]	textData	Text data to generate offsets for.
-		 * @param[in]	width		Width of the text bounds into which to constrain the text, in pixels.
-		 * @param[in]	height		Height of the text bounds into which to constrain the text, in pixels.
-		 * @param[in]	horzAlign	Specifies how is text horizontally aligned within its bounds.
-		 * @param[in]	vertAlign	Specifies how is text vertically aligned within its bounds.
-		 * @param[out]	output		Pre-allocated buffer to output the results in. Buffer must have an element
-		 *							for every line in @p textData.
-		 */
-		static void getAlignmentOffsets(const TextDataBase& textData, 
-			UINT32 width, UINT32 height, TextHorzAlign horzAlign, TextVertAlign vertAlign, Vector2I* output);
-
-		/**
-		 * Calculates text quads you may use for text rendering, based on the specified text data. Only generates quads for
-		 * the specified page.
-		 *
-		 * @param[in]	page			Font page to generate the data for.
-		 * @param[in]	textData		Text data to generate offsets for.
-		 * @param[in]	width			Width of the text bounds into which to constrain the text, in pixels.
-		 * @param[in]	height			Height of the text bounds into which to constrain the text, in pixels.
-		 * @param[in]	horzAlign		Specifies how is text horizontally aligned within its bounds.
-		 * @param[in]	vertAlign		Specifies how is text vertically aligned within its bounds.
-		 * @param[in]	anchor			Determines how to anchor the text within the bounds.
-		 * @param[out]	vertices		Output buffer containing quad positions. Must be allocated and of adequate size.
-		 * @param[out]	uv				Output buffer containing quad UV coordinates. Must be allocated and of adequate 
-		 *								size. Can be null.
-		 * @param[out]	indices			Output buffer containing quad indices. Must be allocated and of adequate size. Can
-		 *								be null.
-		 * @param[in]	bufferSizeQuads	Size of the output buffers, in number of quads.
-		 * @return						Number of generated quads.
-		 */
-		static UINT32 genTextQuads(UINT32 page, const TextDataBase& textData, UINT32 width, UINT32 height, 
-			TextHorzAlign horzAlign, TextVertAlign vertAlign, SpriteAnchor anchor, Vector2* vertices, Vector2* uv, UINT32* indices, 
-			UINT32 bufferSizeQuads);
-
-		/**
-		 * Calculates text quads you may use for text rendering, based on the specified text data. Generates quads for all 
-		 * pages.
-		 * 			
-		 * @param[in]	textData		Text data to generate offsets for.
-		 * @param[in]	width			Width of the text bounds into which to constrain the text, in pixels.
-		 * @param[in]	height			Height of the text bounds into which to constrain the text, in pixels.
-		 * @param[in]	horzAlign		Specifies how is text horizontally aligned within its bounds.
-		 * @param[in]	vertAlign		Specifies how is text vertically aligned within its bounds.
-		 * @param[in]	anchor			Determines how to anchor the text within the bounds.
-		 * @param[out]	vertices		Output buffer containing quad positions. Must be allocated and of adequate size.
-		 * @param[out]	uv				Output buffer containing quad UV coordinates. Must be allocated and of adequate 
-		 *								size. Can be null.
-		 * @param[out]	indices			Output buffer containing quad indices. Must be allocated and of adequate size. Can
-		 *								be null.
-		 * @param[in]	bufferSizeQuads	Size of the output buffers, in number of quads.
-		 * @return						Number of generated quads.
-		 */
-		static UINT32 genTextQuads(const TextDataBase& textData, UINT32 width, UINT32 height,
-			TextHorzAlign horzAlign, TextVertAlign vertAlign, SpriteAnchor anchor, Vector2* vertices, Vector2* uv, UINT32* indices, 
-			UINT32 bufferSizeQuads);
-
-	private:
-		static const int STATIC_CHARS_TO_BUFFER = 25;
-		static const int STATIC_BUFFER_SIZE = STATIC_CHARS_TO_BUFFER * (4 * (2 * sizeof(Vector2)) + (6 * sizeof(UINT32)));
-
-		/**	Clears internal geometry buffers. */
-		void clearMesh();
-
-		mutable StaticAlloc<STATIC_BUFFER_SIZE, STATIC_BUFFER_SIZE> mAlloc;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsSprite.h"
+#include "BsTextData.h"
+#include "BsColor.h"
+#include "BsVector2.h"
+#include "BsStaticAlloc.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup 2D
+	 *  @{
+	 */
+
+	/**	Specifies how is text horizontally aligned within its bounds. */
+	enum TextHorzAlign
+	{
+		THA_Left, THA_Center, THA_Right
+	};
+
+	/**	Specifies how is text vertically aligned within its bounds. */
+	enum TextVertAlign
+	{
+		TVA_Top, TVA_Center, TVA_Bottom
+	};
+
+	/**	Text sprite description structure used for initializing or updating a text sprite. */
+	struct TEXT_SPRITE_DESC
+	{
+		TEXT_SPRITE_DESC()
+			:width(0), height(0), anchor(SA_TopLeft), fontSize(0),
+			horzAlign(THA_Left), vertAlign(TVA_Top), wordWrap(false), wordBreak(true)
+		{ }
+
+		UINT32 width; /**< Width of the bounds to render the text within, in pixels. */
+		UINT32 height; /**< Height of the bounds to render the text within, in pixels. */
+		SpriteAnchor anchor; /**< Determines how to anchor the text within the bounds. */
+
+		WString text; /**< Text to generate geometry for. */
+		HFont font; /**< Font containing the data about character glyphs. */
+		UINT32 fontSize; /**< Size of the font to use when displaying the text. */
+		Color color; /**< Color tint of the text. */
+		TextHorzAlign horzAlign; /**< Specifies how is text horizontally aligned within its bounds. */
+		TextVertAlign vertAlign; /**< Specifies how is text vertically aligned within its bounds. */
+		bool wordWrap; /**< If true the text will word wrap when it doesn't fit, otherwise it will overflow. */
+		bool wordBreak; /**< If enabled together with word wrap it will allow words to be broken if they don't fit. */
+	};
+
+	/**	A sprite consisting of a quads representing a text string. */
+	class BS_EXPORT TextSprite : public Sprite
+	{
+	public:
+		TextSprite();
+		~TextSprite();
+
+		/**
+		 * Recreates internal sprite data according the specified description structure.
+		 *
+		 * @param[in]	desc	Describes the geometry and material of the sprite.
+		 * @param[in]	groupId	Group identifier that forces different materials to be used for different groups (for 
+		 *						example you don't want the sprites to share the same group if they use different world
+		 *						transform matrices).
+		 */
+		void update(const TEXT_SPRITE_DESC& desc, UINT64 groupId);
+
+		/**
+		 * Calculates and returns offset for each individual text line. The offsets provide information on how much to 
+		 * offset the lines within provided bounds.
+		 *
+		 * @param[in]	textData	Text data to generate offsets for.
+		 * @param[in]	width		Width of the text bounds into which to constrain the text, in pixels.
+		 * @param[in]	height		Height of the text bounds into which to constrain the text, in pixels.
+		 * @param[in]	horzAlign	Specifies how is text horizontally aligned within its bounds.
+		 * @param[in]	vertAlign	Specifies how is text vertically aligned within its bounds.
+		 * @param[out]	output		Pre-allocated buffer to output the results in. Buffer must have an element
+		 *							for every line in @p textData.
+		 */
+		static void getAlignmentOffsets(const TextDataBase& textData, 
+			UINT32 width, UINT32 height, TextHorzAlign horzAlign, TextVertAlign vertAlign, Vector2I* output);
+
+		/**
+		 * Calculates text quads you may use for text rendering, based on the specified text data. Only generates quads for
+		 * the specified page.
+		 *
+		 * @param[in]	page			Font page to generate the data for.
+		 * @param[in]	textData		Text data to generate offsets for.
+		 * @param[in]	width			Width of the text bounds into which to constrain the text, in pixels.
+		 * @param[in]	height			Height of the text bounds into which to constrain the text, in pixels.
+		 * @param[in]	horzAlign		Specifies how is text horizontally aligned within its bounds.
+		 * @param[in]	vertAlign		Specifies how is text vertically aligned within its bounds.
+		 * @param[in]	anchor			Determines how to anchor the text within the bounds.
+		 * @param[out]	vertices		Output buffer containing quad positions. Must be allocated and of adequate size.
+		 * @param[out]	uv				Output buffer containing quad UV coordinates. Must be allocated and of adequate 
+		 *								size. Can be null.
+		 * @param[out]	indices			Output buffer containing quad indices. Must be allocated and of adequate size. Can
+		 *								be null.
+		 * @param[in]	bufferSizeQuads	Size of the output buffers, in number of quads.
+		 * @return						Number of generated quads.
+		 */
+		static UINT32 genTextQuads(UINT32 page, const TextDataBase& textData, UINT32 width, UINT32 height, 
+			TextHorzAlign horzAlign, TextVertAlign vertAlign, SpriteAnchor anchor, Vector2* vertices, Vector2* uv, UINT32* indices, 
+			UINT32 bufferSizeQuads);
+
+		/**
+		 * Calculates text quads you may use for text rendering, based on the specified text data. Generates quads for all 
+		 * pages.
+		 * 			
+		 * @param[in]	textData		Text data to generate offsets for.
+		 * @param[in]	width			Width of the text bounds into which to constrain the text, in pixels.
+		 * @param[in]	height			Height of the text bounds into which to constrain the text, in pixels.
+		 * @param[in]	horzAlign		Specifies how is text horizontally aligned within its bounds.
+		 * @param[in]	vertAlign		Specifies how is text vertically aligned within its bounds.
+		 * @param[in]	anchor			Determines how to anchor the text within the bounds.
+		 * @param[out]	vertices		Output buffer containing quad positions. Must be allocated and of adequate size.
+		 * @param[out]	uv				Output buffer containing quad UV coordinates. Must be allocated and of adequate 
+		 *								size. Can be null.
+		 * @param[out]	indices			Output buffer containing quad indices. Must be allocated and of adequate size. Can
+		 *								be null.
+		 * @param[in]	bufferSizeQuads	Size of the output buffers, in number of quads.
+		 * @return						Number of generated quads.
+		 */
+		static UINT32 genTextQuads(const TextDataBase& textData, UINT32 width, UINT32 height,
+			TextHorzAlign horzAlign, TextVertAlign vertAlign, SpriteAnchor anchor, Vector2* vertices, Vector2* uv, UINT32* indices, 
+			UINT32 bufferSizeQuads);
+
+	private:
+		static const int STATIC_CHARS_TO_BUFFER = 25;
+		static const int STATIC_BUFFER_SIZE = STATIC_CHARS_TO_BUFFER * (4 * (2 * sizeof(Vector2)) + (6 * sizeof(UINT32)));
+
+		/**	Clears internal geometry buffers. */
+		void clearMesh();
+
+		mutable StaticAlloc<STATIC_BUFFER_SIZE, STATIC_BUFFER_SIZE> mAlloc;
+	};
+
+	/** @} */
 }

+ 137 - 137
Source/BansheeEngine/Include/BsVirtualInput.h

@@ -1,138 +1,138 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsPrerequisites.h"
-#include "BsModule.h"
-#include "BsInputConfiguration.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup Input-Engine
-	 *  @{
-	 */
-
-	/**
-	 * Handles virtual input that allows you to receive virtual input events that hide the actual physical input, allowing
-	 * you to easily change the input keys while being transparent to the external code.
-	 */
-	class BS_EXPORT VirtualInput : public Module<VirtualInput>
-	{
-		/**	Possible states of virtual buttons. */
-		enum class ButtonState
-		{
-			Off,
-			On,
-			ToggledOn,
-			ToggledOff
-		};
-
-		/**	Data container for a single virtual button. */
-		struct ButtonData
-		{
-			VirtualButton button;
-			ButtonState state;
-			UINT64 timestamp;
-			UINT64 updateFrameIdx;
-			bool allowRepeat;
-		};
-
-		/**	Contains button data for a specific input device. */
-		struct DeviceData
-		{
-			Map<UINT32, ButtonData> cachedStates;
-		};
-
-		/**	Data container for a virtual button event. */
-		struct VirtualButtonEvent
-		{
-			VirtualButton button;
-			ButtonState state;
-			UINT32 deviceIdx;
-		};
-
-	public:
-		VirtualInput();
-
-		/**	Creates a new empty input configuration. */
-		static SPtr<InputConfiguration> createConfiguration();
-
-		/**	Sets an input configuration that determines how physical keys map to virtual buttons. */
-		void setConfiguration(const SPtr<InputConfiguration>& input);
-
-		/**	Retrieves the active input configuration that determines how physical keys map to virtual buttons. */
-		SPtr<InputConfiguration> getConfiguration() const { return mInputConfiguration; }
-
-		/**
-		 * Check is the virtual button just getting pressed. This state is only active for one frame.
-		 *
-		 * @param[in]	button		Virtual button identifier.
-		 * @param[in]	deviceIdx	Optional device index in case multiple input devices are available.
-		 */
-		bool isButtonDown(const VirtualButton& button, UINT32 deviceIdx = 0) const;
-
-		/**
-		 * Check is the virtual button just getting released. This state is only active for one frame.
-		 *
-		 * @param[in]	button		Virtual button identifier.
-		 * @param[in]	deviceIdx	Optional device index in case multiple input devices are available.
-		 */
-		bool isButtonUp(const VirtualButton& button, UINT32 deviceIdx = 0) const;
-
-		/**
-		 * Check is the virtual button is being held. This state is active as long as the button is being held down, 
-		 * i.e. possibly multiple frames.
-		 *
-		 * @param[in]	button		Virtual button identifier.
-		 * @param[in]	deviceIdx	Optional device index in case multiple input devices are available.
-		 */
-		bool isButtonHeld(const VirtualButton& button, UINT32 deviceIdx = 0) const;
-
-		/**
-		 * Returns normalized value for the specified input axis. Returned value will usually be in [-1.0, 1.0] range, but
-		 * can be outside the range for devices with unbound axes (e.g. mouse).
-		 *
-		 * @param[in]	axis		Virtual axis identifier.
-		 * @param[in]	deviceIdx	Optional device index in case multiple input devices are available.
-		 */
-		float getAxisValue(const VirtualAxis& axis, UINT32 deviceIdx = 0) const;
-
-		/**	Triggered when a virtual button is pressed. */
-		Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonDown;
-
-		/**	Triggered when a virtual button is released. */
-		Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonUp;
-
-		/**	Triggered every frame when a virtual button is being held down. */
-		Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonHeld;
-
-		/** @cond INTERNAL */
-
-		/** Called once every frame. Triggers button callbacks. */
-		void _update();
-
-		/** @endcond */
-	private:
-		friend class VirtualButton;
-
-		/** Performs all logic related to a button press. */
-		void buttonDown(const ButtonEvent& event);
-
-		/** Performs all logic related to a button release. */
-		void buttonUp(const ButtonEvent& event);
-
-		std::shared_ptr<InputConfiguration> mInputConfiguration;
-		Vector<DeviceData> mDevices;
-		Queue<VirtualButtonEvent> mEvents;
-		UINT32 mActiveModifiers;
-
-		// Transient
-		Vector<VirtualButton> tempButtons;
-		Vector<VIRTUAL_BUTTON_DESC> tempBtnDescs;
-	};
-
-	/** Provides easier access to VirtualInput. */
-	BS_EXPORT VirtualInput& gVirtualInput();
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsModule.h"
+#include "BsInputConfiguration.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Input-Engine
+	 *  @{
+	 */
+
+	/**
+	 * Handles virtual input that allows you to receive virtual input events that hide the actual physical input, allowing
+	 * you to easily change the input keys while being transparent to the external code.
+	 */
+	class BS_EXPORT VirtualInput : public Module<VirtualInput>
+	{
+		/**	Possible states of virtual buttons. */
+		enum class ButtonState
+		{
+			Off,
+			On,
+			ToggledOn,
+			ToggledOff
+		};
+
+		/**	Data container for a single virtual button. */
+		struct ButtonData
+		{
+			VirtualButton button;
+			ButtonState state;
+			UINT64 timestamp;
+			UINT64 updateFrameIdx;
+			bool allowRepeat;
+		};
+
+		/**	Contains button data for a specific input device. */
+		struct DeviceData
+		{
+			Map<UINT32, ButtonData> cachedStates;
+		};
+
+		/**	Data container for a virtual button event. */
+		struct VirtualButtonEvent
+		{
+			VirtualButton button;
+			ButtonState state;
+			UINT32 deviceIdx;
+		};
+
+	public:
+		VirtualInput();
+
+		/**	Creates a new empty input configuration. */
+		static SPtr<InputConfiguration> createConfiguration();
+
+		/**	Sets an input configuration that determines how physical keys map to virtual buttons. */
+		void setConfiguration(const SPtr<InputConfiguration>& input);
+
+		/**	Retrieves the active input configuration that determines how physical keys map to virtual buttons. */
+		SPtr<InputConfiguration> getConfiguration() const { return mInputConfiguration; }
+
+		/**
+		 * Check is the virtual button just getting pressed. This state is only active for one frame.
+		 *
+		 * @param[in]	button		Virtual button identifier.
+		 * @param[in]	deviceIdx	Optional device index in case multiple input devices are available.
+		 */
+		bool isButtonDown(const VirtualButton& button, UINT32 deviceIdx = 0) const;
+
+		/**
+		 * Check is the virtual button just getting released. This state is only active for one frame.
+		 *
+		 * @param[in]	button		Virtual button identifier.
+		 * @param[in]	deviceIdx	Optional device index in case multiple input devices are available.
+		 */
+		bool isButtonUp(const VirtualButton& button, UINT32 deviceIdx = 0) const;
+
+		/**
+		 * Check is the virtual button is being held. This state is active as long as the button is being held down, 
+		 * i.e. possibly multiple frames.
+		 *
+		 * @param[in]	button		Virtual button identifier.
+		 * @param[in]	deviceIdx	Optional device index in case multiple input devices are available.
+		 */
+		bool isButtonHeld(const VirtualButton& button, UINT32 deviceIdx = 0) const;
+
+		/**
+		 * Returns normalized value for the specified input axis. Returned value will usually be in [-1.0, 1.0] range, but
+		 * can be outside the range for devices with unbound axes (for example mouse).
+		 *
+		 * @param[in]	axis		Virtual axis identifier.
+		 * @param[in]	deviceIdx	Optional device index in case multiple input devices are available.
+		 */
+		float getAxisValue(const VirtualAxis& axis, UINT32 deviceIdx = 0) const;
+
+		/**	Triggered when a virtual button is pressed. */
+		Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonDown;
+
+		/**	Triggered when a virtual button is released. */
+		Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonUp;
+
+		/**	Triggered every frame when a virtual button is being held down. */
+		Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonHeld;
+
+		/** @cond INTERNAL */
+
+		/** Called once every frame. Triggers button callbacks. */
+		void _update();
+
+		/** @endcond */
+	private:
+		friend class VirtualButton;
+
+		/** Performs all logic related to a button press. */
+		void buttonDown(const ButtonEvent& event);
+
+		/** Performs all logic related to a button release. */
+		void buttonUp(const ButtonEvent& event);
+
+		std::shared_ptr<InputConfiguration> mInputConfiguration;
+		Vector<DeviceData> mDevices;
+		Queue<VirtualButtonEvent> mEvents;
+		UINT32 mActiveModifiers;
+
+		// Transient
+		Vector<VirtualButton> tempButtons;
+		Vector<VIRTUAL_BUTTON_DESC> tempBtnDescs;
+	};
+
+	/** Provides easier access to VirtualInput. */
+	BS_EXPORT VirtualInput& gVirtualInput();
+
+	/** @} */
 }

+ 95 - 95
Source/BansheeEngine/Source/BsDragAndDropManager.cpp

@@ -1,96 +1,96 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsDragAndDropManager.h"
-#include "BsPlatform.h"
-#include "BsCoreApplication.h"
-#include <BsTime.h>
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	DragAndDropManager::DragAndDropManager()
-		:mIsDragInProgress(false), mDragTypeId(0), mData(nullptr), mCaptureChanged(false), mCaptureActive(0), mNeedsValidDropTarget(false)
-	{
-		mMouseCaptureChangedConn = Platform::onMouseCaptureChanged.connect(std::bind(&DragAndDropManager::mouseCaptureChanged, this));
-		Input::instance().onPointerReleased.connect(std::bind(&DragAndDropManager::cursorReleased, this, _1));
-	}
-
-	DragAndDropManager::~DragAndDropManager()
-	{
-		mMouseCaptureChangedConn.disconnect();
-	}
-
-	void DragAndDropManager::addDropCallback(std::function<void(bool)> dropCallback)
-	{
-		mDropCallbacks.push_back(dropCallback);
-	}
-
-	void DragAndDropManager::startDrag(UINT32 typeId, void* data, std::function<void(bool)> dropCallback, bool needsValidDropTarget)
-	{
-		if (mIsDragInProgress)
-			endDrag(false);
-
-		mDragTypeId = typeId;
-		mData = data;
-		mNeedsValidDropTarget = needsValidDropTarget;
-		addDropCallback(dropCallback);
-		mIsDragInProgress = true;
-
-		mCaptureActive.store(false);
-		mCaptureChanged.store(false);
-
-		Platform::captureMouse(*gCoreApplication().getPrimaryWindow());
-	}
-
-	void DragAndDropManager::_update()
-	{
-		if(!mIsDragInProgress)
-			return;
-
-		// This generally happens when window loses focus and capture is lost (e.g. alt+tab)
-		int captureActive = mCaptureActive.load();
-		if (!captureActive && mCaptureChanged.load() && 
-			(gTime().getFrameIdx() > mCaptureChangeFrame.load())) // Wait one frame to insure input (like mouse up) gets a chance to be processed
-		{
-			endDrag(false);
-			mCaptureChanged.store(false);
-		}
-	}
-
-	void DragAndDropManager::endDrag(bool processed)
-	{
-		for(auto& callback : mDropCallbacks)
-			callback(processed);
-
-		mDragTypeId = 0;
-		mData = nullptr;
-		mDropCallbacks.clear();
-		mIsDragInProgress = false;
-	}
-
-	void DragAndDropManager::mouseCaptureChanged()
-	{
-		mCaptureActive.fetch_xor(1); // mCaptureActive = !mCaptureActive;
-		mCaptureChanged.store(true);
-		mCaptureChangeFrame.store(gTime().getFrameIdx());
-	}
-
-	void DragAndDropManager::cursorReleased(const PointerEvent& event)
-	{
-		if(!mIsDragInProgress)
-			return;
-
-		if(!onDragEnded.empty())
-		{
-			DragCallbackInfo info;
-			onDragEnded(event, info);
-
-			endDrag(info.processed);
-		}
-		else
-			endDrag(false);
-
-		Platform::releaseMouseCapture();
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsDragAndDropManager.h"
+#include "BsPlatform.h"
+#include "BsCoreApplication.h"
+#include <BsTime.h>
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	DragAndDropManager::DragAndDropManager()
+		:mIsDragInProgress(false), mDragTypeId(0), mData(nullptr), mCaptureChanged(false), mCaptureActive(0), mNeedsValidDropTarget(false)
+	{
+		mMouseCaptureChangedConn = Platform::onMouseCaptureChanged.connect(std::bind(&DragAndDropManager::mouseCaptureChanged, this));
+		Input::instance().onPointerReleased.connect(std::bind(&DragAndDropManager::cursorReleased, this, _1));
+	}
+
+	DragAndDropManager::~DragAndDropManager()
+	{
+		mMouseCaptureChangedConn.disconnect();
+	}
+
+	void DragAndDropManager::addDropCallback(std::function<void(bool)> dropCallback)
+	{
+		mDropCallbacks.push_back(dropCallback);
+	}
+
+	void DragAndDropManager::startDrag(UINT32 typeId, void* data, std::function<void(bool)> dropCallback, bool needsValidDropTarget)
+	{
+		if (mIsDragInProgress)
+			endDrag(false);
+
+		mDragTypeId = typeId;
+		mData = data;
+		mNeedsValidDropTarget = needsValidDropTarget;
+		addDropCallback(dropCallback);
+		mIsDragInProgress = true;
+
+		mCaptureActive.store(false);
+		mCaptureChanged.store(false);
+
+		Platform::captureMouse(*gCoreApplication().getPrimaryWindow());
+	}
+
+	void DragAndDropManager::_update()
+	{
+		if(!mIsDragInProgress)
+			return;
+
+		// This generally happens when window loses focus and capture is lost (for example alt+tab)
+		int captureActive = mCaptureActive.load();
+		if (!captureActive && mCaptureChanged.load() && 
+			(gTime().getFrameIdx() > mCaptureChangeFrame.load())) // Wait one frame to insure input (like mouse up) gets a chance to be processed
+		{
+			endDrag(false);
+			mCaptureChanged.store(false);
+		}
+	}
+
+	void DragAndDropManager::endDrag(bool processed)
+	{
+		for(auto& callback : mDropCallbacks)
+			callback(processed);
+
+		mDragTypeId = 0;
+		mData = nullptr;
+		mDropCallbacks.clear();
+		mIsDragInProgress = false;
+	}
+
+	void DragAndDropManager::mouseCaptureChanged()
+	{
+		mCaptureActive.fetch_xor(1); // mCaptureActive = !mCaptureActive;
+		mCaptureChanged.store(true);
+		mCaptureChangeFrame.store(gTime().getFrameIdx());
+	}
+
+	void DragAndDropManager::cursorReleased(const PointerEvent& event)
+	{
+		if(!mIsDragInProgress)
+			return;
+
+		if(!onDragEnded.empty())
+		{
+			DragCallbackInfo info;
+			onDragEnded(event, info);
+
+			endDrag(info.processed);
+		}
+		else
+			endDrag(false);
+
+		Platform::releaseMouseCapture();
+	}
 }

+ 88 - 87
Source/BansheeMono/Include/BsMonoField.h

@@ -1,88 +1,89 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsMonoPrerequisites.h"
-#include <mono/jit/jit.h>
-#include <mono/metadata/class.h>
-
-namespace BansheeEngine
-{
-	/** @addtogroup Mono
-	 *  @{
-	 */
-
-	/**	Returns the level of field visibility in the class. */
-	enum class MonoFieldVisibility
-	{
-		Private,
-		ProtectedInternal,
-		Internal,
-		Protected,
-		Public
-	};
-
-	/**
-	 * Encapsulates information about a single Mono (i.e. managed) field belonging to some managed class. This object also
-	 * allows you to set or retrieve values to/from specific instances containing the field.
-	 */
-	class BS_MONO_EXPORT MonoField
-	{
-	public:
-		/**	Returns the name of the field. */
-		const String& getName() const { return mName; }
-
-		/**	Returns the class representing the type of data the field holds. */
-		MonoClass* getType();
-
-		/**
-		 * Retrieves value currently set in the field on the specified object instance. If field is static object instance
-		 * can be null. 
-		 *
-		 * @note	
-		 * Value will be a pointer to raw data type for value types (e.g. int, float), and a MonoObject* for reference types.
-		 */
-		void getValue(MonoObject* instance, void* outValue);
-
-		/**
-		 * Retrieves value currently set in the field on the specified object instance. If field is static object instance
-		 * can be null. If returned value is a value type it will be boxed.
-		 */
-		MonoObject* getValueBoxed(MonoObject* instance);
-
-		/**
-		 * Sets a value for the field on the specified object instance. If field is static object instance can be null. 
-		 *
-		 * @note	
-		 * Value should be a pointer to raw data type for value types (e.g. int, float), and a MonoObject* for reference 
-		 * types.
-		 */
-		void setValue(MonoObject* instance, void* value);
-
-		/**	Checks if field has an attribute of the specified type. */
-		bool hasAttribute(MonoClass* monoClass);
-
-		/**
-		 * Returns an instance of an attribute of the specified type. Returns null if the field doesn't have such an 
-		 * attribute.
-		 */
-		MonoObject* getAttribute(MonoClass* monoClass);
-
-		/**	Returns field visibility in the class. */
-		MonoFieldVisibility getVisibility();
-
-		/**	Query if the field is static. */
-		bool isStatic();
-
-	private:
-		friend class MonoClass;
-
-		MonoField(MonoClassField* field);
-
-		String mName;
-		MonoClassField* mField;
-		MonoClass* mFieldType;
-	};
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsMonoPrerequisites.h"
+#include <mono/jit/jit.h>
+#include <mono/metadata/class.h>
+
+namespace BansheeEngine
+{
+	/** @addtogroup Mono
+	 *  @{
+	 */
+
+	/**	Returns the level of field visibility in the class. */
+	enum class MonoFieldVisibility
+	{
+		Private,
+		ProtectedInternal,
+		Internal,
+		Protected,
+		Public
+	};
+
+	/**
+	 * Encapsulates information about a single Mono (i.e. managed) field belonging to some managed class. This object also
+	 * allows you to set or retrieve values to/from specific instances containing the field.
+	 */
+	class BS_MONO_EXPORT MonoField
+	{
+	public:
+		/**	Returns the name of the field. */
+		const String& getName() const { return mName; }
+
+		/**	Returns the class representing the type of data the field holds. */
+		MonoClass* getType();
+
+		/**
+		 * Retrieves value currently set in the field on the specified object instance. If field is static object instance
+		 * can be null. 
+		 *
+		 * @note	
+		 * Value will be a pointer to raw data type for value types (for example int, float), and a MonoObject* for
+		 * reference types.
+		 */
+		void getValue(MonoObject* instance, void* outValue);
+
+		/**
+		 * Retrieves value currently set in the field on the specified object instance. If field is static object instance
+		 * can be null. If returned value is a value type it will be boxed.
+		 */
+		MonoObject* getValueBoxed(MonoObject* instance);
+
+		/**
+		 * Sets a value for the field on the specified object instance. If field is static object instance can be null. 
+		 *
+		 * @note	
+		 * Value should be a pointer to raw data type for value types (for example int, float), and a MonoObject* for
+		 * reference types.
+		 */
+		void setValue(MonoObject* instance, void* value);
+
+		/**	Checks if field has an attribute of the specified type. */
+		bool hasAttribute(MonoClass* monoClass);
+
+		/**
+		 * Returns an instance of an attribute of the specified type. Returns null if the field doesn't have such an 
+		 * attribute.
+		 */
+		MonoObject* getAttribute(MonoClass* monoClass);
+
+		/**	Returns field visibility in the class. */
+		MonoFieldVisibility getVisibility();
+
+		/**	Query if the field is static. */
+		bool isStatic();
+
+	private:
+		friend class MonoClass;
+
+		MonoField(MonoClassField* field);
+
+		String mName;
+		MonoClassField* mField;
+		MonoClass* mFieldType;
+	};
+
+	/** @} */
 }

+ 1049 - 1049
Source/BansheeUtility/Include/BsRTTIType.h

@@ -1,1050 +1,1050 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include <string>
-#include <algorithm>
-#include <unordered_map>
-
-#include "BsPrerequisitesUtil.h"
-#include "BsManagedDataBlock.h"
-#include "BsRTTIField.h"
-#include "BsRTTIPlainField.h"
-#include "BsRTTIReflectableField.h"
-#include "BsRTTIReflectablePtrField.h"
-#include "BsRTTIManagedDataBlockField.h"
-#include "BsIReflectable.h"
-#include "BsBinaryDiff.h"
-
-/** @addtogroup RTTI
- *  @{
- */
-
-namespace BansheeEngine
-{
-#define BS_PLAIN_MEMBER_NAMED(name, field)								\
-	decltype(OwnerType::##field)& get##name(OwnerType* obj) { return obj->##field; }				\
-	void set##name(OwnerType* obj, decltype(OwnerType::##field)& val) { obj->##field = val; } 
-
-#define BS_REFL_MEMBER_NAMED(name, field)								\
-	decltype(OwnerType::##field)& get##name(OwnerType* obj) { return obj->##field; }				\
-	void set##name(OwnerType* obj, decltype(OwnerType::##field)& val) { obj->##field = val; } 
-
-#define BS_REFLPTR_MEMBER_NAMED(name, field)								\
-	decltype(OwnerType::##field) get##name(OwnerType* obj) { return obj->##field; }				\
-	void set##name(OwnerType* obj, decltype(OwnerType::##field) val) { obj->##field = val; } 
-
-#define BS_PLAIN_MEMBER(name)								\
-	decltype(OwnerType::##name)& get##name(OwnerType* obj) { return obj->##name; }				\
-	void set##name(OwnerType* obj, decltype(OwnerType::##name)& val) { obj->##name = val; } 
-
-#define BS_REFL_MEMBER(name)								\
-	decltype(OwnerType::##name)& get##name(OwnerType* obj) { return obj->##name; }				\
-	void set##name(OwnerType* obj, decltype(OwnerType::##name)& val) { obj->##name = val; } 
-
-#define BS_REFLPTR_MEMBER(name)								\
-	decltype(OwnerType::##name) get##name(OwnerType* obj) { return obj->##name; }				\
-	void set##name(OwnerType* obj, decltype(OwnerType::##name) val) { obj->##name = val; } 
-
-#define BS_ADD_PLAIN_FIELD(name, id) \
-	addPlainField(#name, id##, &MyType::get##name, &MyType::set##name);
-
-#define BS_ADD_REFL_FIELD(name, id) \
-	addReflectableField(#name, id##, &MyType::get##name, &MyType::set##name);
-
-#define BS_ADD_REFLPTR_FIELD(name, id) \
-	addReflectablePtrField(#name, id##, &MyType::get##name, &MyType::set##name);
-
-#define BS_PLAIN_MEMBER_VEC(name)								\
-	std::common_type<decltype(OwnerType::##name)>::type::value_type& get##name(OwnerType* obj, UINT32 idx) { return obj->##name[idx]; }				\
-	void set##name(OwnerType* obj, UINT32 idx, std::common_type<decltype(OwnerType::##name)>::type::value_type& val) { obj->##name[idx] = val; }		\
-	UINT32 getSize##name(OwnerType* obj) { return (UINT32)obj->##name.size(); }	\
-	void setSize##name(OwnerType* obj, UINT32 val) { obj->##name.resize(val); }
-
-#define BS_REFL_MEMBER_VEC(name)								\
-	std::common_type<decltype(OwnerType::##name)>::type::value_type& get##name(OwnerType* obj, UINT32 idx) { return obj->##name[idx]; }				\
-	void set##name(OwnerType* obj, UINT32 idx, std::common_type<decltype(OwnerType::##name)>::type::value_type& val) { obj->##name[idx] = val; }		\
-	UINT32 getSize##name(OwnerType* obj) { return (UINT32)obj->##name.size(); }	\
-	void setSize##name(OwnerType* obj, UINT32 val) { obj->##name.resize(val); }
-
-#define BS_REFLPTR_MEMBER_VEC(name)								\
-	std::common_type<decltype(OwnerType::##name)>::type::value_type get##name(OwnerType* obj, UINT32 idx) { return obj->##name[idx]; }				\
-	void set##name(OwnerType* obj, UINT32 idx, std::common_type<decltype(OwnerType::##name)>::type::value_type val) { obj->##name[idx] = val; }		\
-	UINT32 getSize##name(OwnerType* obj) { return (UINT32)obj->##name.size(); }	\
-	void setSize##name(OwnerType* obj, UINT32 val) { obj->##name.resize(val); }
-
-#define BS_ADD_PLAIN_FIELD_ARR(name, id) \
-	addPlainArrayField(#name, id##, &MyType::get##name, &MyType::getSize##name, \
-	&MyType::set##name, &MyType::setSize##name);
-
-#define BS_ADD_REFL_FIELD_ARR(name, id) \
-	addReflectableArrayField(#name, id##, &MyType::get##name, &MyType::getSize##name, \
-	&MyType::set##name, &MyType::setSize##name);
-
-#define BS_ADD_REFLPTR_FIELD_ARR(name, id) \
-	addReflectablePtrArrayField(#name, id##, &MyType::get##name, &MyType::getSize##name, \
-	&MyType::set##name, &MyType::setSize##name);
-
-	/** @cond INTERNAL */
-
-	/**
-	 * Provides an interface for accessing fields of a certain class.
-	 * Data can be easily accessed by getter and setter methods.
-	 * 			
-	 * Supported data types:
-	 *	- Plain types - All types defined in BsRTTIField.h, mostly native types and POD (plain old data) structs. Data is parsed byte by byte.  
-	 *	                No pointers to plain types are supported. Data is passed around by value.
-	 *	- Reflectable types - Any class deriving from IReflectable. Data is parsed based on fields in its RTTI class. Can be pointer or value type.
-	 *	- Arrays of both plain and reflectable types are supported
-	 *	- Data blocks - A managed or unmanaged block of data. See ManagedDataBlock.
-	 */
-	class BS_UTILITY_EXPORT RTTITypeBase
-	{
-	public:
-		RTTITypeBase();
-		virtual ~RTTITypeBase();
-
-		/** Returns RTTI type information for all classes that derive from the class that owns this RTTI type. */
-		virtual Vector<RTTITypeBase*>& getDerivedClasses() = 0;
-
-		/**
-		 * Returns RTTI type information for the class that owns this RTTI type. If the class has not base type, null is 
-		 * returned instead.
-		 */
-		virtual RTTITypeBase* getBaseClass() = 0;
-
-		/** Returns true if current RTTI class is derived from @p base. (Or if it is the same type as base) */
-		virtual bool isDerivedFrom(RTTITypeBase* base) = 0;
-
-		/**
-		 *  Called by the RTTI system when a class is first found in order to form child/parent class hierarchy.
-		 *
-		 * @note	Internal method.
-		 */
-		virtual void _registerDerivedClass(RTTITypeBase* derivedClass) = 0;
-
-		/** Creates a new instance of the class owning this RTTI type. */
-		virtual std::shared_ptr<IReflectable> newRTTIObject() = 0;
-
-		/** Returns the name of the class owning this RTTI type. */
-		virtual const String& getRTTIName() = 0;
-
-		/** Returns an RTTI id that uniquely represents each class in the RTTI system. */
-		virtual UINT32 getRTTIId() = 0;
-
-		/**
-		 * Called by the serializers when serialization for this object has started. Use this to do any preprocessing on 
-		 * data you might need during serialization itself.
-		 */
-		virtual void onSerializationStarted(IReflectable* obj) {}
-
-		/**
-		 * Called by the serializers when serialization for this object has ended. After serialization has ended you can 
-		 * be sure that the type has been fully serialized, and you may clean up any temporary data.
-		 */
-		virtual void onSerializationEnded(IReflectable* obj) {}
-
-		/**
-		 * Called by the serializers when deserialization for this object has started. Use this to do any preprocessing 
-		 * on data you might need during deserialization itself.
-		 */
-		virtual void onDeserializationStarted(IReflectable* obj) {}
-
-		/**
-		 * Called by the serializers when deserialization for this object has ended. At this point you can be sure the 
-		 * instance has been fully deserialized and you may safely use it.
-		 *
-		 * One exception being are fields you marked with RTTI_Flag_WeakRef, as they might be resolved only after 
-		 * deserialization has fully completed for all objects.
-		 */
-		virtual void onDeserializationEnded(IReflectable* obj) {}
-
-		/**
-		 * Returns a handler that determines how are "diffs" generated and applied when it comes to objects of this RTTI 
-		 * type. A "diff" is a list of differences between two objects that may be saved, viewed or applied to another 
-		 * object to transform it.
-		 */
-		virtual IDiff& getDiffHandler() const
-		{
-			static BinaryDiff diffHandler;
-			return diffHandler;
-		}
-
-		/**
-		 * Allows you to assign a value to a plain field with the specified name on the provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType, class DataType>
-		void setPlainValue(ObjectType* object, const String& name, DataType& value)
-		{
-			RTTIField* genericField = findField(name);
-			genericField->checkIsPlain(false);
-
-			RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
-
-			UINT32 typeSize = 0;
-			if(RTTIPlainType<DataType>::hasDynamicSize)
-				typeSize = RTTIPlainType<DataType>::getDynamicSize(value);
-			else
-				typeSize = sizeof(DataType);
-
-			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
-			RTTIPlainType<DataType>::toMemory(value, (char*)tempBuffer);
-			
-			field->fromBuffer(object, tempBuffer);
-
-			bs_stack_free(tempBuffer);
-		}
-
-		/**
-		 * Allows you to assign a value to a plain field array element with the specified name and index on the provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType, class DataType>
-		void setPlainArrayValue(ObjectType* object, const String& name, UINT32 index, DataType& value)
-		{
-			RTTIField* genericField = findField(name);
-			genericField->checkIsPlain(true);
-
-			RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
-
-			UINT32 typeSize = 0;
-			if(RTTIPlainType<DataType>::hasDynamicSize)
-				typeSize = RTTIPlainType<DataType>::getDynamicSize(value);
-			else
-				typeSize = sizeof(DataType);
-
-			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
-			RTTIPlainType<DataType>::toMemory(value, (char*)tempBuffer);
-
-			field->arrayElemFromBuffer(object, index, tempBuffer);
-
-			bs_stack_free(tempBuffer);
-		}
-
-		/**
-		 * Allows you to assign a value to a reflectable field with the specified name on the provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType, class DataType>
-		void setReflectableValue(ObjectType* object, const String& name, DataType& value)
-		{
-			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
-				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
-
-			RTTIField* genericField = findField(name);
-			genericField->checkIsComplex(false);
-
-			RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
-			field->setValue(object, value);
-		}
-
-		/**
-		 * Allows you to assign a value to a reflectable field array element with the specified name and index on the 
-		 * provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType, class DataType>
-		void setReflectableArrayValue(ObjectType* object, const String& name, UINT32 index, DataType& value)
-		{
-			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
-				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
-
-			RTTIField* genericField = findField(name);
-			genericField->checkIsComplex(true);
-
-			RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
-			field->setArrayValue(object, index, value);
-		}
-
-		/**
-		 * Allows you to assign a value to a managed data block field with the specified name on the provided instance.
-		 *
-		 * @note	Caller must ensure instance type is valid for this field.
-		 */
-		template <class ObjectType>
-		void setDataBlockValue(ObjectType* object, const String& name, ManagedDataBlock value)
-		{
-			RTTIField* genericField = findField(name);
-			genericField->checkIsDataBlock();
-
-			RTTIManagedDataBlockFieldBase* field = static_cast<RTTIManagedDataBlockFieldBase*>(genericField);
-			field->setValue(object, value);
-		}
-
-		/**
-		 * Allows you to assign a value to a reflectable pointer field with the specified name on the provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType, class DataType>
-		void setReflectablePtrValue(ObjectType* object, const String& name, std::shared_ptr<DataType> value)
-		{
-			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
-				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
-
-			RTTIField* genericField = findField(name);
-			genericField->checkIsComplexPtr(false);
-
-			RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
-			field->setValue(object, value);
-		}
-
-		/**
-		 * Allows you to assign a value to a reflectable pointer field array element with the specified name and index on 
-		 * the provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType, class DataType>
-		void setReflectablePtrArrayValue(ObjectType* object, const String& name, UINT32 index, std::shared_ptr<DataType> value)
-		{
-			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
-				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
-
-			RTTIField* genericField = findField(name);
-			genericField->checkIsComplexPtr(true);
-
-			RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
-			field->setArrayValue(object, index, value);
-		}
-
-		/**
-		 * Reads a value from a plain field with the specified name from the provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType, class DataType>
-		void getPlainValue(ObjectType* object, const String& name, DataType& value)
-		{
-			RTTIField* genericField = findField(name);
-			genericField->checkIsPlain(false);
-
-			RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
-
-			UINT32 typeSize = 0;
-			if(field->hasDynamicSize())
-				typeSize = field->getDynamicSize(object);
-			else
-				typeSize = field->getTypeSize();
-
-			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
-
-			field->toBuffer(object, tempBuffer);
-			RTTIPlainType<DataType>::fromMemory(value, (char*)tempBuffer);
-
-			bs_stack_free(tempBuffer);
-		}
-
-		/**
-		 * Reads a value from a plain array field with the specified name and index from the provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType, class DataType>
-		void getPlainArrayValue(ObjectType* object, const String& name, UINT32 index, DataType& value)
-		{
-			RTTIField* genericField = findField(name);
-			genericField->checkIsPlain(true);
-
-			RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
-
-			UINT32 typeSize = 0;
-			if(field->hasDynamicSize())
-				typeSize = field->getArrayElemDynamicSize(object, arrIdx);
-			else
-				typeSize = field->getTypeSize();
-
-			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
-
-			field->arrayElemToBuffer(object, index, tempBuffer);
-			RTTIPlainType<DataType>::fromMemory(value, (char*)tempBuffer);
-
-			bs_stack_free(tempBuffer);
-		}	
-
-		/**
-		 * Reads a value from a reflectable object field with the specified name from the provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType>
-		IReflectable& getReflectableValue(ObjectType* object, const String& name)
-		{
-			RTTIField* genericField = findField(name);
-			genericField->checkIsComplex(false);
-
-			RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
-			return field->getValue(object);
-		}
-
-		/**
-		 * Reads a value from a reflectable object array field with the specified name and index from the provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType>
-		IReflectable& getReflectableArrayValue(ObjectType* object, const String& name, UINT32 index)
-		{
-			RTTIField* genericField = findField(name);
-			genericField->checkIsComplex(true);
-
-			RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
-			return field->getArrayValue(object, index);
-		}
-
-		/**
-		 * Reads a managed data block field with the specified name from the provided instance.
-		 *
-		 * @note	Caller must ensure instance type is valid for this field.
-		 */
-		template <class ObjectType>
-		ManagedDataBlock getDataBlockValue(ObjectType* object, const String& name)
-		{
-			RTTIField* genericField = findField(name);
-			genericField->checkIsDataBlock();
-
-			RTTIManagedDataBlockFieldBase* field = static_cast<RTTIManagedDataBlockFieldBase*>(genericField);
-			return field->getValue(object);
-		}
-
-		/**
-		 * Reads a value from a reflectable object pointer field with the specified name from the provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType>
-		std::shared_ptr<IReflectable> getReflectablePtrValue(ObjectType* object, const String& name)
-		{
-			RTTIField* genericField = findField(name);
-			genericField->checkIsComplexPtr(false);
-
-			RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
-			return field->getValue(object);
-		}
-
-		/**
-		 * Reads a value from a reflectable pointer array field with the specified name and index from the provided instance.
-		 *
-		 * @note	Caller must ensure instance and value types are valid for this field.
-		 */
-		template <class ObjectType>
-		std::shared_ptr<IReflectable> getReflectablePtrArrayValue(ObjectType* object, const String& name, UINT32 index)
-		{
-			RTTIField* genericField = findField(name);
-			genericField->checkIsComplexPtr(true);
-
-			RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
-			return field->getArrayValue(object, index);
-		}
-
-		/**
-		 * Returns the size of the array of the field with the specified name on the provided instance.
-		 *
-		 * @note	Caller must ensure instance type is valid and that the field as an array.
-		 */
-		template <class ObjectType>
-		UINT32 getArraySize(ObjectType* object, const String& name)
-		{
-			RTTIField* field = findField(name);
-			return field->getArraySize(object);
-		}
-
-		/**
-		 * Sets the size of the array of the field with the specified name on the provided instance.
-		 *
-		 * @note	
-		 * Caller must ensure instance type is valid and that the field as an array. This might clear any existing data 
-		 * from the array.
-		 */
-		template <class ObjectType>
-		void setArraySize(ObjectType* object, const String& name, UINT32 size)
-		{
-			RTTIField* field = findField(name);
-			field->setArraySize(object, size);
-		}	
-
-		/** Returns the total number of fields in this RTTI type. */
-		UINT32 getNumFields() const { return (UINT32)mFields.size(); }
-
-		/** Returns a field based on the field index. Use getNumFields() to get total number of fields available. */
-		RTTIField* getField(UINT32 idx) { return mFields.at(idx); }
-
-		/**
-		 * Tries to find a field with the specified name. Throws an exception if it can't.
-		 *
-		 * @param	name	The name of the field.
-		 */
-		RTTIField* findField(const String& name);
-
-		/**
-		 * Tries to find a field with the specified unique ID. Doesn't throw an exception if it can't find the field 
-		 * (Unlike findField(const String&)). 
-		 *
-		 * @param	uniqueFieldId	Unique identifier for the field.
-		 *
-		 * @return	nullptr if it can't find the field.
-		 */
-		RTTIField* findField(int uniqueFieldId);
-
-	protected:
-		/**
-		 * Tries to add a new field to the fields array, and throws an exception if a field with the same name or id 
-		 * already exists.
-		 *
-		 * @param[in]	field	Field, must be non-null.
-		 */
-		void addNewField(RTTIField* field);
-
-	private:
-		Vector<RTTIField*> mFields;
-	};
-
-	/** Used for initializing a certain type as soon as the program is loaded. */
-	template<typename Type, typename BaseType>
-	struct InitRTTIOnStart
-	{
-	public:
-		InitRTTIOnStart()
-		{
-			BaseType::getRTTIStatic()->_registerDerivedClass(Type::getRTTIStatic());
-		}
-
-		void makeSureIAmInstantiated() { }
-	};
-
-	/** Specialization for root class of RTTI hierarchy - IReflectable */
-	template<typename Type>
-	struct InitRTTIOnStart<Type, IReflectable>
-	{
-	public:
-		InitRTTIOnStart()
-		{
-			IReflectable::_registerDerivedClass(Type::getRTTIStatic());
-		}
-
-		void makeSureIAmInstantiated() { }
-	};
-
-	/**
-	 * Template that returns RTTI type of the specified type, unless the specified type is IReflectable in which case it 
-	 * returns a null.
-	 */
-	template<typename Type>
-	struct GetRTTIType
-	{
-		RTTITypeBase* operator()() { return Type::getRTTIStatic(); }
-	};
-
-	/** Specialization for root class of RTTI hierarchy - IReflectable. */
-	template<>
-	struct GetRTTIType<IReflectable>
-	{
-		RTTITypeBase* operator()() { return nullptr; }
-	};
-
-	/** @endcond */
-
-	/**
-	 * Allows you to provide a run-time type information for a specific class, along with support for 
-	 * serialization/deserialization.
-	 * 			
-	 * Derive from this class and return the that class from IReflectable::getRTTI. This way you can separate serialization 
-	 * logic from the actual class you're serializing.
-	 *
-	 * This class will provide a way to register individual fields in the class, together with ways to read and write them, 
-	 * as well a providing information about class hierarchy, and run-time type checking.
-	 */
-	template <typename Type, typename BaseType, typename MyRTTIType>
-	class RTTIType : public RTTITypeBase
-	{
-	protected:
-		/************************************************************************/
-		/* 						RTTI CLASS META DATA							*/
-		/************************************************************************/
-
-		static InitRTTIOnStart<Type, BaseType> initOnStart;
-
-	public:
-		RTTIType() 
-		{
-			// Compiler will only generate code for stuff that is directly used, including static data members,
-			// so we fool it here like we're using the class directly. Otherwise compiler won't generate the code for the member
-			// and our type won't get initialized on start (Actual behavior is a bit more random)
-			initOnStart.makeSureIAmInstantiated();
-		}
-		virtual ~RTTIType() {}
-
-		/** Returns a singleton of this RTTI type. */
-		static MyRTTIType* instance()
-		{
-			static MyRTTIType inst;
-			return &inst;
-		}
-
-		/** @copydoc RTTITypeBase::getDerivedClasses */
-		Vector<RTTITypeBase*>& getDerivedClasses() override
-		{
-			static Vector<RTTITypeBase*> mRTTIDerivedClasses;
-			return mRTTIDerivedClasses;
-		}
-
-		/** @copydoc RTTITypeBase::getBaseClass */
-		RTTITypeBase* getBaseClass() override
-		{
-			return GetRTTIType<BaseType>()();
-		}
-
-		/** @copydoc RTTITypeBase::isDerivedFrom */
-		bool isDerivedFrom(RTTITypeBase* base) override
-		{
-			assert(base != nullptr);
-
-			Stack<RTTITypeBase*> todo;
-			todo.push(base);
-
-			while (!todo.empty())
-			{
-				RTTITypeBase* currentType = todo.top();
-				todo.pop();
-
-				if (currentType->getRTTIId() == getRTTIId())
-					return true;
-
-				const Vector<RTTITypeBase*>& derivedClasses = currentType->getDerivedClasses();
-				for (auto iter = derivedClasses.begin(); iter != derivedClasses.end(); ++iter)
-					todo.push(*iter);
-			}
-
-			return false;
-		}
-
-		/** @copydoc	RTTITypeBase::_registerDerivedClass */
-		void _registerDerivedClass(RTTITypeBase* derivedClass) override
-		{
-			if(IReflectable::_isTypeIdDuplicate(derivedClass->getRTTIId()))
-			{
-				BS_EXCEPT(InternalErrorException, "RTTI type \"" + derivedClass->getRTTIName() + 
-					"\" has a duplicate ID: " + toString(derivedClass->getRTTIId()));
-			}
-
-			getDerivedClasses().push_back(derivedClass);
-		}
-
-		/************************************************************************/
-		/* 			FIELDS OPERATING DIRECTLY ON SERIALIZABLE OBJECT            */
-		/************************************************************************/
-
-		/**
-		 * Registers a new plain field. This field can then be accessed dynamically from the RTTI system and used for 
-		 * automatic serialization. See RTTIField for more information about field types.
-		 *
-		 * @param[in]	name		Name of the field.
-		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *							small data type that can be used for efficiently serializing data to disk and similar. 
-		 *							It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  	Method used for retrieving the value of this field.
-		 * @param[in]	setter  	Method used for setting the value of this field.
-		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
-		 */
-		template<class ObjectType, class DataType>
-		void addPlainField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(), 
-			void (ObjectType::*setter)(DataType&) = nullptr, UINT64 flags = 0)
-		{
-			addPlainField<ObjectType, DataType>(name, uniqueId, 
-				std::function<DataType&(ObjectType*)>(getter), 
-				std::function<void(ObjectType*, DataType&)>(setter), flags);
-		}
-
-		/**
-		 * Registers a new reflectable object field. This field can then be accessed dynamically from the RTTI system and
-		 * used for automatic serialization. See RTTIField for more information about field types.
-		 *
-		 * @param[in]	name		Name of the field.
-		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *							small data type that can be used for efficiently serializing data to disk and similar. 
-		 *							It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  	Method used for retrieving the value of this field.
-		 * @param[in]	setter  	Method used for setting the value of this field.
-		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
-		 */
-		template<class ObjectType, class DataType>
-		void addReflectableField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(), 
-			void (ObjectType::*setter)(DataType&) = nullptr, UINT64 flags = 0)
-		{
-			addReflectableField<ObjectType, DataType>(name, uniqueId, 
-				std::function<DataType&(ObjectType*)>(getter), 
-				std::function<void(ObjectType*, DataType&)>(setter), flags);
-		}
-
-		/**
-		 * Registers a new reflectable object pointer field. This field can then be accessed dynamically from the RTTI 
-		 * system and used for automatic serialization. See RTTIField for more information about field types.
-		 *
-		 * @param[in]	name		Name of the field.
-		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *							small data type that can be used for efficiently serializing data to disk and similar. 
-		 *							It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  	Method used for retrieving the value of this field.
-		 * @param[in]	setter  	Method used for setting the value of this field.
-		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
-		 */
-		template<class ObjectType, class DataType>
-		void addReflectablePtrField(const String& name, UINT32 uniqueId, std::shared_ptr<DataType> (ObjectType::*getter)(), 
-			void (ObjectType::*setter)(std::shared_ptr<DataType>) = nullptr, UINT64 flags = 0)
-		{
-			addReflectablePtrField<ObjectType, DataType>(name, uniqueId, 
-				std::function<std::shared_ptr<DataType>(ObjectType*)>(getter), 
-				std::function<void(ObjectType*, std::shared_ptr<DataType>)>(setter), flags);
-		}
-
-		/**
-		 * Registers a new field containg an array of plain values. This field can then be accessed dynamically from the 
-		 * RTTI system and used for automatic serialization. See RTTIField for more information about field types.
-		 *
-		 * @param[in]	name		Name of the field.
-		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *							small data type that can be used for efficiently serializing data to disk and similar. 
-		 *							It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  	Method used for retrieving a single element of the array.
-		 * @param[in]	getSize 	Getter method that returns the size of the array.
-		 * @param[in]	setter  	Method used for setting the a single element of the field.
-		 * @param[in]	setSize 	Setter method that allows you to resize the array. 
-		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
-		 */
-		template<class ObjectType, class DataType>
-		void addPlainArrayField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
-			void (ObjectType::*setter)(UINT32, DataType&) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
-		{
-			addPlainArrayField<ObjectType, DataType>(name, uniqueId, 
-				std::function<DataType&(ObjectType*, UINT32)>(getter), 
-				std::function<UINT32(ObjectType*)>(getSize), 
-				std::function<void(ObjectType*, UINT32, DataType&)>(setter), 
-				std::function<void(ObjectType*, UINT32)>(setSize), flags);
-		}	
-
-		/**
-		 * Registers a new field containg an array of reflectable object values. This field can then be accessed dynamically
-		 * from the RTTI system and used for automatic serialization. See RTTIField for more information about field types.
-		 *
-		 * @param[in]	name		Name of the field.
-		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *							small data type that can be used for efficiently serializing data to disk and similar. 
-		 *							It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  	Method used for retrieving a single element of the array.
-		 * @param[in]	getSize 	Getter method that returns the size of the array.
-		 * @param[in]	setter  	Method used for setting the a single element of the field.
-		 * @param[in]	setSize 	Setter method that allows you to resize the array. 
-		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
-		 */
-		template<class ObjectType, class DataType>
-		void addReflectableArrayField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
-			void (ObjectType::*setter)(UINT32, DataType&) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
-		{
-			addReflectableArrayField<ObjectType, DataType>(name, uniqueId, 
-				std::function<DataType&(ObjectType*, UINT32)>(getter), 
-				std::function<UINT32(ObjectType*)>(getSize), 
-				std::function<void(ObjectType*, UINT32, DataType&)>(setter), 
-				std::function<void(ObjectType*, UINT32)>(setSize), flags);
-		}
-
-		/**
-		 * Registers a new field containg an array of reflectable obejct pointers. This field can then be accessed 
-		 * dynamically from the RTTI system and used for automatic serialization. See RTTIField for more information 
-		 * about field types.
-		 *
-		 * @param[in]	name		Name of the field.
-		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *							small data type that can be used for efficiently serializing data to disk and similar. 
-		 *							It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  	Method used for retrieving a single element of the array.
-		 * @param[in]	getSize 	Getter method that returns the size of the array.
-		 * @param[in]	setter  	Method used for setting the a single element of the field.
-		 * @param[in]	setSize 	Setter method that allows you to resize the array. 
-		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
-		 */
-		template<class ObjectType, class DataType>
-		void addReflectablePtrArrayField(const String& name, UINT32 uniqueId, std::shared_ptr<DataType> (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
-			void (ObjectType::*setter)(UINT32, std::shared_ptr<DataType>) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
-		{
-			addReflectablePtrArrayField<ObjectType, DataType>(name, uniqueId, 
-				std::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>(getter), 
-				std::function<UINT32(ObjectType*)>(getSize), 
-				std::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>(setter), 
-				std::function<void(ObjectType*, UINT32)>(setSize), flags);
-		}
-
-		/**
-		 * Registers a new managed data block field. This field can then be accessed dynamically from the RTTI system and
-		 * used for automatic serialization. See RTTIField for more information about field types.
-		 *
-		 * @param[in]	name		Name of the field.
-		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
-		 *							small data type that can be used for efficiently serializing data to disk and similar. 
-		 *							It is primarily used for compatibility between different versions of serialized data.
-		 * @param[in]	getter  	Method used for retrieving the value of this field.
-		 * @param[in]	setter  	Method used for setting the value of this field.
-		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
-		 */
-		template<class ObjectType>
-		void addDataBlockField(const String& name, UINT32 uniqueId, ManagedDataBlock (ObjectType::*getter)(), 
-			void (ObjectType::*setter)(ManagedDataBlock) = nullptr, UINT64 flags = 0, UINT8* (customAllocator)(ObjectType*, UINT32) = 0)
-		{
-			addDataBlockField<ObjectType>(name, uniqueId, 
-				std::function<ManagedDataBlock(ObjectType*)>(getter),  
-				std::function<void(ObjectType*, ManagedDataBlock)>(setter), flags, customAllocator);
-		}	
-
-	protected:
-		typedef Type OwnerType;
-		typedef MyRTTIType MyType;
-
-		virtual void initSerializableFields() {}
-
-		/************************************************************************/
-		/* 		FIELDS OPERATING ON DERIVED SERIALIZATION INTERFACE				*/
-		/*		(Needs an extra pointer to the actual object)					*/
-		/************************************************************************/
-		template<class InterfaceType, class ObjectType, class DataType>
-		void addPlainField(const String& name, UINT32 uniqueId, 
-			DataType& (InterfaceType::*getter)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, DataType&), UINT64 flags = 0)
-		{
-			using namespace std::placeholders;
-
-			static_assert((std::is_base_of<BansheeEngine::RTTIType<Type, BaseType, MyRTTIType>, InterfaceType>::value), 
-				"Class with the get/set methods must derive from BansheeEngine::RTTIType.");
-
-			static_assert(!(std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
-				"Data type derives from IReflectable but it is being added as a plain field.");
-
-			addPlainField<ObjectType, DataType>(name, uniqueId, 
-				std::function<DataType&(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)), 
-				std::function<void(ObjectType*, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
-		}
-
-		template<class InterfaceType, class ObjectType, class DataType>
-		void addReflectableField(const String& name, UINT32 uniqueId, 
-			DataType& (InterfaceType::*getter)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, DataType&), UINT64 flags = 0)
-		{
-			using namespace std::placeholders;
-
-			addReflectableField<ObjectType, DataType>(name, uniqueId, 
-				std::function<DataType&(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)), 
-				std::function<void(ObjectType*, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
-		}
-
-		template<class InterfaceType, class ObjectType, class DataType>
-		void addReflectablePtrField(const String& name, UINT32 uniqueId, 
-			std::shared_ptr<DataType> (InterfaceType::*getter)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, std::shared_ptr<DataType>), UINT64 flags = 0)
-		{
-			using namespace std::placeholders;
-
-			addReflectablePtrField<ObjectType, DataType>(name, uniqueId, 
-				std::function<std::shared_ptr<DataType>(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)), 
-				std::function<void(ObjectType*, std::shared_ptr<DataType>)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
-		}
-
-		template<class InterfaceType, class ObjectType, class DataType>
-		void addPlainArrayField(const String& name, UINT32 uniqueId, 
-			DataType& (InterfaceType::*getter)(ObjectType*, UINT32), 
-			UINT32 (InterfaceType::*getSize)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, UINT32, DataType&), 
-			void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
-		{
-			using namespace std::placeholders;
-
-			static_assert((std::is_base_of<BansheeEngine::RTTIType<Type, BaseType, MyRTTIType>, InterfaceType>::value), 
-				"Class with the get/set methods must derive from BansheeEngine::RTTIType.");
-
-			static_assert(!(std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
-				"Data type derives from IReflectable but it is being added as a plain field.");
-
-			addPlainArrayField<ObjectType, DataType>(name, uniqueId, 
-				std::function<DataType&(ObjectType*, UINT32)>(std::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
-				std::function<UINT32(ObjectType*)>(std::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
-				std::function<void(ObjectType*, UINT32, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
-				std::function<void(ObjectType*, UINT32)>(std::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
-		}	
-
-		template<class InterfaceType, class ObjectType, class DataType>
-		void addReflectableArrayField(const String& name, UINT32 uniqueId, 
-			DataType& (InterfaceType::*getter)(ObjectType*, UINT32), 
-			UINT32 (InterfaceType::*getSize)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, UINT32, DataType&), 
-			void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
-		{
-			using namespace std::placeholders;
-
-			addReflectableArrayField<ObjectType, DataType>(name, uniqueId, 
-				std::function<DataType&(ObjectType*, UINT32)>(std::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
-				std::function<UINT32(ObjectType*)>(std::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
-				std::function<void(ObjectType*, UINT32, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
-				std::function<void(ObjectType*, UINT32)>(std::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
-		}
-
-		template<class InterfaceType, class ObjectType, class DataType>
-		void addReflectablePtrArrayField(const String& name, UINT32 uniqueId, 
-			std::shared_ptr<DataType> (InterfaceType::*getter)(ObjectType*, UINT32), 
-			UINT32 (InterfaceType::*getSize)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, UINT32, std::shared_ptr<DataType>), 
-			void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
-		{
-			using namespace std::placeholders;
-
-			addReflectablePtrArrayField<ObjectType, DataType>(name, uniqueId, 
-				std::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>(std::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
-				std::function<UINT32(ObjectType*)>(std::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
-				std::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
-				std::function<void(ObjectType*, UINT32)>(std::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
-		}
-
-		template<class InterfaceType, class ObjectType>
-		void addDataBlockField(const String& name, UINT32 uniqueId, ManagedDataBlock (InterfaceType::*getter)(ObjectType*), 
-			void (InterfaceType::*setter)(ObjectType*, ManagedDataBlock), UINT64 flags = 0, 
-			UINT8* (customAllocator)(ObjectType*, UINT32) = 0)
-		{
-			using namespace std::placeholders;
-
-			if(customAllocator != 0)
-			{
-				std::function<UINT8*(ObjectType*, UINT32)> customAllocFunc = std::bind(customAllocator, _1, _2);
-
-				addDataBlockField<ObjectType>(name, uniqueId, 
-					std::function<ManagedDataBlock(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)),  
-					std::function<void(ObjectType*, ManagedDataBlock)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags, 
-					customAllocFunc);
-			}
-			else
-			{
-				addDataBlockField<ObjectType>(name, uniqueId, 
-					std::function<ManagedDataBlock(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)),  
-					std::function<void(ObjectType*, ManagedDataBlock)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
-			}
-		}	
-
-	private:
-		template<class ObjectType, class DataType>
-		void addPlainField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags)
-		{
-			RTTIPlainField<DataType, ObjectType>* newField = 
-				bs_new<RTTIPlainField<DataType, ObjectType>>();
-			newField->initSingle(name, uniqueId, getter, setter, flags);
-			addNewField(newField);
-		}
-		
-		template<class ObjectType, class DataType>
-		void addReflectableField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags)
-		{
-			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
-				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
-
-			RTTIReflectableField<DataType, ObjectType>* newField = 
-				bs_new<RTTIReflectableField<DataType, ObjectType>>();
-			newField->initSingle(name, uniqueId, getter, setter, flags);
-			addNewField(newField);
-		}
-
-		template<class ObjectType, class DataType>
-		void addReflectablePtrField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags)
-		{
-			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
-				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
-
-			RTTIReflectablePtrField<DataType, ObjectType>* newField = 
-				bs_new<RTTIReflectablePtrField<DataType, ObjectType>>();
-			newField->initSingle(name, uniqueId, getter, setter, flags);
-			addNewField(newField);
-		}
-
-		template<class ObjectType, class DataType>
-		void addPlainArrayField(const String& name, UINT32 uniqueId, Any getter, Any getSize,
-			Any setter, Any setSize, UINT64 flags)
-		{
-			RTTIPlainField<DataType, ObjectType>* newField = 
-				bs_new<RTTIPlainField<DataType, ObjectType>>();
-			newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
-			addNewField(newField);
-		}	
-
-		template<class ObjectType, class DataType>
-		void addReflectableArrayField(const String& name, UINT32 uniqueId, Any getter, Any getSize,
-			Any setter, Any setSize, UINT64 flags)
-		{
-			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
-				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
-
-			RTTIReflectableField<DataType, ObjectType>* newField = 
-				bs_new<RTTIReflectableField<DataType, ObjectType>>();
-			newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
-			addNewField(newField);
-		}
-
-		template<class ObjectType, class DataType>
-		void addReflectablePtrArrayField(const String& name, UINT32 uniqueId, Any getter, Any getSize,
-			Any setter, Any setSize, UINT64 flags)
-		{
-			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
-				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
-
-			RTTIReflectablePtrField<DataType, ObjectType>* newField = 
-				bs_new<RTTIReflectablePtrField<DataType, ObjectType>>();
-			newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
-			addNewField(newField);
-		}
-
-		template<class ObjectType>
-		void addDataBlockField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags, 
-			Any customAllocator = Any())
-		{
-			RTTIManagedDataBlockField<ManagedDataBlock, ObjectType>* newField = 
-				bs_new<RTTIManagedDataBlockField<ManagedDataBlock, ObjectType>>();
-			newField->initSingle(name, uniqueId, getter,  setter, flags, customAllocator);
-			addNewField(newField);
-		}	
-	};
-
-	template <typename Type, typename BaseType, typename MyRTTIType>
-	InitRTTIOnStart<Type, BaseType> RTTIType<Type, BaseType, MyRTTIType>::initOnStart;
-
-	/** 	Returns true if the provided object can be safely cast into type T. */
-	template<class T>
-	bool rtti_is_of_type(IReflectable* object)
-	{
-		static_assert((std::is_base_of<BansheeEngine::IReflectable, T>::value), 
-			"Invalid data type for type checking. It needs to derive from BansheeEngine::IReflectable.");
-
-		return object->getTypeId() == T::getRTTIStatic()->getRTTIId();
-	}
-
-	/** Returns true if the provided object can be safely cast into type T. */
-	template<class T>
-	bool rtti_is_of_type(std::shared_ptr<IReflectable> object)
-	{
-		static_assert((std::is_base_of<BansheeEngine::IReflectable, T>::value), 
-			"Invalid data type for type checking. It needs to derive from BansheeEngine::IReflectable.");
-
-		return object->getTypeId() == T::getRTTIStatic()->getRTTIId();
-	}
-
-	/** Creates a new object just from its type ID. */
-	std::shared_ptr<IReflectable> rtti_create(UINT32 rttiId);
-
-	/** Checks is the current object a subclass of some type. */
-	template<class T>
-	bool rtti_is_subclass(IReflectable* object)
-	{
-		static_assert((std::is_base_of<BansheeEngine::IReflectable, T>::value),
-			"Invalid data type for type checking. It needs to derive from BansheeEngine::IReflectable.");
-
-		return object->isDerivedFrom(T::getRTTIStatic());
-	}
-
-	/** @} */
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include <string>
+#include <algorithm>
+#include <unordered_map>
+
+#include "BsPrerequisitesUtil.h"
+#include "BsManagedDataBlock.h"
+#include "BsRTTIField.h"
+#include "BsRTTIPlainField.h"
+#include "BsRTTIReflectableField.h"
+#include "BsRTTIReflectablePtrField.h"
+#include "BsRTTIManagedDataBlockField.h"
+#include "BsIReflectable.h"
+#include "BsBinaryDiff.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup RTTI
+	 *  @{
+	 */
+
+#define BS_PLAIN_MEMBER_NAMED(name, field)								\
+	decltype(OwnerType::##field)& get##name(OwnerType* obj) { return obj->##field; }				\
+	void set##name(OwnerType* obj, decltype(OwnerType::##field)& val) { obj->##field = val; } 
+
+#define BS_REFL_MEMBER_NAMED(name, field)								\
+	decltype(OwnerType::##field)& get##name(OwnerType* obj) { return obj->##field; }				\
+	void set##name(OwnerType* obj, decltype(OwnerType::##field)& val) { obj->##field = val; } 
+
+#define BS_REFLPTR_MEMBER_NAMED(name, field)								\
+	decltype(OwnerType::##field) get##name(OwnerType* obj) { return obj->##field; }				\
+	void set##name(OwnerType* obj, decltype(OwnerType::##field) val) { obj->##field = val; } 
+
+#define BS_PLAIN_MEMBER(name)								\
+	decltype(OwnerType::##name)& get##name(OwnerType* obj) { return obj->##name; }				\
+	void set##name(OwnerType* obj, decltype(OwnerType::##name)& val) { obj->##name = val; } 
+
+#define BS_REFL_MEMBER(name)								\
+	decltype(OwnerType::##name)& get##name(OwnerType* obj) { return obj->##name; }				\
+	void set##name(OwnerType* obj, decltype(OwnerType::##name)& val) { obj->##name = val; } 
+
+#define BS_REFLPTR_MEMBER(name)								\
+	decltype(OwnerType::##name) get##name(OwnerType* obj) { return obj->##name; }				\
+	void set##name(OwnerType* obj, decltype(OwnerType::##name) val) { obj->##name = val; } 
+
+#define BS_ADD_PLAIN_FIELD(name, id) \
+	addPlainField(#name, id##, &MyType::get##name, &MyType::set##name);
+
+#define BS_ADD_REFL_FIELD(name, id) \
+	addReflectableField(#name, id##, &MyType::get##name, &MyType::set##name);
+
+#define BS_ADD_REFLPTR_FIELD(name, id) \
+	addReflectablePtrField(#name, id##, &MyType::get##name, &MyType::set##name);
+
+#define BS_PLAIN_MEMBER_VEC(name)								\
+	std::common_type<decltype(OwnerType::##name)>::type::value_type& get##name(OwnerType* obj, UINT32 idx) { return obj->##name[idx]; }				\
+	void set##name(OwnerType* obj, UINT32 idx, std::common_type<decltype(OwnerType::##name)>::type::value_type& val) { obj->##name[idx] = val; }		\
+	UINT32 getSize##name(OwnerType* obj) { return (UINT32)obj->##name.size(); }	\
+	void setSize##name(OwnerType* obj, UINT32 val) { obj->##name.resize(val); }
+
+#define BS_REFL_MEMBER_VEC(name)								\
+	std::common_type<decltype(OwnerType::##name)>::type::value_type& get##name(OwnerType* obj, UINT32 idx) { return obj->##name[idx]; }				\
+	void set##name(OwnerType* obj, UINT32 idx, std::common_type<decltype(OwnerType::##name)>::type::value_type& val) { obj->##name[idx] = val; }		\
+	UINT32 getSize##name(OwnerType* obj) { return (UINT32)obj->##name.size(); }	\
+	void setSize##name(OwnerType* obj, UINT32 val) { obj->##name.resize(val); }
+
+#define BS_REFLPTR_MEMBER_VEC(name)								\
+	std::common_type<decltype(OwnerType::##name)>::type::value_type get##name(OwnerType* obj, UINT32 idx) { return obj->##name[idx]; }				\
+	void set##name(OwnerType* obj, UINT32 idx, std::common_type<decltype(OwnerType::##name)>::type::value_type val) { obj->##name[idx] = val; }		\
+	UINT32 getSize##name(OwnerType* obj) { return (UINT32)obj->##name.size(); }	\
+	void setSize##name(OwnerType* obj, UINT32 val) { obj->##name.resize(val); }
+
+#define BS_ADD_PLAIN_FIELD_ARR(name, id) \
+	addPlainArrayField(#name, id##, &MyType::get##name, &MyType::getSize##name, \
+	&MyType::set##name, &MyType::setSize##name);
+
+#define BS_ADD_REFL_FIELD_ARR(name, id) \
+	addReflectableArrayField(#name, id##, &MyType::get##name, &MyType::getSize##name, \
+	&MyType::set##name, &MyType::setSize##name);
+
+#define BS_ADD_REFLPTR_FIELD_ARR(name, id) \
+	addReflectablePtrArrayField(#name, id##, &MyType::get##name, &MyType::getSize##name, \
+	&MyType::set##name, &MyType::setSize##name);
+
+	/** @cond INTERNAL */
+
+	/**
+	 * Provides an interface for accessing fields of a certain class.
+	 * Data can be easily accessed by getter and setter methods.
+	 * 			
+	 * Supported data types:
+	 *	- Plain types - All types defined in BsRTTIField.h, mostly native types and POD (plain old data) structs. Data is parsed byte by byte.  
+	 *	                No pointers to plain types are supported. Data is passed around by value.
+	 *	- Reflectable types - Any class deriving from IReflectable. Data is parsed based on fields in its RTTI class. Can be pointer or value type.
+	 *	- Arrays of both plain and reflectable types are supported
+	 *	- Data blocks - A managed or unmanaged block of data. See ManagedDataBlock.
+	 */
+	class BS_UTILITY_EXPORT RTTITypeBase
+	{
+	public:
+		RTTITypeBase();
+		virtual ~RTTITypeBase();
+
+		/** Returns RTTI type information for all classes that derive from the class that owns this RTTI type. */
+		virtual Vector<RTTITypeBase*>& getDerivedClasses() = 0;
+
+		/**
+		 * Returns RTTI type information for the class that owns this RTTI type. If the class has not base type, null is 
+		 * returned instead.
+		 */
+		virtual RTTITypeBase* getBaseClass() = 0;
+
+		/** Returns true if current RTTI class is derived from @p base. (Or if it is the same type as base) */
+		virtual bool isDerivedFrom(RTTITypeBase* base) = 0;
+
+		/**
+		 *  Called by the RTTI system when a class is first found in order to form child/parent class hierarchy.
+		 *
+		 * @note	Internal method.
+		 */
+		virtual void _registerDerivedClass(RTTITypeBase* derivedClass) = 0;
+
+		/** Creates a new instance of the class owning this RTTI type. */
+		virtual std::shared_ptr<IReflectable> newRTTIObject() = 0;
+
+		/** Returns the name of the class owning this RTTI type. */
+		virtual const String& getRTTIName() = 0;
+
+		/** Returns an RTTI id that uniquely represents each class in the RTTI system. */
+		virtual UINT32 getRTTIId() = 0;
+
+		/**
+		 * Called by the serializers when serialization for this object has started. Use this to do any preprocessing on 
+		 * data you might need during serialization itself.
+		 */
+		virtual void onSerializationStarted(IReflectable* obj) {}
+
+		/**
+		 * Called by the serializers when serialization for this object has ended. After serialization has ended you can 
+		 * be sure that the type has been fully serialized, and you may clean up any temporary data.
+		 */
+		virtual void onSerializationEnded(IReflectable* obj) {}
+
+		/**
+		 * Called by the serializers when deserialization for this object has started. Use this to do any preprocessing 
+		 * on data you might need during deserialization itself.
+		 */
+		virtual void onDeserializationStarted(IReflectable* obj) {}
+
+		/**
+		 * Called by the serializers when deserialization for this object has ended. At this point you can be sure the 
+		 * instance has been fully deserialized and you may safely use it.
+		 *
+		 * One exception being are fields you marked with RTTI_Flag_WeakRef, as they might be resolved only after 
+		 * deserialization has fully completed for all objects.
+		 */
+		virtual void onDeserializationEnded(IReflectable* obj) {}
+
+		/**
+		 * Returns a handler that determines how are "diffs" generated and applied when it comes to objects of this RTTI 
+		 * type. A "diff" is a list of differences between two objects that may be saved, viewed or applied to another 
+		 * object to transform it.
+		 */
+		virtual IDiff& getDiffHandler() const
+		{
+			static BinaryDiff diffHandler;
+			return diffHandler;
+		}
+
+		/**
+		 * Allows you to assign a value to a plain field with the specified name on the provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType, class DataType>
+		void setPlainValue(ObjectType* object, const String& name, DataType& value)
+		{
+			RTTIField* genericField = findField(name);
+			genericField->checkIsPlain(false);
+
+			RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
+
+			UINT32 typeSize = 0;
+			if(RTTIPlainType<DataType>::hasDynamicSize)
+				typeSize = RTTIPlainType<DataType>::getDynamicSize(value);
+			else
+				typeSize = sizeof(DataType);
+
+			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
+			RTTIPlainType<DataType>::toMemory(value, (char*)tempBuffer);
+			
+			field->fromBuffer(object, tempBuffer);
+
+			bs_stack_free(tempBuffer);
+		}
+
+		/**
+		 * Allows you to assign a value to a plain field array element with the specified name and index on the provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType, class DataType>
+		void setPlainArrayValue(ObjectType* object, const String& name, UINT32 index, DataType& value)
+		{
+			RTTIField* genericField = findField(name);
+			genericField->checkIsPlain(true);
+
+			RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
+
+			UINT32 typeSize = 0;
+			if(RTTIPlainType<DataType>::hasDynamicSize)
+				typeSize = RTTIPlainType<DataType>::getDynamicSize(value);
+			else
+				typeSize = sizeof(DataType);
+
+			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
+			RTTIPlainType<DataType>::toMemory(value, (char*)tempBuffer);
+
+			field->arrayElemFromBuffer(object, index, tempBuffer);
+
+			bs_stack_free(tempBuffer);
+		}
+
+		/**
+		 * Allows you to assign a value to a reflectable field with the specified name on the provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType, class DataType>
+		void setReflectableValue(ObjectType* object, const String& name, DataType& value)
+		{
+			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
+				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
+
+			RTTIField* genericField = findField(name);
+			genericField->checkIsComplex(false);
+
+			RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
+			field->setValue(object, value);
+		}
+
+		/**
+		 * Allows you to assign a value to a reflectable field array element with the specified name and index on the 
+		 * provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType, class DataType>
+		void setReflectableArrayValue(ObjectType* object, const String& name, UINT32 index, DataType& value)
+		{
+			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
+				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
+
+			RTTIField* genericField = findField(name);
+			genericField->checkIsComplex(true);
+
+			RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
+			field->setArrayValue(object, index, value);
+		}
+
+		/**
+		 * Allows you to assign a value to a managed data block field with the specified name on the provided instance.
+		 *
+		 * @note	Caller must ensure instance type is valid for this field.
+		 */
+		template <class ObjectType>
+		void setDataBlockValue(ObjectType* object, const String& name, ManagedDataBlock value)
+		{
+			RTTIField* genericField = findField(name);
+			genericField->checkIsDataBlock();
+
+			RTTIManagedDataBlockFieldBase* field = static_cast<RTTIManagedDataBlockFieldBase*>(genericField);
+			field->setValue(object, value);
+		}
+
+		/**
+		 * Allows you to assign a value to a reflectable pointer field with the specified name on the provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType, class DataType>
+		void setReflectablePtrValue(ObjectType* object, const String& name, std::shared_ptr<DataType> value)
+		{
+			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
+				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
+
+			RTTIField* genericField = findField(name);
+			genericField->checkIsComplexPtr(false);
+
+			RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
+			field->setValue(object, value);
+		}
+
+		/**
+		 * Allows you to assign a value to a reflectable pointer field array element with the specified name and index on 
+		 * the provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType, class DataType>
+		void setReflectablePtrArrayValue(ObjectType* object, const String& name, UINT32 index, std::shared_ptr<DataType> value)
+		{
+			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
+				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
+
+			RTTIField* genericField = findField(name);
+			genericField->checkIsComplexPtr(true);
+
+			RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
+			field->setArrayValue(object, index, value);
+		}
+
+		/**
+		 * Reads a value from a plain field with the specified name from the provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType, class DataType>
+		void getPlainValue(ObjectType* object, const String& name, DataType& value)
+		{
+			RTTIField* genericField = findField(name);
+			genericField->checkIsPlain(false);
+
+			RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
+
+			UINT32 typeSize = 0;
+			if(field->hasDynamicSize())
+				typeSize = field->getDynamicSize(object);
+			else
+				typeSize = field->getTypeSize();
+
+			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
+
+			field->toBuffer(object, tempBuffer);
+			RTTIPlainType<DataType>::fromMemory(value, (char*)tempBuffer);
+
+			bs_stack_free(tempBuffer);
+		}
+
+		/**
+		 * Reads a value from a plain array field with the specified name and index from the provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType, class DataType>
+		void getPlainArrayValue(ObjectType* object, const String& name, UINT32 index, DataType& value)
+		{
+			RTTIField* genericField = findField(name);
+			genericField->checkIsPlain(true);
+
+			RTTIPlainFieldBase* field = static_cast<RTTIPlainFieldBase*>(genericField);
+
+			UINT32 typeSize = 0;
+			if(field->hasDynamicSize())
+				typeSize = field->getArrayElemDynamicSize(object, arrIdx);
+			else
+				typeSize = field->getTypeSize();
+
+			UINT8* tempBuffer = (UINT8*)bs_stack_alloc(typeSize);
+
+			field->arrayElemToBuffer(object, index, tempBuffer);
+			RTTIPlainType<DataType>::fromMemory(value, (char*)tempBuffer);
+
+			bs_stack_free(tempBuffer);
+		}	
+
+		/**
+		 * Reads a value from a reflectable object field with the specified name from the provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType>
+		IReflectable& getReflectableValue(ObjectType* object, const String& name)
+		{
+			RTTIField* genericField = findField(name);
+			genericField->checkIsComplex(false);
+
+			RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
+			return field->getValue(object);
+		}
+
+		/**
+		 * Reads a value from a reflectable object array field with the specified name and index from the provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType>
+		IReflectable& getReflectableArrayValue(ObjectType* object, const String& name, UINT32 index)
+		{
+			RTTIField* genericField = findField(name);
+			genericField->checkIsComplex(true);
+
+			RTTIReflectableFieldBase* field = static_cast<RTTIReflectableFieldBase*>(genericField);
+			return field->getArrayValue(object, index);
+		}
+
+		/**
+		 * Reads a managed data block field with the specified name from the provided instance.
+		 *
+		 * @note	Caller must ensure instance type is valid for this field.
+		 */
+		template <class ObjectType>
+		ManagedDataBlock getDataBlockValue(ObjectType* object, const String& name)
+		{
+			RTTIField* genericField = findField(name);
+			genericField->checkIsDataBlock();
+
+			RTTIManagedDataBlockFieldBase* field = static_cast<RTTIManagedDataBlockFieldBase*>(genericField);
+			return field->getValue(object);
+		}
+
+		/**
+		 * Reads a value from a reflectable object pointer field with the specified name from the provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType>
+		std::shared_ptr<IReflectable> getReflectablePtrValue(ObjectType* object, const String& name)
+		{
+			RTTIField* genericField = findField(name);
+			genericField->checkIsComplexPtr(false);
+
+			RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
+			return field->getValue(object);
+		}
+
+		/**
+		 * Reads a value from a reflectable pointer array field with the specified name and index from the provided instance.
+		 *
+		 * @note	Caller must ensure instance and value types are valid for this field.
+		 */
+		template <class ObjectType>
+		std::shared_ptr<IReflectable> getReflectablePtrArrayValue(ObjectType* object, const String& name, UINT32 index)
+		{
+			RTTIField* genericField = findField(name);
+			genericField->checkIsComplexPtr(true);
+
+			RTTIReflectablePtrFieldBase* field = static_cast<RTTIReflectablePtrFieldBase*>(genericField);
+			return field->getArrayValue(object, index);
+		}
+
+		/**
+		 * Returns the size of the array of the field with the specified name on the provided instance.
+		 *
+		 * @note	Caller must ensure instance type is valid and that the field as an array.
+		 */
+		template <class ObjectType>
+		UINT32 getArraySize(ObjectType* object, const String& name)
+		{
+			RTTIField* field = findField(name);
+			return field->getArraySize(object);
+		}
+
+		/**
+		 * Sets the size of the array of the field with the specified name on the provided instance.
+		 *
+		 * @note	
+		 * Caller must ensure instance type is valid and that the field as an array. This might clear any existing data 
+		 * from the array.
+		 */
+		template <class ObjectType>
+		void setArraySize(ObjectType* object, const String& name, UINT32 size)
+		{
+			RTTIField* field = findField(name);
+			field->setArraySize(object, size);
+		}	
+
+		/** Returns the total number of fields in this RTTI type. */
+		UINT32 getNumFields() const { return (UINT32)mFields.size(); }
+
+		/** Returns a field based on the field index. Use getNumFields() to get total number of fields available. */
+		RTTIField* getField(UINT32 idx) { return mFields.at(idx); }
+
+		/**
+		 * Tries to find a field with the specified name. Throws an exception if it can't.
+		 *
+		 * @param	name	The name of the field.
+		 */
+		RTTIField* findField(const String& name);
+
+		/**
+		 * Tries to find a field with the specified unique ID. Doesn't throw an exception if it can't find the field 
+		 * (Unlike findField(const String&)). 
+		 *
+		 * @param	uniqueFieldId	Unique identifier for the field.
+		 *
+		 * @return	nullptr if it can't find the field.
+		 */
+		RTTIField* findField(int uniqueFieldId);
+
+	protected:
+		/**
+		 * Tries to add a new field to the fields array, and throws an exception if a field with the same name or id 
+		 * already exists.
+		 *
+		 * @param[in]	field	Field, must be non-null.
+		 */
+		void addNewField(RTTIField* field);
+
+	private:
+		Vector<RTTIField*> mFields;
+	};
+
+	/** Used for initializing a certain type as soon as the program is loaded. */
+	template<typename Type, typename BaseType>
+	struct InitRTTIOnStart
+	{
+	public:
+		InitRTTIOnStart()
+		{
+			BaseType::getRTTIStatic()->_registerDerivedClass(Type::getRTTIStatic());
+		}
+
+		void makeSureIAmInstantiated() { }
+	};
+
+	/** Specialization for root class of RTTI hierarchy - IReflectable */
+	template<typename Type>
+	struct InitRTTIOnStart<Type, IReflectable>
+	{
+	public:
+		InitRTTIOnStart()
+		{
+			IReflectable::_registerDerivedClass(Type::getRTTIStatic());
+		}
+
+		void makeSureIAmInstantiated() { }
+	};
+
+	/**
+	 * Template that returns RTTI type of the specified type, unless the specified type is IReflectable in which case it 
+	 * returns a null.
+	 */
+	template<typename Type>
+	struct GetRTTIType
+	{
+		RTTITypeBase* operator()() { return Type::getRTTIStatic(); }
+	};
+
+	/** Specialization for root class of RTTI hierarchy - IReflectable. */
+	template<>
+	struct GetRTTIType<IReflectable>
+	{
+		RTTITypeBase* operator()() { return nullptr; }
+	};
+
+	/** @endcond */
+
+	/**
+	 * Allows you to provide a run-time type information for a specific class, along with support for 
+	 * serialization/deserialization.
+	 * 			
+	 * Derive from this class and return the that class from IReflectable::getRTTI. This way you can separate serialization 
+	 * logic from the actual class you're serializing.
+	 *
+	 * This class will provide a way to register individual fields in the class, together with ways to read and write them, 
+	 * as well a providing information about class hierarchy, and run-time type checking.
+	 */
+	template <typename Type, typename BaseType, typename MyRTTIType>
+	class RTTIType : public RTTITypeBase
+	{
+	protected:
+		/************************************************************************/
+		/* 						RTTI CLASS META DATA							*/
+		/************************************************************************/
+
+		static InitRTTIOnStart<Type, BaseType> initOnStart;
+
+	public:
+		RTTIType() 
+		{
+			// Compiler will only generate code for stuff that is directly used, including static data members,
+			// so we fool it here like we're using the class directly. Otherwise compiler won't generate the code for the member
+			// and our type won't get initialized on start (Actual behavior is a bit more random)
+			initOnStart.makeSureIAmInstantiated();
+		}
+		virtual ~RTTIType() {}
+
+		/** Returns a singleton of this RTTI type. */
+		static MyRTTIType* instance()
+		{
+			static MyRTTIType inst;
+			return &inst;
+		}
+
+		/** @copydoc RTTITypeBase::getDerivedClasses */
+		Vector<RTTITypeBase*>& getDerivedClasses() override
+		{
+			static Vector<RTTITypeBase*> mRTTIDerivedClasses;
+			return mRTTIDerivedClasses;
+		}
+
+		/** @copydoc RTTITypeBase::getBaseClass */
+		RTTITypeBase* getBaseClass() override
+		{
+			return GetRTTIType<BaseType>()();
+		}
+
+		/** @copydoc RTTITypeBase::isDerivedFrom */
+		bool isDerivedFrom(RTTITypeBase* base) override
+		{
+			assert(base != nullptr);
+
+			Stack<RTTITypeBase*> todo;
+			todo.push(base);
+
+			while (!todo.empty())
+			{
+				RTTITypeBase* currentType = todo.top();
+				todo.pop();
+
+				if (currentType->getRTTIId() == getRTTIId())
+					return true;
+
+				const Vector<RTTITypeBase*>& derivedClasses = currentType->getDerivedClasses();
+				for (auto iter = derivedClasses.begin(); iter != derivedClasses.end(); ++iter)
+					todo.push(*iter);
+			}
+
+			return false;
+		}
+
+		/** @copydoc	RTTITypeBase::_registerDerivedClass */
+		void _registerDerivedClass(RTTITypeBase* derivedClass) override
+		{
+			if(IReflectable::_isTypeIdDuplicate(derivedClass->getRTTIId()))
+			{
+				BS_EXCEPT(InternalErrorException, "RTTI type \"" + derivedClass->getRTTIName() + 
+					"\" has a duplicate ID: " + toString(derivedClass->getRTTIId()));
+			}
+
+			getDerivedClasses().push_back(derivedClass);
+		}
+
+		/************************************************************************/
+		/* 			FIELDS OPERATING DIRECTLY ON SERIALIZABLE OBJECT            */
+		/************************************************************************/
+
+		/**
+		 * Registers a new plain field. This field can then be accessed dynamically from the RTTI system and used for 
+		 * automatic serialization. See RTTIField for more information about field types.
+		 *
+		 * @param[in]	name		Name of the field.
+		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *							small data type that can be used for efficiently serializing data to disk and similar. 
+		 *							It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  	Method used for retrieving the value of this field.
+		 * @param[in]	setter  	Method used for setting the value of this field.
+		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
+		 */
+		template<class ObjectType, class DataType>
+		void addPlainField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(), 
+			void (ObjectType::*setter)(DataType&) = nullptr, UINT64 flags = 0)
+		{
+			addPlainField<ObjectType, DataType>(name, uniqueId, 
+				std::function<DataType&(ObjectType*)>(getter), 
+				std::function<void(ObjectType*, DataType&)>(setter), flags);
+		}
+
+		/**
+		 * Registers a new reflectable object field. This field can then be accessed dynamically from the RTTI system and
+		 * used for automatic serialization. See RTTIField for more information about field types.
+		 *
+		 * @param[in]	name		Name of the field.
+		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *							small data type that can be used for efficiently serializing data to disk and similar. 
+		 *							It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  	Method used for retrieving the value of this field.
+		 * @param[in]	setter  	Method used for setting the value of this field.
+		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
+		 */
+		template<class ObjectType, class DataType>
+		void addReflectableField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(), 
+			void (ObjectType::*setter)(DataType&) = nullptr, UINT64 flags = 0)
+		{
+			addReflectableField<ObjectType, DataType>(name, uniqueId, 
+				std::function<DataType&(ObjectType*)>(getter), 
+				std::function<void(ObjectType*, DataType&)>(setter), flags);
+		}
+
+		/**
+		 * Registers a new reflectable object pointer field. This field can then be accessed dynamically from the RTTI 
+		 * system and used for automatic serialization. See RTTIField for more information about field types.
+		 *
+		 * @param[in]	name		Name of the field.
+		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *							small data type that can be used for efficiently serializing data to disk and similar. 
+		 *							It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  	Method used for retrieving the value of this field.
+		 * @param[in]	setter  	Method used for setting the value of this field.
+		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
+		 */
+		template<class ObjectType, class DataType>
+		void addReflectablePtrField(const String& name, UINT32 uniqueId, std::shared_ptr<DataType> (ObjectType::*getter)(), 
+			void (ObjectType::*setter)(std::shared_ptr<DataType>) = nullptr, UINT64 flags = 0)
+		{
+			addReflectablePtrField<ObjectType, DataType>(name, uniqueId, 
+				std::function<std::shared_ptr<DataType>(ObjectType*)>(getter), 
+				std::function<void(ObjectType*, std::shared_ptr<DataType>)>(setter), flags);
+		}
+
+		/**
+		 * Registers a new field containg an array of plain values. This field can then be accessed dynamically from the 
+		 * RTTI system and used for automatic serialization. See RTTIField for more information about field types.
+		 *
+		 * @param[in]	name		Name of the field.
+		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *							small data type that can be used for efficiently serializing data to disk and similar. 
+		 *							It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  	Method used for retrieving a single element of the array.
+		 * @param[in]	getSize 	Getter method that returns the size of the array.
+		 * @param[in]	setter  	Method used for setting the a single element of the field.
+		 * @param[in]	setSize 	Setter method that allows you to resize the array. 
+		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
+		 */
+		template<class ObjectType, class DataType>
+		void addPlainArrayField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
+			void (ObjectType::*setter)(UINT32, DataType&) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
+		{
+			addPlainArrayField<ObjectType, DataType>(name, uniqueId, 
+				std::function<DataType&(ObjectType*, UINT32)>(getter), 
+				std::function<UINT32(ObjectType*)>(getSize), 
+				std::function<void(ObjectType*, UINT32, DataType&)>(setter), 
+				std::function<void(ObjectType*, UINT32)>(setSize), flags);
+		}	
+
+		/**
+		 * Registers a new field containg an array of reflectable object values. This field can then be accessed dynamically
+		 * from the RTTI system and used for automatic serialization. See RTTIField for more information about field types.
+		 *
+		 * @param[in]	name		Name of the field.
+		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *							small data type that can be used for efficiently serializing data to disk and similar. 
+		 *							It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  	Method used for retrieving a single element of the array.
+		 * @param[in]	getSize 	Getter method that returns the size of the array.
+		 * @param[in]	setter  	Method used for setting the a single element of the field.
+		 * @param[in]	setSize 	Setter method that allows you to resize the array. 
+		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
+		 */
+		template<class ObjectType, class DataType>
+		void addReflectableArrayField(const String& name, UINT32 uniqueId, DataType& (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
+			void (ObjectType::*setter)(UINT32, DataType&) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
+		{
+			addReflectableArrayField<ObjectType, DataType>(name, uniqueId, 
+				std::function<DataType&(ObjectType*, UINT32)>(getter), 
+				std::function<UINT32(ObjectType*)>(getSize), 
+				std::function<void(ObjectType*, UINT32, DataType&)>(setter), 
+				std::function<void(ObjectType*, UINT32)>(setSize), flags);
+		}
+
+		/**
+		 * Registers a new field containg an array of reflectable obejct pointers. This field can then be accessed 
+		 * dynamically from the RTTI system and used for automatic serialization. See RTTIField for more information 
+		 * about field types.
+		 *
+		 * @param[in]	name		Name of the field.
+		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *							small data type that can be used for efficiently serializing data to disk and similar. 
+		 *							It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  	Method used for retrieving a single element of the array.
+		 * @param[in]	getSize 	Getter method that returns the size of the array.
+		 * @param[in]	setter  	Method used for setting the a single element of the field.
+		 * @param[in]	setSize 	Setter method that allows you to resize the array. 
+		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
+		 */
+		template<class ObjectType, class DataType>
+		void addReflectablePtrArrayField(const String& name, UINT32 uniqueId, std::shared_ptr<DataType> (ObjectType::*getter)(UINT32), UINT32 (ObjectType::*getSize)(), 
+			void (ObjectType::*setter)(UINT32, std::shared_ptr<DataType>) = nullptr, void(ObjectType::*setSize)(UINT32) = nullptr, UINT64 flags = 0)
+		{
+			addReflectablePtrArrayField<ObjectType, DataType>(name, uniqueId, 
+				std::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>(getter), 
+				std::function<UINT32(ObjectType*)>(getSize), 
+				std::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>(setter), 
+				std::function<void(ObjectType*, UINT32)>(setSize), flags);
+		}
+
+		/**
+		 * Registers a new managed data block field. This field can then be accessed dynamically from the RTTI system and
+		 * used for automatic serialization. See RTTIField for more information about field types.
+		 *
+		 * @param[in]	name		Name of the field.
+		 * @param[in]	uniqueId	Unique identifier for this field. Although name is also a unique identifier we want a 
+		 *							small data type that can be used for efficiently serializing data to disk and similar. 
+		 *							It is primarily used for compatibility between different versions of serialized data.
+		 * @param[in]	getter  	Method used for retrieving the value of this field.
+		 * @param[in]	setter  	Method used for setting the value of this field.
+		 * @param[in]	flags		Various flags you can use to specialize how systems handle this field. See RTTIFieldFlag.
+		 */
+		template<class ObjectType>
+		void addDataBlockField(const String& name, UINT32 uniqueId, ManagedDataBlock (ObjectType::*getter)(), 
+			void (ObjectType::*setter)(ManagedDataBlock) = nullptr, UINT64 flags = 0, UINT8* (customAllocator)(ObjectType*, UINT32) = 0)
+		{
+			addDataBlockField<ObjectType>(name, uniqueId, 
+				std::function<ManagedDataBlock(ObjectType*)>(getter),  
+				std::function<void(ObjectType*, ManagedDataBlock)>(setter), flags, customAllocator);
+		}	
+
+	protected:
+		typedef Type OwnerType;
+		typedef MyRTTIType MyType;
+
+		virtual void initSerializableFields() {}
+
+		/************************************************************************/
+		/* 		FIELDS OPERATING ON DERIVED SERIALIZATION INTERFACE				*/
+		/*		(Needs an extra pointer to the actual object)					*/
+		/************************************************************************/
+		template<class InterfaceType, class ObjectType, class DataType>
+		void addPlainField(const String& name, UINT32 uniqueId, 
+			DataType& (InterfaceType::*getter)(ObjectType*), 
+			void (InterfaceType::*setter)(ObjectType*, DataType&), UINT64 flags = 0)
+		{
+			using namespace std::placeholders;
+
+			static_assert((std::is_base_of<BansheeEngine::RTTIType<Type, BaseType, MyRTTIType>, InterfaceType>::value), 
+				"Class with the get/set methods must derive from BansheeEngine::RTTIType.");
+
+			static_assert(!(std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
+				"Data type derives from IReflectable but it is being added as a plain field.");
+
+			addPlainField<ObjectType, DataType>(name, uniqueId, 
+				std::function<DataType&(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)), 
+				std::function<void(ObjectType*, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
+		}
+
+		template<class InterfaceType, class ObjectType, class DataType>
+		void addReflectableField(const String& name, UINT32 uniqueId, 
+			DataType& (InterfaceType::*getter)(ObjectType*), 
+			void (InterfaceType::*setter)(ObjectType*, DataType&), UINT64 flags = 0)
+		{
+			using namespace std::placeholders;
+
+			addReflectableField<ObjectType, DataType>(name, uniqueId, 
+				std::function<DataType&(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)), 
+				std::function<void(ObjectType*, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
+		}
+
+		template<class InterfaceType, class ObjectType, class DataType>
+		void addReflectablePtrField(const String& name, UINT32 uniqueId, 
+			std::shared_ptr<DataType> (InterfaceType::*getter)(ObjectType*), 
+			void (InterfaceType::*setter)(ObjectType*, std::shared_ptr<DataType>), UINT64 flags = 0)
+		{
+			using namespace std::placeholders;
+
+			addReflectablePtrField<ObjectType, DataType>(name, uniqueId, 
+				std::function<std::shared_ptr<DataType>(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)), 
+				std::function<void(ObjectType*, std::shared_ptr<DataType>)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
+		}
+
+		template<class InterfaceType, class ObjectType, class DataType>
+		void addPlainArrayField(const String& name, UINT32 uniqueId, 
+			DataType& (InterfaceType::*getter)(ObjectType*, UINT32), 
+			UINT32 (InterfaceType::*getSize)(ObjectType*), 
+			void (InterfaceType::*setter)(ObjectType*, UINT32, DataType&), 
+			void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
+		{
+			using namespace std::placeholders;
+
+			static_assert((std::is_base_of<BansheeEngine::RTTIType<Type, BaseType, MyRTTIType>, InterfaceType>::value), 
+				"Class with the get/set methods must derive from BansheeEngine::RTTIType.");
+
+			static_assert(!(std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
+				"Data type derives from IReflectable but it is being added as a plain field.");
+
+			addPlainArrayField<ObjectType, DataType>(name, uniqueId, 
+				std::function<DataType&(ObjectType*, UINT32)>(std::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
+				std::function<UINT32(ObjectType*)>(std::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
+				std::function<void(ObjectType*, UINT32, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
+				std::function<void(ObjectType*, UINT32)>(std::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
+		}	
+
+		template<class InterfaceType, class ObjectType, class DataType>
+		void addReflectableArrayField(const String& name, UINT32 uniqueId, 
+			DataType& (InterfaceType::*getter)(ObjectType*, UINT32), 
+			UINT32 (InterfaceType::*getSize)(ObjectType*), 
+			void (InterfaceType::*setter)(ObjectType*, UINT32, DataType&), 
+			void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
+		{
+			using namespace std::placeholders;
+
+			addReflectableArrayField<ObjectType, DataType>(name, uniqueId, 
+				std::function<DataType&(ObjectType*, UINT32)>(std::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
+				std::function<UINT32(ObjectType*)>(std::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
+				std::function<void(ObjectType*, UINT32, DataType&)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
+				std::function<void(ObjectType*, UINT32)>(std::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
+		}
+
+		template<class InterfaceType, class ObjectType, class DataType>
+		void addReflectablePtrArrayField(const String& name, UINT32 uniqueId, 
+			std::shared_ptr<DataType> (InterfaceType::*getter)(ObjectType*, UINT32), 
+			UINT32 (InterfaceType::*getSize)(ObjectType*), 
+			void (InterfaceType::*setter)(ObjectType*, UINT32, std::shared_ptr<DataType>), 
+			void(InterfaceType::*setSize)(ObjectType*, UINT32), UINT64 flags = 0)
+		{
+			using namespace std::placeholders;
+
+			addReflectablePtrArrayField<ObjectType, DataType>(name, uniqueId, 
+				std::function<std::shared_ptr<DataType>(ObjectType*, UINT32)>(std::bind(getter, static_cast<InterfaceType*>(this), _1, _2)), 
+				std::function<UINT32(ObjectType*)>(std::bind(getSize, static_cast<InterfaceType*>(this), _1)), 
+				std::function<void(ObjectType*, UINT32, std::shared_ptr<DataType>)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2, _3)), 
+				std::function<void(ObjectType*, UINT32)>(std::bind(setSize, static_cast<InterfaceType*>(this), _1, _2)), flags);
+		}
+
+		template<class InterfaceType, class ObjectType>
+		void addDataBlockField(const String& name, UINT32 uniqueId, ManagedDataBlock (InterfaceType::*getter)(ObjectType*), 
+			void (InterfaceType::*setter)(ObjectType*, ManagedDataBlock), UINT64 flags = 0, 
+			UINT8* (customAllocator)(ObjectType*, UINT32) = 0)
+		{
+			using namespace std::placeholders;
+
+			if(customAllocator != 0)
+			{
+				std::function<UINT8*(ObjectType*, UINT32)> customAllocFunc = std::bind(customAllocator, _1, _2);
+
+				addDataBlockField<ObjectType>(name, uniqueId, 
+					std::function<ManagedDataBlock(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)),  
+					std::function<void(ObjectType*, ManagedDataBlock)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags, 
+					customAllocFunc);
+			}
+			else
+			{
+				addDataBlockField<ObjectType>(name, uniqueId, 
+					std::function<ManagedDataBlock(ObjectType*)>(std::bind(getter, static_cast<InterfaceType*>(this), _1)),  
+					std::function<void(ObjectType*, ManagedDataBlock)>(std::bind(setter, static_cast<InterfaceType*>(this), _1, _2)), flags);
+			}
+		}	
+
+	private:
+		template<class ObjectType, class DataType>
+		void addPlainField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags)
+		{
+			RTTIPlainField<DataType, ObjectType>* newField = 
+				bs_new<RTTIPlainField<DataType, ObjectType>>();
+			newField->initSingle(name, uniqueId, getter, setter, flags);
+			addNewField(newField);
+		}
+		
+		template<class ObjectType, class DataType>
+		void addReflectableField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags)
+		{
+			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
+				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
+
+			RTTIReflectableField<DataType, ObjectType>* newField = 
+				bs_new<RTTIReflectableField<DataType, ObjectType>>();
+			newField->initSingle(name, uniqueId, getter, setter, flags);
+			addNewField(newField);
+		}
+
+		template<class ObjectType, class DataType>
+		void addReflectablePtrField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags)
+		{
+			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
+				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
+
+			RTTIReflectablePtrField<DataType, ObjectType>* newField = 
+				bs_new<RTTIReflectablePtrField<DataType, ObjectType>>();
+			newField->initSingle(name, uniqueId, getter, setter, flags);
+			addNewField(newField);
+		}
+
+		template<class ObjectType, class DataType>
+		void addPlainArrayField(const String& name, UINT32 uniqueId, Any getter, Any getSize,
+			Any setter, Any setSize, UINT64 flags)
+		{
+			RTTIPlainField<DataType, ObjectType>* newField = 
+				bs_new<RTTIPlainField<DataType, ObjectType>>();
+			newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
+			addNewField(newField);
+		}	
+
+		template<class ObjectType, class DataType>
+		void addReflectableArrayField(const String& name, UINT32 uniqueId, Any getter, Any getSize,
+			Any setter, Any setSize, UINT64 flags)
+		{
+			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
+				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
+
+			RTTIReflectableField<DataType, ObjectType>* newField = 
+				bs_new<RTTIReflectableField<DataType, ObjectType>>();
+			newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
+			addNewField(newField);
+		}
+
+		template<class ObjectType, class DataType>
+		void addReflectablePtrArrayField(const String& name, UINT32 uniqueId, Any getter, Any getSize,
+			Any setter, Any setSize, UINT64 flags)
+		{
+			static_assert((std::is_base_of<BansheeEngine::IReflectable, DataType>::value), 
+				"Invalid data type for complex field. It needs to derive from BansheeEngine::IReflectable.");
+
+			RTTIReflectablePtrField<DataType, ObjectType>* newField = 
+				bs_new<RTTIReflectablePtrField<DataType, ObjectType>>();
+			newField->initArray(name, uniqueId, getter, getSize, setter, setSize, flags);
+			addNewField(newField);
+		}
+
+		template<class ObjectType>
+		void addDataBlockField(const String& name, UINT32 uniqueId, Any getter, Any setter, UINT64 flags, 
+			Any customAllocator = Any())
+		{
+			RTTIManagedDataBlockField<ManagedDataBlock, ObjectType>* newField = 
+				bs_new<RTTIManagedDataBlockField<ManagedDataBlock, ObjectType>>();
+			newField->initSingle(name, uniqueId, getter,  setter, flags, customAllocator);
+			addNewField(newField);
+		}	
+	};
+
+	template <typename Type, typename BaseType, typename MyRTTIType>
+	InitRTTIOnStart<Type, BaseType> RTTIType<Type, BaseType, MyRTTIType>::initOnStart;
+
+	/** Returns true if the provided object can be safely cast into type T. */
+	template<class T>
+	bool rtti_is_of_type(IReflectable* object)
+	{
+		static_assert((std::is_base_of<BansheeEngine::IReflectable, T>::value), 
+			"Invalid data type for type checking. It needs to derive from BansheeEngine::IReflectable.");
+
+		return object->getTypeId() == T::getRTTIStatic()->getRTTIId();
+	}
+
+	/** Returns true if the provided object can be safely cast into type T. */
+	template<class T>
+	bool rtti_is_of_type(std::shared_ptr<IReflectable> object)
+	{
+		static_assert((std::is_base_of<BansheeEngine::IReflectable, T>::value), 
+			"Invalid data type for type checking. It needs to derive from BansheeEngine::IReflectable.");
+
+		return object->getTypeId() == T::getRTTIStatic()->getRTTIId();
+	}
+
+	/** Creates a new object just from its type ID. */
+	std::shared_ptr<IReflectable> rtti_create(UINT32 rttiId);
+
+	/** Checks is the current object a subclass of some type. */
+	template<class T>
+	bool rtti_is_subclass(IReflectable* object)
+	{
+		static_assert((std::is_base_of<BansheeEngine::IReflectable, T>::value),
+			"Invalid data type for type checking. It needs to derive from BansheeEngine::IReflectable.");
+
+		return object->isDerivedFrom(T::getRTTIStatic());
+	}
+
+	/** @} */
 }

+ 65 - 65
Source/MBansheeEditor/BrowseDialog.cs

@@ -1,65 +1,65 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Contains methods for opening various OS-specific browse, open and save file/folder dialogs.
-    /// </summary>
-    public static class BrowseDialog
-    {
-        /// <summary>
-        /// Displays a platform specific dialog that allows the user to select file(s).
-        /// </summary>
-        /// <param name="defaultPath">Default path the dialog should point to.</param>
-        /// <param name="filterList">Semi-colon separated list of file names or types to display in the dialog, 
-        ///                          e.g. "exe;txt;png".</param>
-        /// <param name="allowMultiselect">True if user is allowed to select multiple files.</param>
-        /// <param name="outPaths">A list of file paths selected by the user.</param>
-        /// <returns>True if the user selected the file(s), false if the user canceled out of the dialog.</returns>
-        public static bool OpenFile(string defaultPath, string filterList, bool allowMultiselect, out string[] outPaths)
-        {
-            return Internal_OpenFile(defaultPath, filterList, allowMultiselect, out outPaths);
-        }
-
-        /// <summary>
-        /// Displays a platform specific dialog that allows the user to select a folder.
-        /// </summary>
-        /// <param name="defaultPath">Default path the dialog should point to.</param>
-        /// <param name="outPath">Path to the selected folder.</param>
-        /// <returns>True if the user selected the folder, false if the user canceled out of the dialog.</returns>
-        public static bool OpenFolder(string defaultPath, out string outPath)
-        {
-            return Internal_OpenFolder(defaultPath, out outPath);
-        }
-
-        /// <summary>
-        /// Displays a platform specific dialog that allows the user to select where to save a file.
-        /// </summary>
-        /// <param name="defaultPath">Default path the dialog should point to.</param>
-        /// <param name="filterList">Semi-colon separated list of file names or types to display in the dialog,
-        ///                          e.g. "exe;txt;png".</param>
-        /// <param name="outPath">File path selected by the user.</param>
-        /// <returns>True if the user selected the file, false if the user canceled out of the dialog.</returns>
-        public static bool SaveFile(string defaultPath, string filterList, out string outPath)
-        {
-            return Internal_SaveFile(defaultPath, filterList, out outPath);
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_OpenFile(string defaultPath, string filterList, bool allowMultiselect, out string[] outPaths);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_OpenFolder(string defaultPath, out string outPath);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_SaveFile(string defaultPath, string filterList, out string outPath);
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Contains methods for opening various OS-specific browse, open and save file/folder dialogs.
+    /// </summary>
+    public static class BrowseDialog
+    {
+        /// <summary>
+        /// Displays a platform specific dialog that allows the user to select file(s).
+        /// </summary>
+        /// <param name="defaultPath">Default path the dialog should point to.</param>
+        /// <param name="filterList">Semi-colon separated list of file names or types to display in the dialog, 
+        ///                          for example "exe;txt;png".</param>
+        /// <param name="allowMultiselect">True if user is allowed to select multiple files.</param>
+        /// <param name="outPaths">A list of file paths selected by the user.</param>
+        /// <returns>True if the user selected the file(s), false if the user canceled out of the dialog.</returns>
+        public static bool OpenFile(string defaultPath, string filterList, bool allowMultiselect, out string[] outPaths)
+        {
+            return Internal_OpenFile(defaultPath, filterList, allowMultiselect, out outPaths);
+        }
+
+        /// <summary>
+        /// Displays a platform specific dialog that allows the user to select a folder.
+        /// </summary>
+        /// <param name="defaultPath">Default path the dialog should point to.</param>
+        /// <param name="outPath">Path to the selected folder.</param>
+        /// <returns>True if the user selected the folder, false if the user canceled out of the dialog.</returns>
+        public static bool OpenFolder(string defaultPath, out string outPath)
+        {
+            return Internal_OpenFolder(defaultPath, out outPath);
+        }
+
+        /// <summary>
+        /// Displays a platform specific dialog that allows the user to select where to save a file.
+        /// </summary>
+        /// <param name="defaultPath">Default path the dialog should point to.</param>
+        /// <param name="filterList">Semi-colon separated list of file names or types to display in the dialog,
+        ///                          for example "exe;txt;png".</param>
+        /// <param name="outPath">File path selected by the user.</param>
+        /// <returns>True if the user selected the file, false if the user canceled out of the dialog.</returns>
+        public static bool SaveFile(string defaultPath, string filterList, out string outPath)
+        {
+            return Internal_SaveFile(defaultPath, filterList, out outPath);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_OpenFile(string defaultPath, string filterList, bool allowMultiselect, out string[] outPaths);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_OpenFolder(string defaultPath, out string outPath);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_SaveFile(string defaultPath, string filterList, out string outPath);
+    }
+}

+ 515 - 515
Source/MBansheeEditor/BuildManager.cs

@@ -1,515 +1,515 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.IO;
-using System.Runtime.CompilerServices;
-using System.Threading;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Contains a list of valid platforms that can be built for.
-    /// </summary>
-    public enum PlatformType // Note: Must match C++ enum PlatformType
-    {
-        Windows,
-        Count // Keep at end
-    }
-
-    /// <summary>
-    /// Contains build data for a specific platform.
-    /// </summary>
-    public abstract class PlatformInfo : ScriptObject
-    {
-        /// <summary>
-        /// Creates a new platform info. For internal runtime use only.
-        /// </summary>
-        protected PlatformInfo()
-        { }
-
-        /// <summary>
-        /// Returns the platform that this object contains data for.
-        /// </summary>
-        public PlatformType Type
-        {
-            get { return Internal_GetType(mCachedPtr); }
-        }
-
-        /// <summary>
-        /// Initial scene that is loaded when application is first started.
-        /// </summary>
-        public ResourceRef MainScene
-        {
-            get { return Internal_GetMainScene(mCachedPtr); }
-            set
-            {
-                IntPtr scenePtr = IntPtr.Zero;
-                if (value != null)
-                    scenePtr = value.GetCachedPtr();
-
-                Internal_SetMainScene(mCachedPtr, scenePtr);
-            }
-        }
-
-        /// <summary>
-        /// Determines should the application be started in fullscreen using the user's desktop resolution.
-        /// </summary>
-        public bool Fullscreen
-        {
-            get { return Internal_GetFullscreen(mCachedPtr); }
-            set { Internal_SetFullscreen(mCachedPtr, value); }
-        }
-
-        /// <summary>
-        /// Width of a window if the game is started in windowed mode. This is only relevant if <see cref="Fullscreen"/>
-        /// is off.
-        /// </summary>
-        public int WindowedWidth
-        {
-            get
-            {
-                int width, height;
-                Internal_GetResolution(mCachedPtr, out width, out height);
-
-                return width;
-            }
-
-            set { Internal_SetResolution(mCachedPtr, value, WindowedHeight); }
-        }
-
-        /// <summary>
-        /// Height of a window if the game is started in windowed mode. This is only relevant if <see cref="Fullscreen"/>
-        /// is off.
-        /// </summary>
-        public int WindowedHeight
-        {
-            get
-            {
-                int width, height;
-                Internal_GetResolution(mCachedPtr, out width, out height);
-
-                return height;
-            }
-
-            set { Internal_SetResolution(mCachedPtr, WindowedWidth, value); }
-        }
-
-        /// <summary>
-        /// Determines should the scripts be output in debug mode (worse performance but better error reporting).
-        /// </summary>
-        public bool Debug
-        {
-            get { return Internal_GetDebug(mCachedPtr); }
-            set { Internal_SetDebug(mCachedPtr, value); }
-        }
-
-        /// <summary>
-        /// A set of semicolon separated defines to use when compiling scripts for this platform.
-        /// </summary>
-        public string Defines
-        {
-            get { return Internal_GetDefines(mCachedPtr); }
-            set { Internal_SetDefines(mCachedPtr, value); }
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern PlatformType Internal_GetType(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetDefines(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetDefines(IntPtr thisPtr, string value);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern ResourceRef Internal_GetMainScene(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        static extern void Internal_SetMainScene(IntPtr thisPtr, IntPtr prefabPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        static extern bool Internal_GetFullscreen(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        static extern void Internal_SetFullscreen(IntPtr thisPtr, bool fullscreen);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        static extern void Internal_GetResolution(IntPtr thisPtr, out int width, out int height);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        static extern void Internal_SetResolution(IntPtr thisPtr, int width, int height);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        static extern bool Internal_GetDebug(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        static extern void Internal_SetDebug(IntPtr thisPtr, bool fullscreen);
-    }
-
-    /// <summary>
-    /// Supported icon sizes for Windows platform.
-    /// </summary>
-    public enum WinIconSizes
-    {
-        Icon16 = 16,
-        Icon32 = 32,
-        Icon48 = 48,
-        Icon64 = 64,
-        Icon96 = 96,
-        Icon128 = 128,
-        Icon196 = 196,
-        Icon256 = 256
-    }
-
-    /// <summary>
-    /// Platform data specific to Windows.
-    /// </summary>
-    public class WinPlatformInfo : PlatformInfo
-    {
-        /// <summary>
-        /// Texture that will be displayed on the application's executable.
-        /// </summary>
-        public ResourceRef Icon
-        {
-            get { return Internal_GetIcon(mCachedPtr); }
-            set
-            {
-                IntPtr texturePtr = IntPtr.Zero;
-                if (value != null)
-                    texturePtr = value.GetCachedPtr();
-
-                Internal_SetIcon(mCachedPtr, texturePtr);
-            }
-        }
-
-        /// <summary>
-        /// Text that will be displayed in the application's title bar.
-        /// </summary>
-        public string TitleText
-        {
-            get { return Internal_GetTitleText(mCachedPtr); }
-            set { Internal_SetTitleText(mCachedPtr, value); }
-        }
-        
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern ResourceRef Internal_GetIcon(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetIcon(IntPtr thisPtr, IntPtr texturePtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetTitleText(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetTitleText(IntPtr thisPtr, string value);
-    }
-
-    /// <summary>
-    /// Handles building of the game executable and packaging of all necessary resources, making the game be ready to ran
-    /// as a standalone product.
-    /// </summary>
-    public static class BuildManager
-    {
-        /// <summary>
-        /// Returns a list of all available platforms that can be built for.
-        /// </summary>
-        public static PlatformType[] AvailablePlatforms
-        {
-            get { return Internal_GetAvailablePlatforms(); }
-        }
-
-        /// <summary>
-        /// Returns the currently active platform.
-        /// </summary>
-        public static PlatformType ActivePlatform
-        {
-            get { return Internal_GetActivePlatform(); }
-            set { Internal_SetActivePlatform(value); }
-        }
-
-        /// <summary>
-        /// Returns the data about the currently active platform.
-        /// </summary>
-        public static PlatformInfo ActivePlatformInfo
-        {
-            get { return Internal_GetActivePlatformInfo(); }
-        }
-
-        /// <summary>
-        /// Returns absolute path to the folder where builds for the currently active platform are output.
-        /// </summary>
-        public static string OutputFolder
-        {
-            get { return GetBuildFolder(BuildFolder.DestinationRoot, ActivePlatform); }
-        }
-
-        /// <summary>
-        /// Returns a path to a specific folder used in the build process. See entries of BuildFolder enum for explanations 
-        /// of individual folder types.
-        /// </summary>
-        /// <param name="folder">Type of folder to retrieve the path for.</param>
-        /// <param name="platform">Platform to retrieve the path for.</param>
-        /// <returns>Path for the requested folder. This can be absolute or relative, see <see cref="BuildFolder"/> enum
-        ///          for details.</returns>
-        private static string GetBuildFolder(BuildFolder folder, PlatformType platform)
-        {
-            return Internal_GetBuildFolder(folder, platform);
-        }
-
-        /// <summary>
-        /// Returns a list of names of all native binaries required for a specific platform.
-        /// </summary>
-        /// <param name="platform">Platform type for which to get the binaries for.</param>
-        /// <returns>Array of names of native binary files.</returns>
-        private static string[] GetNativeBinaries(PlatformType platform)
-        {
-            return Internal_GetNativeBinaries(platform);
-        }
-
-        /// <summary>
-        /// Builds the executable and packages the game.
-        /// </summary>
-        public static void Build()
-        {
-            PlatformType activePlatform = ActivePlatform;
-            PlatformInfo platformInfo = ActivePlatformInfo;
-
-            string srcRoot = GetBuildFolder(BuildFolder.SourceRoot, activePlatform);
-            string destRoot = GetBuildFolder(BuildFolder.DestinationRoot, activePlatform);
-
-            // Prepare clean destination folder
-            if(Directory.Exists(destRoot))
-                Directory.Delete(destRoot, true);
-
-            Directory.CreateDirectory(destRoot);
-
-            // Compile game assembly
-            string bansheeAssemblyFolder;
-            if(platformInfo.Debug)
-                bansheeAssemblyFolder = GetBuildFolder(BuildFolder.BansheeDebugAssemblies, activePlatform);
-            else
-                bansheeAssemblyFolder = GetBuildFolder(BuildFolder.BansheeReleaseAssemblies, activePlatform);
-
-            string srcBansheeAssemblyFolder = Path.Combine(srcRoot, bansheeAssemblyFolder);
-            string destBansheeAssemblyFolder = Path.Combine(destRoot, bansheeAssemblyFolder);
-
-            Directory.CreateDirectory(destBansheeAssemblyFolder);
-            CompilerInstance ci = ScriptCompiler.CompileAsync(ScriptAssemblyType.Game, ActivePlatform, platformInfo.Debug, destBansheeAssemblyFolder);
-
-            // Copy engine assembly
-            {
-                string srcFile = Path.Combine(srcBansheeAssemblyFolder, EditorApplication.EngineAssemblyName);
-                string destFile = Path.Combine(destBansheeAssemblyFolder, EditorApplication.EngineAssemblyName);
-
-                File.Copy(srcFile, destFile);
-            }
-
-            // Copy builtin data
-            string dataFolder = GetBuildFolder(BuildFolder.Data, activePlatform);
-            string srcData = Path.Combine(srcRoot, dataFolder);
-            string destData = Path.Combine(destRoot, dataFolder);
-
-            DirectoryEx.Copy(srcData, destData);
-
-            // Copy native binaries
-            string binaryFolder = GetBuildFolder(BuildFolder.NativeBinaries, activePlatform);
-            string srcBin = Path.Combine(srcRoot, binaryFolder);
-            string destBin = destRoot;
-
-            string[] nativeBinaries = GetNativeBinaries(activePlatform);
-            foreach (var entry in nativeBinaries)
-            {
-                string srcFile = Path.Combine(srcBin, entry);
-                string destFile = Path.Combine(destBin, entry);
-
-                File.Copy(srcFile, destFile);
-            }
-
-            // Copy .NET framework assemblies
-            string frameworkAssemblyFolder = GetBuildFolder(BuildFolder.FrameworkAssemblies, activePlatform);
-            string srcFrameworkAssemblyFolder = Path.Combine(srcRoot, frameworkAssemblyFolder);
-            string destFrameworkAssemblyFolder = Path.Combine(destRoot, frameworkAssemblyFolder);
-
-            Directory.CreateDirectory(destFrameworkAssemblyFolder);
-
-            string[] frameworkAssemblies = GetFrameworkAssemblies(activePlatform);
-            foreach (var entry in frameworkAssemblies)
-            {
-                string srcFile = Path.Combine(srcFrameworkAssemblyFolder, entry + ".dll");
-                string destFile = Path.Combine(destFrameworkAssemblyFolder, entry + ".dll");
-
-                File.Copy(srcFile, destFile);
-            }
-
-            // Copy Mono
-            string monoFolder = GetBuildFolder(BuildFolder.Mono, activePlatform);
-            string srcMonoFolder = Path.Combine(srcRoot, monoFolder);
-            string destMonoFolder = Path.Combine(destRoot, monoFolder);
-
-            DirectoryEx.Copy(srcMonoFolder, destMonoFolder);
-
-            string srcExecFile = GetMainExecutable(activePlatform);
-            string destExecFile = Path.Combine(destBin, Path.GetFileName(srcExecFile));
-
-            File.Copy(srcExecFile, destExecFile);
-
-            InjectIcons(destExecFile, platformInfo);
-            PackageResources(destRoot, platformInfo);
-            CreateStartupSettings(destRoot, platformInfo);
-
-            // Wait until compile finishes
-            while (!ci.IsDone)
-                Thread.Sleep(200);
-
-            ci.Dispose();
-        }
-
-        /// <summary>
-        /// Injects icons specified in <see cref="PlatformInfo"/> into an executable at the specified path.
-        /// </summary>
-        /// <param name="filePath">Absolute path to the executable to inject icons in.</param>
-        /// <param name="info">Object containing references to icons to inject.</param>
-        private static void InjectIcons(string filePath, PlatformInfo info)
-        {
-            IntPtr infoPtr = IntPtr.Zero;
-            if (info != null)
-                infoPtr = info.GetCachedPtr();
-
-            Internal_InjectIcons(filePath, infoPtr);
-        }
-
-        /// <summary>
-        /// Finds all used resources by the build and packages them into an output folder.
-        /// </summary>
-        /// <param name="buildFolder">Absolute path to the root folder of the build. This is where the packaged resource
-        ///                           folder be placed.</param>
-        /// <param name="info">Platform information about the current build.</param>
-        private static void PackageResources(string buildFolder, PlatformInfo info)
-        {
-            IntPtr infoPtr = IntPtr.Zero;
-            if (info != null)
-                infoPtr = info.GetCachedPtr();
-
-            Internal_PackageResources(buildFolder, infoPtr);
-        }
-
-        /// <summary>
-        /// Creates a game settings asset that contains necessary data for starting up the game (e.g. initial scene).
-        /// </summary>
-        /// <param name="buildFolder">Absolute path to the root folder of the build. This is where the settings assets
-        ///                           will be output.</param>
-        /// <param name="info">Platform information about the current build.</param>
-        private static void CreateStartupSettings(string buildFolder, PlatformInfo info)
-        {
-            IntPtr infoPtr = IntPtr.Zero;
-            if (info != null)
-                infoPtr = info.GetCachedPtr();
-
-            Internal_CreateStartupSettings(buildFolder, infoPtr);
-        }
-
-        /// <summary>
-        /// Returns a list of .NET framework managed assemblies (without extension) to be included for the specified platform.
-        /// </summary>
-        /// <param name="type">Platform type to retrieve the list of assemblies for.</param>
-        /// <returns>A list of .NET framework managed assemblies (without extension) that will be included with the build.</returns>
-        internal static string[] GetFrameworkAssemblies(PlatformType type)
-        {
-            return Internal_GetFrameworkAssemblies(type);
-        }
-
-        /// <summary>
-        /// Returns the absolute path to the executable for the provided platform.
-        /// </summary>
-        /// <param name="type">Platform type to retrieve the executable location for.</param>
-        /// <returns>Absolute path to the executable.</returns>
-        internal static string GetMainExecutable(PlatformType type)
-        {
-            return Internal_GetMainExecutable(type);
-        }
-
-        /// <summary>
-        /// Returns a list of semicolon separated defines that will be used when compiling scripts for the specified 
-        /// platform.
-        /// </summary>
-        /// <param name="type">Platfrom type to retrieve the defines for.</param>
-        /// <returns>Semicolor separated defines that will be passed along to the script compiler.</returns>
-        internal static string GetDefines(PlatformType type)
-        {
-            return Internal_GetDefines(type);
-        }
-
-        /// <summary>
-        /// Returns an object containing all platform specific build data.
-        /// </summary>
-        /// <param name="type">Platform type to retrieve the data for.</param>
-        /// <returns>An object containing all platform specific build data</returns>
-        internal static PlatformInfo GetPlatformInfo(PlatformType type)
-        {
-            return Internal_GetPlatformInfo(type);
-        }
-
-        /// <summary>
-        /// Types of various folders used by the build manager.
-        /// </summary>
-        private enum BuildFolder // Note: Must match C++ enum ScriptBuildFolder
-        {
-            /// <summary>Absolute path to the root folder where all the prebuilt binaries and data exist.</summary>
-            SourceRoot,
-            /// <summary>Absolute path to the root folder for a build for a specific platform.</summary>
-            DestinationRoot,
-            /// <summary>Folder where native binaries are stored. Relative to root.</summary>
-            NativeBinaries,
-            /// <summary>Folder where Banshee specific debug assemblies are stored. Relative to root.</summary>
-            BansheeDebugAssemblies,
-            /// <summary>Folder where Banshee specific release assemblies are stored. Relative to root.</summary>
-            BansheeReleaseAssemblies,
-            /// <summary>Folder where .NET framework assemblies are stored. Relative to root.</summary>
-            FrameworkAssemblies,
-            /// <summary>Folder where miscelaneous Mono files are stored. Relative to root.</summary>
-            Mono,
-            /// <summary>Folder where builtin data is stored. Relative to root.</summary>
-            Data
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern PlatformType[] Internal_GetAvailablePlatforms();
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern PlatformType Internal_GetActivePlatform();
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetActivePlatform(PlatformType value);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern PlatformInfo Internal_GetActivePlatformInfo();
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern PlatformInfo Internal_GetPlatformInfo(PlatformType type);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string[] Internal_GetFrameworkAssemblies(PlatformType type);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetMainExecutable(PlatformType type);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetDefines(PlatformType type);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string[] Internal_GetNativeBinaries(PlatformType type);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetBuildFolder(BuildFolder folder, PlatformType platform);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_InjectIcons(string filePath, IntPtr info);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_PackageResources(string buildFolder, IntPtr info);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateStartupSettings(string buildFolder, IntPtr info);
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Contains a list of valid platforms that can be built for.
+    /// </summary>
+    public enum PlatformType // Note: Must match C++ enum PlatformType
+    {
+        Windows,
+        Count // Keep at end
+    }
+
+    /// <summary>
+    /// Contains build data for a specific platform.
+    /// </summary>
+    public abstract class PlatformInfo : ScriptObject
+    {
+        /// <summary>
+        /// Creates a new platform info. For internal runtime use only.
+        /// </summary>
+        protected PlatformInfo()
+        { }
+
+        /// <summary>
+        /// Returns the platform that this object contains data for.
+        /// </summary>
+        public PlatformType Type
+        {
+            get { return Internal_GetType(mCachedPtr); }
+        }
+
+        /// <summary>
+        /// Initial scene that is loaded when application is first started.
+        /// </summary>
+        public ResourceRef MainScene
+        {
+            get { return Internal_GetMainScene(mCachedPtr); }
+            set
+            {
+                IntPtr scenePtr = IntPtr.Zero;
+                if (value != null)
+                    scenePtr = value.GetCachedPtr();
+
+                Internal_SetMainScene(mCachedPtr, scenePtr);
+            }
+        }
+
+        /// <summary>
+        /// Determines should the application be started in fullscreen using the user's desktop resolution.
+        /// </summary>
+        public bool Fullscreen
+        {
+            get { return Internal_GetFullscreen(mCachedPtr); }
+            set { Internal_SetFullscreen(mCachedPtr, value); }
+        }
+
+        /// <summary>
+        /// Width of a window if the game is started in windowed mode. This is only relevant if <see cref="Fullscreen"/>
+        /// is off.
+        /// </summary>
+        public int WindowedWidth
+        {
+            get
+            {
+                int width, height;
+                Internal_GetResolution(mCachedPtr, out width, out height);
+
+                return width;
+            }
+
+            set { Internal_SetResolution(mCachedPtr, value, WindowedHeight); }
+        }
+
+        /// <summary>
+        /// Height of a window if the game is started in windowed mode. This is only relevant if <see cref="Fullscreen"/>
+        /// is off.
+        /// </summary>
+        public int WindowedHeight
+        {
+            get
+            {
+                int width, height;
+                Internal_GetResolution(mCachedPtr, out width, out height);
+
+                return height;
+            }
+
+            set { Internal_SetResolution(mCachedPtr, WindowedWidth, value); }
+        }
+
+        /// <summary>
+        /// Determines should the scripts be output in debug mode (worse performance but better error reporting).
+        /// </summary>
+        public bool Debug
+        {
+            get { return Internal_GetDebug(mCachedPtr); }
+            set { Internal_SetDebug(mCachedPtr, value); }
+        }
+
+        /// <summary>
+        /// A set of semicolon separated defines to use when compiling scripts for this platform.
+        /// </summary>
+        public string Defines
+        {
+            get { return Internal_GetDefines(mCachedPtr); }
+            set { Internal_SetDefines(mCachedPtr, value); }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern PlatformType Internal_GetType(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetDefines(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetDefines(IntPtr thisPtr, string value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern ResourceRef Internal_GetMainScene(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        static extern void Internal_SetMainScene(IntPtr thisPtr, IntPtr prefabPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        static extern bool Internal_GetFullscreen(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        static extern void Internal_SetFullscreen(IntPtr thisPtr, bool fullscreen);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        static extern void Internal_GetResolution(IntPtr thisPtr, out int width, out int height);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        static extern void Internal_SetResolution(IntPtr thisPtr, int width, int height);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        static extern bool Internal_GetDebug(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        static extern void Internal_SetDebug(IntPtr thisPtr, bool fullscreen);
+    }
+
+    /// <summary>
+    /// Supported icon sizes for Windows platform.
+    /// </summary>
+    public enum WinIconSizes
+    {
+        Icon16 = 16,
+        Icon32 = 32,
+        Icon48 = 48,
+        Icon64 = 64,
+        Icon96 = 96,
+        Icon128 = 128,
+        Icon196 = 196,
+        Icon256 = 256
+    }
+
+    /// <summary>
+    /// Platform data specific to Windows.
+    /// </summary>
+    public class WinPlatformInfo : PlatformInfo
+    {
+        /// <summary>
+        /// Texture that will be displayed on the application's executable.
+        /// </summary>
+        public ResourceRef Icon
+        {
+            get { return Internal_GetIcon(mCachedPtr); }
+            set
+            {
+                IntPtr texturePtr = IntPtr.Zero;
+                if (value != null)
+                    texturePtr = value.GetCachedPtr();
+
+                Internal_SetIcon(mCachedPtr, texturePtr);
+            }
+        }
+
+        /// <summary>
+        /// Text that will be displayed in the application's title bar.
+        /// </summary>
+        public string TitleText
+        {
+            get { return Internal_GetTitleText(mCachedPtr); }
+            set { Internal_SetTitleText(mCachedPtr, value); }
+        }
+        
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern ResourceRef Internal_GetIcon(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetIcon(IntPtr thisPtr, IntPtr texturePtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetTitleText(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetTitleText(IntPtr thisPtr, string value);
+    }
+
+    /// <summary>
+    /// Handles building of the game executable and packaging of all necessary resources, making the game be ready to ran
+    /// as a standalone product.
+    /// </summary>
+    public static class BuildManager
+    {
+        /// <summary>
+        /// Returns a list of all available platforms that can be built for.
+        /// </summary>
+        public static PlatformType[] AvailablePlatforms
+        {
+            get { return Internal_GetAvailablePlatforms(); }
+        }
+
+        /// <summary>
+        /// Returns the currently active platform.
+        /// </summary>
+        public static PlatformType ActivePlatform
+        {
+            get { return Internal_GetActivePlatform(); }
+            set { Internal_SetActivePlatform(value); }
+        }
+
+        /// <summary>
+        /// Returns the data about the currently active platform.
+        /// </summary>
+        public static PlatformInfo ActivePlatformInfo
+        {
+            get { return Internal_GetActivePlatformInfo(); }
+        }
+
+        /// <summary>
+        /// Returns absolute path to the folder where builds for the currently active platform are output.
+        /// </summary>
+        public static string OutputFolder
+        {
+            get { return GetBuildFolder(BuildFolder.DestinationRoot, ActivePlatform); }
+        }
+
+        /// <summary>
+        /// Returns a path to a specific folder used in the build process. See entries of BuildFolder enum for explanations 
+        /// of individual folder types.
+        /// </summary>
+        /// <param name="folder">Type of folder to retrieve the path for.</param>
+        /// <param name="platform">Platform to retrieve the path for.</param>
+        /// <returns>Path for the requested folder. This can be absolute or relative, see <see cref="BuildFolder"/> enum
+        ///          for details.</returns>
+        private static string GetBuildFolder(BuildFolder folder, PlatformType platform)
+        {
+            return Internal_GetBuildFolder(folder, platform);
+        }
+
+        /// <summary>
+        /// Returns a list of names of all native binaries required for a specific platform.
+        /// </summary>
+        /// <param name="platform">Platform type for which to get the binaries for.</param>
+        /// <returns>Array of names of native binary files.</returns>
+        private static string[] GetNativeBinaries(PlatformType platform)
+        {
+            return Internal_GetNativeBinaries(platform);
+        }
+
+        /// <summary>
+        /// Builds the executable and packages the game.
+        /// </summary>
+        public static void Build()
+        {
+            PlatformType activePlatform = ActivePlatform;
+            PlatformInfo platformInfo = ActivePlatformInfo;
+
+            string srcRoot = GetBuildFolder(BuildFolder.SourceRoot, activePlatform);
+            string destRoot = GetBuildFolder(BuildFolder.DestinationRoot, activePlatform);
+
+            // Prepare clean destination folder
+            if(Directory.Exists(destRoot))
+                Directory.Delete(destRoot, true);
+
+            Directory.CreateDirectory(destRoot);
+
+            // Compile game assembly
+            string bansheeAssemblyFolder;
+            if(platformInfo.Debug)
+                bansheeAssemblyFolder = GetBuildFolder(BuildFolder.BansheeDebugAssemblies, activePlatform);
+            else
+                bansheeAssemblyFolder = GetBuildFolder(BuildFolder.BansheeReleaseAssemblies, activePlatform);
+
+            string srcBansheeAssemblyFolder = Path.Combine(srcRoot, bansheeAssemblyFolder);
+            string destBansheeAssemblyFolder = Path.Combine(destRoot, bansheeAssemblyFolder);
+
+            Directory.CreateDirectory(destBansheeAssemblyFolder);
+            CompilerInstance ci = ScriptCompiler.CompileAsync(ScriptAssemblyType.Game, ActivePlatform, platformInfo.Debug, destBansheeAssemblyFolder);
+
+            // Copy engine assembly
+            {
+                string srcFile = Path.Combine(srcBansheeAssemblyFolder, EditorApplication.EngineAssemblyName);
+                string destFile = Path.Combine(destBansheeAssemblyFolder, EditorApplication.EngineAssemblyName);
+
+                File.Copy(srcFile, destFile);
+            }
+
+            // Copy builtin data
+            string dataFolder = GetBuildFolder(BuildFolder.Data, activePlatform);
+            string srcData = Path.Combine(srcRoot, dataFolder);
+            string destData = Path.Combine(destRoot, dataFolder);
+
+            DirectoryEx.Copy(srcData, destData);
+
+            // Copy native binaries
+            string binaryFolder = GetBuildFolder(BuildFolder.NativeBinaries, activePlatform);
+            string srcBin = Path.Combine(srcRoot, binaryFolder);
+            string destBin = destRoot;
+
+            string[] nativeBinaries = GetNativeBinaries(activePlatform);
+            foreach (var entry in nativeBinaries)
+            {
+                string srcFile = Path.Combine(srcBin, entry);
+                string destFile = Path.Combine(destBin, entry);
+
+                File.Copy(srcFile, destFile);
+            }
+
+            // Copy .NET framework assemblies
+            string frameworkAssemblyFolder = GetBuildFolder(BuildFolder.FrameworkAssemblies, activePlatform);
+            string srcFrameworkAssemblyFolder = Path.Combine(srcRoot, frameworkAssemblyFolder);
+            string destFrameworkAssemblyFolder = Path.Combine(destRoot, frameworkAssemblyFolder);
+
+            Directory.CreateDirectory(destFrameworkAssemblyFolder);
+
+            string[] frameworkAssemblies = GetFrameworkAssemblies(activePlatform);
+            foreach (var entry in frameworkAssemblies)
+            {
+                string srcFile = Path.Combine(srcFrameworkAssemblyFolder, entry + ".dll");
+                string destFile = Path.Combine(destFrameworkAssemblyFolder, entry + ".dll");
+
+                File.Copy(srcFile, destFile);
+            }
+
+            // Copy Mono
+            string monoFolder = GetBuildFolder(BuildFolder.Mono, activePlatform);
+            string srcMonoFolder = Path.Combine(srcRoot, monoFolder);
+            string destMonoFolder = Path.Combine(destRoot, monoFolder);
+
+            DirectoryEx.Copy(srcMonoFolder, destMonoFolder);
+
+            string srcExecFile = GetMainExecutable(activePlatform);
+            string destExecFile = Path.Combine(destBin, Path.GetFileName(srcExecFile));
+
+            File.Copy(srcExecFile, destExecFile);
+
+            InjectIcons(destExecFile, platformInfo);
+            PackageResources(destRoot, platformInfo);
+            CreateStartupSettings(destRoot, platformInfo);
+
+            // Wait until compile finishes
+            while (!ci.IsDone)
+                Thread.Sleep(200);
+
+            ci.Dispose();
+        }
+
+        /// <summary>
+        /// Injects icons specified in <see cref="PlatformInfo"/> into an executable at the specified path.
+        /// </summary>
+        /// <param name="filePath">Absolute path to the executable to inject icons in.</param>
+        /// <param name="info">Object containing references to icons to inject.</param>
+        private static void InjectIcons(string filePath, PlatformInfo info)
+        {
+            IntPtr infoPtr = IntPtr.Zero;
+            if (info != null)
+                infoPtr = info.GetCachedPtr();
+
+            Internal_InjectIcons(filePath, infoPtr);
+        }
+
+        /// <summary>
+        /// Finds all used resources by the build and packages them into an output folder.
+        /// </summary>
+        /// <param name="buildFolder">Absolute path to the root folder of the build. This is where the packaged resource
+        ///                           folder be placed.</param>
+        /// <param name="info">Platform information about the current build.</param>
+        private static void PackageResources(string buildFolder, PlatformInfo info)
+        {
+            IntPtr infoPtr = IntPtr.Zero;
+            if (info != null)
+                infoPtr = info.GetCachedPtr();
+
+            Internal_PackageResources(buildFolder, infoPtr);
+        }
+
+        /// <summary>
+        /// Creates a game settings asset that contains necessary data for starting up the game (for example initial scene).
+        /// </summary>
+        /// <param name="buildFolder">Absolute path to the root folder of the build. This is where the settings assets
+        ///                           will be output.</param>
+        /// <param name="info">Platform information about the current build.</param>
+        private static void CreateStartupSettings(string buildFolder, PlatformInfo info)
+        {
+            IntPtr infoPtr = IntPtr.Zero;
+            if (info != null)
+                infoPtr = info.GetCachedPtr();
+
+            Internal_CreateStartupSettings(buildFolder, infoPtr);
+        }
+
+        /// <summary>
+        /// Returns a list of .NET framework managed assemblies (without extension) to be included for the specified platform.
+        /// </summary>
+        /// <param name="type">Platform type to retrieve the list of assemblies for.</param>
+        /// <returns>A list of .NET framework managed assemblies (without extension) that will be included with the build.</returns>
+        internal static string[] GetFrameworkAssemblies(PlatformType type)
+        {
+            return Internal_GetFrameworkAssemblies(type);
+        }
+
+        /// <summary>
+        /// Returns the absolute path to the executable for the provided platform.
+        /// </summary>
+        /// <param name="type">Platform type to retrieve the executable location for.</param>
+        /// <returns>Absolute path to the executable.</returns>
+        internal static string GetMainExecutable(PlatformType type)
+        {
+            return Internal_GetMainExecutable(type);
+        }
+
+        /// <summary>
+        /// Returns a list of semicolon separated defines that will be used when compiling scripts for the specified 
+        /// platform.
+        /// </summary>
+        /// <param name="type">Platfrom type to retrieve the defines for.</param>
+        /// <returns>Semicolor separated defines that will be passed along to the script compiler.</returns>
+        internal static string GetDefines(PlatformType type)
+        {
+            return Internal_GetDefines(type);
+        }
+
+        /// <summary>
+        /// Returns an object containing all platform specific build data.
+        /// </summary>
+        /// <param name="type">Platform type to retrieve the data for.</param>
+        /// <returns>An object containing all platform specific build data</returns>
+        internal static PlatformInfo GetPlatformInfo(PlatformType type)
+        {
+            return Internal_GetPlatformInfo(type);
+        }
+
+        /// <summary>
+        /// Types of various folders used by the build manager.
+        /// </summary>
+        private enum BuildFolder // Note: Must match C++ enum ScriptBuildFolder
+        {
+            /// <summary>Absolute path to the root folder where all the prebuilt binaries and data exist.</summary>
+            SourceRoot,
+            /// <summary>Absolute path to the root folder for a build for a specific platform.</summary>
+            DestinationRoot,
+            /// <summary>Folder where native binaries are stored. Relative to root.</summary>
+            NativeBinaries,
+            /// <summary>Folder where Banshee specific debug assemblies are stored. Relative to root.</summary>
+            BansheeDebugAssemblies,
+            /// <summary>Folder where Banshee specific release assemblies are stored. Relative to root.</summary>
+            BansheeReleaseAssemblies,
+            /// <summary>Folder where .NET framework assemblies are stored. Relative to root.</summary>
+            FrameworkAssemblies,
+            /// <summary>Folder where miscelaneous Mono files are stored. Relative to root.</summary>
+            Mono,
+            /// <summary>Folder where builtin data is stored. Relative to root.</summary>
+            Data
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern PlatformType[] Internal_GetAvailablePlatforms();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern PlatformType Internal_GetActivePlatform();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetActivePlatform(PlatformType value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern PlatformInfo Internal_GetActivePlatformInfo();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern PlatformInfo Internal_GetPlatformInfo(PlatformType type);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string[] Internal_GetFrameworkAssemblies(PlatformType type);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetMainExecutable(PlatformType type);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetDefines(PlatformType type);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string[] Internal_GetNativeBinaries(PlatformType type);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetBuildFolder(BuildFolder folder, PlatformType platform);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_InjectIcons(string filePath, IntPtr info);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_PackageResources(string buildFolder, IntPtr info);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateStartupSettings(string buildFolder, IntPtr info);
+    }
+}

+ 175 - 175
Source/MBansheeEditor/EditorInput.cs

@@ -1,175 +1,175 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Companion class to <see cref="Input"/> for use in editor only. Supplies events that trigger regardless whether
-    /// game is playing or not (unlike <see cref="Input"/>) which makes them usable for editor only scripts. Pollable
-    /// input should still be used from <see cref="Input"/>.
-    /// </summary>
-    public static class EditorInput
-    {
-        public delegate void ButtonEventDelegate(ButtonEvent ev);
-        public delegate void TextInputEventDelegate(TextInputEvent ev);
-        public delegate void PointerEventDelegate(PointerEvent ev);
-
-        /// <summary>
-        /// Triggered when a button on any device is pressed.
-        /// </summary>
-        public static event ButtonEventDelegate OnButtonDown;
-
-        /// <summary>
-        /// Triggered when a button on any device is released.
-        /// </summary>
-        public static event ButtonEventDelegate OnButtonUp;
-
-        /// <summary>
-        /// Triggered when a textual character is entered.
-        /// </summary>
-        public static event TextInputEventDelegate OnCharInput;
-
-        /// <summary>
-        /// Triggered when the pointing device (mouse, touch) is moved.
-        /// </summary>
-        public static event PointerEventDelegate OnPointerMoved;
-
-        /// <summary>
-        /// Triggered when a button on the pointing device (mouse, touch) is pressed.
-        /// </summary>
-        public static event PointerEventDelegate OnPointerPressed;
-
-        /// <summary>
-        /// Triggered when a button on the pointing device (mouse, touch) is released.
-        /// </summary>
-        public static event PointerEventDelegate OnPointerReleased;
-
-        /// <summary>
-        /// Triggered when a button on the pointing device (mouse, touch) is pressed twice in rappid succession.
-        /// </summary>
-        public static event PointerEventDelegate OnPointerDoubleClick;
-
-        /// <summary>
-        /// Triggered by runtime when a button is pressed.
-        /// </summary>
-        /// <param name="code">Code of the pressed button.</param>
-        /// <param name="deviceIdx">Device the event originated from.</param>
-        private static void Internal_TriggerButtonDown(ButtonCode code, int deviceIdx)
-        {
-            ButtonEvent ev = new ButtonEvent(code, deviceIdx);
-
-            if (OnButtonDown != null)
-                OnButtonDown(ev);
-        }
-
-        /// <summary>
-        /// Triggered by runtime when a button is released.
-        /// </summary>
-        /// <param name="code">Code of the released button.</param>
-        /// <param name="deviceIdx">Device the event originated from.</param>
-        private static void Internal_TriggerButtonUp(ButtonCode code, int deviceIdx)
-        {
-            ButtonEvent ev = new ButtonEvent(code, deviceIdx);
-
-            if (OnButtonUp != null)
-                OnButtonUp(ev);
-        }
-
-        /// <summary>
-        /// Triggered by runtime when character is input.
-        /// </summary>
-        /// <param name="textChar">Code of input character.</param>
-        private static void Internal_TriggerCharInput(int textChar)
-        {
-            TextInputEvent ev = new TextInputEvent(textChar);
-
-            if (OnCharInput != null)
-                OnCharInput(ev);
-        }
-
-        /// <summary>
-        /// Triggers when some pointing device (mouse cursor, touch) moves.
-        /// </summary>
-        /// <param name="screenPos">Screen position where the input event occurred.</param>
-        /// <param name="delta">Change in movement since last sent event.</param>
-        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
-        ///                      (e.g. move events don't correspond to a button.</param>
-        /// <param name="shift">Is shift button on the keyboard being held down.</param>
-        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
-        /// <param name="alt">Is alt button on the keyboard being held down.</param>
-        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
-        ///                            move events.</param>
-        private static void Internal_TriggerPointerMove(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
-            bool ctrl, bool alt, float scrollAmount)
-        {
-            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
-
-            if (OnPointerMoved != null)
-                OnPointerMoved(ev);
-        }
-
-        /// <summary>
-        /// Triggers when some pointing device (mouse cursor, touch) button is pressed.
-        /// </summary>
-        /// <param name="screenPos">Screen position where the input event occurred.</param>
-        /// <param name="delta">Change in movement since last sent event.</param>
-        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
-        ///                      (e.g. move events don't correspond to a button.</param>
-        /// <param name="shift">Is shift button on the keyboard being held down.</param>
-        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
-        /// <param name="alt">Is alt button on the keyboard being held down.</param>
-        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
-        ///                            move events.</param>
-        private static void Internal_TriggerPointerPressed(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
-            bool ctrl, bool alt, float scrollAmount)
-        {
-            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
-
-            if (OnPointerPressed != null)
-                OnPointerPressed(ev);
-        }
-
-        /// <summary>
-        /// Triggers when some pointing device (mouse cursor, touch) button is released.
-        /// </summary>
-        /// <param name="screenPos">Screen position where the input event occurred.</param>
-        /// <param name="delta">Change in movement since last sent event.</param>
-        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
-        ///                      (e.g. move events don't correspond to a button.</param>
-        /// <param name="shift">Is shift button on the keyboard being held down.</param>
-        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
-        /// <param name="alt">Is alt button on the keyboard being held down.</param>
-        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
-        ///                            move events.</param>
-        private static void Internal_TriggerPointerReleased(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
-            bool ctrl, bool alt, float scrollAmount)
-        {
-            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
-
-            if (OnPointerReleased != null)
-                OnPointerReleased(ev);
-        }
-
-        /// <summary>
-        /// Triggers when some pointing device (mouse cursor, touch) button is double clicked.
-        /// </summary>
-        /// <param name="screenPos">Screen position where the input event occurred.</param>
-        /// <param name="delta">Change in movement since last sent event.</param>
-        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
-        ///                      (e.g. move events don't correspond to a button.</param>
-        /// <param name="shift">Is shift button on the keyboard being held down.</param>
-        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
-        /// <param name="alt">Is alt button on the keyboard being held down.</param>
-        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
-        ///                            move events.</param>
-        private static void Internal_TriggerPointerDoubleClick(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
-            bool ctrl, bool alt, float scrollAmount)
-        {
-            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
-
-            if (OnPointerDoubleClick != null)
-                OnPointerDoubleClick(ev);
-        }
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Companion class to <see cref="Input"/> for use in editor only. Supplies events that trigger regardless whether
+    /// game is playing or not (unlike <see cref="Input"/>) which makes them usable for editor only scripts. Pollable
+    /// input should still be used from <see cref="Input"/>.
+    /// </summary>
+    public static class EditorInput
+    {
+        public delegate void ButtonEventDelegate(ButtonEvent ev);
+        public delegate void TextInputEventDelegate(TextInputEvent ev);
+        public delegate void PointerEventDelegate(PointerEvent ev);
+
+        /// <summary>
+        /// Triggered when a button on any device is pressed.
+        /// </summary>
+        public static event ButtonEventDelegate OnButtonDown;
+
+        /// <summary>
+        /// Triggered when a button on any device is released.
+        /// </summary>
+        public static event ButtonEventDelegate OnButtonUp;
+
+        /// <summary>
+        /// Triggered when a textual character is entered.
+        /// </summary>
+        public static event TextInputEventDelegate OnCharInput;
+
+        /// <summary>
+        /// Triggered when the pointing device (mouse, touch) is moved.
+        /// </summary>
+        public static event PointerEventDelegate OnPointerMoved;
+
+        /// <summary>
+        /// Triggered when a button on the pointing device (mouse, touch) is pressed.
+        /// </summary>
+        public static event PointerEventDelegate OnPointerPressed;
+
+        /// <summary>
+        /// Triggered when a button on the pointing device (mouse, touch) is released.
+        /// </summary>
+        public static event PointerEventDelegate OnPointerReleased;
+
+        /// <summary>
+        /// Triggered when a button on the pointing device (mouse, touch) is pressed twice in rappid succession.
+        /// </summary>
+        public static event PointerEventDelegate OnPointerDoubleClick;
+
+        /// <summary>
+        /// Triggered by runtime when a button is pressed.
+        /// </summary>
+        /// <param name="code">Code of the pressed button.</param>
+        /// <param name="deviceIdx">Device the event originated from.</param>
+        private static void Internal_TriggerButtonDown(ButtonCode code, int deviceIdx)
+        {
+            ButtonEvent ev = new ButtonEvent(code, deviceIdx);
+
+            if (OnButtonDown != null)
+                OnButtonDown(ev);
+        }
+
+        /// <summary>
+        /// Triggered by runtime when a button is released.
+        /// </summary>
+        /// <param name="code">Code of the released button.</param>
+        /// <param name="deviceIdx">Device the event originated from.</param>
+        private static void Internal_TriggerButtonUp(ButtonCode code, int deviceIdx)
+        {
+            ButtonEvent ev = new ButtonEvent(code, deviceIdx);
+
+            if (OnButtonUp != null)
+                OnButtonUp(ev);
+        }
+
+        /// <summary>
+        /// Triggered by runtime when character is input.
+        /// </summary>
+        /// <param name="textChar">Code of input character.</param>
+        private static void Internal_TriggerCharInput(int textChar)
+        {
+            TextInputEvent ev = new TextInputEvent(textChar);
+
+            if (OnCharInput != null)
+                OnCharInput(ev);
+        }
+
+        /// <summary>
+        /// Triggers when some pointing device (mouse cursor, touch) moves.
+        /// </summary>
+        /// <param name="screenPos">Screen position where the input event occurred.</param>
+        /// <param name="delta">Change in movement since last sent event.</param>
+        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
+        ///                      (for example move events don't correspond to a button.</param>
+        /// <param name="shift">Is shift button on the keyboard being held down.</param>
+        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
+        /// <param name="alt">Is alt button on the keyboard being held down.</param>
+        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
+        ///                            move events.</param>
+        private static void Internal_TriggerPointerMove(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
+            bool ctrl, bool alt, float scrollAmount)
+        {
+            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
+
+            if (OnPointerMoved != null)
+                OnPointerMoved(ev);
+        }
+
+        /// <summary>
+        /// Triggers when some pointing device (mouse cursor, touch) button is pressed.
+        /// </summary>
+        /// <param name="screenPos">Screen position where the input event occurred.</param>
+        /// <param name="delta">Change in movement since last sent event.</param>
+        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
+        ///                      (for example move events don't correspond to a button.</param>
+        /// <param name="shift">Is shift button on the keyboard being held down.</param>
+        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
+        /// <param name="alt">Is alt button on the keyboard being held down.</param>
+        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
+        ///                            move events.</param>
+        private static void Internal_TriggerPointerPressed(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
+            bool ctrl, bool alt, float scrollAmount)
+        {
+            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
+
+            if (OnPointerPressed != null)
+                OnPointerPressed(ev);
+        }
+
+        /// <summary>
+        /// Triggers when some pointing device (mouse cursor, touch) button is released.
+        /// </summary>
+        /// <param name="screenPos">Screen position where the input event occurred.</param>
+        /// <param name="delta">Change in movement since last sent event.</param>
+        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
+        ///                      (for example move events don't correspond to a button.</param>
+        /// <param name="shift">Is shift button on the keyboard being held down.</param>
+        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
+        /// <param name="alt">Is alt button on the keyboard being held down.</param>
+        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
+        ///                            move events.</param>
+        private static void Internal_TriggerPointerReleased(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
+            bool ctrl, bool alt, float scrollAmount)
+        {
+            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
+
+            if (OnPointerReleased != null)
+                OnPointerReleased(ev);
+        }
+
+        /// <summary>
+        /// Triggers when some pointing device (mouse cursor, touch) button is double clicked.
+        /// </summary>
+        /// <param name="screenPos">Screen position where the input event occurred.</param>
+        /// <param name="delta">Change in movement since last sent event.</param>
+        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
+        ///                      (for example move events don't correspond to a button.</param>
+        /// <param name="shift">Is shift button on the keyboard being held down.</param>
+        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
+        /// <param name="alt">Is alt button on the keyboard being held down.</param>
+        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
+        ///                            move events.</param>
+        private static void Internal_TriggerPointerDoubleClick(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
+            bool ctrl, bool alt, float scrollAmount)
+        {
+            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
+
+            if (OnPointerDoubleClick != null)
+                OnPointerDoubleClick(ev);
+        }
+    }
+}

+ 2 - 2
Source/MBansheeEditor/Library/LibraryGUIEntry.cs

@@ -311,7 +311,7 @@ namespace BansheeEditor
         }
 
         /// <summary>
-        /// Clears the underlay GUI element (e.g. ping, hover, select).
+        /// Clears the underlay GUI element (for example ping, hover, select).
         /// </summary>
         private void ClearUnderlay()
         {
@@ -325,7 +325,7 @@ namespace BansheeEditor
         }
 
         /// <summary>
-        /// Creates a GUI elements that may be used for underlay effects (e.g. ping, hover, select).
+        /// Creates a GUI elements that may be used for underlay effects (for example ping, hover, select).
         /// </summary>
         private void CreateUnderlay()
         {

+ 69 - 69
Source/MBansheeEditor/MenuItem.cs

@@ -1,69 +1,69 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Adds an entry to the main menu bar. Clicking on that entry will trigger the method the attribute is attached to.
-    /// The method must be static, have no parameters or return values otherwise the attribute will be ignored.
-    /// </summary>
-    [AttributeUsage(AttributeTargets.Method)]
-    public sealed class MenuItem : Attribute
-    {
-        /// <summary>
-        /// Creates a new menu item attribute with a shortcut. Pressing the shortcut key or selecting the item in the menu
-        /// will trigger the menu item callback.
-        /// </summary>
-        /// <param name="path">Path that determines where in the menu to add the element. All path elements must be 
-        ///                    separated by /, e.g. "View/Toolbars/Find"</param>
-        /// <param name="shortcutModifier">Optional shortcut modifier that needs to be pressed along with the shortcut 
-        ///                                button in order to trigger the shortcut.</param>
-        /// <param name="shortcutKey">Shortcut key that will trigger the shortcut.</param>
-        /// <param name="priority">Priority determines the position of the menu item relative to its siblings.
-        ///                        Higher priority means it will be placed earlier in the menu.</param>
-        /// <param name="separator">Determines should a separator be inserted just before this element.</param>
-        /// <param name="contextCallback">Name of a method that returns a boolean determining whether the menu item callback
-        ///                               is allowed to trigger. This is useful if menu items are only valid in specific
-        ///                               situations (e.g. a scene object must be selected). The method must be static,
-        ///                               return a boolean value, accept no parameters and be in the same class as
-        ///                               the method this attribute is attached to.</param>
-        public MenuItem(string path, ButtonModifier shortcutModifier, ButtonCode shortcutKey, int priority = 0, 
-            bool separator = false, string contextCallback = null)
-        {
-            this.path = path;
-            this.shortcut = new ShortcutKey(shortcutModifier, shortcutKey);
-            this.priority = priority;
-            this.separator = separator;
-            this.contextCallback = contextCallback;
-        }
-
-        /// <summary>
-        /// Creates a new menu item attribute. Selecting the item in the menu will trigger the menu item callback.
-        /// </summary>
-        /// <param name="path">Path that determines where in the menu to add the element. All path elements must be 
-        ///                    separated by /, e.g. "View/Toolbars/Find"</param>
-        /// <param name="priority">Priority determines the position of the menu item relative to its siblings.
-        ///                        Higher priority means it will be placed earlier in the menu.</param>
-        /// <param name="separator">Determines should a separator be inserted just before this element.</param>
-        /// <param name="contextCallback">Name of a method that returns a boolean determining whether the menu item callback
-        ///                               is allowed to trigger. This is useful if menu items are only valid in specific
-        ///                               situations (e.g. a scene object must be selected). The method must be static,
-        ///                               return a boolean value, accept no parameters and be in the same class as
-        ///                               the method this attribute is attached to.</param>
-        public MenuItem(string path, int priority = 0, bool separator = false, string contextCallback = null)
-        {
-            this.path = path;
-            this.priority = priority;
-            this.separator = separator;
-            this.contextCallback = contextCallback;
-        }
-
-        private string path;
-        private ShortcutKey shortcut;
-        private int priority;
-        private bool separator;
-        private string contextCallback;
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Adds an entry to the main menu bar. Clicking on that entry will trigger the method the attribute is attached to.
+    /// The method must be static, have no parameters or return values otherwise the attribute will be ignored.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Method)]
+    public sealed class MenuItem : Attribute
+    {
+        /// <summary>
+        /// Creates a new menu item attribute with a shortcut. Pressing the shortcut key or selecting the item in the menu
+        /// will trigger the menu item callback.
+        /// </summary>
+        /// <param name="path">Path that determines where in the menu to add the element. All path elements must be 
+        ///                    separated by /, for example "View/Toolbars/Find".</param>
+        /// <param name="shortcutModifier">Optional shortcut modifier that needs to be pressed along with the shortcut 
+        ///                                button in order to trigger the shortcut.</param>
+        /// <param name="shortcutKey">Shortcut key that will trigger the shortcut.</param>
+        /// <param name="priority">Priority determines the position of the menu item relative to its siblings.
+        ///                        Higher priority means it will be placed earlier in the menu.</param>
+        /// <param name="separator">Determines should a separator be inserted just before this element.</param>
+        /// <param name="contextCallback">Name of a method that returns a boolean determining whether the menu item callback
+        ///                               is allowed to trigger. This is useful if menu items are only valid in specific
+        ///                               situations (for example a scene object must be selected). The method must be
+        ///                               static, return a boolean value, accept no parameters and be in the same class as
+        ///                               the method this attribute is attached to.</param>
+        public MenuItem(string path, ButtonModifier shortcutModifier, ButtonCode shortcutKey, int priority = 0, 
+            bool separator = false, string contextCallback = null)
+        {
+            this.path = path;
+            this.shortcut = new ShortcutKey(shortcutModifier, shortcutKey);
+            this.priority = priority;
+            this.separator = separator;
+            this.contextCallback = contextCallback;
+        }
+
+        /// <summary>
+        /// Creates a new menu item attribute. Selecting the item in the menu will trigger the menu item callback.
+        /// </summary>
+        /// <param name="path">Path that determines where in the menu to add the element. All path elements must be 
+        ///                    separated by /, for example "View/Toolbars/Find".</param>
+        /// <param name="priority">Priority determines the position of the menu item relative to its siblings.
+        ///                        Higher priority means it will be placed earlier in the menu.</param>
+        /// <param name="separator">Determines should a separator be inserted just before this element.</param>
+        /// <param name="contextCallback">Name of a method that returns a boolean determining whether the menu item callback
+        ///                               is allowed to trigger. This is useful if menu items are only valid in specific
+        ///                               situations (for example a scene object must be selected). The method must be
+        ///                               static, return a boolean value, accept no parameters and be in the same class as
+        ///                               the method this attribute is attached to.</param>
+        public MenuItem(string path, int priority = 0, bool separator = false, string contextCallback = null)
+        {
+            this.path = path;
+            this.priority = priority;
+            this.separator = separator;
+            this.contextCallback = contextCallback;
+        }
+
+        private string path;
+        private ShortcutKey shortcut;
+        private int priority;
+        private bool separator;
+        private string contextCallback;
+    }
+}

+ 574 - 574
Source/MBansheeEditor/ProjectLibrary.cs

@@ -1,574 +1,574 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Runtime.CompilerServices;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// The primary location for interacting with all the resources in the current project. A complete hierarchy of 
-    /// resources is provided which can be interacted with by importing new ones, deleting them, moving, renaming and similar.
-    /// </summary>
-    public sealed class ProjectLibrary : ScriptObject
-    {
-        /// <summary>
-        /// Root entry of the project library, referencing the top level resources folder.
-        /// </summary>
-        public static DirectoryEntry Root { get { return Internal_GetRoot(); } }
-
-        /// <summary>
-        /// Absolute path to the current project's project library resource folder.
-        /// </summary>
-        public static string ResourceFolder { get { return Internal_GetResourceFolder(); } }
-
-        /// <summary>
-        /// Triggered when a new entry is added to the project library. Provided path relative to the project library 
-        /// resources folder.
-        /// </summary>
-        public static event Action<string> OnEntryAdded;
-
-        /// <summary>
-        /// Triggered when an entry is removed from the project library. Provided path relative to the project library 
-        /// resources folder.
-        /// </summary>
-        public static event Action<string> OnEntryRemoved;
-
-        /// <summary>
-        /// Triggered when an entry is (re)imported in the project library. Provided path relative to the project library 
-        /// resources folder.
-        /// </summary>
-        public static event Action<string> OnEntryImported;
-
-        /// <summary>
-        /// Checks wheher an asset import is currently in progress.
-        /// </summary>
-        internal static bool ImportInProgress { get { return importInProgress; } }
-
-        private static HashSet<string> queuedForImport = new HashSet<string>();
-        private static int numImportedFiles;
-        private static int totalFilesToImport;
-        private static bool importInProgress;
-
-        private const float TIME_SLICE_SECONDS = 0.030f;
-
-        /// <summary>
-        /// Checks the project library folder for any modifications and reimports the required resources.
-        /// </summary>
-        /// <param name="synchronous">If true this method will block until the project library has done refreshing, 
-        ///                           otherwise the refresh will happen over the course of this and next frames.</param>
-        public static void Refresh(bool synchronous = false)
-        {
-            string[] modifiedPaths = Internal_Refresh(ResourceFolder, synchronous);
-
-            if (!synchronous)
-            {
-                foreach (var modifiedPath in modifiedPaths)
-                {
-                    if (queuedForImport.Add(modifiedPath))
-                        totalFilesToImport++;
-                }
-            }
-            else
-            {
-                foreach (var path in queuedForImport)
-                    Internal_Refresh(path, true);
-
-                queuedForImport.Clear();
-                numImportedFiles = 0;
-                totalFilesToImport = 0;
-            }
-        }
-
-        /// <summary>
-        /// Checks the specified folder for any modifications and reimports the required resources.
-        /// </summary>
-        /// <param name="path">Path to a file or folder to refresh. Relative to the project library resources folder or 
-        ///                    absolute.</param>
-        public static void Refresh(string path)
-        {
-            string[] modifiedPaths = Internal_Refresh(path, false);
-            foreach (var modifiedPath in modifiedPaths)
-            {
-                if (queuedForImport.Add(modifiedPath))
-                    totalFilesToImport++;
-            }
-        }
-
-        /// <summary>
-        /// Registers a new resource in the library.
-        /// </summary>
-        /// <param name="resource">Resource instance to add to the library. A copy of the resource will be saved at the 
-        ///                        provided path.</param>
-        /// <param name="path">Path where where to store the resource. Absolute or relative to the resources folder.</param>
-        public static void Create(Resource resource, string path)
-        {
-            Internal_Create(resource, path);
-        }
-
-        /// <summary>
-        /// Updates a resource that is already in the library.
-        /// </summary>
-        /// <param name="resource">Resource to save.</param>
-        public static void Save(Resource resource)
-        {
-            Internal_Save(resource);
-        }
-
-        /// <summary>
-        /// Loads a resource from the project library.
-        /// </summary>
-        /// <typeparam name="T">Type of the resource to load.</typeparam>
-        /// <param name="path">Path of the resource to load. Absolute or relative to the resources folder. If a 
-        ///                    sub-resource within a file is needed, append the name of the subresource to the path (e.g. 
-        ///                    mymesh.fbx/my_animation).</param>
-        /// <returns>Instance of the loaded resource, or null if not found.</returns>
-        public static T Load<T>(string path) where T : Resource
-        {
-            return (T) Internal_Load(path);
-        }
-
-        /// <summary>
-        /// Triggers a reimport of a resource using the provided import options, if needed.
-        /// </summary>
-        /// <param name="path">Path to the resource to reimport, absolute or relative to resources folder.</param>
-        /// <param name="options">ptional import options to use when importing the resource. Caller must ensure the import
-        ///                       options are of the correct type for the resource in question. If null is provided default 
-        ///                       import options are used.</param>
-        /// <param name="force">Should the resource be reimported even if no changes are detected.</param>
-        public static void Reimport(string path, ImportOptions options = null, bool force = false)
-        {
-            Internal_Reimport(path, options, force);
-        }
-
-        /// <summary>
-        /// Checks does the project library contain a file or folder at the specified path.
-        /// </summary>
-        /// <param name="path">Path to the file/folder to check, absolute or relative to resources folder.</param>
-        /// <returns>True if the element exists, false otherwise.</returns>
-        public static bool Exists(string path)
-        {
-            return GetEntry(path) != null;
-        }
-
-        /// <summary>
-        /// Attempts to locate a library entry that describes a file or a folder in the project library.
-        /// </summary>
-        /// <param name="path">Path to the entry to retrieve, absolute or relative to resources folder.</param>
-        /// <returns>Library entry if found, null otherwise. This object can become invalid on the next library refresh
-        ///          and you are not meant to hold a permanent reference to it.</returns>
-        public static LibraryEntry GetEntry(string path)
-        {
-            return Internal_GetEntry(path);
-        }
-
-        /// <summary>
-        /// Checks whether the provided path points to a sub-resource. Sub-resource is any resource that is not the
-        /// primary resource in the file.
-        /// </summary>
-        /// <param name="path">Path to the entry, absolute or relative to resources folder.</param>
-        /// <returns>True if the path is a sub-resource, false otherwise.</returns>
-        public static bool IsSubresource(string path)
-        {
-            return Internal_IsSubresource(path);
-        }
-
-        /// <summary>
-        /// Attempts to locate meta-data for a resource at the specified path.
-        /// </summary>
-        /// <param name="path">Path to the entry to retrieve, absolute or relative to resources folder. If a sub-resource 
-        ///                    within a file is needed, append the name of the subresource to the path (e.g. 
-        ///                    mymesh.fbx/my_animation).</param>
-        /// <returns>Resource meta-data if the resource was found, null otherwise.</returns>
-        public static ResourceMeta GetMeta(string path)
-        {
-            return Internal_GetMeta(path);
-        }
-
-        /// <summary>
-        /// Searches the library for a pattern and returns all entries matching it.
-        /// </summary>
-        /// <param name="pattern">Pattern to search for. Use wildcard * to match any character(s).</param>
-        /// <param name="types">Type of resources to search for. If null all entries will be searched.</param>
-        /// <returns>A set of entries matching the pattern. These objects can become invalid on the next library refresh
-        ///          and you are not meant to hold a permanent reference to them.</returns>
-        public static LibraryEntry[] Search(string pattern, ResourceType[] types = null)
-        {
-            return Internal_Search(pattern, types);
-        }
-
-        /// <summary>
-        /// Returns a path to a resource stored in the project library.
-        /// </summary>
-        /// <param name="resource">Resource to find the path for.</param>
-        /// <returns>Path to relative to the project library resources folder if resource was found, null otherwise.
-        ///          </returns>
-        public static string GetPath(Resource resource)
-        {
-            return Internal_GetPath(resource);
-        }
-
-        /// <summary>
-        /// Returns a path to a resource with the specified UUID stored in the project library.
-        /// </summary>
-        /// <param name="uuid">Unique identifier of the resources to retrieve the path of.</param>
-        /// <returns>Path to relative to the project library resources folder if resource was found, null otherwise.
-        ///          </returns>
-        public static string GetPath(string uuid)
-        {
-            return Internal_GetPathFromUUID(uuid);
-        }
-
-        /// <summary>
-        /// Deletes a resource in the project library.
-        /// </summary>
-        /// <param name="path">Path to the entry to delete, absolute or relative to resources folder.</param>
-        public static void Delete(string path)
-        {
-            Internal_Delete(path);
-        }
-
-        /// <summary>
-        /// Creates a new folder in the library.
-        /// </summary>
-        /// <param name="path">Path of the folder to create. Absolute or relative to the resources folder.</param>
-        public static void CreateFolder(string path)
-        {
-            Internal_CreateFolder(path);
-        }
-
-        /// <summary>
-        /// Renames an entry in the project library.
-        /// </summary>
-        /// <param name="path">Path of the entry to rename, absolute or relative to resources folder.</param>
-        /// <param name="name">New name of the entry with an extension.</param>
-        /// <param name="overwrite">Determines should the entry be deleted if one with the provided name already exists. If
-        ///                         this is false and an entry already exists, no rename operation will be performed.</param>
-        public static void Rename(string path, string name, bool overwrite = false)
-        {
-            Internal_Rename(path, name, false);
-        }
-
-        /// <summary>
-        /// Moves an entry in the project library from one path to another.
-        /// </summary>
-        /// <param name="oldPath">Source path of the entry, absolute or relative to resources folder.</param>
-        /// <param name="newPath">Destination path of the entry, absolute or relative to resources folder.</param>
-        /// <param name="overwrite">Determines should the entry be deleted if one at the destination path already exists. If
-        ///                         this is false and an entry already exists, no move operation will be performed.</param>
-        public static void Move(string oldPath, string newPath, bool overwrite = false)
-        {
-            Internal_Move(oldPath, newPath, overwrite);
-        }
-
-        /// <summary>
-        /// Copies an entry in the project library from one path to another.
-        /// </summary>
-        /// <param name="source">Source path of the entry, absolute or relative to resources folder.</param>
-        /// <param name="destination">Destination path of the entry, absolute or relative to resources folder.</param>
-        /// <param name="overwrite">Determines should the entry be deleted if one at the destination path already exists. If
-        ///                         this is false and an entry already exists, no copy operation will be performed.</param>
-        public static void Copy(string source, string destination, bool overwrite = false)
-        {
-            Internal_Copy(source, destination, overwrite);
-        }
-
-        /// <summary>
-        /// Controls should a resource be included an a build. All dependant resources will also be included.
-        /// </summary>
-        /// <param name="path">Path of the resource to include, absolute or relative to resources folder.</param>
-        /// <param name="include">True if it should be included, false otherwise.</param>
-        public static void SetIncludeInBuild(string path, bool include)
-        {
-            Internal_SetIncludeInBuild(path, include);
-        }
-
-        /// <summary>
-        /// Triggers reimport for queued resource. Should be called once per frame.
-        /// </summary>
-        internal static void Update()
-        {
-            if (queuedForImport.Count > 0)
-            {
-                // Skip first frame to get the progress bar a chance to show up
-                if (importInProgress)
-                {
-                    UInt64 start = Time.Precise;
-                    List<string> toRemove = new List<string>();
-
-                    foreach (var entry in queuedForImport)
-                    {
-                        Internal_Refresh(entry, true);
-                        toRemove.Add(entry);
-                        numImportedFiles++;
-
-                        UInt64 end = Time.Precise;
-                        UInt64 elapsed = end - start;
-
-                        float elapsedSeconds = elapsed * Time.MicroToSecond;
-                        if (elapsedSeconds > TIME_SLICE_SECONDS)
-                            break;
-                    }
-
-                    foreach (var entry in toRemove)
-                        queuedForImport.Remove(entry);
-                }
-
-                if (queuedForImport.Count == 0)
-                {
-                    numImportedFiles = 0;
-                    totalFilesToImport = 0;
-
-                    ProgressBar.Hide();
-                }
-                else
-                {
-                    IEnumerator<string> enumerator = queuedForImport.GetEnumerator();
-                    enumerator.MoveNext();
-
-                    string displayName = enumerator.Current;
-                    displayName = displayName.Replace("\\", "\\\\");
-
-                    if (displayName.Length > 60)
-                    {
-                        displayName = displayName.Remove(0, displayName.Length - 60);
-                        displayName = "..." + displayName;
-                    }
-
-                    float pct = numImportedFiles / (float)totalFilesToImport;
-                    ProgressBar.Show("Importing (" + numImportedFiles + "/" + totalFilesToImport + ")", displayName, pct);
-                }
-
-                importInProgress = true;
-            }
-            else
-                importInProgress = false;
-        }
-
-        /// <summary>
-        /// Triggered internally by the runtime when a new entry is added to the project library.
-        /// </summary>
-        /// <param name="path">Path relative to the project library resources folder.</param>
-        private static void Internal_DoOnEntryAdded(string path)
-        {
-            if (OnEntryAdded != null)
-                OnEntryAdded(path);
-        }
-
-        /// <summary>
-        /// Triggered internally by the runtime when an entry is removed from the project library.
-        /// </summary>
-        /// <param name="path">Path relative to the project library resources folder.</param>
-        private static void Internal_DoOnEntryRemoved(string path)
-        {
-            if (OnEntryRemoved != null)
-                OnEntryRemoved(path);
-        }
-
-        /// <summary>
-        /// Triggered internally by the runtime when an entry is (re)imported in the project library.
-        /// </summary>
-        /// <param name="path">Path relative to the project library resources folder.</param>
-        private static void Internal_DoOnEntryImported(string path)
-        {
-            if (OnEntryImported != null)
-                OnEntryImported(path);
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string[] Internal_Refresh(string path, bool import);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_Create(Resource resource, string path);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern Resource Internal_Load(string path);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_Save(Resource resource);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern DirectoryEntry Internal_GetRoot();
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_IsSubresource(string path);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_Reimport(string path, ImportOptions options, bool force);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern LibraryEntry Internal_GetEntry(string path);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern ResourceMeta Internal_GetMeta(string path);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern LibraryEntry[] Internal_Search(string path, ResourceType[] types);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetPath(Resource resource);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetPathFromUUID(string uuid);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_Delete(string path);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateFolder(string path);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_Rename(string path, string name, bool overwrite);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_Move(string oldPath, string newPath, bool overwrite);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_Copy(string source, string destination, bool overwrite);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetResourceFolder();
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetIncludeInBuild(string path, bool force);
-    }
-
-    /// <summary>
-    /// Type of project library entries.
-    /// </summary>
-    public enum LibraryEntryType // Note: Must match the C++ enum ProjectLibrary::LibraryEntryType
-    {
-        File, Directory
-    }
-
-    /// <summary>
-    /// Type of resources supported by the project library.
-    /// </summary>
-    public enum ResourceType // Note: Must match the C++ enum ScriptResourceType
-    {
-        Texture, SpriteTexture, Mesh, Font, Shader, ShaderInclude, Material, Prefab, PlainText, 
-        ScriptCode, StringTable, GUISkin, PhysicsMaterial, PhysicsMesh, Undefined
-    }
-
-    /// <summary>
-    /// A generic project library entry that may be a file or a folder.
-    /// </summary>
-    public class LibraryEntry : ScriptObject
-    {
-        /// <summary>
-        /// Path of the library entry, relative to the project library resources folder.
-        /// </summary>
-        public string Path { get { return Internal_GetPath(mCachedPtr); } }
-
-        /// <summary>
-        /// Name of the library entry.
-        /// </summary>
-        public string Name { get { return Internal_GetName(mCachedPtr); } }
-
-        /// <summary>
-        /// Type of the library entry.
-        /// </summary>
-        public LibraryEntryType Type { get { return Internal_GetType(mCachedPtr); } }
-
-        /// <summary>
-        /// Directory entry that contains this entry. This may be null for the root entry.
-        /// </summary>
-        public DirectoryEntry Parent { get { return Internal_GetParent(mCachedPtr); } }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetPath(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetName(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern LibraryEntryType Internal_GetType(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern DirectoryEntry Internal_GetParent(IntPtr thisPtr);
-    }
-
-    /// <summary>
-    /// A project library entry representing a directory that contains other entries.
-    /// </summary>
-    public class DirectoryEntry : LibraryEntry
-    {
-        /// <summary>
-        /// A set of entries contained in this entry.
-        /// </summary>
-        public LibraryEntry[] Children { get { return Internal_GetChildren(mCachedPtr); } }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern LibraryEntry[] Internal_GetChildren(IntPtr thisPtr);
-    }
-
-    /// <summary>
-    /// A library entry representing a file.
-    /// </summary>
-    public class FileEntry : LibraryEntry
-    {
-        /// <summary>
-        /// Import options used for importing the resources in the file.
-        /// </summary>
-        public ImportOptions Options { get { return Internal_GetImportOptions(mCachedPtr); } }
-
-        /// <summary>
-        /// Returns meta-data for all resources part of the file represented by this object.
-        /// </summary>
-        public ResourceMeta[] ResourceMetas { get { return Internal_GetResourceMetas(mCachedPtr); } }
-
-        /// <summary>
-        /// Determines will the resources in the file be included in the project build.
-        /// </summary>
-        public bool IncludeInBuild { get { return Internal_GetIncludeInBuild(mCachedPtr); } }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern ImportOptions Internal_GetImportOptions(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern ResourceMeta[] Internal_GetResourceMetas(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_GetIncludeInBuild(IntPtr thisPtr);
-    }
-
-    /// <summary>
-    /// Contains meta-data for a resource in the ProjectLibrary.
-    /// </summary>
-    public class ResourceMeta : ScriptObject
-    {
-        /// <summary>
-        /// Unique identifier of the resource.
-        /// </summary>
-        public string UUID { get { return Internal_GetUUID(mCachedPtr); } }
-
-        /// <summary>
-        /// Returns a name of the subresources. Each resource within a file has a unique name.
-        /// </summary>
-        public string SubresourceName { get { return Internal_GetSubresourceName(mCachedPtr); } }
-
-        /// <summary>
-        /// Custom icon for the resource to display in the editor, if the resource has one.
-        /// </summary>
-        public Texture2D Icon { get { return Internal_GetIcon(mCachedPtr); } }
-
-        /// <summary>
-        /// Type of the resource referenced by this entry.
-        /// </summary>
-        public ResourceType ResType { get { return Internal_GetResourceType(mCachedPtr); } }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetUUID(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern string Internal_GetSubresourceName(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern Texture2D Internal_GetIcon(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern ResourceType Internal_GetResourceType(IntPtr thisPtr);
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// The primary location for interacting with all the resources in the current project. A complete hierarchy of 
+    /// resources is provided which can be interacted with by importing new ones, deleting them, moving, renaming and similar.
+    /// </summary>
+    public sealed class ProjectLibrary : ScriptObject
+    {
+        /// <summary>
+        /// Root entry of the project library, referencing the top level resources folder.
+        /// </summary>
+        public static DirectoryEntry Root { get { return Internal_GetRoot(); } }
+
+        /// <summary>
+        /// Absolute path to the current project's project library resource folder.
+        /// </summary>
+        public static string ResourceFolder { get { return Internal_GetResourceFolder(); } }
+
+        /// <summary>
+        /// Triggered when a new entry is added to the project library. Provided path relative to the project library 
+        /// resources folder.
+        /// </summary>
+        public static event Action<string> OnEntryAdded;
+
+        /// <summary>
+        /// Triggered when an entry is removed from the project library. Provided path relative to the project library 
+        /// resources folder.
+        /// </summary>
+        public static event Action<string> OnEntryRemoved;
+
+        /// <summary>
+        /// Triggered when an entry is (re)imported in the project library. Provided path relative to the project library 
+        /// resources folder.
+        /// </summary>
+        public static event Action<string> OnEntryImported;
+
+        /// <summary>
+        /// Checks wheher an asset import is currently in progress.
+        /// </summary>
+        internal static bool ImportInProgress { get { return importInProgress; } }
+
+        private static HashSet<string> queuedForImport = new HashSet<string>();
+        private static int numImportedFiles;
+        private static int totalFilesToImport;
+        private static bool importInProgress;
+
+        private const float TIME_SLICE_SECONDS = 0.030f;
+
+        /// <summary>
+        /// Checks the project library folder for any modifications and reimports the required resources.
+        /// </summary>
+        /// <param name="synchronous">If true this method will block until the project library has done refreshing, 
+        ///                           otherwise the refresh will happen over the course of this and next frames.</param>
+        public static void Refresh(bool synchronous = false)
+        {
+            string[] modifiedPaths = Internal_Refresh(ResourceFolder, synchronous);
+
+            if (!synchronous)
+            {
+                foreach (var modifiedPath in modifiedPaths)
+                {
+                    if (queuedForImport.Add(modifiedPath))
+                        totalFilesToImport++;
+                }
+            }
+            else
+            {
+                foreach (var path in queuedForImport)
+                    Internal_Refresh(path, true);
+
+                queuedForImport.Clear();
+                numImportedFiles = 0;
+                totalFilesToImport = 0;
+            }
+        }
+
+        /// <summary>
+        /// Checks the specified folder for any modifications and reimports the required resources.
+        /// </summary>
+        /// <param name="path">Path to a file or folder to refresh. Relative to the project library resources folder or 
+        ///                    absolute.</param>
+        public static void Refresh(string path)
+        {
+            string[] modifiedPaths = Internal_Refresh(path, false);
+            foreach (var modifiedPath in modifiedPaths)
+            {
+                if (queuedForImport.Add(modifiedPath))
+                    totalFilesToImport++;
+            }
+        }
+
+        /// <summary>
+        /// Registers a new resource in the library.
+        /// </summary>
+        /// <param name="resource">Resource instance to add to the library. A copy of the resource will be saved at the 
+        ///                        provided path.</param>
+        /// <param name="path">Path where where to store the resource. Absolute or relative to the resources folder.</param>
+        public static void Create(Resource resource, string path)
+        {
+            Internal_Create(resource, path);
+        }
+
+        /// <summary>
+        /// Updates a resource that is already in the library.
+        /// </summary>
+        /// <param name="resource">Resource to save.</param>
+        public static void Save(Resource resource)
+        {
+            Internal_Save(resource);
+        }
+
+        /// <summary>
+        /// Loads a resource from the project library.
+        /// </summary>
+        /// <typeparam name="T">Type of the resource to load.</typeparam>
+        /// <param name="path">Path of the resource to load. Absolute or relative to the resources folder. If a 
+        ///                    sub-resource within a file is needed, append the name of the subresource to the path ( 
+        ///                    for example mymesh.fbx/my_animation).</param>
+        /// <returns>Instance of the loaded resource, or null if not found.</returns>
+        public static T Load<T>(string path) where T : Resource
+        {
+            return (T) Internal_Load(path);
+        }
+
+        /// <summary>
+        /// Triggers a reimport of a resource using the provided import options, if needed.
+        /// </summary>
+        /// <param name="path">Path to the resource to reimport, absolute or relative to resources folder.</param>
+        /// <param name="options">ptional import options to use when importing the resource. Caller must ensure the import
+        ///                       options are of the correct type for the resource in question. If null is provided default 
+        ///                       import options are used.</param>
+        /// <param name="force">Should the resource be reimported even if no changes are detected.</param>
+        public static void Reimport(string path, ImportOptions options = null, bool force = false)
+        {
+            Internal_Reimport(path, options, force);
+        }
+
+        /// <summary>
+        /// Checks does the project library contain a file or folder at the specified path.
+        /// </summary>
+        /// <param name="path">Path to the file/folder to check, absolute or relative to resources folder.</param>
+        /// <returns>True if the element exists, false otherwise.</returns>
+        public static bool Exists(string path)
+        {
+            return GetEntry(path) != null;
+        }
+
+        /// <summary>
+        /// Attempts to locate a library entry that describes a file or a folder in the project library.
+        /// </summary>
+        /// <param name="path">Path to the entry to retrieve, absolute or relative to resources folder.</param>
+        /// <returns>Library entry if found, null otherwise. This object can become invalid on the next library refresh
+        ///          and you are not meant to hold a permanent reference to it.</returns>
+        public static LibraryEntry GetEntry(string path)
+        {
+            return Internal_GetEntry(path);
+        }
+
+        /// <summary>
+        /// Checks whether the provided path points to a sub-resource. Sub-resource is any resource that is not the
+        /// primary resource in the file.
+        /// </summary>
+        /// <param name="path">Path to the entry, absolute or relative to resources folder.</param>
+        /// <returns>True if the path is a sub-resource, false otherwise.</returns>
+        public static bool IsSubresource(string path)
+        {
+            return Internal_IsSubresource(path);
+        }
+
+        /// <summary>
+        /// Attempts to locate meta-data for a resource at the specified path.
+        /// </summary>
+        /// <param name="path">Path to the entry to retrieve, absolute or relative to resources folder. If a sub-resource 
+        ///                    within a file is needed, append the name of the subresource to the path (for example
+        ///                    mymesh.fbx/my_animation).</param>
+        /// <returns>Resource meta-data if the resource was found, null otherwise.</returns>
+        public static ResourceMeta GetMeta(string path)
+        {
+            return Internal_GetMeta(path);
+        }
+
+        /// <summary>
+        /// Searches the library for a pattern and returns all entries matching it.
+        /// </summary>
+        /// <param name="pattern">Pattern to search for. Use wildcard * to match any character(s).</param>
+        /// <param name="types">Type of resources to search for. If null all entries will be searched.</param>
+        /// <returns>A set of entries matching the pattern. These objects can become invalid on the next library refresh
+        ///          and you are not meant to hold a permanent reference to them.</returns>
+        public static LibraryEntry[] Search(string pattern, ResourceType[] types = null)
+        {
+            return Internal_Search(pattern, types);
+        }
+
+        /// <summary>
+        /// Returns a path to a resource stored in the project library.
+        /// </summary>
+        /// <param name="resource">Resource to find the path for.</param>
+        /// <returns>Path to relative to the project library resources folder if resource was found, null otherwise.
+        ///          </returns>
+        public static string GetPath(Resource resource)
+        {
+            return Internal_GetPath(resource);
+        }
+
+        /// <summary>
+        /// Returns a path to a resource with the specified UUID stored in the project library.
+        /// </summary>
+        /// <param name="uuid">Unique identifier of the resources to retrieve the path of.</param>
+        /// <returns>Path to relative to the project library resources folder if resource was found, null otherwise.
+        ///          </returns>
+        public static string GetPath(string uuid)
+        {
+            return Internal_GetPathFromUUID(uuid);
+        }
+
+        /// <summary>
+        /// Deletes a resource in the project library.
+        /// </summary>
+        /// <param name="path">Path to the entry to delete, absolute or relative to resources folder.</param>
+        public static void Delete(string path)
+        {
+            Internal_Delete(path);
+        }
+
+        /// <summary>
+        /// Creates a new folder in the library.
+        /// </summary>
+        /// <param name="path">Path of the folder to create. Absolute or relative to the resources folder.</param>
+        public static void CreateFolder(string path)
+        {
+            Internal_CreateFolder(path);
+        }
+
+        /// <summary>
+        /// Renames an entry in the project library.
+        /// </summary>
+        /// <param name="path">Path of the entry to rename, absolute or relative to resources folder.</param>
+        /// <param name="name">New name of the entry with an extension.</param>
+        /// <param name="overwrite">Determines should the entry be deleted if one with the provided name already exists. If
+        ///                         this is false and an entry already exists, no rename operation will be performed.</param>
+        public static void Rename(string path, string name, bool overwrite = false)
+        {
+            Internal_Rename(path, name, false);
+        }
+
+        /// <summary>
+        /// Moves an entry in the project library from one path to another.
+        /// </summary>
+        /// <param name="oldPath">Source path of the entry, absolute or relative to resources folder.</param>
+        /// <param name="newPath">Destination path of the entry, absolute or relative to resources folder.</param>
+        /// <param name="overwrite">Determines should the entry be deleted if one at the destination path already exists. If
+        ///                         this is false and an entry already exists, no move operation will be performed.</param>
+        public static void Move(string oldPath, string newPath, bool overwrite = false)
+        {
+            Internal_Move(oldPath, newPath, overwrite);
+        }
+
+        /// <summary>
+        /// Copies an entry in the project library from one path to another.
+        /// </summary>
+        /// <param name="source">Source path of the entry, absolute or relative to resources folder.</param>
+        /// <param name="destination">Destination path of the entry, absolute or relative to resources folder.</param>
+        /// <param name="overwrite">Determines should the entry be deleted if one at the destination path already exists. If
+        ///                         this is false and an entry already exists, no copy operation will be performed.</param>
+        public static void Copy(string source, string destination, bool overwrite = false)
+        {
+            Internal_Copy(source, destination, overwrite);
+        }
+
+        /// <summary>
+        /// Controls should a resource be included an a build. All dependant resources will also be included.
+        /// </summary>
+        /// <param name="path">Path of the resource to include, absolute or relative to resources folder.</param>
+        /// <param name="include">True if it should be included, false otherwise.</param>
+        public static void SetIncludeInBuild(string path, bool include)
+        {
+            Internal_SetIncludeInBuild(path, include);
+        }
+
+        /// <summary>
+        /// Triggers reimport for queued resource. Should be called once per frame.
+        /// </summary>
+        internal static void Update()
+        {
+            if (queuedForImport.Count > 0)
+            {
+                // Skip first frame to get the progress bar a chance to show up
+                if (importInProgress)
+                {
+                    UInt64 start = Time.Precise;
+                    List<string> toRemove = new List<string>();
+
+                    foreach (var entry in queuedForImport)
+                    {
+                        Internal_Refresh(entry, true);
+                        toRemove.Add(entry);
+                        numImportedFiles++;
+
+                        UInt64 end = Time.Precise;
+                        UInt64 elapsed = end - start;
+
+                        float elapsedSeconds = elapsed * Time.MicroToSecond;
+                        if (elapsedSeconds > TIME_SLICE_SECONDS)
+                            break;
+                    }
+
+                    foreach (var entry in toRemove)
+                        queuedForImport.Remove(entry);
+                }
+
+                if (queuedForImport.Count == 0)
+                {
+                    numImportedFiles = 0;
+                    totalFilesToImport = 0;
+
+                    ProgressBar.Hide();
+                }
+                else
+                {
+                    IEnumerator<string> enumerator = queuedForImport.GetEnumerator();
+                    enumerator.MoveNext();
+
+                    string displayName = enumerator.Current;
+                    displayName = displayName.Replace("\\", "\\\\");
+
+                    if (displayName.Length > 60)
+                    {
+                        displayName = displayName.Remove(0, displayName.Length - 60);
+                        displayName = "..." + displayName;
+                    }
+
+                    float pct = numImportedFiles / (float)totalFilesToImport;
+                    ProgressBar.Show("Importing (" + numImportedFiles + "/" + totalFilesToImport + ")", displayName, pct);
+                }
+
+                importInProgress = true;
+            }
+            else
+                importInProgress = false;
+        }
+
+        /// <summary>
+        /// Triggered internally by the runtime when a new entry is added to the project library.
+        /// </summary>
+        /// <param name="path">Path relative to the project library resources folder.</param>
+        private static void Internal_DoOnEntryAdded(string path)
+        {
+            if (OnEntryAdded != null)
+                OnEntryAdded(path);
+        }
+
+        /// <summary>
+        /// Triggered internally by the runtime when an entry is removed from the project library.
+        /// </summary>
+        /// <param name="path">Path relative to the project library resources folder.</param>
+        private static void Internal_DoOnEntryRemoved(string path)
+        {
+            if (OnEntryRemoved != null)
+                OnEntryRemoved(path);
+        }
+
+        /// <summary>
+        /// Triggered internally by the runtime when an entry is (re)imported in the project library.
+        /// </summary>
+        /// <param name="path">Path relative to the project library resources folder.</param>
+        private static void Internal_DoOnEntryImported(string path)
+        {
+            if (OnEntryImported != null)
+                OnEntryImported(path);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string[] Internal_Refresh(string path, bool import);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Create(Resource resource, string path);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Resource Internal_Load(string path);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Save(Resource resource);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern DirectoryEntry Internal_GetRoot();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsSubresource(string path);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Reimport(string path, ImportOptions options, bool force);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern LibraryEntry Internal_GetEntry(string path);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern ResourceMeta Internal_GetMeta(string path);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern LibraryEntry[] Internal_Search(string path, ResourceType[] types);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetPath(Resource resource);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetPathFromUUID(string uuid);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Delete(string path);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateFolder(string path);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Rename(string path, string name, bool overwrite);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Move(string oldPath, string newPath, bool overwrite);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Copy(string source, string destination, bool overwrite);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetResourceFolder();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetIncludeInBuild(string path, bool force);
+    }
+
+    /// <summary>
+    /// Type of project library entries.
+    /// </summary>
+    public enum LibraryEntryType // Note: Must match the C++ enum ProjectLibrary::LibraryEntryType
+    {
+        File, Directory
+    }
+
+    /// <summary>
+    /// Type of resources supported by the project library.
+    /// </summary>
+    public enum ResourceType // Note: Must match the C++ enum ScriptResourceType
+    {
+        Texture, SpriteTexture, Mesh, Font, Shader, ShaderInclude, Material, Prefab, PlainText, 
+        ScriptCode, StringTable, GUISkin, PhysicsMaterial, PhysicsMesh, Undefined
+    }
+
+    /// <summary>
+    /// A generic project library entry that may be a file or a folder.
+    /// </summary>
+    public class LibraryEntry : ScriptObject
+    {
+        /// <summary>
+        /// Path of the library entry, relative to the project library resources folder.
+        /// </summary>
+        public string Path { get { return Internal_GetPath(mCachedPtr); } }
+
+        /// <summary>
+        /// Name of the library entry.
+        /// </summary>
+        public string Name { get { return Internal_GetName(mCachedPtr); } }
+
+        /// <summary>
+        /// Type of the library entry.
+        /// </summary>
+        public LibraryEntryType Type { get { return Internal_GetType(mCachedPtr); } }
+
+        /// <summary>
+        /// Directory entry that contains this entry. This may be null for the root entry.
+        /// </summary>
+        public DirectoryEntry Parent { get { return Internal_GetParent(mCachedPtr); } }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetPath(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetName(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern LibraryEntryType Internal_GetType(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern DirectoryEntry Internal_GetParent(IntPtr thisPtr);
+    }
+
+    /// <summary>
+    /// A project library entry representing a directory that contains other entries.
+    /// </summary>
+    public class DirectoryEntry : LibraryEntry
+    {
+        /// <summary>
+        /// A set of entries contained in this entry.
+        /// </summary>
+        public LibraryEntry[] Children { get { return Internal_GetChildren(mCachedPtr); } }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern LibraryEntry[] Internal_GetChildren(IntPtr thisPtr);
+    }
+
+    /// <summary>
+    /// A library entry representing a file.
+    /// </summary>
+    public class FileEntry : LibraryEntry
+    {
+        /// <summary>
+        /// Import options used for importing the resources in the file.
+        /// </summary>
+        public ImportOptions Options { get { return Internal_GetImportOptions(mCachedPtr); } }
+
+        /// <summary>
+        /// Returns meta-data for all resources part of the file represented by this object.
+        /// </summary>
+        public ResourceMeta[] ResourceMetas { get { return Internal_GetResourceMetas(mCachedPtr); } }
+
+        /// <summary>
+        /// Determines will the resources in the file be included in the project build.
+        /// </summary>
+        public bool IncludeInBuild { get { return Internal_GetIncludeInBuild(mCachedPtr); } }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern ImportOptions Internal_GetImportOptions(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern ResourceMeta[] Internal_GetResourceMetas(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_GetIncludeInBuild(IntPtr thisPtr);
+    }
+
+    /// <summary>
+    /// Contains meta-data for a resource in the ProjectLibrary.
+    /// </summary>
+    public class ResourceMeta : ScriptObject
+    {
+        /// <summary>
+        /// Unique identifier of the resource.
+        /// </summary>
+        public string UUID { get { return Internal_GetUUID(mCachedPtr); } }
+
+        /// <summary>
+        /// Returns a name of the subresources. Each resource within a file has a unique name.
+        /// </summary>
+        public string SubresourceName { get { return Internal_GetSubresourceName(mCachedPtr); } }
+
+        /// <summary>
+        /// Custom icon for the resource to display in the editor, if the resource has one.
+        /// </summary>
+        public Texture2D Icon { get { return Internal_GetIcon(mCachedPtr); } }
+
+        /// <summary>
+        /// Type of the resource referenced by this entry.
+        /// </summary>
+        public ResourceType ResType { get { return Internal_GetResourceType(mCachedPtr); } }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetUUID(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern string Internal_GetSubresourceName(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Texture2D Internal_GetIcon(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern ResourceType Internal_GetResourceType(IntPtr thisPtr);
+    }
+}

+ 67 - 67
Source/MBansheeEditor/ToolbarItem.cs

@@ -1,67 +1,67 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Adds an entry to the main tool. Clicking on that entry will trigger the method the attribute is attached to.
-    /// The method must be static, have no parameters or return values otherwise the attribute will be ignored.
-    /// </summary>
-    [AttributeUsage(AttributeTargets.Method)]
-    class ToolbarItem : Attribute
-    {
-        /// <summary>
-        /// Creates a new toolbar item attribute. Selecting the item in the toolbar will trigger the callback.
-        /// </summary>
-        /// <param name="name">Path that determines where in the menu to add the element. All path elements must be 
-        ///                    separated by /, e.g. "View/Toolbars/Find"</param>
-        /// <param name="icon">Path to the sprite texture to display on the toolbar entry. Relative to project library 
-        ///                    resources folder.</param>
-        /// <param name="tooltip">Optional tooltip to display when the user hovers over the toolbar entry.</param>
-        /// <param name="priority">Priority determines the position of the toolbar item relative to its siblings.
-        ///                        Higher priority means it will be placed earlier.</param>
-        /// <param name="separator">Determines should a separator be inserted just before this element.</param>
-        public ToolbarItem(string name, string icon, string tooltip = "", int priority = 0, bool separator = false)
-        {
-            this.name = name;
-            this.icon = icon;
-            this.tooltip = tooltip;
-            this.priority = priority;
-            this.separator = separator;
-            this.builtinIcon = -1;
-        }
-
-        /// <summary>
-        /// Creates a new toolbar item attribute. Selecting the item in the toolbar will trigger the callback.
-        /// </summary>
-        /// <param name="name">Path that determines where in the menu to add the element. All path elements must be 
-        ///                    separated by /, e.g. "View/Toolbars/Find"</param>
-        /// <param name="icon">Type of builtin icon to display on the toolbar entry.</param>
-        /// <param name="tooltip">Optional tooltip to display when the user hovers over the toolbar entry.</param>
-        /// <param name="priority">Priority determines the position of the toolbar item relative to its siblings.
-        ///                        Higher priority means it will be placed earlier.</param>
-        /// <param name="separator">Determines should a separator be inserted just before this element.</param>
-        internal ToolbarItem(string name, ToolbarIcon icon, string tooltip = "", int priority = 0, bool separator = false)
-        {
-            this.name = name;
-            this.icon = null;
-            this.tooltip = tooltip;
-            this.priority = priority;
-            this.separator = separator;
-            this.builtinIcon = (int)icon;
-        }
-
-        private string name;
-        private string icon;
-        private int builtinIcon;
-        private string tooltip;
-        private int priority;
-        private bool separator;
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Adds an entry to the main tool. Clicking on that entry will trigger the method the attribute is attached to.
+    /// The method must be static, have no parameters or return values otherwise the attribute will be ignored.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Method)]
+    class ToolbarItem : Attribute
+    {
+        /// <summary>
+        /// Creates a new toolbar item attribute. Selecting the item in the toolbar will trigger the callback.
+        /// </summary>
+        /// <param name="name">Path that determines where in the menu to add the element. All path elements must be 
+        ///                    separated by /, for example "View/Toolbars/Find".</param>
+        /// <param name="icon">Path to the sprite texture to display on the toolbar entry. Relative to project library 
+        ///                    resources folder.</param>
+        /// <param name="tooltip">Optional tooltip to display when the user hovers over the toolbar entry.</param>
+        /// <param name="priority">Priority determines the position of the toolbar item relative to its siblings.
+        ///                        Higher priority means it will be placed earlier.</param>
+        /// <param name="separator">Determines should a separator be inserted just before this element.</param>
+        public ToolbarItem(string name, string icon, string tooltip = "", int priority = 0, bool separator = false)
+        {
+            this.name = name;
+            this.icon = icon;
+            this.tooltip = tooltip;
+            this.priority = priority;
+            this.separator = separator;
+            this.builtinIcon = -1;
+        }
+
+        /// <summary>
+        /// Creates a new toolbar item attribute. Selecting the item in the toolbar will trigger the callback.
+        /// </summary>
+        /// <param name="name">Path that determines where in the menu to add the element. All path elements must be 
+        ///                    separated by /, for example "View/Toolbars/Find".</param>
+        /// <param name="icon">Type of builtin icon to display on the toolbar entry.</param>
+        /// <param name="tooltip">Optional tooltip to display when the user hovers over the toolbar entry.</param>
+        /// <param name="priority">Priority determines the position of the toolbar item relative to its siblings.
+        ///                        Higher priority means it will be placed earlier.</param>
+        /// <param name="separator">Determines should a separator be inserted just before this element.</param>
+        internal ToolbarItem(string name, ToolbarIcon icon, string tooltip = "", int priority = 0, bool separator = false)
+        {
+            this.name = name;
+            this.icon = null;
+            this.tooltip = tooltip;
+            this.priority = priority;
+            this.separator = separator;
+            this.builtinIcon = (int)icon;
+        }
+
+        private string name;
+        private string icon;
+        private int builtinIcon;
+        private string tooltip;
+        private int priority;
+        private bool separator;
+    }
+}

+ 130 - 130
Source/MBansheeEngine/ContextMenu.cs

@@ -1,130 +1,130 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Contains data used for initializing a context menu used on GUI elements. When specifying menu items you must provide
-    /// a path. Path must be formated in a certain way. All path elements must be separated by /, e.g. "View/Toolbars/Find". 
-    /// "View" would be the top level path element, "Toolbars" a child in its menu that opens up its own submenu, and "Find"
-    /// a child in the "Toolbars" sub-menu with an optional callback.
-    /// </summary>
-    public class ContextMenu : ScriptObject
-    {
-        private List<Action> callbacks = new List<Action>(); 
-
-        /// <summary>
-        /// Creates a new empty context menu data.
-        /// </summary>
-        public ContextMenu()
-        {
-            Internal_CreateInstance(this);
-        }
-
-        /// <summary>
-        /// Adds a new item to the menu.
-        /// </summary>
-        /// <param name="path">Path that determines where to add the element. See class information on how to specify paths.
-        ///                    All sub-elements of a path will be added automatically.</param>
-        /// <param name="callback">Callback to trigger when the path element is selected.</param>
-        public void AddItem(string path, Action callback)
-        {
-            Internal_AddItem(mCachedPtr, path, callbacks.Count, ref ShortcutKey.None);
-            callbacks.Add(callback);
-        }
-
-        /// <summary>
-        /// Adds a new item to the menu.
-        /// </summary>
-        /// <param name="path">Path that determines where to add the element. See class information on how to specify paths.
-        ///                    All sub-elements of a path will be added automatically.</param>
-        /// <param name="callback">Callback to trigger when the path element is selected.</param>
-        /// <param name="shortcut">Keyboard shortcut to display next to the item name.</param>
-        public void AddItem(string path, Action callback, ShortcutKey shortcut)
-        {
-            Internal_AddItem(mCachedPtr, path, callbacks.Count, ref shortcut);
-            callbacks.Add(callback);
-        }
-
-        /// <summary>
-        /// Adds a new item to the menu.
-        /// </summary>
-        /// <param name="path">Path that determines where to add the element. See class information on how to specify paths.
-        ///                    All sub-elements of a path will be added automatically.</param>
-        /// <param name="callback">Callback to trigger when the path element is selected.</param>
-        /// <param name="name">Localized name for the menu item.</param>
-        public void AddItem(string path, Action callback, LocString name)
-        {
-            Internal_AddItem(mCachedPtr, path, callbacks.Count, ref ShortcutKey.None);
-            callbacks.Add(callback);
-        }
-
-        /// <summary>
-        /// Adds a new item to the menu.
-        /// </summary>
-        /// <param name="path">Path that determines where to add the element. See class information on how to specify paths.
-        ///                    All sub-elements of a path will be added automatically.</param>
-        /// <param name="callback">Callback to trigger when the path element is selected.</param>
-        /// <param name="shortcut">Keyboard shortcut to display next to the item name.</param>
-        /// <param name="name">Localized name for the menu item.</param>
-        public void AddItem(string path, Action callback, ShortcutKey shortcut, LocString name)
-        {
-            Internal_AddItem(mCachedPtr, path, callbacks.Count, ref shortcut);
-            callbacks.Add(callback);
-        }
-
-        /// <summary>
-        /// Adds a new separator to the menu.
-        /// </summary>
-        /// <param name="path">Path that determines where to add the element. See class information on how to specify paths.
-        ///                    All sub-elements of a path will be added automatically.</param>
-        public void AddSeparator(string path)
-        {
-            Internal_AddSeparator(mCachedPtr, path);
-        }
-
-        /// <summary>
-        /// Sets a localized name of a specific menu element. If no localized name is set element labels will be displayed
-        /// as their names.
-        /// </summary>
-        /// <param name="label">Label of the element.</param>
-        /// <param name="name">Name to display when the menu is shown.</param>
-        public void SetLocalizedName(string label, LocString name)
-        {
-            IntPtr namePtr = IntPtr.Zero;
-            if (name != null)
-                namePtr = name.GetCachedPtr();
-
-            Internal_SetLocalizedName(mCachedPtr, label, namePtr);
-        }
-
-        /// <summary>
-        /// Triggered by the runtime when an element is selected the context menu.
-        /// </summary>
-        /// <param name="callbackIdx">Unique index of the element that was selected.</param>
-        private void InternalDoOnEntryTriggered(int callbackIdx)
-        {
-            if (callbackIdx < 0 || callbackIdx >= callbacks.Count)
-                return;
-
-            Action callback = callbacks[callbackIdx];
-            if (callback != null)
-                callback();
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(ContextMenu instance);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_AddItem(IntPtr instance, string path, int callbackIdx, ref ShortcutKey shortcut);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_AddSeparator(IntPtr instance, string path);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetLocalizedName(IntPtr instance, string label, IntPtr name);
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Contains data used for initializing a context menu used on GUI elements. When specifying menu items you must provide
+    /// a path. Path must be formated in a certain way. All path elements must be separated by /, for example 
+    /// "View/Toolbars/Find". "View" would be the top level path element, "Toolbars" a child in its menu that opens up its
+    /// own submenu, and "Find" a child in the "Toolbars" sub-menu with an optional callback.
+    /// </summary>
+    public class ContextMenu : ScriptObject
+    {
+        private List<Action> callbacks = new List<Action>(); 
+
+        /// <summary>
+        /// Creates a new empty context menu data.
+        /// </summary>
+        public ContextMenu()
+        {
+            Internal_CreateInstance(this);
+        }
+
+        /// <summary>
+        /// Adds a new item to the menu.
+        /// </summary>
+        /// <param name="path">Path that determines where to add the element. See class information on how to specify paths.
+        ///                    All sub-elements of a path will be added automatically.</param>
+        /// <param name="callback">Callback to trigger when the path element is selected.</param>
+        public void AddItem(string path, Action callback)
+        {
+            Internal_AddItem(mCachedPtr, path, callbacks.Count, ref ShortcutKey.None);
+            callbacks.Add(callback);
+        }
+
+        /// <summary>
+        /// Adds a new item to the menu.
+        /// </summary>
+        /// <param name="path">Path that determines where to add the element. See class information on how to specify paths.
+        ///                    All sub-elements of a path will be added automatically.</param>
+        /// <param name="callback">Callback to trigger when the path element is selected.</param>
+        /// <param name="shortcut">Keyboard shortcut to display next to the item name.</param>
+        public void AddItem(string path, Action callback, ShortcutKey shortcut)
+        {
+            Internal_AddItem(mCachedPtr, path, callbacks.Count, ref shortcut);
+            callbacks.Add(callback);
+        }
+
+        /// <summary>
+        /// Adds a new item to the menu.
+        /// </summary>
+        /// <param name="path">Path that determines where to add the element. See class information on how to specify paths.
+        ///                    All sub-elements of a path will be added automatically.</param>
+        /// <param name="callback">Callback to trigger when the path element is selected.</param>
+        /// <param name="name">Localized name for the menu item.</param>
+        public void AddItem(string path, Action callback, LocString name)
+        {
+            Internal_AddItem(mCachedPtr, path, callbacks.Count, ref ShortcutKey.None);
+            callbacks.Add(callback);
+        }
+
+        /// <summary>
+        /// Adds a new item to the menu.
+        /// </summary>
+        /// <param name="path">Path that determines where to add the element. See class information on how to specify paths.
+        ///                    All sub-elements of a path will be added automatically.</param>
+        /// <param name="callback">Callback to trigger when the path element is selected.</param>
+        /// <param name="shortcut">Keyboard shortcut to display next to the item name.</param>
+        /// <param name="name">Localized name for the menu item.</param>
+        public void AddItem(string path, Action callback, ShortcutKey shortcut, LocString name)
+        {
+            Internal_AddItem(mCachedPtr, path, callbacks.Count, ref shortcut);
+            callbacks.Add(callback);
+        }
+
+        /// <summary>
+        /// Adds a new separator to the menu.
+        /// </summary>
+        /// <param name="path">Path that determines where to add the element. See class information on how to specify paths.
+        ///                    All sub-elements of a path will be added automatically.</param>
+        public void AddSeparator(string path)
+        {
+            Internal_AddSeparator(mCachedPtr, path);
+        }
+
+        /// <summary>
+        /// Sets a localized name of a specific menu element. If no localized name is set element labels will be displayed
+        /// as their names.
+        /// </summary>
+        /// <param name="label">Label of the element.</param>
+        /// <param name="name">Name to display when the menu is shown.</param>
+        public void SetLocalizedName(string label, LocString name)
+        {
+            IntPtr namePtr = IntPtr.Zero;
+            if (name != null)
+                namePtr = name.GetCachedPtr();
+
+            Internal_SetLocalizedName(mCachedPtr, label, namePtr);
+        }
+
+        /// <summary>
+        /// Triggered by the runtime when an element is selected the context menu.
+        /// </summary>
+        /// <param name="callbackIdx">Unique index of the element that was selected.</param>
+        private void InternalDoOnEntryTriggered(int callbackIdx)
+        {
+            if (callbackIdx < 0 || callbackIdx >= callbacks.Count)
+                return;
+
+            Action callback = callbacks[callbackIdx];
+            if (callback != null)
+                callback();
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(ContextMenu instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_AddItem(IntPtr instance, string path, int callbackIdx, ref ShortcutKey shortcut);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_AddSeparator(IntPtr instance, string path);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetLocalizedName(IntPtr instance, string label, IntPtr name);
+    }
+}

+ 200 - 200
Source/MBansheeEngine/Font.cs

@@ -1,200 +1,200 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Font resource containing data about textual characters and how to render text. Contains one or multiple font 
-    /// bitmaps, each for a specific size.
-    /// </summary>
-    public sealed class Font : Resource
-    {
-        /// <summary>
-        /// Creates a new font resource. For runtime use only.
-        /// </summary>
-        private Font()
-        { }
-
-        /// <summary>
-        /// Returns font bitmap for a specific font size.
-        /// </summary>
-        /// <param name="size">Size of the bitmap in points.</param>
-        /// <returns>Bitmap object if size was found, null otherwise.</returns>
-        public FontBitmap GetBitmap(int size)
-        {
-            return Internal_GetBitmap(mCachedPtr, size);
-        }
-
-        /// <summary>
-        /// Finds the available font bitmap size closest to the provided size.
-        /// </summary>
-        /// <param name="size">Size of the bitmap in points.</param>
-        /// <returns>Nearest available bitmap size.</returns>
-        public int GetClosestSize(int size)
-        {
-            return Internal_GetClosestSize(mCachedPtr, size);
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern FontBitmap Internal_GetBitmap(IntPtr instance, int size);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern int Internal_GetClosestSize(IntPtr instance, int size);
-    }
-
-    /// <summary>
-    /// Contains textures and data about every character for a bitmap font of a specific size.
-    /// </summary>
-    public sealed class FontBitmap : ScriptObject
-    {
-        /// <summary>
-        /// Constructor for internal runtime use only.
-        /// </summary>
-        internal FontBitmap()
-        { }
-
-        /// <summary>
-        /// Size of the font in the bitmap, in points.
-        /// </summary>
-        public int Size { get { return Internal_GetSize(mCachedPtr); } }
-
-        /// <summary>
-        /// Y offset to the baseline on which the characters are placed, in pixels.
-        /// </summary>
-        public int BaselineOffset { get { return Internal_GetBaselineOffset(mCachedPtr); } }
-
-        /// <summary>
-        /// Height of a single line of the font, in pixels.
-        /// </summary>
-        public int LineHeight { get { return Internal_GetLineHeight(mCachedPtr); } }
-
-        /// <summary>
-        /// Width of a space in pixels.
-        /// </summary>
-        public int SpaceWidth { get { return Internal_GetSpaceWidth(mCachedPtr); } }
-
-        /// <summary>
-        /// Character to use when data for a character is missing.
-        /// </summary>
-        public CharDesc MissingChar { get { CharDesc value; Internal_GetMissingChar(mCachedPtr, out value); return value; } }
-
-        /// <summary>
-        /// Textures in which the character's pixels are stored.
-        /// </summary>
-        public Texture2D[] Pages { get { return Internal_GetPages(mCachedPtr); } }
-
-        /// <summary>
-        /// Returns a description of the character in the bitmap.
-        /// </summary>
-        /// <param name="id">Unicode key of the character to retrieve.</param>
-        /// <returns>Character data if it was found in the bitmap, missing character data otherwise.</returns>
-        public CharDesc GetChar(int id)
-        {
-            CharDesc value;
-            Internal_GetChar(mCachedPtr, id, out value);
-            return value;
-        }
-
-        /// <summary>
-        /// Returns a set of pairs that determine if the provided character should be closer or father together than normal
-        /// with a specific other character. e.g. the combination of "A" and "V" characters is normally a kerning pair "AV" 
-        /// as their bounds overlap and are closer together than characters would be normally.
-        /// </summary>
-        /// <param name="id">Unicode key of the character to retrieve kerning pairs for.</param>
-        /// <returns>A set of kerning pairs for the character.</returns>
-        public KerningPair[] GetKerning(int id)
-        {
-            return Internal_GetKerning(mCachedPtr, id);
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern int Internal_GetSize(IntPtr instance);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern int Internal_GetBaselineOffset(IntPtr instance);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern int Internal_GetLineHeight(IntPtr instance);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern int Internal_GetSpaceWidth(IntPtr instance);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_GetMissingChar(IntPtr instance, out CharDesc output);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern Texture2D[] Internal_GetPages(IntPtr instance);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_GetChar(IntPtr instance, int id, out CharDesc output);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern KerningPair[] Internal_GetKerning(IntPtr instance, int id);
-    }
-
-    /// <summary>
-    /// Marks a range of characters in a font.
-    /// </summary>
-    [StructLayout(LayoutKind.Sequential), SerializeObject]
-    public struct CharRange
-    {
-        public int start;
-        public int end;
-    }
-
-    /// <summary>
-    /// Kerning pair representing larger or smaller offset between a specific pair of characters.
-    /// </summary>
-    [StructLayout(LayoutKind.Sequential), SerializeObject]
-    public struct KerningPair // Note: Must match C++ struct KerningPair
-    {
-        public int OtherChar;
-        public int Amount;
-    }
-
-    /// <summary>
-    /// Describes a single character in a font of a specific size.
-    /// </summary>
-    [StructLayout(LayoutKind.Sequential), SerializeObject]
-    public struct CharDesc // Note: Must match C++ struct ScriptCharDesc
-    {
-        /// <summary>Character ID, corresponding to a Unicode key.</summary>
-        public int Id;
-
-        /// <summary>Index of the texture the character is located on.</summary>
-        public int Page; 
-
-        /// <summary>Texture coordinates of the character in the page texture.</summary>
-        public float UVX;
-
-        /// <summary>Texture coordinates of the character in the page texture.</summary>
-        public float UVY;
-
-        /// <summary>Size of the character in texture coordinates.</summary>
-        public float UVWidth;
-
-        /// <summary>Size of the character in texture coordinates.</summary>
-        public float UVHeight;
-
-        /// <summary>Size of the character in pixels.</summary>
-        public int Width;
-
-        /// <summary>Size of the character in pixels.</summary>
-        public int Height;
-
-        /// <summary>Offset for the visible portion of the character in pixels.</summary>
-        public int XOffset;
-
-        /// <summary>Offset for the visible portion of the character in pixels.</summary>
-        public int YOffset;
-
-        /// <summary>Determines how much to advance the pen after writing this character, in pixels.</summary>
-        public int XAdvance;
-
-        /// <summary>Determines how much to advance the pen after writing this character, in pixels.</summary>
-        public int YAdvance;
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Font resource containing data about textual characters and how to render text. Contains one or multiple font 
+    /// bitmaps, each for a specific size.
+    /// </summary>
+    public sealed class Font : Resource
+    {
+        /// <summary>
+        /// Creates a new font resource. For runtime use only.
+        /// </summary>
+        private Font()
+        { }
+
+        /// <summary>
+        /// Returns font bitmap for a specific font size.
+        /// </summary>
+        /// <param name="size">Size of the bitmap in points.</param>
+        /// <returns>Bitmap object if size was found, null otherwise.</returns>
+        public FontBitmap GetBitmap(int size)
+        {
+            return Internal_GetBitmap(mCachedPtr, size);
+        }
+
+        /// <summary>
+        /// Finds the available font bitmap size closest to the provided size.
+        /// </summary>
+        /// <param name="size">Size of the bitmap in points.</param>
+        /// <returns>Nearest available bitmap size.</returns>
+        public int GetClosestSize(int size)
+        {
+            return Internal_GetClosestSize(mCachedPtr, size);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern FontBitmap Internal_GetBitmap(IntPtr instance, int size);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetClosestSize(IntPtr instance, int size);
+    }
+
+    /// <summary>
+    /// Contains textures and data about every character for a bitmap font of a specific size.
+    /// </summary>
+    public sealed class FontBitmap : ScriptObject
+    {
+        /// <summary>
+        /// Constructor for internal runtime use only.
+        /// </summary>
+        internal FontBitmap()
+        { }
+
+        /// <summary>
+        /// Size of the font in the bitmap, in points.
+        /// </summary>
+        public int Size { get { return Internal_GetSize(mCachedPtr); } }
+
+        /// <summary>
+        /// Y offset to the baseline on which the characters are placed, in pixels.
+        /// </summary>
+        public int BaselineOffset { get { return Internal_GetBaselineOffset(mCachedPtr); } }
+
+        /// <summary>
+        /// Height of a single line of the font, in pixels.
+        /// </summary>
+        public int LineHeight { get { return Internal_GetLineHeight(mCachedPtr); } }
+
+        /// <summary>
+        /// Width of a space in pixels.
+        /// </summary>
+        public int SpaceWidth { get { return Internal_GetSpaceWidth(mCachedPtr); } }
+
+        /// <summary>
+        /// Character to use when data for a character is missing.
+        /// </summary>
+        public CharDesc MissingChar { get { CharDesc value; Internal_GetMissingChar(mCachedPtr, out value); return value; } }
+
+        /// <summary>
+        /// Textures in which the character's pixels are stored.
+        /// </summary>
+        public Texture2D[] Pages { get { return Internal_GetPages(mCachedPtr); } }
+
+        /// <summary>
+        /// Returns a description of the character in the bitmap.
+        /// </summary>
+        /// <param name="id">Unicode key of the character to retrieve.</param>
+        /// <returns>Character data if it was found in the bitmap, missing character data otherwise.</returns>
+        public CharDesc GetChar(int id)
+        {
+            CharDesc value;
+            Internal_GetChar(mCachedPtr, id, out value);
+            return value;
+        }
+
+        /// <summary>
+        /// Returns a set of pairs that determine if the provided character should be closer or father together than normal
+        /// with a specific other character. For example the combination of "A" and "V" characters is normally a kerning
+        /// pair "AV" as their bounds overlap and are closer together than characters would be normally.
+        /// </summary>
+        /// <param name="id">Unicode key of the character to retrieve kerning pairs for.</param>
+        /// <returns>A set of kerning pairs for the character.</returns>
+        public KerningPair[] GetKerning(int id)
+        {
+            return Internal_GetKerning(mCachedPtr, id);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetSize(IntPtr instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetBaselineOffset(IntPtr instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetLineHeight(IntPtr instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetSpaceWidth(IntPtr instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetMissingChar(IntPtr instance, out CharDesc output);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Texture2D[] Internal_GetPages(IntPtr instance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetChar(IntPtr instance, int id, out CharDesc output);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern KerningPair[] Internal_GetKerning(IntPtr instance, int id);
+    }
+
+    /// <summary>
+    /// Marks a range of characters in a font.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
+    public struct CharRange
+    {
+        public int start;
+        public int end;
+    }
+
+    /// <summary>
+    /// Kerning pair representing larger or smaller offset between a specific pair of characters.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
+    public struct KerningPair // Note: Must match C++ struct KerningPair
+    {
+        public int OtherChar;
+        public int Amount;
+    }
+
+    /// <summary>
+    /// Describes a single character in a font of a specific size.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
+    public struct CharDesc // Note: Must match C++ struct ScriptCharDesc
+    {
+        /// <summary>Character ID, corresponding to a Unicode key.</summary>
+        public int Id;
+
+        /// <summary>Index of the texture the character is located on.</summary>
+        public int Page; 
+
+        /// <summary>Texture coordinates of the character in the page texture.</summary>
+        public float UVX;
+
+        /// <summary>Texture coordinates of the character in the page texture.</summary>
+        public float UVY;
+
+        /// <summary>Size of the character in texture coordinates.</summary>
+        public float UVWidth;
+
+        /// <summary>Size of the character in texture coordinates.</summary>
+        public float UVHeight;
+
+        /// <summary>Size of the character in pixels.</summary>
+        public int Width;
+
+        /// <summary>Size of the character in pixels.</summary>
+        public int Height;
+
+        /// <summary>Offset for the visible portion of the character in pixels.</summary>
+        public int XOffset;
+
+        /// <summary>Offset for the visible portion of the character in pixels.</summary>
+        public int YOffset;
+
+        /// <summary>Determines how much to advance the pen after writing this character, in pixels.</summary>
+        public int XAdvance;
+
+        /// <summary>Determines how much to advance the pen after writing this character, in pixels.</summary>
+        public int YAdvance;
+    }
+}

+ 656 - 656
Source/MBansheeEngine/Input.cs

@@ -1,656 +1,656 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Text;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Contains data about a button input event.
-    /// </summary>
-	public struct ButtonEvent
-	{
-		internal ButtonCode buttonCode;
-        internal int deviceIdx;
-
-        /// <summary>
-        /// Creates a new button input event. For runtime use only.
-        /// </summary>
-        /// <param name="buttonCode">Button code this event is referring to.</param>
-        /// <param name="deviceIdx">Index of the device that the event originated from.</param>
-	    internal ButtonEvent(ButtonCode buttonCode, int deviceIdx)
-	    {
-	        this.buttonCode = buttonCode;
-	        this.deviceIdx = deviceIdx;
-	    }
-
-        /// <summary>
-        /// Button code this event is referring to.
-        /// </summary>
-        public ButtonCode Button { get { return buttonCode; } }
-
-        /// <summary>
-        /// Index of the device that the event originated from.
-        /// </summary>
-        public int DeviceIndex { get { return deviceIdx; } }
-
-        /// <summary>
-        /// Query is the pressed button a keyboard button.
-        /// </summary>
-		public bool IsKeyboard { get { return ((int)buttonCode & 0xC0000000) == 0; }}
-
-        /// <summary>
-        /// Query is the pressed button a mouse button.
-        /// </summary>
-        public bool IsMouse { get { return ((int)buttonCode & 0x80000000) != 0; } }
-
-        /// <summary>
-        /// Query is the pressed button a gamepad button.
-        /// </summary>
-        public bool IsGamepad { get { return ((int)buttonCode & 0x40000000) != 0; } }
-	};
-
-    /// <summary>
-    /// Pointer buttons. Generally these correspond to mouse buttons, but may be used in some form for touch input as well.
-    /// </summary>
-    public enum PointerButton // Note: Must match C++ enum PointerEventButton 
-	{
-		Left, Middle, Right, Count
-	};
-
-    /// <summary>
-    /// Event that gets sent out when user interacts with the screen in some way, usually by moving the mouse cursor or 
-    /// using touch input.
-    /// </summary>
-    public struct PointerEvent
-    {
-        internal Vector2I _screenPos;
-        internal Vector2I _delta;
-        internal PointerButton _button;
-
-        internal bool _shift;
-        internal bool _control;
-        internal bool _alt;
-
-        internal float _mouseWheelScrollAmount;
-
-        /// <summary>
-        /// Creates a new pointer event. For runtime use only.
-        /// </summary>
-        /// <param name="screenPos">Screen position where the input event occurred.</param>
-        /// <param name="delta">Change in movement since last sent event.</param>
-        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
-        ///                      (e.g. move events don't correspond to a button.</param>
-        /// <param name="shift">Is shift button on the keyboard being held down.</param>
-        /// <param name="control">Is control button on the keyboard being held down.</param>
-        /// <param name="alt">Is alt button on the keyboard being held down.</param>
-        /// <param name="mouseWheelScrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
-        ///                                      move events.</param>
-        internal PointerEvent(Vector2I screenPos, Vector2I delta, PointerButton button,
-            bool shift, bool control, bool alt, float mouseWheelScrollAmount)
-        {
-            _screenPos = screenPos;
-            _delta = delta;
-            _button = button;
-
-            _shift = shift;
-            _control = control;
-            _alt = alt;
-
-            _mouseWheelScrollAmount = mouseWheelScrollAmount;
-        }
-
-        /// <summary>
-        /// Screen position where the input event occurred.
-        /// </summary>
-        public Vector2I ScreenPos { get { return _screenPos; } }
-
-        /// <summary>
-        /// Change in movement since last sent event.
-        /// </summary>
-        public Vector2I Delta { get { return _delta; } }
-
-        /// <summary>
-        /// Button that triggered the pointer event. Might be irrelevant depending on event type. 
-        /// (e.g. move events don't correspond to a button.
-        /// </summary>
-        public PointerButton Button { get { return _button; } }
-
-        /// <summary>
-        /// Is shift button on the keyboard being held down.
-        /// </summary>
-        public bool Shift { get { return _shift; } }
-
-        /// <summary>
-        /// Is control button on the keyboard being held down.
-        /// </summary>
-        public bool Control { get { return _control; } }
-
-        /// <summary>
-        /// Is alt button on the keyboard being held down.
-        /// </summary>
-        public bool Alt { get { return _alt; } }
-
-        /// <summary>
-        /// If mouse wheel is being scrolled, what is the amount. Only relevant for move events.
-        /// </summary>
-        public float ScrollAmount { get { return _mouseWheelScrollAmount; } }
-    }
-
-    /// <summary>
-    /// Event that gets sent out when user inputs some text. These events may be preceeded by normal button events if user 
-    /// is typing on a keyboard.
-    /// </summary>
-    public struct TextInputEvent
-    {
-        internal int textChar;
-
-        /// <summary>
-        /// Creates a new text input event. For runtime use only.
-        /// </summary>
-        /// <param name="textChar">Character the that was input.</param>
-        internal TextInputEvent(int textChar)
-        {
-            this.textChar = textChar;
-        }
-
-        /// <summary>
-        /// Character the that was input.
-        /// </summary>
-        public int Char { get { return textChar; } }
-    }
-
-    /// <summary>
-    /// Allows you to query and receive events from all connected input devices.
-    /// </summary>
-    public static class Input
-    {
-        public delegate void ButtonEventDelegate(ButtonEvent ev);
-        public delegate void TextInputEventDelegate(TextInputEvent ev);
-        public delegate void PointerEventDelegate(PointerEvent ev);
-
-        /// <summary>
-        /// Triggered when a button on any device is pressed.
-        /// </summary>
-		public static event ButtonEventDelegate OnButtonDown;
-
-        /// <summary>
-        /// Triggered when a button on any device is released.
-        /// </summary>
-        public static event ButtonEventDelegate OnButtonUp;
-
-        /// <summary>
-        /// Triggered when a textual character is entered.
-        /// </summary>
-        public static event TextInputEventDelegate OnCharInput;
-
-        /// <summary>
-        /// Triggered when the pointing device (mouse, touch) is moved.
-        /// </summary>
-        public static event PointerEventDelegate OnPointerMoved;
-
-        /// <summary>
-        /// Triggered when a button on the pointing device (mouse, touch) is pressed.
-        /// </summary>
-        public static event PointerEventDelegate OnPointerPressed;
-
-        /// <summary>
-        /// Triggered when a button on the pointing device (mouse, touch) is released.
-        /// </summary>
-        public static event PointerEventDelegate OnPointerReleased;
-
-        /// <summary>
-        /// Triggered when a button on the pointing device (mouse, touch) is pressed twice in rappid succession.
-        /// </summary>
-        public static event PointerEventDelegate OnPointerDoubleClick;
-
-        /// <summary>
-        /// Returns value of the specified input axis. 
-        /// </summary>
-        /// <param name="axis">Type of axis to query.</param>
-        /// <param name="deviceIdx">Index of the device in case more than one is hooked up (0 - primary).</param>
-        /// <returns>Value of the axis in range [-1.0, 1.0]. Canan be outside the range for devices with unbound axes 
-        ///          (e.g. mouse).</returns>
-        public static float GetAxisValue(InputAxis axis, int deviceIdx = 0)
-        {
-            return Internal_GetAxisValue(axis, deviceIdx);
-        }
-
-        /// <summary>
-        /// Query if the provided button is currently being held (this frame or previous frames).
-        /// </summary>
-        /// <param name="code">Code of the button to query.</param>
-        /// <param name="deviceIdx">Device to query the button on (0 - primary).</param>
-        /// <returns>True if the button is held.</returns>
-        public static bool IsButtonHeld(ButtonCode code, int deviceIdx = 0)
-        {
-            return Internal_IsButtonHeld(code, deviceIdx);
-        }
-
-        /// <summary>
-        /// Query if the provided button is currently being released (only true for one frame).
-        /// </summary>
-        /// <param name="code">Code of the button to query.</param>
-        /// <param name="deviceIdx">Device to query the button on (0 - primary).</param>
-        /// <returns>True if the button is being released.</returns>
-        public static bool IsButtonUp(ButtonCode code, int deviceIdx = 0)
-        {
-            return Internal_IsButtonUp(code, deviceIdx);
-        }
-
-        /// <summary>
-        /// Query if the provided button is currently being pressed (only true for one frame).
-        /// </summary>
-        /// <param name="code">Code of the button to query.</param>
-        /// <param name="deviceIdx">Device to query the button on (0 - primary).</param>
-        /// <returns>True if the button is being pressed.</returns>
-        public static bool IsButtonDown(ButtonCode code, int deviceIdx = 0)
-        {
-            return Internal_IsButtonDown(code, deviceIdx);
-        }
-
-        /// <summary>
-        /// Query if the provided pointer button is currently being held (this frame or previous frames).
-        /// </summary>
-        /// <param name="code">Code of the button to query.</param>
-        /// <returns>True if the button is being held.</returns>
-        public static bool IsPointerButtonHeld(PointerButton code)
-        {
-            return Internal_IsPointerButtonHeld(code);
-        }
-
-        /// <summary>
-        /// Query if the provided pointer button is currently being being released (only true for one frame).
-        /// </summary>
-        /// <param name="code">Code of the button to query.</param>
-        /// <returns>True if the button is being released.</returns>
-        public static bool IsPointerButtonUp(PointerButton code)
-        {
-            return Internal_IsPointerButtonUp(code);
-        }
-
-        /// <summary>
-        /// Query if the provided pointer button is currently being being pressed (only true for one frame).
-        /// </summary>
-        /// <param name="code">Code of the button to query.</param>
-        /// <returns>True if the button is being pressed.</returns>
-        public static bool IsPointerButtonDown(PointerButton code)
-        {
-            return Internal_IsPointerButtonDown(code);
-        }
-
-        /// <summary>
-        /// Query has the left pointer button been double-clicked this frame.
-        /// </summary>
-        /// <returns>True if double-click occurred.</returns>
-        public static bool IsPointerDoubleClicked()
-        {
-            return Internal_IsPointerDoubleClicked();
-        }
-
-        /// <summary>
-        /// Returns position of the pointer (e.g. mouse cursor) relative to the screen.
-        /// </summary>
-        public static Vector2I PointerPosition
-        {
-            get
-            {
-                Vector2I value;
-                Internal_GetPointerPosition(out value);
-                return value;
-            }
-        }
-
-        /// <summary>
-        /// Returns difference between last and current pointer position.
-        /// </summary>
-        public static Vector2I PointerDelta
-        {
-            get
-            {
-                Vector2I value;
-                Internal_GetPointerDelta(out value);
-                return value;
-            }
-        }
-
-        /// <summary>
-        /// Triggered by runtime when a button is pressed.
-        /// </summary>
-        /// <param name="code">Code of the pressed button.</param>
-        /// <param name="deviceIdx">Device the event originated from.</param>
-        private static void Internal_TriggerButtonDown(ButtonCode code, int deviceIdx)
-        {
-            ButtonEvent ev = new ButtonEvent(code, deviceIdx);
-
-            if (OnButtonDown != null)
-                OnButtonDown(ev);
-        }
-
-        /// <summary>
-        /// Triggered by runtime when a button is released.
-        /// </summary>
-        /// <param name="code">Code of the released button.</param>
-        /// <param name="deviceIdx">Device the event originated from.</param>
-        private static void Internal_TriggerButtonUp(ButtonCode code, int deviceIdx)
-        {
-            ButtonEvent ev = new ButtonEvent(code, deviceIdx);
-
-            if (OnButtonUp != null)
-                OnButtonUp(ev);
-        }
-
-        /// <summary>
-        /// Triggered by runtime when character is input.
-        /// </summary>
-        /// <param name="textChar">Code of input character.</param>
-        private static void Internal_TriggerCharInput(int textChar)
-        {
-            TextInputEvent ev = new TextInputEvent(textChar);
-
-            if (OnCharInput != null)
-                OnCharInput(ev);
-        }
-
-        /// <summary>
-        /// Triggers when some pointing device (mouse cursor, touch) moves.
-        /// </summary>
-        /// <param name="screenPos">Screen position where the input event occurred.</param>
-        /// <param name="delta">Change in movement since last sent event.</param>
-        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
-        ///                      (e.g. move events don't correspond to a button.</param>
-        /// <param name="shift">Is shift button on the keyboard being held down.</param>
-        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
-        /// <param name="alt">Is alt button on the keyboard being held down.</param>
-        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
-        ///                            move events.</param>
-        private static void Internal_TriggerPointerMove(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift, 
-            bool ctrl, bool alt, float scrollAmount)
-        {
-            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
-
-            if (OnPointerMoved != null)
-                OnPointerMoved(ev);
-        }
-
-        /// <summary>
-        /// Triggers when some pointing device (mouse cursor, touch) button is pressed.
-        /// </summary>
-        /// <param name="screenPos">Screen position where the input event occurred.</param>
-        /// <param name="delta">Change in movement since last sent event.</param>
-        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
-        ///                      (e.g. move events don't correspond to a button.</param>
-        /// <param name="shift">Is shift button on the keyboard being held down.</param>
-        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
-        /// <param name="alt">Is alt button on the keyboard being held down.</param>
-        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
-        ///                            move events.</param>
-        private static void Internal_TriggerPointerPressed(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
-            bool ctrl, bool alt, float scrollAmount)
-        {
-            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
-
-            if (OnPointerPressed != null)
-                OnPointerPressed(ev);
-        }
-
-        /// <summary>
-        /// Triggers when some pointing device (mouse cursor, touch) button is released.
-        /// </summary>
-        /// <param name="screenPos">Screen position where the input event occurred.</param>
-        /// <param name="delta">Change in movement since last sent event.</param>
-        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
-        ///                      (e.g. move events don't correspond to a button.</param>
-        /// <param name="shift">Is shift button on the keyboard being held down.</param>
-        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
-        /// <param name="alt">Is alt button on the keyboard being held down.</param>
-        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
-        ///                            move events.</param>
-        private static void Internal_TriggerPointerReleased(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
-            bool ctrl, bool alt, float scrollAmount)
-        {
-            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
-
-            if (OnPointerReleased != null)
-                OnPointerReleased(ev);
-        }
-
-        /// <summary>
-        /// Triggers when some pointing device (mouse cursor, touch) button is double clicked.
-        /// </summary>
-        /// <param name="screenPos">Screen position where the input event occurred.</param>
-        /// <param name="delta">Change in movement since last sent event.</param>
-        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
-        ///                      (e.g. move events don't correspond to a button.</param>
-        /// <param name="shift">Is shift button on the keyboard being held down.</param>
-        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
-        /// <param name="alt">Is alt button on the keyboard being held down.</param>
-        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
-        ///                            move events.</param>
-        private static void Internal_TriggerPointerDoubleClick(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
-            bool ctrl, bool alt, float scrollAmount)
-        {
-            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
-
-            if (OnPointerDoubleClick != null)
-                OnPointerDoubleClick(ev);
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetAxisValue(InputAxis axis, int deviceIdx);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_IsButtonHeld(ButtonCode keyCode, int deviceIdx);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_IsButtonUp(ButtonCode keyCode, int deviceIdx);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_IsButtonDown(ButtonCode keyCode, int deviceIdx);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_IsPointerDoubleClicked();
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_IsPointerButtonHeld(PointerButton keyCode);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_IsPointerButtonUp(PointerButton keyCode);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_IsPointerButtonDown(PointerButton keyCode);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_GetPointerPosition(out Vector2I position);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_GetPointerDelta(out Vector2I delta);
-    }
-
-    /// <summary>
-    /// Contains all possible input buttons, including keyboard scan codes, mouse buttons and gamepad buttons.
-    /// </summary>
-    public enum ButtonCode : uint // Note: Must match C++ enum ButtonCode
-    {
-        Unassigned = 0x00,
-        Escape = 0x01,
-        Num1 = 0x02,
-        Num2 = 0x03,
-        Num3 = 0x04,
-        Num4 = 0x05,
-        Num5 = 0x06,
-        Num6 = 0x07,
-        Num7 = 0x08,
-        Num8 = 0x09,
-        Num9 = 0x0A,
-        Num0 = 0x0B,
-        Minus = 0x0C, 
-        Equals = 0x0D,
-        Back = 0x0E,
-        Tab = 0x0F,
-        Q = 0x10,
-        W = 0x11,
-        E = 0x12,
-        R = 0x13,
-        T = 0x14,
-        Y = 0x15,
-        U = 0x16,
-        I = 0x17,
-        O = 0x18,
-        P = 0x19,
-        LeftBracket = 0x1A,
-        RightBracket = 0x1B,
-        Return = 0x1C,
-        LeftControl = 0x1D,
-        A = 0x1E,
-        S = 0x1F,
-        D = 0x20,
-        F = 0x21,
-        G = 0x22,
-        H = 0x23,
-        J = 0x24,
-        K = 0x25,
-        L = 0x26,
-        Semicolon = 0x27,
-        Apostrophe = 0x28,
-        Grave = 0x29,
-        LeftShift = 0x2A,
-        Backslash = 0x2B,
-        Z = 0x2C,
-        X = 0x2D,
-        C = 0x2E,
-        V = 0x2F,
-        B = 0x30,
-        N = 0x31,
-        M = 0x32,
-        Comma = 0x33,
-        Period = 0x34, 
-        Slash = 0x35,
-        RightShift = 0x36,
-        KeypadMultiply = 0x37,
-        LeftMenu = 0x38,
-        Space = 0x39,
-        CapsLock = 0x3A,
-        F1 = 0x3B,
-        F2 = 0x3C,
-        F3 = 0x3D,
-        F4 = 0x3E,
-        F5 = 0x3F,
-        F6 = 0x40,
-        F7 = 0x41,
-        F8 = 0x42,
-        F9 = 0x43,
-        F10 = 0x44,
-        NumLock = 0x45,
-        ScrollLock = 0x46,
-        Keypad7 = 0x47,
-        Keypad8 = 0x48,
-        Keypad9 = 0x49,
-        KeypadSubtract = 0x4A,
-        Keypad4 = 0x4B,
-        Keypad5 = 0x4C,
-        Keypad6 = 0x4D,
-        KeypadAdd = 0x4E,
-        Keypad1 = 0x4F,
-        Keypad2 = 0x50,
-        Keypad3 = 0x51,
-        Keypad0 = 0x52,
-        KeypadDecimal = 0x53,
-        F11 = 0x57,
-        F12 = 0x58,
-        F13 = 0x64,
-        F14 = 0x65,
-        F15 = 0x66,
-        KeypadEquals = 0x8D,
-        At = 0x91,
-        Colon = 0x92,
-        NumpadEnter = 0x9C,
-        RightControl = 0x9D,
-        KeypadComma = 0xB3,
-        KeypadDivide = 0xB5,
-        RightMenu = 0xB8,
-        Pause = 0xC5,
-        Home = 0xC7,
-        Up = 0xC8,
-        PageUp = 0xC9,
-        Left = 0xCB,
-        Right = 0xCD,
-        End = 0xCF,
-        Down = 0xD0,
-        PageDown = 0xD1,
-        Insert = 0xD2,
-        Delete = 0xD3,
-        LeftWindows = 0xDB,
-        RightWindows = 0xDC,
-        MouseLeft = 0x800000EE,
-        MouseRight = 0x800000EF,
-        MouseMiddle = 0x800000F0,
-        MouseBtn4 = 0x800000F1,
-        MouseBtn5 = 0x800000F2,
-        MouseBtn6 = 0x800000F3,
-        MouseBtn7 = 0x800000F4,
-        MouseBtn8 = 0x800000F5,
-        MouseBtn9 = 0x800000F6,
-        MouseBtn10 = 0x800000F7,
-        MouseBtn11 = 0x800000F8,
-        MouseBtn12 = 0x800000F9,
-        MouseBtn13 = 0x800000FA,
-        MouseBtn14 = 0x800000FB,
-        MouseBtn15 = 0x800000FC,
-        MouseBtn16 = 0x800000FD,
-        GamepadA = 0x4000010F,
-        GamepadB = 0x40000110,
-        GamepadX = 0x40000111,
-        GamepadY = 0x40000112,
-        GamepadLB = 0x40000113,
-        GamepadRB = 0x40000114,
-        GamepadLS = 0x40000115,
-        GamepadRS = 0x40000116,
-        GamepadBack = 0x40000117,
-        GamepadStart = 0x40000118,
-        GamepadDPadLeft = 0x40000119,
-        GamepadDPadRight = 0x4000011A,
-        GamepadDPadUp = 0x4000011B,
-        GamepadDPatDown = 0x4000011C,
-        GamepadBtn1 = 0x4000011D,
-        GamepadBtn2 = 0x4000011E,
-        GamepadBtn3 = 0x4000011F,
-        GamepadBtn4 = 0x40000120,
-        GamepadBtn5 = 0x40000121,
-        GamepadBtn6 = 0x40000122,
-        GamepadBtn7 = 0x40000123,
-        GamepadBtn8 = 0x40000124,
-        GamepadBtn9 = 0x40000125,
-        GamepadBtn10 = 0x40000126,
-        GamepadBtn11 = 0x40000127,
-        GamepadBtn12 = 0x40000128,
-        GamepadBtn13 = 0x40000129,
-        GamepadBtn14 = 0x4000012A,
-        GamepadBtn15 = 0x4000012B,
-        GamepadBtn16 = 0x4000012C,
-        Count = 249,
-        NumKeys = 203, // IMPORTANT: Make sure to update these if you modify the values above
-        NumMouseButtons = 16,
-        NumGamepadButtons = 30,
-    };
-
-    /// <summary>
-    /// Available types of input axes.
-    /// </summary>
-	public enum InputAxis // Note: Must match C++ enum InputBox
-	{
-		MouseX,
-		MouseY,
-		MouseZ,
-		LeftStickX,
-		LeftStickY,
-		RightStickX,
-		RightStickY,
-		LeftTrigger,
-		RightTrigger,
-		Count // Keep at end
-	};
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Contains data about a button input event.
+    /// </summary>
+	public struct ButtonEvent
+	{
+		internal ButtonCode buttonCode;
+        internal int deviceIdx;
+
+        /// <summary>
+        /// Creates a new button input event. For runtime use only.
+        /// </summary>
+        /// <param name="buttonCode">Button code this event is referring to.</param>
+        /// <param name="deviceIdx">Index of the device that the event originated from.</param>
+	    internal ButtonEvent(ButtonCode buttonCode, int deviceIdx)
+	    {
+	        this.buttonCode = buttonCode;
+	        this.deviceIdx = deviceIdx;
+	    }
+
+        /// <summary>
+        /// Button code this event is referring to.
+        /// </summary>
+        public ButtonCode Button { get { return buttonCode; } }
+
+        /// <summary>
+        /// Index of the device that the event originated from.
+        /// </summary>
+        public int DeviceIndex { get { return deviceIdx; } }
+
+        /// <summary>
+        /// Query is the pressed button a keyboard button.
+        /// </summary>
+		public bool IsKeyboard { get { return ((int)buttonCode & 0xC0000000) == 0; }}
+
+        /// <summary>
+        /// Query is the pressed button a mouse button.
+        /// </summary>
+        public bool IsMouse { get { return ((int)buttonCode & 0x80000000) != 0; } }
+
+        /// <summary>
+        /// Query is the pressed button a gamepad button.
+        /// </summary>
+        public bool IsGamepad { get { return ((int)buttonCode & 0x40000000) != 0; } }
+	};
+
+    /// <summary>
+    /// Pointer buttons. Generally these correspond to mouse buttons, but may be used in some form for touch input as well.
+    /// </summary>
+    public enum PointerButton // Note: Must match C++ enum PointerEventButton 
+	{
+		Left, Middle, Right, Count
+	};
+
+    /// <summary>
+    /// Event that gets sent out when user interacts with the screen in some way, usually by moving the mouse cursor or 
+    /// using touch input.
+    /// </summary>
+    public struct PointerEvent
+    {
+        internal Vector2I _screenPos;
+        internal Vector2I _delta;
+        internal PointerButton _button;
+
+        internal bool _shift;
+        internal bool _control;
+        internal bool _alt;
+
+        internal float _mouseWheelScrollAmount;
+
+        /// <summary>
+        /// Creates a new pointer event. For runtime use only.
+        /// </summary>
+        /// <param name="screenPos">Screen position where the input event occurred.</param>
+        /// <param name="delta">Change in movement since last sent event.</param>
+        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
+        ///                      (for example move events don't correspond to a button.</param>
+        /// <param name="shift">Is shift button on the keyboard being held down.</param>
+        /// <param name="control">Is control button on the keyboard being held down.</param>
+        /// <param name="alt">Is alt button on the keyboard being held down.</param>
+        /// <param name="mouseWheelScrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
+        ///                                      move events.</param>
+        internal PointerEvent(Vector2I screenPos, Vector2I delta, PointerButton button,
+            bool shift, bool control, bool alt, float mouseWheelScrollAmount)
+        {
+            _screenPos = screenPos;
+            _delta = delta;
+            _button = button;
+
+            _shift = shift;
+            _control = control;
+            _alt = alt;
+
+            _mouseWheelScrollAmount = mouseWheelScrollAmount;
+        }
+
+        /// <summary>
+        /// Screen position where the input event occurred.
+        /// </summary>
+        public Vector2I ScreenPos { get { return _screenPos; } }
+
+        /// <summary>
+        /// Change in movement since last sent event.
+        /// </summary>
+        public Vector2I Delta { get { return _delta; } }
+
+        /// <summary>
+        /// Button that triggered the pointer event. Might be irrelevant depending on event type. 
+        /// (for example move events don't correspond to a button.
+        /// </summary>
+        public PointerButton Button { get { return _button; } }
+
+        /// <summary>
+        /// Is shift button on the keyboard being held down.
+        /// </summary>
+        public bool Shift { get { return _shift; } }
+
+        /// <summary>
+        /// Is control button on the keyboard being held down.
+        /// </summary>
+        public bool Control { get { return _control; } }
+
+        /// <summary>
+        /// Is alt button on the keyboard being held down.
+        /// </summary>
+        public bool Alt { get { return _alt; } }
+
+        /// <summary>
+        /// If mouse wheel is being scrolled, what is the amount. Only relevant for move events.
+        /// </summary>
+        public float ScrollAmount { get { return _mouseWheelScrollAmount; } }
+    }
+
+    /// <summary>
+    /// Event that gets sent out when user inputs some text. These events may be preceeded by normal button events if user 
+    /// is typing on a keyboard.
+    /// </summary>
+    public struct TextInputEvent
+    {
+        internal int textChar;
+
+        /// <summary>
+        /// Creates a new text input event. For runtime use only.
+        /// </summary>
+        /// <param name="textChar">Character the that was input.</param>
+        internal TextInputEvent(int textChar)
+        {
+            this.textChar = textChar;
+        }
+
+        /// <summary>
+        /// Character the that was input.
+        /// </summary>
+        public int Char { get { return textChar; } }
+    }
+
+    /// <summary>
+    /// Allows you to query and receive events from all connected input devices.
+    /// </summary>
+    public static class Input
+    {
+        public delegate void ButtonEventDelegate(ButtonEvent ev);
+        public delegate void TextInputEventDelegate(TextInputEvent ev);
+        public delegate void PointerEventDelegate(PointerEvent ev);
+
+        /// <summary>
+        /// Triggered when a button on any device is pressed.
+        /// </summary>
+		public static event ButtonEventDelegate OnButtonDown;
+
+        /// <summary>
+        /// Triggered when a button on any device is released.
+        /// </summary>
+        public static event ButtonEventDelegate OnButtonUp;
+
+        /// <summary>
+        /// Triggered when a textual character is entered.
+        /// </summary>
+        public static event TextInputEventDelegate OnCharInput;
+
+        /// <summary>
+        /// Triggered when the pointing device (mouse, touch) is moved.
+        /// </summary>
+        public static event PointerEventDelegate OnPointerMoved;
+
+        /// <summary>
+        /// Triggered when a button on the pointing device (mouse, touch) is pressed.
+        /// </summary>
+        public static event PointerEventDelegate OnPointerPressed;
+
+        /// <summary>
+        /// Triggered when a button on the pointing device (mouse, touch) is released.
+        /// </summary>
+        public static event PointerEventDelegate OnPointerReleased;
+
+        /// <summary>
+        /// Triggered when a button on the pointing device (mouse, touch) is pressed twice in rappid succession.
+        /// </summary>
+        public static event PointerEventDelegate OnPointerDoubleClick;
+
+        /// <summary>
+        /// Returns value of the specified input axis. 
+        /// </summary>
+        /// <param name="axis">Type of axis to query.</param>
+        /// <param name="deviceIdx">Index of the device in case more than one is hooked up (0 - primary).</param>
+        /// <returns>Value of the axis in range [-1.0, 1.0]. Canan be outside the range for devices with unbound axes 
+        ///          (for example mouse).</returns>
+        public static float GetAxisValue(InputAxis axis, int deviceIdx = 0)
+        {
+            return Internal_GetAxisValue(axis, deviceIdx);
+        }
+
+        /// <summary>
+        /// Query if the provided button is currently being held (this frame or previous frames).
+        /// </summary>
+        /// <param name="code">Code of the button to query.</param>
+        /// <param name="deviceIdx">Device to query the button on (0 - primary).</param>
+        /// <returns>True if the button is held.</returns>
+        public static bool IsButtonHeld(ButtonCode code, int deviceIdx = 0)
+        {
+            return Internal_IsButtonHeld(code, deviceIdx);
+        }
+
+        /// <summary>
+        /// Query if the provided button is currently being released (only true for one frame).
+        /// </summary>
+        /// <param name="code">Code of the button to query.</param>
+        /// <param name="deviceIdx">Device to query the button on (0 - primary).</param>
+        /// <returns>True if the button is being released.</returns>
+        public static bool IsButtonUp(ButtonCode code, int deviceIdx = 0)
+        {
+            return Internal_IsButtonUp(code, deviceIdx);
+        }
+
+        /// <summary>
+        /// Query if the provided button is currently being pressed (only true for one frame).
+        /// </summary>
+        /// <param name="code">Code of the button to query.</param>
+        /// <param name="deviceIdx">Device to query the button on (0 - primary).</param>
+        /// <returns>True if the button is being pressed.</returns>
+        public static bool IsButtonDown(ButtonCode code, int deviceIdx = 0)
+        {
+            return Internal_IsButtonDown(code, deviceIdx);
+        }
+
+        /// <summary>
+        /// Query if the provided pointer button is currently being held (this frame or previous frames).
+        /// </summary>
+        /// <param name="code">Code of the button to query.</param>
+        /// <returns>True if the button is being held.</returns>
+        public static bool IsPointerButtonHeld(PointerButton code)
+        {
+            return Internal_IsPointerButtonHeld(code);
+        }
+
+        /// <summary>
+        /// Query if the provided pointer button is currently being being released (only true for one frame).
+        /// </summary>
+        /// <param name="code">Code of the button to query.</param>
+        /// <returns>True if the button is being released.</returns>
+        public static bool IsPointerButtonUp(PointerButton code)
+        {
+            return Internal_IsPointerButtonUp(code);
+        }
+
+        /// <summary>
+        /// Query if the provided pointer button is currently being being pressed (only true for one frame).
+        /// </summary>
+        /// <param name="code">Code of the button to query.</param>
+        /// <returns>True if the button is being pressed.</returns>
+        public static bool IsPointerButtonDown(PointerButton code)
+        {
+            return Internal_IsPointerButtonDown(code);
+        }
+
+        /// <summary>
+        /// Query has the left pointer button been double-clicked this frame.
+        /// </summary>
+        /// <returns>True if double-click occurred.</returns>
+        public static bool IsPointerDoubleClicked()
+        {
+            return Internal_IsPointerDoubleClicked();
+        }
+
+        /// <summary>
+        /// Returns position of the pointer (for example mouse cursor) relative to the screen.
+        /// </summary>
+        public static Vector2I PointerPosition
+        {
+            get
+            {
+                Vector2I value;
+                Internal_GetPointerPosition(out value);
+                return value;
+            }
+        }
+
+        /// <summary>
+        /// Returns difference between last and current pointer position.
+        /// </summary>
+        public static Vector2I PointerDelta
+        {
+            get
+            {
+                Vector2I value;
+                Internal_GetPointerDelta(out value);
+                return value;
+            }
+        }
+
+        /// <summary>
+        /// Triggered by runtime when a button is pressed.
+        /// </summary>
+        /// <param name="code">Code of the pressed button.</param>
+        /// <param name="deviceIdx">Device the event originated from.</param>
+        private static void Internal_TriggerButtonDown(ButtonCode code, int deviceIdx)
+        {
+            ButtonEvent ev = new ButtonEvent(code, deviceIdx);
+
+            if (OnButtonDown != null)
+                OnButtonDown(ev);
+        }
+
+        /// <summary>
+        /// Triggered by runtime when a button is released.
+        /// </summary>
+        /// <param name="code">Code of the released button.</param>
+        /// <param name="deviceIdx">Device the event originated from.</param>
+        private static void Internal_TriggerButtonUp(ButtonCode code, int deviceIdx)
+        {
+            ButtonEvent ev = new ButtonEvent(code, deviceIdx);
+
+            if (OnButtonUp != null)
+                OnButtonUp(ev);
+        }
+
+        /// <summary>
+        /// Triggered by runtime when character is input.
+        /// </summary>
+        /// <param name="textChar">Code of input character.</param>
+        private static void Internal_TriggerCharInput(int textChar)
+        {
+            TextInputEvent ev = new TextInputEvent(textChar);
+
+            if (OnCharInput != null)
+                OnCharInput(ev);
+        }
+
+        /// <summary>
+        /// Triggers when some pointing device (mouse cursor, touch) moves.
+        /// </summary>
+        /// <param name="screenPos">Screen position where the input event occurred.</param>
+        /// <param name="delta">Change in movement since last sent event.</param>
+        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
+        ///                      (for example move events don't correspond to a button.</param>
+        /// <param name="shift">Is shift button on the keyboard being held down.</param>
+        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
+        /// <param name="alt">Is alt button on the keyboard being held down.</param>
+        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
+        ///                            move events.</param>
+        private static void Internal_TriggerPointerMove(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift, 
+            bool ctrl, bool alt, float scrollAmount)
+        {
+            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
+
+            if (OnPointerMoved != null)
+                OnPointerMoved(ev);
+        }
+
+        /// <summary>
+        /// Triggers when some pointing device (mouse cursor, touch) button is pressed.
+        /// </summary>
+        /// <param name="screenPos">Screen position where the input event occurred.</param>
+        /// <param name="delta">Change in movement since last sent event.</param>
+        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
+        ///                      (for example move events don't correspond to a button.</param>
+        /// <param name="shift">Is shift button on the keyboard being held down.</param>
+        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
+        /// <param name="alt">Is alt button on the keyboard being held down.</param>
+        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
+        ///                            move events.</param>
+        private static void Internal_TriggerPointerPressed(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
+            bool ctrl, bool alt, float scrollAmount)
+        {
+            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
+
+            if (OnPointerPressed != null)
+                OnPointerPressed(ev);
+        }
+
+        /// <summary>
+        /// Triggers when some pointing device (mouse cursor, touch) button is released.
+        /// </summary>
+        /// <param name="screenPos">Screen position where the input event occurred.</param>
+        /// <param name="delta">Change in movement since last sent event.</param>
+        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
+        ///                      (for example move events don't correspond to a button.</param>
+        /// <param name="shift">Is shift button on the keyboard being held down.</param>
+        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
+        /// <param name="alt">Is alt button on the keyboard being held down.</param>
+        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
+        ///                            move events.</param>
+        private static void Internal_TriggerPointerReleased(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
+            bool ctrl, bool alt, float scrollAmount)
+        {
+            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
+
+            if (OnPointerReleased != null)
+                OnPointerReleased(ev);
+        }
+
+        /// <summary>
+        /// Triggers when some pointing device (mouse cursor, touch) button is double clicked.
+        /// </summary>
+        /// <param name="screenPos">Screen position where the input event occurred.</param>
+        /// <param name="delta">Change in movement since last sent event.</param>
+        /// <param name="button">Button that triggered the pointer event. Might be irrelevant depending on event type. 
+        ///                      (for example move events don't correspond to a button.</param>
+        /// <param name="shift">Is shift button on the keyboard being held down.</param>
+        /// <param name="ctrl">Is control button on the keyboard being held down.</param>
+        /// <param name="alt">Is alt button on the keyboard being held down.</param>
+        /// <param name="scrollAmount">If mouse wheel is being scrolled, what is the amount. Only relevant for 
+        ///                            move events.</param>
+        private static void Internal_TriggerPointerDoubleClick(Vector2I screenPos, Vector2I delta, PointerButton button, bool shift,
+            bool ctrl, bool alt, float scrollAmount)
+        {
+            PointerEvent ev = new PointerEvent(screenPos, delta, button, shift, ctrl, alt, scrollAmount);
+
+            if (OnPointerDoubleClick != null)
+                OnPointerDoubleClick(ev);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetAxisValue(InputAxis axis, int deviceIdx);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsButtonHeld(ButtonCode keyCode, int deviceIdx);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsButtonUp(ButtonCode keyCode, int deviceIdx);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsButtonDown(ButtonCode keyCode, int deviceIdx);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsPointerDoubleClicked();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsPointerButtonHeld(PointerButton keyCode);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsPointerButtonUp(PointerButton keyCode);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsPointerButtonDown(PointerButton keyCode);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetPointerPosition(out Vector2I position);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetPointerDelta(out Vector2I delta);
+    }
+
+    /// <summary>
+    /// Contains all possible input buttons, including keyboard scan codes, mouse buttons and gamepad buttons.
+    /// </summary>
+    public enum ButtonCode : uint // Note: Must match C++ enum ButtonCode
+    {
+        Unassigned = 0x00,
+        Escape = 0x01,
+        Num1 = 0x02,
+        Num2 = 0x03,
+        Num3 = 0x04,
+        Num4 = 0x05,
+        Num5 = 0x06,
+        Num6 = 0x07,
+        Num7 = 0x08,
+        Num8 = 0x09,
+        Num9 = 0x0A,
+        Num0 = 0x0B,
+        Minus = 0x0C, 
+        Equals = 0x0D,
+        Back = 0x0E,
+        Tab = 0x0F,
+        Q = 0x10,
+        W = 0x11,
+        E = 0x12,
+        R = 0x13,
+        T = 0x14,
+        Y = 0x15,
+        U = 0x16,
+        I = 0x17,
+        O = 0x18,
+        P = 0x19,
+        LeftBracket = 0x1A,
+        RightBracket = 0x1B,
+        Return = 0x1C,
+        LeftControl = 0x1D,
+        A = 0x1E,
+        S = 0x1F,
+        D = 0x20,
+        F = 0x21,
+        G = 0x22,
+        H = 0x23,
+        J = 0x24,
+        K = 0x25,
+        L = 0x26,
+        Semicolon = 0x27,
+        Apostrophe = 0x28,
+        Grave = 0x29,
+        LeftShift = 0x2A,
+        Backslash = 0x2B,
+        Z = 0x2C,
+        X = 0x2D,
+        C = 0x2E,
+        V = 0x2F,
+        B = 0x30,
+        N = 0x31,
+        M = 0x32,
+        Comma = 0x33,
+        Period = 0x34, 
+        Slash = 0x35,
+        RightShift = 0x36,
+        KeypadMultiply = 0x37,
+        LeftMenu = 0x38,
+        Space = 0x39,
+        CapsLock = 0x3A,
+        F1 = 0x3B,
+        F2 = 0x3C,
+        F3 = 0x3D,
+        F4 = 0x3E,
+        F5 = 0x3F,
+        F6 = 0x40,
+        F7 = 0x41,
+        F8 = 0x42,
+        F9 = 0x43,
+        F10 = 0x44,
+        NumLock = 0x45,
+        ScrollLock = 0x46,
+        Keypad7 = 0x47,
+        Keypad8 = 0x48,
+        Keypad9 = 0x49,
+        KeypadSubtract = 0x4A,
+        Keypad4 = 0x4B,
+        Keypad5 = 0x4C,
+        Keypad6 = 0x4D,
+        KeypadAdd = 0x4E,
+        Keypad1 = 0x4F,
+        Keypad2 = 0x50,
+        Keypad3 = 0x51,
+        Keypad0 = 0x52,
+        KeypadDecimal = 0x53,
+        F11 = 0x57,
+        F12 = 0x58,
+        F13 = 0x64,
+        F14 = 0x65,
+        F15 = 0x66,
+        KeypadEquals = 0x8D,
+        At = 0x91,
+        Colon = 0x92,
+        NumpadEnter = 0x9C,
+        RightControl = 0x9D,
+        KeypadComma = 0xB3,
+        KeypadDivide = 0xB5,
+        RightMenu = 0xB8,
+        Pause = 0xC5,
+        Home = 0xC7,
+        Up = 0xC8,
+        PageUp = 0xC9,
+        Left = 0xCB,
+        Right = 0xCD,
+        End = 0xCF,
+        Down = 0xD0,
+        PageDown = 0xD1,
+        Insert = 0xD2,
+        Delete = 0xD3,
+        LeftWindows = 0xDB,
+        RightWindows = 0xDC,
+        MouseLeft = 0x800000EE,
+        MouseRight = 0x800000EF,
+        MouseMiddle = 0x800000F0,
+        MouseBtn4 = 0x800000F1,
+        MouseBtn5 = 0x800000F2,
+        MouseBtn6 = 0x800000F3,
+        MouseBtn7 = 0x800000F4,
+        MouseBtn8 = 0x800000F5,
+        MouseBtn9 = 0x800000F6,
+        MouseBtn10 = 0x800000F7,
+        MouseBtn11 = 0x800000F8,
+        MouseBtn12 = 0x800000F9,
+        MouseBtn13 = 0x800000FA,
+        MouseBtn14 = 0x800000FB,
+        MouseBtn15 = 0x800000FC,
+        MouseBtn16 = 0x800000FD,
+        GamepadA = 0x4000010F,
+        GamepadB = 0x40000110,
+        GamepadX = 0x40000111,
+        GamepadY = 0x40000112,
+        GamepadLB = 0x40000113,
+        GamepadRB = 0x40000114,
+        GamepadLS = 0x40000115,
+        GamepadRS = 0x40000116,
+        GamepadBack = 0x40000117,
+        GamepadStart = 0x40000118,
+        GamepadDPadLeft = 0x40000119,
+        GamepadDPadRight = 0x4000011A,
+        GamepadDPadUp = 0x4000011B,
+        GamepadDPatDown = 0x4000011C,
+        GamepadBtn1 = 0x4000011D,
+        GamepadBtn2 = 0x4000011E,
+        GamepadBtn3 = 0x4000011F,
+        GamepadBtn4 = 0x40000120,
+        GamepadBtn5 = 0x40000121,
+        GamepadBtn6 = 0x40000122,
+        GamepadBtn7 = 0x40000123,
+        GamepadBtn8 = 0x40000124,
+        GamepadBtn9 = 0x40000125,
+        GamepadBtn10 = 0x40000126,
+        GamepadBtn11 = 0x40000127,
+        GamepadBtn12 = 0x40000128,
+        GamepadBtn13 = 0x40000129,
+        GamepadBtn14 = 0x4000012A,
+        GamepadBtn15 = 0x4000012B,
+        GamepadBtn16 = 0x4000012C,
+        Count = 249,
+        NumKeys = 203, // IMPORTANT: Make sure to update these if you modify the values above
+        NumMouseButtons = 16,
+        NumGamepadButtons = 30,
+    };
+
+    /// <summary>
+    /// Available types of input axes.
+    /// </summary>
+	public enum InputAxis // Note: Must match C++ enum InputBox
+	{
+		MouseX,
+		MouseY,
+		MouseZ,
+		LeftStickX,
+		LeftStickY,
+		RightStickX,
+		RightStickY,
+		LeftTrigger,
+		RightTrigger,
+		Count // Keep at end
+	};
+}

+ 83 - 83
Source/MBansheeEngine/LocString.cs

@@ -1,83 +1,83 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Runtime.CompilerServices;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Handle to a localized string.
-    /// </summary>
-    public sealed class LocString : ScriptObject
-    {
-        /// <summary>
-        /// Creates a new empty localized string.
-        /// </summary>
-        public LocString()
-        {
-            Internal_CreateInstance(this, "", 0);
-        }
-
-        /// <summary>
-        /// Creates a new empty localized string.
-        /// </summary>
-        /// <param name="tableId">Unique identifier of the string table to retrieve the string from.</param>
-        public LocString(int tableId)
-        {
-            Internal_CreateInstance(this, "", tableId);
-        }
-
-        /// <summary>
-        /// Creates a new localized string with the specified identifier. If the identifier doesn't previously exist in 
-        /// the string table, identifier value will also be used for initializing the default language version of the string.
-        /// </summary>
-        /// <param name="identifier">String you can use for later referencing the localized string.</param>
-        /// <param name="tableId">Unique identifier of the string table to retrieve the string from.</param>
-        public LocString(string identifier, int tableId = 0)
-        {
-            Internal_CreateInstance(this, identifier, tableId);
-        }
-
-        /// <summary>
-        /// Converts a normal string into a localized string by using the normal string as the identifier.
-        /// </summary>
-        /// <param name="identifier">Localized string identifier.</param>
-        /// <returns>Localized string with the provided identifier, from the default string table.</returns>
-        public static implicit operator LocString(string identifier)
-        {
-            return new LocString(identifier);
-        }
-
-        /// <summary>
-        /// Retrieves localized text for the active language from the localized string.
-        /// </summary>
-        /// <param name="text">Localized string to retrieve the text from.</param>
-        /// <returns>Translated text for the currently active language.</returns>
-        public static explicit operator string(LocString text)
-        {
-            string value;
-            Internal_GetValue(text.mCachedPtr, out value);
-            return value;
-        }
-
-        /// <summary>
-        /// Sets a value of a string parameter. Parameters are specified as bracketed values within the string itself 
-        /// (e.g. {0}, {1}) etc. Use ^ as an escape character.
-        /// </summary>
-        /// <param name="idx">Index of the parameter to set.</param>
-        /// <param name="value">Value to insert at the parameter's position.</param>
-        public void SetParameter(int idx, string value)
-        {
-            Internal_SetParameter(mCachedPtr, idx, value);
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(LocString instance, string identifier, int tableId);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetParameter(IntPtr nativeInstance, int idx, string identifier);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_GetValue(IntPtr nativeInstance, out string value);
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Handle to a localized string.
+    /// </summary>
+    public sealed class LocString : ScriptObject
+    {
+        /// <summary>
+        /// Creates a new empty localized string.
+        /// </summary>
+        public LocString()
+        {
+            Internal_CreateInstance(this, "", 0);
+        }
+
+        /// <summary>
+        /// Creates a new empty localized string.
+        /// </summary>
+        /// <param name="tableId">Unique identifier of the string table to retrieve the string from.</param>
+        public LocString(int tableId)
+        {
+            Internal_CreateInstance(this, "", tableId);
+        }
+
+        /// <summary>
+        /// Creates a new localized string with the specified identifier. If the identifier doesn't previously exist in 
+        /// the string table, identifier value will also be used for initializing the default language version of the string.
+        /// </summary>
+        /// <param name="identifier">String you can use for later referencing the localized string.</param>
+        /// <param name="tableId">Unique identifier of the string table to retrieve the string from.</param>
+        public LocString(string identifier, int tableId = 0)
+        {
+            Internal_CreateInstance(this, identifier, tableId);
+        }
+
+        /// <summary>
+        /// Converts a normal string into a localized string by using the normal string as the identifier.
+        /// </summary>
+        /// <param name="identifier">Localized string identifier.</param>
+        /// <returns>Localized string with the provided identifier, from the default string table.</returns>
+        public static implicit operator LocString(string identifier)
+        {
+            return new LocString(identifier);
+        }
+
+        /// <summary>
+        /// Retrieves localized text for the active language from the localized string.
+        /// </summary>
+        /// <param name="text">Localized string to retrieve the text from.</param>
+        /// <returns>Translated text for the currently active language.</returns>
+        public static explicit operator string(LocString text)
+        {
+            string value;
+            Internal_GetValue(text.mCachedPtr, out value);
+            return value;
+        }
+
+        /// <summary>
+        /// Sets a value of a string parameter. Parameters are specified as bracketed values within the string itself 
+        /// (for example {0}, {1}) etc. Use ^ as an escape character.
+        /// </summary>
+        /// <param name="idx">Index of the parameter to set.</param>
+        /// <param name="value">Value to insert at the parameter's position.</param>
+        public void SetParameter(int idx, string value)
+        {
+            Internal_SetParameter(mCachedPtr, idx, value);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(LocString instance, string identifier, int tableId);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetParameter(IntPtr nativeInstance, int idx, string identifier);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetValue(IntPtr nativeInstance, out string value);
+    }
+}

+ 8 - 8
Source/MBansheeEngine/Physics/D6Joint.cs

@@ -5,8 +5,8 @@ namespace BansheeEngine
     /// <summary>
     /// Represents the most customizable type of joint. This joint type can be used to create all other built-in joint 
     /// types, and to design your own custom ones, but is less intuitive to use.Allows a specification of a linear
-    /// constraint (e.g. for slider), twist constraint(rotating around X) and swing constraint(rotating around Y and Z).
-    /// It also allows you to constrain limits to only specific axes or completely lock specific axes.
+    /// constraint (for example for slider), twist constraint(rotating around X) and swing constraint(rotating around Y and
+    /// Z). It also allows you to constrain limits to only specific axes or completely lock specific axes.
     /// </summary>
     public sealed class D6Joint : Joint
     {
@@ -211,19 +211,19 @@ namespace BansheeEngine
 
         /// <summary>
         /// Allows you to constrain motion of the specified axis. Be aware that when setting drives for a specific axis
-        ///  you must also take care not to constrain its motion in a conflicting way(e.g.you cannot add a drive that
-        /// moves the joint on X axis, and then lock the X axis).
+        /// you must also take care not to constrain its motion in a conflicting way(for example you cannot add a drive
+        /// that moves the joint on X axis, and then lock the X axis).
         /// 
         /// Unlocking translations degrees of freedom allows the bodies to move along the subset of the unlocked axes.
-        /// (e.g.unlocking just one translational axis is the equivalent of a slider joint.)
+        /// (for example unlocking just one translational axis is the equivalent of a slider joint.)
         /// 
         /// Angular degrees of freedom are partitioned as twist(around X axis) and swing(around Y and Z axes). Different
         /// effects can be achieves by unlocking their various combinations: 
         ///  - If a single degree of angular freedom is unlocked it should be the twist degree as it has extra options for
-        ///    that case (e.g. for a hinge joint).
+        ///    that case (for example for a hinge joint).
         ///  - If both swing degrees are unlocked but twist is locked the result is a zero-twist joint.
-        ///  - If one swing and one twist degree of freedom are unlocked the result is a zero-swing joint (e.g.an arm
-        ///    attached at the elbow)
+        ///  - If one swing and one twist degree of freedom are unlocked the result is a zero-swing joint (for example an 
+        ///    arm attached at the elbow)
         ///  - If all angular degrees of freedom are unlocked the result is the same as the spherical joint.
         /// </summary>
         /// <param name="axis">Axis to change the motion type for.</param>

+ 172 - 171
Source/MBansheeEngine/Physics/HingeJoint.cs

@@ -1,171 +1,172 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Hinge joint removes all but a single rotation degree of freedom from its two attached bodies (e.g. a door hinge).
-    /// </summary>
-    public sealed class HingeJoint : Joint
-    {
-        /// <summary>
-        /// Flags to control hinge joint behaviour.
-        /// </summary>
-        [Flags]
-        private enum Flag
-        {
-            Limit = 0x01,
-            Drive = 0x02,
-        }
-
-        [SerializeField]
-        private LimitAngularRange limit = new LimitAngularRange();
-        [SerializeField]
-        private HingeJointDrive drive = new HingeJointDrive();
-        [SerializeField]
-        private Flag flags = 0;
-
-        /// <summary>
-        /// Returns the current angle between the two attached bodes.
-        /// </summary>
-        public Radian Angle
-        {
-            get
-            {
-                if (Native != null)
-                    return Native.Angle;
-
-                return new Radian(0.0f);
-            }
-        }
-
-        /// <summary>
-        /// Returns the current angular speed of the joint.
-        /// </summary>
-        public float Speed
-        {
-            get
-            {
-                if (Native != null)
-                    return Native.Speed;
-
-                return 0.0f;
-            }
-        }
-
-        /// <summary>
-        /// Determines the limit of the joint. Limit constrains the motion to the specified angle range. You must enable
-        /// <see cref="EnableLimit"/> for this to be enforced.
-        /// </summary>
-        public LimitAngularRange Limit
-        {
-            get { return limit; }
-            set
-            {
-                if (limit == value)
-                    return;
-
-                limit = value;
-
-                if (Native != null)
-                    Native.Limit = value;
-            }
-        }
-
-        /// <summary>
-        /// Determines the drive properties of the joint. It drives the joint's angular velocity towards a particular value.
-        /// You must enable <see cref="EnableDrive"/> for this to be applied.
-        /// </summary>
-        public HingeJointDrive Drive
-        {
-            get { return drive; }
-            set
-            {
-                if (drive == value)
-                    return;
-
-                drive = value;
-
-                if (Native != null)
-                    Native.Drive = value;
-            }
-        }
-
-        /// <summary>
-        /// Enables or disables a limit that contrains the joint's motion to a specified angle range.
-        /// </summary>
-        public bool EnableLimit
-        {
-            get { return (flags & Flag.Limit) != 0; }
-            set
-            {
-                if (!SetFlag(Flag.Limit, value))
-                    return;
-
-                if (Native != null)
-                    Native.EnableLimit = value;
-            }
-        }
-
-        /// <summary>
-        /// Enables or disables a drive that drives the joint's angular velocity towards a particular value.
-        /// </summary>
-        public bool EnableDrive
-        {
-            get { return (flags & Flag.Drive) != 0; }
-            set
-            {
-                if (!SetFlag(Flag.Drive, value))
-                    return;
-
-                if (Native != null)
-                    Native.EnableDrive = value;
-            }
-        }
-
-        /// <summary>
-        /// Toggles a specific distance joint flag on or off.
-        /// </summary>
-        /// <param name="flag">Flag to toggle.</param>
-        /// <param name="enabled">Should the flag be turned on or off.</param>
-        /// <returns>True if the new newly set flag state was different from the previous one.</returns>
-        private bool SetFlag(Flag flag, bool enabled)
-        {
-            Flag newFlags = flags;
-
-            if (enabled)
-                newFlags |= flag;
-            else
-                newFlags &= ~flag;
-
-            if (newFlags == flags)
-                return false;
-
-            flags = newFlags;
-            return true;
-        }
-
-        /// <summary>
-        /// Returns the native joint wrapped by this component.
-        /// </summary>
-        private NativeHingeJoint Native
-        {
-            get { return (NativeHingeJoint)native; }
-        }
-
-        /// <inheritdoc/>
-        internal override NativeJoint CreateNative()
-        {
-            NativeHingeJoint joint = new NativeHingeJoint();
-
-            // TODO - Apply this all at once to avoid all the individual interop function calls
-            joint.Limit = limit;
-            joint.Drive = drive;
-            joint.EnableLimit = EnableLimit;
-            joint.EnableDrive = EnableDrive;
-
-            return joint;
-        }
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Hinge joint removes all but a single rotation degree of freedom from its two attached bodies (for example a door
+    /// hinge).
+    /// </summary>
+    public sealed class HingeJoint : Joint
+    {
+        /// <summary>
+        /// Flags to control hinge joint behaviour.
+        /// </summary>
+        [Flags]
+        private enum Flag
+        {
+            Limit = 0x01,
+            Drive = 0x02,
+        }
+
+        [SerializeField]
+        private LimitAngularRange limit = new LimitAngularRange();
+        [SerializeField]
+        private HingeJointDrive drive = new HingeJointDrive();
+        [SerializeField]
+        private Flag flags = 0;
+
+        /// <summary>
+        /// Returns the current angle between the two attached bodes.
+        /// </summary>
+        public Radian Angle
+        {
+            get
+            {
+                if (Native != null)
+                    return Native.Angle;
+
+                return new Radian(0.0f);
+            }
+        }
+
+        /// <summary>
+        /// Returns the current angular speed of the joint.
+        /// </summary>
+        public float Speed
+        {
+            get
+            {
+                if (Native != null)
+                    return Native.Speed;
+
+                return 0.0f;
+            }
+        }
+
+        /// <summary>
+        /// Determines the limit of the joint. Limit constrains the motion to the specified angle range. You must enable
+        /// <see cref="EnableLimit"/> for this to be enforced.
+        /// </summary>
+        public LimitAngularRange Limit
+        {
+            get { return limit; }
+            set
+            {
+                if (limit == value)
+                    return;
+
+                limit = value;
+
+                if (Native != null)
+                    Native.Limit = value;
+            }
+        }
+
+        /// <summary>
+        /// Determines the drive properties of the joint. It drives the joint's angular velocity towards a particular value.
+        /// You must enable <see cref="EnableDrive"/> for this to be applied.
+        /// </summary>
+        public HingeJointDrive Drive
+        {
+            get { return drive; }
+            set
+            {
+                if (drive == value)
+                    return;
+
+                drive = value;
+
+                if (Native != null)
+                    Native.Drive = value;
+            }
+        }
+
+        /// <summary>
+        /// Enables or disables a limit that contrains the joint's motion to a specified angle range.
+        /// </summary>
+        public bool EnableLimit
+        {
+            get { return (flags & Flag.Limit) != 0; }
+            set
+            {
+                if (!SetFlag(Flag.Limit, value))
+                    return;
+
+                if (Native != null)
+                    Native.EnableLimit = value;
+            }
+        }
+
+        /// <summary>
+        /// Enables or disables a drive that drives the joint's angular velocity towards a particular value.
+        /// </summary>
+        public bool EnableDrive
+        {
+            get { return (flags & Flag.Drive) != 0; }
+            set
+            {
+                if (!SetFlag(Flag.Drive, value))
+                    return;
+
+                if (Native != null)
+                    Native.EnableDrive = value;
+            }
+        }
+
+        /// <summary>
+        /// Toggles a specific distance joint flag on or off.
+        /// </summary>
+        /// <param name="flag">Flag to toggle.</param>
+        /// <param name="enabled">Should the flag be turned on or off.</param>
+        /// <returns>True if the new newly set flag state was different from the previous one.</returns>
+        private bool SetFlag(Flag flag, bool enabled)
+        {
+            Flag newFlags = flags;
+
+            if (enabled)
+                newFlags |= flag;
+            else
+                newFlags &= ~flag;
+
+            if (newFlags == flags)
+                return false;
+
+            flags = newFlags;
+            return true;
+        }
+
+        /// <summary>
+        /// Returns the native joint wrapped by this component.
+        /// </summary>
+        private NativeHingeJoint Native
+        {
+            get { return (NativeHingeJoint)native; }
+        }
+
+        /// <inheritdoc/>
+        internal override NativeJoint CreateNative()
+        {
+            NativeHingeJoint joint = new NativeHingeJoint();
+
+            // TODO - Apply this all at once to avoid all the individual interop function calls
+            joint.Limit = limit;
+            joint.Drive = drive;
+            joint.EnableLimit = EnableLimit;
+            joint.EnableDrive = EnableDrive;
+
+            return joint;
+        }
+    }
+}

+ 2 - 2
Source/MBansheeEngine/Physics/Joint.cs

@@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
 namespace BansheeEngine
 {
     /// <summary>
-    /// Base class for all Joint types. Joints constrain how two rigidbodies move relative to one another (e.g. a door 
-    /// hinge). One of the bodies in the joint must always be movable (i.e. non-kinematic).
+    /// Base class for all Joint types. Joints constrain how two rigidbodies move relative to one another (for example a
+    /// door hinge). One of the bodies in the joint must always be movable (that is non-kinematic).
     /// </summary>
     public abstract class Joint : Component
     {

+ 87 - 87
Source/MBansheeEngine/Physics/PhysicsMaterial.cs

@@ -1,87 +1,87 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Runtime.CompilerServices;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Material that controls how two physical objects interact with each other. Materials of both objects are used during
-    /// their interaction and their combined values are used.
-    /// </summary>
-    public class PhysicsMaterial : Resource
-    {
-        /// <summary>
-        /// Constructor for internal use by the runtime.
-        /// </summary>
-        private PhysicsMaterial(int dummy)
-        { }
-
-        /// <summary>
-        /// Creates a brand new physics material.
-        /// </summary>
-        /// <param name="staticFriction">Controls friction when two in-contact objects are not moving lateral to each other.
-        ///                              </param>
-        /// <param name="dynamicFriction">Controls friction when two in-contact objects are moving lateral to each other.
-        ///                               </param>
-        /// <param name="restitution">Controls "bounciness" of an object during a collision. Value of 1 means the collision
-        /// is elastic, and value of 0 means the value is inelastic.</param>
-        public PhysicsMaterial(float staticFriction = 0.0f, float dynamicFriction = 0.0f, float restitution = 0.0f)
-        {
-            Internal_CreateInstance(this, staticFriction, dynamicFriction, restitution);
-        }
-
-        /// <summary>
-        /// Controls friction when two in-contact objects are not moving lateral to each other (e.g. how difficult is to 
-        /// get an object moving from a static state while it is in contact other object(s)).
-        /// </summary>
-        public float StaticFriction
-        {
-            get { return Internal_GetStaticFriction(mCachedPtr); }
-            set { Internal_SetStaticFriction(mCachedPtr, value); }
-        }
-
-
-        /// <summary>
-        /// Controls friction when two in-contact objects are moving lateral to each other (e.g. how quickly does an object
-        /// slow down when sliding along another object).
-        /// </summary>
-        public float DynamicFriction
-        {
-            get { return Internal_GetDynamicFriction(mCachedPtr); }
-            set { Internal_SetDynamicFriction(mCachedPtr, value); }
-        }
-
-        /// <summary>
-        /// Controls "bounciness" of an object during a collision. Value of 1 means the collision is elastic, and value
-        /// of 0 means the value is inelastic. Must be in [0, 1] range.
-        /// </summary>
-        public float Restitution
-        {
-            get { return Internal_GetRestitution(mCachedPtr); }
-            set { Internal_SetRestitution(mCachedPtr, value); }
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(PhysicsMaterial instance, float staticFriction,
-            float dynamicFriction, float restitution);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetStaticFriction(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetStaticFriction(IntPtr thisPtr, float value);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetDynamicFriction(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetDynamicFriction(IntPtr thisPtr, float value);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetRestitution(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetRestitution(IntPtr thisPtr, float value);
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Material that controls how two physical objects interact with each other. Materials of both objects are used during
+    /// their interaction and their combined values are used.
+    /// </summary>
+    public class PhysicsMaterial : Resource
+    {
+        /// <summary>
+        /// Constructor for internal use by the runtime.
+        /// </summary>
+        private PhysicsMaterial(int dummy)
+        { }
+
+        /// <summary>
+        /// Creates a brand new physics material.
+        /// </summary>
+        /// <param name="staticFriction">Controls friction when two in-contact objects are not moving lateral to each other.
+        ///                              </param>
+        /// <param name="dynamicFriction">Controls friction when two in-contact objects are moving lateral to each other.
+        ///                               </param>
+        /// <param name="restitution">Controls "bounciness" of an object during a collision. Value of 1 means the collision
+        /// is elastic, and value of 0 means the value is inelastic.</param>
+        public PhysicsMaterial(float staticFriction = 0.0f, float dynamicFriction = 0.0f, float restitution = 0.0f)
+        {
+            Internal_CreateInstance(this, staticFriction, dynamicFriction, restitution);
+        }
+
+        /// <summary>
+        /// Controls friction when two in-contact objects are not moving lateral to each other (for example how difficult is
+        /// to get an object moving from a static state while it is in contact other object(s)).
+        /// </summary>
+        public float StaticFriction
+        {
+            get { return Internal_GetStaticFriction(mCachedPtr); }
+            set { Internal_SetStaticFriction(mCachedPtr, value); }
+        }
+
+
+        /// <summary>
+        /// Controls friction when two in-contact objects are moving lateral to each other (for example how quickly does an
+        /// object slow down when sliding along another object).
+        /// </summary>
+        public float DynamicFriction
+        {
+            get { return Internal_GetDynamicFriction(mCachedPtr); }
+            set { Internal_SetDynamicFriction(mCachedPtr, value); }
+        }
+
+        /// <summary>
+        /// Controls "bounciness" of an object during a collision. Value of 1 means the collision is elastic, and value
+        /// of 0 means the value is inelastic. Must be in [0, 1] range.
+        /// </summary>
+        public float Restitution
+        {
+            get { return Internal_GetRestitution(mCachedPtr); }
+            set { Internal_SetRestitution(mCachedPtr, value); }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(PhysicsMaterial instance, float staticFriction,
+            float dynamicFriction, float restitution);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetStaticFriction(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetStaticFriction(IntPtr thisPtr, float value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetDynamicFriction(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetDynamicFriction(IntPtr thisPtr, float value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetRestitution(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetRestitution(IntPtr thisPtr, float value);
+    }
+}

+ 3 - 3
Source/MBansheeEngine/Physics/Rigidbody.cs

@@ -58,9 +58,9 @@ namespace BansheeEngine
         }
 
         /// <summary>
-        /// Determines if the body is kinematic. Kinematic body will not move in response to external forces (e.g. gravity,
-        /// or another object pushing it), essentially behaving like collider. Unlike a collider though, you can still move
-        /// the object and have other dynamic objects respond correctly (i.e. it will push other objects).
+        /// Determines if the body is kinematic. Kinematic body will not move in response to external forces (for example
+        /// gravity, or another object pushing it), essentially behaving like collider. Unlike a collider though, you can
+        /// still move the object and have other dynamic objects respond correctly (that is, it will push other objects).
         /// </summary>
         public bool Kinematic
         {

+ 48 - 48
Source/MBansheeEngine/Prefab.cs

@@ -1,48 +1,48 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Prefab is a saveable hierarchy of scene objects. In general it can serve as any grouping of scene objects 
-    /// (e.g. a level) or be used as a form of a template instantiated and reused throughout the scene.
-    /// </summary>
-    public class Prefab : Resource
-    {
-        /// <summary>
-        /// Constructor for internal use by the runtime.
-        /// </summary>
-        private Prefab()
-        { }
-
-        /// <summary>
-        /// Creates a new prefab from the provided scene object. If the scene object has an existing prefab link it will 
-        /// be broken. After the prefab is created the scene object will be automatically linked to it.
-        /// </summary>
-        /// <param name="so">Scene object to generate the prefab for.</param>
-        public Prefab(SceneObject so)
-        {
-            IntPtr soPtr = so.GetCachedPtr();
-            Internal_CreateInstance(this, soPtr);
-        }
-
-        /// <summary>
-        /// Instantiates a prefab by creating an instance of the prefab's scene object hierarchy. The returned hierarchy 
-        /// will be parented to world root by default.
-        /// </summary>
-        /// <returns>New scene object instance containing a copy of the prefab's hierarchy.</returns>
-        public SceneObject Instantiate()
-        {
-            return Internal_Instantiate(mCachedPtr);
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(Prefab instance, IntPtr so);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern SceneObject Internal_Instantiate(IntPtr thisPtr);
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Prefab is a saveable hierarchy of scene objects. In general it can serve as any grouping of scene objects 
+    /// (for example a level) or be used as a form of a template instantiated and reused throughout the scene.
+    /// </summary>
+    public class Prefab : Resource
+    {
+        /// <summary>
+        /// Constructor for internal use by the runtime.
+        /// </summary>
+        private Prefab()
+        { }
+
+        /// <summary>
+        /// Creates a new prefab from the provided scene object. If the scene object has an existing prefab link it will 
+        /// be broken. After the prefab is created the scene object will be automatically linked to it.
+        /// </summary>
+        /// <param name="so">Scene object to generate the prefab for.</param>
+        public Prefab(SceneObject so)
+        {
+            IntPtr soPtr = so.GetCachedPtr();
+            Internal_CreateInstance(this, soPtr);
+        }
+
+        /// <summary>
+        /// Instantiates a prefab by creating an instance of the prefab's scene object hierarchy. The returned hierarchy 
+        /// will be parented to world root by default.
+        /// </summary>
+        /// <returns>New scene object instance containing a copy of the prefab's hierarchy.</returns>
+        public SceneObject Instantiate()
+        {
+            return Internal_Instantiate(mCachedPtr);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(Prefab instance, IntPtr so);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern SceneObject Internal_Instantiate(IntPtr thisPtr);
+    }
+}

+ 112 - 112
Source/MBansheeEngine/Resources.cs

@@ -1,112 +1,112 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Runtime.CompilerServices;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Handles dynamic loading of resources during runtime. 
-    /// </summary>
-    public static class Resources
-    {
-        /// <summary>
-        /// Loads a resource at the specified path. If running outside of the editor you must make sure to mark that 
-        /// the resource gets included in the build. If running inside the editor this has similar functionality as
-        /// if loading using the project library. If resource is already loaded an existing instance is returned.
-        /// 
-        /// All resources are automatically unloaded when they go out of scope unless <see cref="keepLoaded"/> parameter
-        /// is specified. 
-        /// </summary>
-        /// <typeparam name="T">Type of the resource.</typeparam>
-        /// <param name="path">Path of the resource, relative to game directory. If running from editor this will be
-        ///                    the same location as resource location in the project library. If a sub-resource within
-        ///                    a file is needed, append the name of the subresource to the path (e.g. 
-        ///                    mymesh.fbx/my_animation).</param>
-        /// <param name="keepLoaded">If true the system will keep the resource loaded even when it goes out of scope.
-        ///                          You must call <see cref="Release(Resource)"/> in order to allow the resource to be
-        ///                          unloaded (it must be called once for each corresponding load). </param>
-        /// <returns>Loaded resource, or null if resource cannot be found.</returns>
-        public static T Load<T>(string path, bool keepLoaded = true) where T : Resource
-        {
-            return (T)Internal_Load(path, keepLoaded);
-        }
-
-        /// <summary>
-        /// Loads a resource referenced by the provided reference. If running outside of the editor you must make sure 
-        /// to mark that the resource gets included in the build. If running inside the editor this has similar functionality 
-        /// as if loading using the project library. If resource is already loaded an existing instance is returned.
-        ///
-        /// All resources are automatically unloaded when they go out of scope unless <see cref="keepLoaded"/> parameter
-        /// is specified.
-        /// </summary>
-        /// <typeparam name="T">Type of the resource.</typeparam>
-        /// <param name="reference">Reference to the resource to load.</param>
-        /// <param name="keepLoaded">If true the system will keep the resource loaded even when it goes out of scope.
-        ///                          You must call <see cref="Release(ResourceRef)"/> in order to allow the resource to be
-        ///                          unloaded (it must be called once for each corresponding load). </param> 
-        /// <returns>Loaded resource, or null if resource cannot be found.</returns>
-        public static T Load<T>(ResourceRef reference, bool keepLoaded = true) where T : Resource
-        {
-            return (T)Internal_LoadRef(reference, keepLoaded);
-        }
-
-        /// <summary>
-        /// Releases an internal reference to the resource held by the resources system. This allows the resource
-        ///	to be unloaded when it goes out of scope, if the resource was loaded with "keepLoaded" parameter.
-        ///
-        /// Alternatively you can also skip manually calling <see cref="Release(ResourceRef)"/> and call <see cref="UnloadUnused"/> 
-        /// which will unload all resources that do not have any external references, but you lose the fine grained control 
-        /// of what will be unloaded.
-        /// </summary>
-        /// <param name="resource">Resource to release</param>
-        public static void Release(ResourceRef resource)
-        {
-            if (resource == null)
-                return;
-
-            Internal_ReleaseRef(resource.GetCachedPtr());
-        }
-
-        /// <summary>
-        /// Releases an internal reference to the resource held by the resources system. This allows the resource
-        ///	to be unloaded when it goes out of scope, if the resource was loaded with "keepLoaded" parameter.
-        ///
-        /// Alternatively you can also skip manually calling <see cref="Release(Resource)"/> and call <see cref="UnloadUnused"/> 
-        /// which will unload all resources that do not have any external references, but you lose the fine grained control 
-        /// of what will be unloaded.
-        /// </summary>
-        /// <param name="resource">Resource to release</param>
-        public static void Release(Resource resource)
-        {
-            if(resource == null)
-                return;
-
-            Internal_Release(resource.GetCachedPtr());
-        }
-
-        /// <summary>
-        /// Unloads all resources that are no longer referenced. This only applies to resources loaded with "keepLoaded"
-        /// parameter, as all other resources will be unloaded when they go out of scope.
-        /// </summary>
-        public static void UnloadUnused()
-        {
-            Internal_UnloadUnused();
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern Resource Internal_Load(string path, bool keepLoaded);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern Resource Internal_LoadRef(ResourceRef reference, bool keepLoaded);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_Release(IntPtr resource);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_ReleaseRef(IntPtr resource);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_UnloadUnused();
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Handles dynamic loading of resources during runtime. 
+    /// </summary>
+    public static class Resources
+    {
+        /// <summary>
+        /// Loads a resource at the specified path. If running outside of the editor you must make sure to mark that 
+        /// the resource gets included in the build. If running inside the editor this has similar functionality as
+        /// if loading using the project library. If resource is already loaded an existing instance is returned.
+        /// 
+        /// All resources are automatically unloaded when they go out of scope unless <see cref="keepLoaded"/> parameter
+        /// is specified. 
+        /// </summary>
+        /// <typeparam name="T">Type of the resource.</typeparam>
+        /// <param name="path">Path of the resource, relative to game directory. If running from editor this will be
+        ///                    the same location as resource location in the project library. If a sub-resource within
+        ///                    a file is needed, append the name of the subresource to the path (for example 
+        ///                    mymesh.fbx/my_animation).</param>
+        /// <param name="keepLoaded">If true the system will keep the resource loaded even when it goes out of scope.
+        ///                          You must call <see cref="Release(Resource)"/> in order to allow the resource to be
+        ///                          unloaded (it must be called once for each corresponding load). </param>
+        /// <returns>Loaded resource, or null if resource cannot be found.</returns>
+        public static T Load<T>(string path, bool keepLoaded = true) where T : Resource
+        {
+            return (T)Internal_Load(path, keepLoaded);
+        }
+
+        /// <summary>
+        /// Loads a resource referenced by the provided reference. If running outside of the editor you must make sure 
+        /// to mark that the resource gets included in the build. If running inside the editor this has similar functionality 
+        /// as if loading using the project library. If resource is already loaded an existing instance is returned.
+        ///
+        /// All resources are automatically unloaded when they go out of scope unless <see cref="keepLoaded"/> parameter
+        /// is specified.
+        /// </summary>
+        /// <typeparam name="T">Type of the resource.</typeparam>
+        /// <param name="reference">Reference to the resource to load.</param>
+        /// <param name="keepLoaded">If true the system will keep the resource loaded even when it goes out of scope.
+        ///                          You must call <see cref="Release(ResourceRef)"/> in order to allow the resource to be
+        ///                          unloaded (it must be called once for each corresponding load). </param> 
+        /// <returns>Loaded resource, or null if resource cannot be found.</returns>
+        public static T Load<T>(ResourceRef reference, bool keepLoaded = true) where T : Resource
+        {
+            return (T)Internal_LoadRef(reference, keepLoaded);
+        }
+
+        /// <summary>
+        /// Releases an internal reference to the resource held by the resources system. This allows the resource
+        ///	to be unloaded when it goes out of scope, if the resource was loaded with "keepLoaded" parameter.
+        ///
+        /// Alternatively you can also skip manually calling <see cref="Release(ResourceRef)"/> and call <see cref="UnloadUnused"/> 
+        /// which will unload all resources that do not have any external references, but you lose the fine grained control 
+        /// of what will be unloaded.
+        /// </summary>
+        /// <param name="resource">Resource to release</param>
+        public static void Release(ResourceRef resource)
+        {
+            if (resource == null)
+                return;
+
+            Internal_ReleaseRef(resource.GetCachedPtr());
+        }
+
+        /// <summary>
+        /// Releases an internal reference to the resource held by the resources system. This allows the resource
+        ///	to be unloaded when it goes out of scope, if the resource was loaded with "keepLoaded" parameter.
+        ///
+        /// Alternatively you can also skip manually calling <see cref="Release(Resource)"/> and call <see cref="UnloadUnused"/> 
+        /// which will unload all resources that do not have any external references, but you lose the fine grained control 
+        /// of what will be unloaded.
+        /// </summary>
+        /// <param name="resource">Resource to release</param>
+        public static void Release(Resource resource)
+        {
+            if(resource == null)
+                return;
+
+            Internal_Release(resource.GetCachedPtr());
+        }
+
+        /// <summary>
+        /// Unloads all resources that are no longer referenced. This only applies to resources loaded with "keepLoaded"
+        /// parameter, as all other resources will be unloaded when they go out of scope.
+        /// </summary>
+        public static void UnloadUnused()
+        {
+            Internal_UnloadUnused();
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Resource Internal_Load(string path, bool keepLoaded);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Resource Internal_LoadRef(ResourceRef reference, bool keepLoaded);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Release(IntPtr resource);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_ReleaseRef(IntPtr resource);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_UnloadUnused();
+    }
+}

+ 122 - 122
Source/MBansheeEngine/SpriteTexture.cs

@@ -1,122 +1,122 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Runtime.CompilerServices;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Texture interface that encapsulates underlying texture which allows us to create a sprite texture atlas 
-    /// (e.g. multiple sprite textures referencing different parts of a single texture).
-    /// </summary>
-    public sealed class SpriteTexture : Resource
-    {
-        /// <summary>
-        /// Constructor for internal use by the runtime.
-        /// </summary>
-        private SpriteTexture()
-        { }
-
-        /// <summary>
-        /// Creates a new sprite texture that references the entire area of the provided texture.
-        /// </summary>
-        /// <param name="texture">Texture to wrap by the sprite texture.</param>
-        public SpriteTexture(Texture2D texture)
-        {
-            Vector2 offset = Vector2.Zero;
-            Vector2 scale = Vector2.One;
-
-            Internal_CreateInstance(this, texture, ref offset, ref scale);
-        }
-
-        /// <summary>
-        /// Creates a new sprite texture that references a sub-area of the provided texture.
-        /// </summary>
-        /// <param name="texture">Texture to wrap by the sprite texture.</param>
-        /// <param name="uvOffset">Top-left position of the area used by the sprite texture, in normalized coordinates.
-        ///                        </param>
-        /// <param name="uvScale">Size of the area used by the sprite texture, in normalized coordinates.</param>
-        public SpriteTexture(Texture2D texture, Vector2 uvOffset, Vector2 uvScale)
-        {
-            Internal_CreateInstance(this, texture, ref uvOffset, ref uvScale);
-        }
-
-        /// <summary>
-        /// Texture that the sprite texture references.
-        /// </summary>
-        public Texture2D Texture
-        {
-            get { return Internal_GetTexture(mCachedPtr); }
-            set
-            {
-                IntPtr texturePtr = IntPtr.Zero;
-                if (value != null)
-                    texturePtr = value.GetCachedPtr();
-
-                Internal_SetTexture(mCachedPtr, texturePtr);
-            }
-        }
-
-        /// <summary>
-        /// Offset into the referenced texture where the sprite starts. In UV coordinates, range [0, 1].
-        /// </summary>
-        public Vector2 Offset
-        {
-            get { Vector2 value; Internal_GetOffset(mCachedPtr, out value); return value; }
-            set { Internal_SetOffset(mCachedPtr, ref value); }
-        }
-
-        /// <summary>
-        /// Size of the sprite in the referenced texture. In UV coordinates, range [0, 1].
-        /// </summary>
-        public Vector2 Scale
-        {
-            get { Vector2 value; Internal_GetScale(mCachedPtr, out value); return value; }
-            set { Internal_SetScale(mCachedPtr, ref value); }
-        }
-
-        /// <summary>
-        /// Returns width of the sprite texture in pixels.
-        /// </summary>
-        public int Width
-        {
-            get { return Internal_GetWidth(mCachedPtr); }
-        }
-
-        /// <summary>
-        /// Returns height of the sprite texture in pixels.
-        /// </summary>
-        public int Height
-        {
-            get { return Internal_GetHeight(mCachedPtr); }
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(SpriteTexture instance, 
-            Texture2D texture, ref Vector2 offset, ref Vector2 scale);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern Texture2D Internal_GetTexture(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetTexture(IntPtr thisPtr, IntPtr value);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_GetOffset(IntPtr thisPtr, out Vector2 value);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetOffset(IntPtr thisPtr, ref Vector2 value);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_GetScale(IntPtr thisPtr, out Vector2 value);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetScale(IntPtr thisPtr, ref Vector2 value);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern int Internal_GetWidth(IntPtr thisPtr);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern int Internal_GetHeight(IntPtr thisPtr);
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Texture interface that encapsulates underlying texture which allows us to create a sprite texture atlas 
+    /// (for example multiple sprite textures referencing different parts of a single texture).
+    /// </summary>
+    public sealed class SpriteTexture : Resource
+    {
+        /// <summary>
+        /// Constructor for internal use by the runtime.
+        /// </summary>
+        private SpriteTexture()
+        { }
+
+        /// <summary>
+        /// Creates a new sprite texture that references the entire area of the provided texture.
+        /// </summary>
+        /// <param name="texture">Texture to wrap by the sprite texture.</param>
+        public SpriteTexture(Texture2D texture)
+        {
+            Vector2 offset = Vector2.Zero;
+            Vector2 scale = Vector2.One;
+
+            Internal_CreateInstance(this, texture, ref offset, ref scale);
+        }
+
+        /// <summary>
+        /// Creates a new sprite texture that references a sub-area of the provided texture.
+        /// </summary>
+        /// <param name="texture">Texture to wrap by the sprite texture.</param>
+        /// <param name="uvOffset">Top-left position of the area used by the sprite texture, in normalized coordinates.
+        ///                        </param>
+        /// <param name="uvScale">Size of the area used by the sprite texture, in normalized coordinates.</param>
+        public SpriteTexture(Texture2D texture, Vector2 uvOffset, Vector2 uvScale)
+        {
+            Internal_CreateInstance(this, texture, ref uvOffset, ref uvScale);
+        }
+
+        /// <summary>
+        /// Texture that the sprite texture references.
+        /// </summary>
+        public Texture2D Texture
+        {
+            get { return Internal_GetTexture(mCachedPtr); }
+            set
+            {
+                IntPtr texturePtr = IntPtr.Zero;
+                if (value != null)
+                    texturePtr = value.GetCachedPtr();
+
+                Internal_SetTexture(mCachedPtr, texturePtr);
+            }
+        }
+
+        /// <summary>
+        /// Offset into the referenced texture where the sprite starts. In UV coordinates, range [0, 1].
+        /// </summary>
+        public Vector2 Offset
+        {
+            get { Vector2 value; Internal_GetOffset(mCachedPtr, out value); return value; }
+            set { Internal_SetOffset(mCachedPtr, ref value); }
+        }
+
+        /// <summary>
+        /// Size of the sprite in the referenced texture. In UV coordinates, range [0, 1].
+        /// </summary>
+        public Vector2 Scale
+        {
+            get { Vector2 value; Internal_GetScale(mCachedPtr, out value); return value; }
+            set { Internal_SetScale(mCachedPtr, ref value); }
+        }
+
+        /// <summary>
+        /// Returns width of the sprite texture in pixels.
+        /// </summary>
+        public int Width
+        {
+            get { return Internal_GetWidth(mCachedPtr); }
+        }
+
+        /// <summary>
+        /// Returns height of the sprite texture in pixels.
+        /// </summary>
+        public int Height
+        {
+            get { return Internal_GetHeight(mCachedPtr); }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(SpriteTexture instance, 
+            Texture2D texture, ref Vector2 offset, ref Vector2 scale);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern Texture2D Internal_GetTexture(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetTexture(IntPtr thisPtr, IntPtr value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetOffset(IntPtr thisPtr, out Vector2 value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetOffset(IntPtr thisPtr, ref Vector2 value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetScale(IntPtr thisPtr, out Vector2 value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetScale(IntPtr thisPtr, ref Vector2 value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetWidth(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetHeight(IntPtr thisPtr);
+    }
+}

+ 141 - 141
Source/MBansheeEngine/VirtualInput.cs

@@ -1,141 +1,141 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System.Runtime.CompilerServices;
-
-namespace BansheeEngine
-{
-    /// <summary>
-    /// Handles virtual input that allows you to receive virtual input events that hide the actual physical input, allowing 
-    /// you to easily change the input keys while being transparent to the external code.
-    /// </summary>
-    public static class VirtualInput
-    {
-        public delegate void OnButtonEventDelegate(VirtualButton btn, int deviceIdx);
-
-        /// <summary>
-        /// Triggered when a physical button combination corresponding to a virtual button is pressed.
-        /// </summary>
-        public static event OnButtonEventDelegate OnButtonDown;
-
-        /// <summary>
-        /// Triggered when a physical button combination corresponding to a virtual button is released.
-        /// </summary>
-        public static event OnButtonEventDelegate OnButtonUp;
-
-        /// <summary>
-        /// Triggered every frame while a physical button combination corresponding to a virtual button is being held down.
-        /// </summary>
-        public static event OnButtonEventDelegate OnButtonHeld;
-
-        /// <summary>
-        /// Input configuration that describes how physical keys map to virtual keys.
-        /// </summary>
-        public static InputConfiguration KeyConfig
-        {
-            get
-            {
-                return Internal_GetKeyConfig();
-            }
-
-            set
-            {
-                Internal_SetKeyConfig(value);
-            }
-        }
-
-        /// <summary>
-        /// Checks if the physical button combination corresponding to the specified virtual button is being pressed this
-        /// frame.
-        /// </summary>
-        /// <param name="button">Virtual button to check.</param>
-        /// <param name="deviceIdx">Optional device index in case multiple input devices are available.</param>
-		public static bool IsButtonDown(VirtualButton button, int deviceIdx = 0)
-	    {
-            return Internal_IsButtonDown(ref button, deviceIdx);
-	    }
-
-        /// <summary>
-        /// Checks if the physical button combination corresponding to the specified virtual button is being released this
-        /// frame.
-        /// </summary>
-        /// <param name="button">Virtual button to check.</param>
-        /// <param name="deviceIdx">Optional device index in case multiple input devices are available.</param>
-        public static bool IsButtonUp(VirtualButton button, int deviceIdx = 0)
-        {
-            return Internal_IsButtonUp(ref button, deviceIdx);
-        }
-
-        /// <summary>
-        /// Checks if the physical button combination corresponding to the specified virtual button is being held down.
-        /// </summary>
-        /// <param name="button">Virtual button to check.</param>
-        /// <param name="deviceIdx">Index of the device to check.</param>
-        public static bool IsButtonHeld(VirtualButton button, int deviceIdx = 0)
-        {
-            return Internal_IsButtonHeld(ref button, deviceIdx);
-        }
-
-        /// <summary>
-        /// Returns normalized value for the specified input axis. 
-        /// </summary>
-        /// <param name="axis">Virtual axis identifier.</param>
-        /// <param name="deviceIdx">Optional device index in case multiple input devices are available.</param>
-        /// <returns>Axis value, normally in [-1.0, 1.0] range, but can be outside the range for devices with unbound axes 
-        ///          (e.g. mouse).</returns>
-        public static float GetAxisValue(VirtualAxis axis, int deviceIdx = 0)
-        {
-            return Internal_GetAxisValue(ref axis, deviceIdx);
-        }
-
-        /// <summary>
-        /// Triggered by the runtime when the virtual button is pressed.
-        /// </summary>
-        /// <param name="button">Virtual button that was pressed.</param>
-        /// <param name="deviceIdx">Index of the device the button was pressed on.</param>
-        private static void Internal_TriggerButtonDown(VirtualButton button, int deviceIdx)
-        {
-            if (OnButtonDown != null)
-                OnButtonDown(button, deviceIdx);
-        }
-
-        /// <summary>
-        /// Triggered by the runtime when the virtual button is released.
-        /// </summary>
-        /// <param name="button">Virtual button that was released.</param>
-        /// <param name="deviceIdx">Index of the device the button was released on.</param>
-        private static void Internal_TriggerButtonUp(VirtualButton button, int deviceIdx)
-        {
-            if (OnButtonUp != null)
-                OnButtonUp(button, deviceIdx);
-        }
-
-        /// <summary>
-        /// Triggered by the runtime every frame while a virtual button is being held down.
-        /// </summary>
-        /// <param name="button">Virtual button that is being held down.</param>
-        /// <param name="deviceIdx">Index of the device the button is being held down on.</param>
-        private static void Internal_TriggerButtonHeld(VirtualButton button, int deviceIdx)
-        {
-            if (OnButtonHeld != null)
-                OnButtonHeld(button, deviceIdx);
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern InputConfiguration Internal_GetKeyConfig();
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetKeyConfig(InputConfiguration inputConfig);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_IsButtonDown(ref VirtualButton button, int deviceIdx);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_IsButtonUp(ref VirtualButton button, int deviceIdx);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_IsButtonHeld(ref VirtualButton button, int deviceIdx);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetAxisValue(ref VirtualAxis button, int deviceIdx);
-	};
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System.Runtime.CompilerServices;
+
+namespace BansheeEngine
+{
+    /// <summary>
+    /// Handles virtual input that allows you to receive virtual input events that hide the actual physical input, allowing 
+    /// you to easily change the input keys while being transparent to the external code.
+    /// </summary>
+    public static class VirtualInput
+    {
+        public delegate void OnButtonEventDelegate(VirtualButton btn, int deviceIdx);
+
+        /// <summary>
+        /// Triggered when a physical button combination corresponding to a virtual button is pressed.
+        /// </summary>
+        public static event OnButtonEventDelegate OnButtonDown;
+
+        /// <summary>
+        /// Triggered when a physical button combination corresponding to a virtual button is released.
+        /// </summary>
+        public static event OnButtonEventDelegate OnButtonUp;
+
+        /// <summary>
+        /// Triggered every frame while a physical button combination corresponding to a virtual button is being held down.
+        /// </summary>
+        public static event OnButtonEventDelegate OnButtonHeld;
+
+        /// <summary>
+        /// Input configuration that describes how physical keys map to virtual keys.
+        /// </summary>
+        public static InputConfiguration KeyConfig
+        {
+            get
+            {
+                return Internal_GetKeyConfig();
+            }
+
+            set
+            {
+                Internal_SetKeyConfig(value);
+            }
+        }
+
+        /// <summary>
+        /// Checks if the physical button combination corresponding to the specified virtual button is being pressed this
+        /// frame.
+        /// </summary>
+        /// <param name="button">Virtual button to check.</param>
+        /// <param name="deviceIdx">Optional device index in case multiple input devices are available.</param>
+		public static bool IsButtonDown(VirtualButton button, int deviceIdx = 0)
+	    {
+            return Internal_IsButtonDown(ref button, deviceIdx);
+	    }
+
+        /// <summary>
+        /// Checks if the physical button combination corresponding to the specified virtual button is being released this
+        /// frame.
+        /// </summary>
+        /// <param name="button">Virtual button to check.</param>
+        /// <param name="deviceIdx">Optional device index in case multiple input devices are available.</param>
+        public static bool IsButtonUp(VirtualButton button, int deviceIdx = 0)
+        {
+            return Internal_IsButtonUp(ref button, deviceIdx);
+        }
+
+        /// <summary>
+        /// Checks if the physical button combination corresponding to the specified virtual button is being held down.
+        /// </summary>
+        /// <param name="button">Virtual button to check.</param>
+        /// <param name="deviceIdx">Index of the device to check.</param>
+        public static bool IsButtonHeld(VirtualButton button, int deviceIdx = 0)
+        {
+            return Internal_IsButtonHeld(ref button, deviceIdx);
+        }
+
+        /// <summary>
+        /// Returns normalized value for the specified input axis. 
+        /// </summary>
+        /// <param name="axis">Virtual axis identifier.</param>
+        /// <param name="deviceIdx">Optional device index in case multiple input devices are available.</param>
+        /// <returns>Axis value, normally in [-1.0, 1.0] range, but can be outside the range for devices with unbound axes 
+        ///          (for example mouse).</returns>
+        public static float GetAxisValue(VirtualAxis axis, int deviceIdx = 0)
+        {
+            return Internal_GetAxisValue(ref axis, deviceIdx);
+        }
+
+        /// <summary>
+        /// Triggered by the runtime when the virtual button is pressed.
+        /// </summary>
+        /// <param name="button">Virtual button that was pressed.</param>
+        /// <param name="deviceIdx">Index of the device the button was pressed on.</param>
+        private static void Internal_TriggerButtonDown(VirtualButton button, int deviceIdx)
+        {
+            if (OnButtonDown != null)
+                OnButtonDown(button, deviceIdx);
+        }
+
+        /// <summary>
+        /// Triggered by the runtime when the virtual button is released.
+        /// </summary>
+        /// <param name="button">Virtual button that was released.</param>
+        /// <param name="deviceIdx">Index of the device the button was released on.</param>
+        private static void Internal_TriggerButtonUp(VirtualButton button, int deviceIdx)
+        {
+            if (OnButtonUp != null)
+                OnButtonUp(button, deviceIdx);
+        }
+
+        /// <summary>
+        /// Triggered by the runtime every frame while a virtual button is being held down.
+        /// </summary>
+        /// <param name="button">Virtual button that is being held down.</param>
+        /// <param name="deviceIdx">Index of the device the button is being held down on.</param>
+        private static void Internal_TriggerButtonHeld(VirtualButton button, int deviceIdx)
+        {
+            if (OnButtonHeld != null)
+                OnButtonHeld(button, deviceIdx);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern InputConfiguration Internal_GetKeyConfig();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetKeyConfig(InputConfiguration inputConfig);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsButtonDown(ref VirtualButton button, int deviceIdx);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsButtonUp(ref VirtualButton button, int deviceIdx);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsButtonHeld(ref VirtualButton button, int deviceIdx);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetAxisValue(ref VirtualAxis button, int deviceIdx);
+	};
+}

+ 2 - 2
Source/SBansheeEditor/Include/BsScriptDragDropManager.h

@@ -137,8 +137,8 @@ namespace BansheeEngine
 		bool isDropInProgress() const { return mIsDropInProgress; }
 
 		/**
-		 * Returns the managed representation of currently dragged data (e.g. SceneObjectDragDropData). This will be null if
-		 * drag or drop is not in progress or of unsupported type.
+		 * Returns the managed representation of currently dragged data (for example SceneObjectDragDropData). This will be
+		 * null if drag or drop is not in progress or of unsupported type.
 		 */
 		MonoObject* getDropData() const;
 

+ 3 - 3
Source/SBansheeEngine/Include/BsManagedSerializableObjectInfo.h

@@ -69,7 +69,7 @@ namespace BansheeEngine
 		/**
 		 * Checks does the managed type this object represents still exists.
 		 *
-		 * @note	e.g. If assemblies get refreshed user could have renamed or removed some types.
+		 * @note	For example if assemblies get refreshed user could have renamed or removed some types.
 		 */
 		virtual bool isTypeLoaded() const = 0;
 
@@ -87,7 +87,7 @@ namespace BansheeEngine
 		virtual RTTITypeBase* getRTTI() const override;
 	};
 
-	/**	Contains information about a type of a managed serializable primitive (e.g. int, float, etc.). */
+	/**	Contains information about a type of a managed serializable primitive (for example int, float, etc.). */
 	class BS_SCR_BE_EXPORT ManagedSerializableTypeInfoPrimitive : public ManagedSerializableTypeInfo
 	{
 	public:
@@ -111,7 +111,7 @@ namespace BansheeEngine
 		virtual RTTITypeBase* getRTTI() const override;
 	};
 
-	/**	Contains information about a type of a managed serializable complex object (e.g. struct or class). */
+	/**	Contains information about a type of a managed serializable complex object (for example struct or class). */
 	class BS_SCR_BE_EXPORT ManagedSerializableTypeInfoObject : public ManagedSerializableTypeInfo
 	{
 	public:

+ 2 - 2
Source/SBansheeEngine/Include/BsScriptEnginePrerequisites.h

@@ -21,6 +21,8 @@
 #endif
 
 /** @addtogroup Plugins
+ *  @{
+ */
 
 /** @defgroup SBansheeEngine SBansheeEngine
  *	Contains script interop objects and other scripting functionality for BansheeEngine.
@@ -29,12 +31,10 @@
 
 /** @defgroup ScriptInteropEngine Script interop objects
  *	Script interop objects for communicating between native code and MBansheeEngine managed assembly.
- *  @{
  */
 
 /** @defgroup RTTI-Impl-SEngine RTTI types
  *	Types containing RTTI for specific classes.
- *  @{
  */
 
 /** @} */