Преглед изворни кода

More work on improving documentation for doxygen generation

BearishSun пре 9 година
родитељ
комит
82fef4f0ff
66 измењених фајлова са 9626 додато и 9612 уклоњено
  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
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 # 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
 # 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
 # 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
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 # 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
 # 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
 # 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
 # Note that the wildcards are matched against the file with absolute path, so to
 # exclude all test directories use the pattern */test/*
 # 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
 # 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
 # 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() { }
 		virtual void _markCoreDirty() { }
 
 
 		/**
 		/**
-		 * @copydoc	IResourceListener::markResourcesDirty
+		 * @copydoc	IResourceListener::markListenerResourcesDirty
 		 *
 		 *
 		 * @note	Internal method.
 		 * @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; }
 		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).
 		 * dragging and not visible).
 		 */
 		 */
 		EditorWindowBase* getParentWindow() const;
 		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). 
 		 * visible). 
 		 */
 		 */
 		EditorWidgetContainer* _getParent() const { return mParent; }
 		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. */
 		/**	Closes the widget, undocking it from its container and freeing any resources related to it. */
 		void close();
 		void close();
 
 
-		/** Internal method. Called once per frame.	 */
+		/** Internal method. Called once per frame.	*/
 		virtual void update() { }
 		virtual void update() { }
 
 
 		Event<void(UINT32, UINT32)> onResized; /**< Triggered whenever widget size changes. */
 		Event<void(UINT32, UINT32)> onResized; /**< Triggered whenever widget size changes. */
@@ -100,8 +100,8 @@ namespace BansheeEngine
 		void _setPosition(INT32 x, INT32 y);
 		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);
 		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.
 	 * 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
 	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
 		 * 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
 		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
 	 * 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
 	 * 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.
 	 * they were normal scene elements.
 	 */
 	 */
@@ -358,7 +358,8 @@ namespace BansheeEngine
 		void limitIconSize(UINT32& width, UINT32& height);
 		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]	tint		Primary tint for the icon.
 		 * @param[in]	camera		Camera in which the icon will be rendered in.
 		 * @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.
 		 * Returns the range of depths that the child elements can be rendered it.
 		 *
 		 *
 		 * @note	
 		 * @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; }
 		virtual UINT32 _getRenderElementDepthRange() const { return 1; }
 
 
@@ -256,8 +256,8 @@ namespace BansheeEngine
 		virtual void updateRenderElementsInternal();
 		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();
 		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
 	 * @par
 	 * This ensures that GUIElements don't recursively modify GUIManager while GUIManager is still using that data.
 	 * This ensures that GUIElements don't recursively modify GUIManager while GUIManager is still using that data.
 	 * @par
 	 * @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
 	 * @note
 	 * Internal class. Unless modifying internal engine systems you should have no need to access this class.
 	 * 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);
 		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);
 		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);
 		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);
 		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);
 		void onPointerDoubleClick(const PointerEvent& event);
 
 
 		/**	Called whenever a text is input. */
 		/**	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. */
 		/**	Returns the maximum size of the scroll handle, in pixels. */
 		UINT32 getMaxHandleSize() const;
 		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;
 		UINT32 getScrollableSize() const;
 
 
 		/** @copydoc GUIElement::setTint */
 		/** @copydoc GUIElement::setTint */

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

@@ -62,7 +62,7 @@ namespace BansheeEngine
 		 */
 		 */
 		static GUISkinPtr _createPtr();
 		static GUISkinPtr _createPtr();
 
 
-		/** @encond */
+		/** @endcond */
 	private:
 	private:
 		GUISkin();
 		GUISkin();
 		GUISkin(const GUISkin& skin); // Disable copying
 		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
 /** @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
 /** @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>
         /// <summary>
-        /// Clears the underlay GUI element (e.g. ping, hover, select).
+        /// Clears the underlay GUI element (for example ping, hover, select).
         /// </summary>
         /// </summary>
         private void ClearUnderlay()
         private void ClearUnderlay()
         {
         {
@@ -325,7 +325,7 @@ namespace BansheeEditor
         }
         }
 
 
         /// <summary>
         /// <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>
         /// </summary>
         private void CreateUnderlay()
         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>
     /// <summary>
     /// Represents the most customizable type of joint. This joint type can be used to create all other built-in joint 
     /// 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
     /// 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>
     /// </summary>
     public sealed class D6Joint : Joint
     public sealed class D6Joint : Joint
     {
     {
@@ -211,19 +211,19 @@ namespace BansheeEngine
 
 
         /// <summary>
         /// <summary>
         /// Allows you to constrain motion of the specified axis. Be aware that when setting drives for a specific axis
         /// 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.
         /// 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
         /// 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: 
         /// 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
         ///  - 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 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.
         ///  - If all angular degrees of freedom are unlocked the result is the same as the spherical joint.
         /// </summary>
         /// </summary>
         /// <param name="axis">Axis to change the motion type for.</param>
         /// <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
 namespace BansheeEngine
 {
 {
     /// <summary>
     /// <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>
     /// </summary>
     public abstract class Joint : Component
     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>
         /// <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>
         /// </summary>
         public bool Kinematic
         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; }
 		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;
 		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.
 		 * 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;
 		virtual bool isTypeLoaded() const = 0;
 
 
@@ -87,7 +87,7 @@ namespace BansheeEngine
 		virtual RTTITypeBase* getRTTI() const override;
 		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
 	class BS_SCR_BE_EXPORT ManagedSerializableTypeInfoPrimitive : public ManagedSerializableTypeInfo
 	{
 	{
 	public:
 	public:
@@ -111,7 +111,7 @@ namespace BansheeEngine
 		virtual RTTITypeBase* getRTTI() const override;
 		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
 	class BS_SCR_BE_EXPORT ManagedSerializableTypeInfoObject : public ManagedSerializableTypeInfo
 	{
 	{
 	public:
 	public:

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

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