Jelajahi Sumber

Added C# PixelData
Added C# Cursor
Refactored handle manager, gizmo manager and scene picking to use CameraHandler

Marko Pintera 11 tahun lalu
induk
melakukan
d5d2171319
37 mengubah file dengan 1129 tambahan dan 65 penghapusan
  1. 6 0
      BansheeCore/Include/BsGpuResourceData.h
  2. 13 0
      BansheeCore/Include/BsPixelData.h
  3. 73 0
      BansheeCore/Source/BsPixelData.cpp
  4. 4 4
      BansheeEditor/Include/BsGizmoManager.h
  5. 1 1
      BansheeEditor/Include/BsHandleDrawManager.h
  6. 4 4
      BansheeEditor/Include/BsHandleManager.h
  7. 3 3
      BansheeEditor/Include/BsHandleSlider.h
  8. 1 1
      BansheeEditor/Include/BsHandleSliderDisc.h
  9. 1 1
      BansheeEditor/Include/BsHandleSliderLine.h
  10. 3 3
      BansheeEditor/Include/BsHandleSliderManager.h
  11. 1 1
      BansheeEditor/Include/BsHandleSliderPlane.h
  12. 2 2
      BansheeEditor/Include/BsScenePicking.h
  13. 0 1
      BansheeEditor/Source/BsEditorApplication.cpp
  14. 8 10
      BansheeEditor/Source/BsGizmoManager.cpp
  15. 3 3
      BansheeEditor/Source/BsHandleDrawManager.cpp
  16. 6 7
      BansheeEditor/Source/BsHandleManager.cpp
  17. 2 2
      BansheeEditor/Source/BsHandleSlider.cpp
  18. 1 1
      BansheeEditor/Source/BsHandleSliderDisc.cpp
  19. 1 1
      BansheeEditor/Source/BsHandleSliderLine.cpp
  20. 3 3
      BansheeEditor/Source/BsHandleSliderManager.cpp
  21. 1 1
      BansheeEditor/Source/BsHandleSliderPlane.cpp
  22. 16 6
      BansheeEditor/Source/BsSceneEditorWidget.cpp
  23. 2 2
      BansheeEditor/Source/BsScenePicking.cpp
  24. 1 1
      BansheeEngine/Include/BsCamera.h
  25. 1 1
      BansheeEngine/Include/BsCursor.h
  26. 130 0
      MBansheeEngine/Cursor.cs
  27. 2 0
      MBansheeEngine/MBansheeEngine.csproj
  28. 251 0
      MBansheeEngine/PixelData.cs
  29. 20 0
      SBansheeEngine/Include/BsScriptColor.h
  30. 31 0
      SBansheeEngine/Include/BsScriptCursor.h
  31. 39 0
      SBansheeEngine/Include/BsScriptPixelData.h
  32. 6 0
      SBansheeEngine/SBansheeEngine.vcxproj
  33. 18 0
      SBansheeEngine/SBansheeEngine.vcxproj.filters
  34. 26 0
      SBansheeEngine/Source/BsScriptColor.cpp
  35. 109 0
      SBansheeEngine/Source/BsScriptCursor.cpp
  36. 295 0
      SBansheeEngine/Source/BsScriptPixelData.cpp
  37. 45 6
      SceneView.txt

+ 6 - 0
BansheeCore/Include/BsGpuResourceData.h

@@ -63,6 +63,12 @@ namespace BansheeEngine
 		 */
 		 */
 		void setExternalBuffer(UINT8* data);
 		void setExternalBuffer(UINT8* data);
 
 
+		/**
+		 * @brief	Checks if the internal buffer is locked due to some other thread
+		 *			using it.
+		 */
+		bool isLocked() const { return mLocked; }
+
 		/**
 		/**
 		 * @brief	Locks the data and makes it available only to the core thread. 
 		 * @brief	Locks the data and makes it available only to the core thread. 
 		 *
 		 *

+ 13 - 0
BansheeCore/Include/BsPixelData.h

@@ -303,6 +303,19 @@ namespace BansheeEngine
 		 */
 		 */
         void setColorAt(Color const &cv, UINT32 x, UINT32 y, UINT32 z = 0);
         void setColorAt(Color const &cv, UINT32 x, UINT32 y, UINT32 z = 0);
 
 
+		/**
+		 * @brief	Converts all the internal data into an array of colors. 
+		 *			Array is mapped as such: arrayIdx = x + y * width + z * width * height.
+		 */
+		Vector<Color> getColors() const;
+
+		/**
+		 * @brief	Initializes the internal buffer with the provided set of colors.
+		 *			The array should be of width * height * depth size and mapped
+		 *			as such: arrayIdx = x + y * width + z * width * height.
+		 */
+		void setColors(const Vector<Color>& colors);
+
 	private:
 	private:
 		/**
 		/**
 		 * @brief	Set the rowPitch and slicePitch so that the buffer is laid out consecutive
 		 * @brief	Set the rowPitch and slicePitch so that the buffer is laid out consecutive

+ 73 - 0
BansheeCore/Source/BsPixelData.cpp

@@ -2,6 +2,7 @@
 #include "BsPixelUtil.h"
 #include "BsPixelUtil.h"
 #include "BsPixelDataRTTI.h"
 #include "BsPixelDataRTTI.h"
 #include "BsColor.h"
 #include "BsColor.h"
+#include "BsDebug.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -87,6 +88,78 @@ namespace BansheeEngine
 		PixelUtil::packColor(cv, mFormat, (unsigned char *)getData() + pixelOffset);
 		PixelUtil::packColor(cv, mFormat, (unsigned char *)getData() + pixelOffset);
 	}
 	}
 
 
+	Vector<Color> PixelData::getColors() const
+	{
+		UINT32 depth = mExtents.getDepth();
+		UINT32 height = mExtents.getHeight();
+		UINT32 width = mExtents.getWidth();
+
+		UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
+		UINT8* data = getData();
+
+		Vector<Color> colors(width * height * depth);
+		for (UINT32 z = 0; z < depth; z++)
+		{
+			UINT32 zArrayIdx = z * width * height;
+			UINT32 zDataIdx = z * mSlicePitch * pixelSize;
+
+			for (UINT32 y = 0; y < height; y++)
+			{
+				UINT32 yArrayIdx = y * width;
+				UINT32 yDataIdx = y * mRowPitch * pixelSize;
+
+				for (UINT32 x = 0; x < width; x++)
+				{
+					UINT32 arrayIdx = x + yArrayIdx + zArrayIdx;
+					UINT32 dataIdx = x * pixelSize + yDataIdx + zDataIdx;
+
+					UINT8* dest = data + dataIdx;
+					PixelUtil::unpackColor(&colors[arrayIdx], mFormat, dest);
+				}
+			}
+		}
+
+		return colors;
+	}
+
+	void PixelData::setColors(const Vector<Color>& colors)
+	{
+		UINT32 depth = mExtents.getDepth();
+		UINT32 height = mExtents.getHeight();
+		UINT32 width = mExtents.getWidth();
+
+		UINT32 totalNumElements = width * height * depth;
+		if (colors.size() != totalNumElements)
+		{
+			LOGERR("Unable to set colors, invalid array size.")
+			return;
+		}
+
+		UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
+		UINT8* data = getData();
+
+		for (UINT32 z = 0; z < depth; z++)
+		{
+			UINT32 zArrayIdx = z * width * height;
+			UINT32 zDataIdx = z * mSlicePitch * pixelSize;
+
+			for (UINT32 y = 0; y < height; y++)
+			{
+				UINT32 yArrayIdx = y * width;
+				UINT32 yDataIdx = y * mRowPitch * pixelSize;
+
+				for (UINT32 x = 0; x < width; x++)
+				{
+					UINT32 arrayIdx = x + yArrayIdx + zArrayIdx;
+					UINT32 dataIdx = x * pixelSize + yDataIdx + zDataIdx;
+
+					UINT8* dest = data + dataIdx;
+					PixelUtil::packColor(colors[arrayIdx], mFormat, dest);
+				}
+			}
+		}
+	}
+
 	UINT32 PixelData::getInternalBufferSize()
 	UINT32 PixelData::getInternalBufferSize()
 	{
 	{
 		return getSize();
 		return getSize();

+ 4 - 4
BansheeEditor/Include/BsGizmoManager.h

@@ -32,8 +32,8 @@ namespace BansheeEngine
 		void drawFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far);
 		void drawFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far);
 		void drawIcon(Vector3 position, HSpriteTexture image, bool fixedScale);
 		void drawIcon(Vector3 position, HSpriteTexture image, bool fixedScale);
 
 
-		void update();
-		void renderForPicking(const HCamera& camera, std::function<Color(UINT32)> idxToColorCallback);
+		void update(const CameraHandlerPtr& camera);
+		void renderForPicking(const CameraHandlerPtr& camera, std::function<Color(UINT32)> idxToColorCallback);
 		void clearGizmos();
 		void clearGizmos();
 
 
 		HSceneObject getSceneObject(UINT32 gizmoIdx);
 		HSceneObject getSceneObject(UINT32 gizmoIdx);
@@ -107,10 +107,10 @@ namespace BansheeEngine
 		typedef Vector<IconRenderData> IconRenderDataVec;
 		typedef Vector<IconRenderData> IconRenderDataVec;
 		typedef std::shared_ptr<IconRenderDataVec> IconRenderDataVecPtr;
 		typedef std::shared_ptr<IconRenderDataVec> IconRenderDataVecPtr;
 
 
-		TransientMeshPtr buildIconMesh(const HCamera& camera, const Vector<IconData>& iconData, bool forPicking, IconRenderDataVecPtr& renderData);
+		TransientMeshPtr buildIconMesh(const CameraHandlerPtr& camera, const Vector<IconData>& iconData, bool forPicking, IconRenderDataVecPtr& renderData);
 
 
 		void limitIconSize(UINT32& width, UINT32& height);
 		void limitIconSize(UINT32& width, UINT32& height);
-		void calculateIconColors(const Color& tint, const Camera& camera, UINT32 iconHeight, bool fixedScale,
+		void calculateIconColors(const Color& tint, const CameraHandlerPtr& camera, UINT32 iconHeight, bool fixedScale,
 			Color& normalColor, Color& fadedColor);
 			Color& normalColor, Color& fadedColor);
 
 
 		void initializeCore(const CoreInitData& initData);
 		void initializeCore(const CoreInitData& initData);

+ 1 - 1
BansheeEditor/Include/BsHandleDrawManager.h

@@ -28,7 +28,7 @@ namespace BansheeEngine
 		void drawWireArc(const Vector3& position, const Vector3& normal, float radius, Degree startAngle, Degree amountAngle, float size = 1.0f);
 		void drawWireArc(const Vector3& position, const Vector3& normal, float radius, Degree startAngle, Degree amountAngle, float size = 1.0f);
 		void drawRect(const Rect3& area, float size = 1.0f);
 		void drawRect(const Rect3& area, float size = 1.0f);
 
 
-		void draw(const HCamera& camera);
+		void draw(const CameraHandlerPtr& camera);
 
 
 	private:
 	private:
 		friend class HandleDrawManagerCore;
 		friend class HandleDrawManagerCore;

+ 4 - 4
BansheeEditor/Include/BsHandleManager.h

@@ -12,14 +12,14 @@ namespace BansheeEngine
 		HandleManager();
 		HandleManager();
 		virtual ~HandleManager();
 		virtual ~HandleManager();
 
 
-		bool hasHitHandle(const HCamera& camera, const Vector2I& inputPos) const;
-		void handleInput(const HCamera& camera, const Vector2I& inputPos, bool pressed);
-		void update(const HCamera& camera);
+		bool hasHitHandle(const CameraHandlerPtr& camera, const Vector2I& inputPos) const;
+		void handleInput(const CameraHandlerPtr& camera, const Vector2I& inputPos, bool pressed);
+		void update(const CameraHandlerPtr& camera);
 
 
 		HandleSliderManager& getSliderManager() const { return *mSliderManager; }
 		HandleSliderManager& getSliderManager() const { return *mSliderManager; }
 		HandleDrawManager& getDrawManager() const { return *mDrawManager; }
 		HandleDrawManager& getDrawManager() const { return *mDrawManager; }
 
 
-		float getHandleSize(const HCamera& camera, const Vector3& handlePos) const;
+		float getHandleSize(const CameraHandlerPtr& camera, const Vector3& handlePos) const;
 
 
 		void setDefaultHandleSize(float value) { mDefaultHandleSize = value; }
 		void setDefaultHandleSize(float value) { mDefaultHandleSize = value; }
 		void setMoveHandleSnapAmount(float value) { mMoveHandleSnapAmount = value; }
 		void setMoveHandleSnapAmount(float value) { mMoveHandleSnapAmount = value; }

+ 3 - 3
BansheeEditor/Include/BsHandleSlider.h

@@ -21,8 +21,8 @@ namespace BansheeEngine
 		virtual ~HandleSlider() { }
 		virtual ~HandleSlider() { }
 
 
 		virtual bool intersects(const Ray& ray, float& t) const = 0;
 		virtual bool intersects(const Ray& ray, float& t) const = 0;
-		virtual void handleInput(const HCamera& camera, const Vector2I& pointerPos, const Ray& ray) = 0;
-		void update(const HCamera& camera);
+		virtual void handleInput(const CameraHandlerPtr& camera, const Vector2I& pointerPos, const Ray& ray) = 0;
+		void update(const CameraHandlerPtr& camera);
 
 
 		State getState() const { return mState; }
 		State getState() const { return mState; }
 		bool getFixedScale() const { return mFixedScale; }
 		bool getFixedScale() const { return mFixedScale; }
@@ -50,7 +50,7 @@ namespace BansheeEngine
 
 
 		virtual void updateCachedTransform() const;
 		virtual void updateCachedTransform() const;
 
 
-		float calcDelta(const HCamera& camera, const Vector3& position, const Vector3& direction, 
+		float calcDelta(const CameraHandlerPtr& camera, const Vector3& position, const Vector3& direction,
 			const Vector2I& pointerStart, const Vector2I& pointerEnd);
 			const Vector2I& pointerStart, const Vector2I& pointerEnd);
 
 
 		bool mFixedScale;
 		bool mFixedScale;

+ 1 - 1
BansheeEditor/Include/BsHandleSliderDisc.h

@@ -13,7 +13,7 @@ namespace BansheeEngine
 		~HandleSliderDisc();
 		~HandleSliderDisc();
 
 
 		bool intersects(const Ray& ray, float& t) const;
 		bool intersects(const Ray& ray, float& t) const;
-		void handleInput(const HCamera& camera, const Vector2I& pointerPos, const Ray& ray);
+		void handleInput(const CameraHandlerPtr& camera, const Vector2I& pointerPos, const Ray& ray);
 
 
 		Vector3 getDeltaDirection() const { return Vector3::ZERO; /* TODO */ }
 		Vector3 getDeltaDirection() const { return Vector3::ZERO; /* TODO */ }
 		Quaternion getNewRotation() const { return mRotation; /* TODO */ }
 		Quaternion getNewRotation() const { return mRotation; /* TODO */ }

+ 1 - 1
BansheeEditor/Include/BsHandleSliderLine.h

@@ -14,7 +14,7 @@ namespace BansheeEngine
 		~HandleSliderLine();
 		~HandleSliderLine();
 
 
 		bool intersects(const Ray& ray, float& t) const;
 		bool intersects(const Ray& ray, float& t) const;
-		void handleInput(const HCamera& camera, const Vector2I& pointerPos, const Ray& ray);
+		void handleInput(const CameraHandlerPtr& camera, const Vector2I& pointerPos, const Ray& ray);
 
 
 		Vector3 getNewPosition() const;
 		Vector3 getNewPosition() const;
 
 

+ 3 - 3
BansheeEditor/Include/BsHandleSliderManager.h

@@ -10,9 +10,9 @@ namespace BansheeEngine
 		HandleSliderManager();
 		HandleSliderManager();
 		~HandleSliderManager();
 		~HandleSliderManager();
 
 
-		void update(const HCamera& camera);
-		bool hasHitSlider(const HCamera& camera, const Vector2I& inputPos) const;
-		void handleInput(const HCamera& camera, const Vector2I& inputPos, bool pressed);
+		void update(const CameraHandlerPtr& camera);
+		bool hasHitSlider(const CameraHandlerPtr& camera, const Vector2I& inputPos) const;
+		void handleInput(const CameraHandlerPtr& camera, const Vector2I& inputPos, bool pressed);
 		bool isSliderActive() const;
 		bool isSliderActive() const;
 
 
 		void _registerSlider(HandleSlider* slider);
 		void _registerSlider(HandleSlider* slider);

+ 1 - 1
BansheeEditor/Include/BsHandleSliderPlane.h

@@ -13,7 +13,7 @@ namespace BansheeEngine
 		~HandleSliderPlane();
 		~HandleSliderPlane();
 
 
 		bool intersects(const Ray& ray, float& t) const;
 		bool intersects(const Ray& ray, float& t) const;
-		void handleInput(const HCamera& camera, const Vector2I& pointerPos, const Ray& ray);
+		void handleInput(const CameraHandlerPtr& camera, const Vector2I& pointerPos, const Ray& ray);
 
 
 		Vector3 getDeltaDirection() const { return Vector3::ZERO; /* TODO */ }
 		Vector3 getDeltaDirection() const { return Vector3::ZERO; /* TODO */ }
 		Vector3 getNewPosition() const { return mPosition; /* TODO */ }
 		Vector3 getNewPosition() const { return mPosition; /* TODO */ }

+ 2 - 2
BansheeEditor/Include/BsScenePicking.h

@@ -44,8 +44,8 @@ namespace BansheeEngine
 	public:
 	public:
 		ScenePicking();
 		ScenePicking();
 
 
-		HSceneObject pickClosestObject(const HCamera& cam, const Vector2I& position, const Vector2I& area);
-		Vector<HSceneObject> pickObjects(const HCamera& cam, const Vector2I& position, const Vector2I& area);
+		HSceneObject pickClosestObject(const CameraHandlerPtr& cam, const Vector2I& position, const Vector2I& area);
+		Vector<HSceneObject> pickObjects(const CameraHandlerPtr& cam, const Vector2I& position, const Vector2I& area);
 
 
 	private:
 	private:
 		typedef Set<RenderablePickData, std::function<bool(const RenderablePickData&, const RenderablePickData&)>> RenderableSet;
 		typedef Set<RenderablePickData, std::function<bool(const RenderablePickData&, const RenderablePickData&)>> RenderableSet;

+ 0 - 1
BansheeEditor/Source/BsEditorApplication.cpp

@@ -389,7 +389,6 @@ namespace BansheeEngine
 
 
 		ProjectLibrary::instance().update();
 		ProjectLibrary::instance().update();
 		EditorWindowManager::instance().update();	
 		EditorWindowManager::instance().update();	
-		GizmoManager::instance().update();
 	}
 	}
 
 
 	bool EditorApplication::isProjectLoaded() const
 	bool EditorApplication::isProjectLoaded() const

+ 8 - 10
BansheeEditor/Source/BsGizmoManager.cpp

@@ -229,20 +229,18 @@ namespace BansheeEngine
 		mIdxToSceneObjectMap[iconData.idx] = mActiveSO;
 		mIdxToSceneObjectMap[iconData.idx] = mActiveSO;
 	}
 	}
 
 
-	void GizmoManager::update()
+	void GizmoManager::update(const CameraHandlerPtr& camera)
 	{
 	{
 		mDrawHelper->clearMeshes();
 		mDrawHelper->clearMeshes();
 
 
 		if (mIconMesh != nullptr)
 		if (mIconMesh != nullptr)
 			mIconMeshHeap->dealloc(mIconMesh);
 			mIconMeshHeap->dealloc(mIconMesh);
 
 
-		HCamera sceneCamera;
 		RenderTargetPtr rt;
 		RenderTargetPtr rt;
 		SceneEditorWidget* sceneView = SceneViewLocator::instance();
 		SceneEditorWidget* sceneView = SceneViewLocator::instance();
 		if (sceneView != nullptr)
 		if (sceneView != nullptr)
 		{
 		{
-			sceneCamera = sceneView->getSceneCamera();
-			rt = sceneCamera->getViewport()->getTarget();
+			rt = camera->getViewport()->getTarget();
 
 
 			IconRenderDataVecPtr iconRenderData;
 			IconRenderDataVecPtr iconRenderData;
 
 
@@ -269,7 +267,7 @@ namespace BansheeEngine
 			// one for solids, one for wireframe
 			// one for solids, one for wireframe
 			assert(meshes.size() <= 2);
 			assert(meshes.size() <= 2);
 
 
-			mIconMesh = buildIconMesh(sceneCamera, mIconData, false, iconRenderData);
+			mIconMesh = buildIconMesh(camera, mIconData, false, iconRenderData);
 			MeshProxyPtr iconMeshProxy = mIconMesh->_createProxy(0);
 			MeshProxyPtr iconMeshProxy = mIconMesh->_createProxy(0);
 
 
 			gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, mCore, rt, solidMeshProxy, wireMeshProxy, iconMeshProxy, iconRenderData));
 			gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, mCore, rt, solidMeshProxy, wireMeshProxy, iconMeshProxy, iconRenderData));
@@ -283,7 +281,7 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	void GizmoManager::renderForPicking(const HCamera& camera, std::function<Color(UINT32)> idxToColorCallback)
+	void GizmoManager::renderForPicking(const CameraHandlerPtr& camera, std::function<Color(UINT32)> idxToColorCallback)
 	{
 	{
 		Vector<IconData> iconData;
 		Vector<IconData> iconData;
 		IconRenderDataVecPtr iconRenderData;
 		IconRenderDataVecPtr iconRenderData;
@@ -415,7 +413,7 @@ namespace BansheeEngine
 		mCurrentIdx = 0;
 		mCurrentIdx = 0;
 	}
 	}
 
 
-	TransientMeshPtr GizmoManager::buildIconMesh(const HCamera& camera, const Vector<IconData>& iconData, 
+	TransientMeshPtr GizmoManager::buildIconMesh(const CameraHandlerPtr& camera, const Vector<IconData>& iconData,
 		bool forPicking, GizmoManager::IconRenderDataVecPtr& iconRenderData)
 		bool forPicking, GizmoManager::IconRenderDataVecPtr& iconRenderData)
 	{
 	{
 		mSortedIconData.clear();
 		mSortedIconData.clear();
@@ -540,7 +538,7 @@ namespace BansheeEngine
 			}
 			}
 
 
 			Color normalColor, fadedColor;
 			Color normalColor, fadedColor;
-			calculateIconColors(curIconData.color, *camera.get(), (UINT32)(halfHeight * 2.0f), curIconData.fixedScale, normalColor, fadedColor);
+			calculateIconColors(curIconData.color, camera, (UINT32)(halfHeight * 2.0f), curIconData.fixedScale, normalColor, fadedColor);
 
 
 			if (forPicking)
 			if (forPicking)
 			{
 			{
@@ -597,14 +595,14 @@ namespace BansheeEngine
 		height = Math::roundToInt(height * scale);
 		height = Math::roundToInt(height * scale);
 	}
 	}
 
 
-	void GizmoManager::calculateIconColors(const Color& tint, const Camera& camera,
+	void GizmoManager::calculateIconColors(const Color& tint, const CameraHandlerPtr& camera,
 		UINT32 iconHeight, bool fixedScale, Color& normalColor, Color& fadedColor)
 		UINT32 iconHeight, bool fixedScale, Color& normalColor, Color& fadedColor)
 	{
 	{
 		normalColor = tint;
 		normalColor = tint;
 
 
 		if (!fixedScale)
 		if (!fixedScale)
 		{
 		{
-			float iconToScreenRatio = iconHeight / (float)camera.getViewport()->getHeight();
+			float iconToScreenRatio = iconHeight / (float)camera->getViewport()->getHeight();
 
 
 			if (iconToScreenRatio > 0.3f)
 			if (iconToScreenRatio > 0.3f)
 			{
 			{

+ 3 - 3
BansheeEditor/Source/BsHandleDrawManager.cpp

@@ -6,7 +6,7 @@
 #include "BsRendererManager.h"
 #include "BsRendererManager.h"
 #include "BsRenderer.h"
 #include "BsRenderer.h"
 #include "BsTransientMesh.h"
 #include "BsTransientMesh.h"
-#include "BsCamera.h"
+#include "BsCameraHandler.h"
 #include "BsSceneObject.h"
 #include "BsSceneObject.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
@@ -153,10 +153,10 @@ namespace BansheeEngine
 		mDrawHelper->rectangle(area);
 		mDrawHelper->rectangle(area);
 	}
 	}
 
 
-	void HandleDrawManager::draw(const HCamera& camera)
+	void HandleDrawManager::draw(const CameraHandlerPtr& camera)
 	{
 	{
 		mDrawHelper->clearMeshes();
 		mDrawHelper->clearMeshes();
-		mDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->SO()->getWorldPosition());
+		mDrawHelper->buildMeshes(DrawHelper::SortType::BackToFront, camera->getPosition());
 
 
 		const Vector<DrawHelper::ShapeMeshData>& meshes = mDrawHelper->getMeshes();
 		const Vector<DrawHelper::ShapeMeshData>& meshes = mDrawHelper->getMeshes();
 		
 		

+ 6 - 7
BansheeEditor/Source/BsHandleManager.cpp

@@ -25,31 +25,30 @@ namespace BansheeEngine
 		return mSliderManager->isSliderActive();
 		return mSliderManager->isSliderActive();
 	}
 	}
 
 
-	void HandleManager::update(const HCamera& camera)
+	void HandleManager::update(const CameraHandlerPtr& camera)
 	{
 	{
 		queueDrawCommands();
 		queueDrawCommands();
 		mDrawManager->draw(camera);
 		mDrawManager->draw(camera);
 	}
 	}
 
 
-	bool HandleManager::hasHitHandle(const HCamera& camera, const Vector2I& inputPos) const
+	bool HandleManager::hasHitHandle(const CameraHandlerPtr& camera, const Vector2I& inputPos) const
 	{
 	{
 		return mSliderManager->hasHitSlider(camera, inputPos);
 		return mSliderManager->hasHitSlider(camera, inputPos);
 	}
 	}
 
 
-	void HandleManager::handleInput(const HCamera& camera, const Vector2I& inputPos, bool pressed)
+	void HandleManager::handleInput(const CameraHandlerPtr& camera, const Vector2I& inputPos, bool pressed)
 	{
 	{
 		refreshHandles();
 		refreshHandles();
 		mSliderManager->handleInput(camera, inputPos, pressed);
 		mSliderManager->handleInput(camera, inputPos, pressed);
 		triggerHandles();
 		triggerHandles();
 	}
 	}
 
 
-	float HandleManager::getHandleSize(const HCamera& camera, const Vector3& handlePos) const
+	float HandleManager::getHandleSize(const CameraHandlerPtr& camera, const Vector3& handlePos) const
 	{
 	{
-		HSceneObject cameraSO = camera->SO();
-		Vector3 cameraPos = camera->SO()->getWorldPosition();
+		Vector3 cameraPos = camera->getPosition();
 
 
 		Vector3 diff = handlePos - cameraPos;
 		Vector3 diff = handlePos - cameraPos;
-		float distAlongViewDir = diff.dot(cameraSO->getForward());
+		float distAlongViewDir = diff.dot(camera->getRotation().zAxis());
 
 
 		return mDefaultHandleSize / std::max(distAlongViewDir, 0.0001f);
 		return mDefaultHandleSize / std::max(distAlongViewDir, 0.0001f);
 	}
 	}

+ 2 - 2
BansheeEditor/Source/BsHandleSlider.cpp

@@ -11,7 +11,7 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	void HandleSlider::update(const HCamera& camera)
+	void HandleSlider::update(const CameraHandlerPtr& camera)
 	{
 	{
 		if (mFixedScale)
 		if (mFixedScale)
 			mDistanceScale = HandleManager::instance().getHandleSize(camera, mPosition);
 			mDistanceScale = HandleManager::instance().getHandleSize(camera, mPosition);
@@ -73,7 +73,7 @@ namespace BansheeEngine
 		return mDelta;
 		return mDelta;
 	}
 	}
 
 
-	float HandleSlider::calcDelta(const HCamera& camera, const Vector3& position, const Vector3& direction,
+	float HandleSlider::calcDelta(const CameraHandlerPtr& camera, const Vector3& position, const Vector3& direction,
 		const Vector2I& pointerStart, const Vector2I& pointerEnd)
 		const Vector2I& pointerStart, const Vector2I& pointerEnd)
 	{
 	{
 		Vector2I handleStart2D = camera->worldToScreenPoint(position);
 		Vector2I handleStart2D = camera->worldToScreenPoint(position);

+ 1 - 1
BansheeEditor/Source/BsHandleSliderDisc.cpp

@@ -58,7 +58,7 @@ namespace BansheeEngine
 		return false;
 		return false;
 	}
 	}
 
 
-	void HandleSliderDisc::handleInput(const HCamera& camera, const Vector2I& pointerPos, const Ray& ray)
+	void HandleSliderDisc::handleInput(const CameraHandlerPtr& camera, const Vector2I& pointerPos, const Ray& ray)
 	{
 	{
 		assert(getState() == State::Active);
 		assert(getState() == State::Active);
 
 

+ 1 - 1
BansheeEditor/Source/BsHandleSliderLine.cpp

@@ -63,7 +63,7 @@ namespace BansheeEngine
 		return gotIntersect;
 		return gotIntersect;
 	}
 	}
 
 
-	void HandleSliderLine::handleInput(const HCamera& camera, const Vector2I& pointerPos, const Ray& ray)
+	void HandleSliderLine::handleInput(const CameraHandlerPtr& camera, const Vector2I& pointerPos, const Ray& ray)
 	{
 	{
 		assert(getState() == State::Active);
 		assert(getState() == State::Active);
 
 

+ 3 - 3
BansheeEditor/Source/BsHandleSliderManager.cpp

@@ -24,13 +24,13 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	void HandleSliderManager::update(const HCamera& camera)
+	void HandleSliderManager::update(const CameraHandlerPtr& camera)
 	{
 	{
 		for (auto& slider : mSliders)
 		for (auto& slider : mSliders)
 			slider->update(camera);
 			slider->update(camera);
 	}
 	}
 
 
-	bool HandleSliderManager::hasHitSlider(const HCamera& camera, const Vector2I& inputPos) const
+	bool HandleSliderManager::hasHitSlider(const CameraHandlerPtr& camera, const Vector2I& inputPos) const
 	{
 	{
 		Ray inputRay = camera->screenPointToRay(inputPos);
 		Ray inputRay = camera->screenPointToRay(inputPos);
 		for (auto& slider : mSliders)
 		for (auto& slider : mSliders)
@@ -43,7 +43,7 @@ namespace BansheeEngine
 		return false;
 		return false;
 	}
 	}
 
 
-	void HandleSliderManager::handleInput(const HCamera& camera, const Vector2I& inputPos, bool pressed)
+	void HandleSliderManager::handleInput(const CameraHandlerPtr& camera, const Vector2I& inputPos, bool pressed)
 	{
 	{
 		Ray inputRay = camera->screenPointToRay(inputPos);
 		Ray inputRay = camera->screenPointToRay(inputPos);
 
 

+ 1 - 1
BansheeEditor/Source/BsHandleSliderPlane.cpp

@@ -45,7 +45,7 @@ namespace BansheeEngine
 		return false;
 		return false;
 	}
 	}
 
 
-	void HandleSliderPlane::handleInput(const HCamera& camera, const Vector2I& pointerPos, const Ray& ray)
+	void HandleSliderPlane::handleInput(const CameraHandlerPtr& camera, const Vector2I& pointerPos, const Ray& ray)
 	{
 	{
 		assert(getState() == State::Active);
 		assert(getState() == State::Active);
 
 

+ 16 - 6
BansheeEditor/Source/BsSceneEditorWidget.cpp

@@ -25,6 +25,7 @@
 #include "BsSelection.h"
 #include "BsSelection.h"
 #include "BsEditorApplication.h"
 #include "BsEditorApplication.h"
 #include "BsProjectSettings.h"
 #include "BsProjectSettings.h"
+#include "BsGizmoManager.h"
 
 
 // DEBUG ONLY
 // DEBUG ONLY
 #include "BsTime.h"
 #include "BsTime.h"
@@ -78,13 +79,16 @@ namespace BansheeEngine
 			mCameraController->update();
 			mCameraController->update();
 		}
 		}
 
 
+		CameraHandlerPtr camera = mCamera->_getHandler();
+
+		GizmoManager::instance().update(camera);
 		HandleManager& handleManager = HandleManager::instance();
 		HandleManager& handleManager = HandleManager::instance();
 
 
 		handleManager.setDefaultHandleSize(projSettings->getHandleSize());
 		handleManager.setDefaultHandleSize(projSettings->getHandleSize());
 		handleManager.setMoveHandleSnapAmount(projSettings->getMoveHandleSnap());
 		handleManager.setMoveHandleSnapAmount(projSettings->getMoveHandleSnap());
 		handleManager.setRotateHandleSnapAmount(projSettings->getRotationHandleSnap());
 		handleManager.setRotateHandleSnapAmount(projSettings->getRotationHandleSnap());
 		handleManager.setScaleHandleSnapAmount(projSettings->getScaleHandleSnap());
 		handleManager.setScaleHandleSnapAmount(projSettings->getScaleHandleSnap());
-		handleManager.update(mCamera);
+		handleManager.update(camera);
 
 
 		mSceneGrid->setSize(projSettings->getGridSize());
 		mSceneGrid->setSize(projSettings->getGridSize());
 		mSceneGrid->setSpacing(projSettings->getGridSpacing());
 		mSceneGrid->setSpacing(projSettings->getGridSpacing());
@@ -130,7 +134,9 @@ namespace BansheeEngine
 		if (!toSceneViewPos(event.screenPos, scenePos))
 		if (!toSceneViewPos(event.screenPos, scenePos))
 			return;
 			return;
 
 
-		HandleManager::instance().handleInput(mCamera, scenePos, mLeftButtonPressed);
+		CameraHandlerPtr camera = mCamera->_getHandler();
+
+		HandleManager::instance().handleInput(camera, scenePos, mLeftButtonPressed);
 	}
 	}
 
 
 	void SceneEditorWidget::onPointerReleased(const PointerEvent& event)
 	void SceneEditorWidget::onPointerReleased(const PointerEvent& event)
@@ -142,8 +148,10 @@ namespace BansheeEngine
 		if (!toSceneViewPos(event.screenPos, scenePos))
 		if (!toSceneViewPos(event.screenPos, scenePos))
 			return;
 			return;
 
 
+		CameraHandlerPtr camera = mCamera->_getHandler();
+
 		mLeftButtonPressed = false;
 		mLeftButtonPressed = false;
-		HandleManager::instance().handleInput(mCamera, scenePos, mLeftButtonPressed);
+		HandleManager::instance().handleInput(camera, scenePos, mLeftButtonPressed);
 	}
 	}
 
 
 	void SceneEditorWidget::onPointerPressed(const PointerEvent& event)
 	void SceneEditorWidget::onPointerPressed(const PointerEvent& event)
@@ -157,11 +165,13 @@ namespace BansheeEngine
 
 
 		mLeftButtonPressed = true;
 		mLeftButtonPressed = true;
 
 
+		CameraHandlerPtr camera = mCamera->_getHandler();
+
 		// If we didn't hit a handle, perform normal selection
 		// If we didn't hit a handle, perform normal selection
-		if (!HandleManager::instance().hasHitHandle(mCamera, scenePos))
+		if (!HandleManager::instance().hasHitHandle(camera, scenePos))
 		{
 		{
 			// TODO - Handle multi-selection (i.e. selection rectangle when dragging)
 			// TODO - Handle multi-selection (i.e. selection rectangle when dragging)
-			HSceneObject pickedObject = ScenePicking::instance().pickClosestObject(mCamera, scenePos, Vector2I(1, 1));
+			HSceneObject pickedObject = ScenePicking::instance().pickClosestObject(camera, scenePos, Vector2I(1, 1));
 
 
 			if (pickedObject)
 			if (pickedObject)
 			{
 			{
@@ -191,7 +201,7 @@ namespace BansheeEngine
 
 
 		// This also causes handles to be created/removed, so perform this only after
 		// This also causes handles to be created/removed, so perform this only after
 		// selection has been updated, otherwise we lag back a frame
 		// selection has been updated, otherwise we lag back a frame
-		HandleManager::instance().handleInput(mCamera, scenePos, mLeftButtonPressed);
+		HandleManager::instance().handleInput(camera, scenePos, mLeftButtonPressed);
 	}
 	}
 
 
 	void SceneEditorWidget::doOnResized(UINT32 width, UINT32 height)
 	void SceneEditorWidget::doOnResized(UINT32 width, UINT32 height)

+ 2 - 2
BansheeEditor/Source/BsScenePicking.cpp

@@ -79,7 +79,7 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	HSceneObject ScenePicking::pickClosestObject(const HCamera& cam, const Vector2I& position, const Vector2I& area)
+	HSceneObject ScenePicking::pickClosestObject(const CameraHandlerPtr& cam, const Vector2I& position, const Vector2I& area)
 	{
 	{
 		Vector<HSceneObject> selectedObjects = pickObjects(cam, position, area);
 		Vector<HSceneObject> selectedObjects = pickObjects(cam, position, area);
 		if (selectedObjects.size() == 0)
 		if (selectedObjects.size() == 0)
@@ -88,7 +88,7 @@ namespace BansheeEngine
 		return selectedObjects[0];
 		return selectedObjects[0];
 	}
 	}
 
 
-	Vector<HSceneObject> ScenePicking::pickObjects(const HCamera& cam, const Vector2I& position, const Vector2I& area)
+	Vector<HSceneObject> ScenePicking::pickObjects(const CameraHandlerPtr& cam, const Vector2I& position, const Vector2I& area)
 	{
 	{
 		auto comparePickElement = [&] (const ScenePicking::RenderablePickData& a, const ScenePicking::RenderablePickData& b)
 		auto comparePickElement = [&] (const ScenePicking::RenderablePickData& a, const ScenePicking::RenderablePickData& b)
 		{
 		{

+ 1 - 1
BansheeEngine/Include/BsCamera.h

@@ -284,7 +284,7 @@ namespace BansheeEngine
 		 * @brief	Returns the internal camera handler that is used for
 		 * @brief	Returns the internal camera handler that is used for
 		 *			majority of operations by this component.
 		 *			majority of operations by this component.
 		 */
 		 */
-		CameraHandlerPtr _getHandler() const { return mInternal; }
+		CameraHandlerPtr _getHandler() const { updateView(); return mInternal; }
 
 
 		/************************************************************************/
 		/************************************************************************/
 		/* 								CORE PROXY                      		*/
 		/* 								CORE PROXY                      		*/

+ 1 - 1
BansheeEngine/Include/BsCursor.h

@@ -74,7 +74,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @brief	Sets a cursor icon. Uses one of the manually registered icons.
 		 * @brief	Sets a cursor icon. Uses one of the manually registered icons.
 		 * 			
 		 * 			
-		 * @param	name		The name to identify the cursor, one set previously by calling "addCursorIcon".
+		 * @param	name		The name to identify the cursor, one set previously by calling "setCursorIcon".
 		 */
 		 */
 		void setCursor(const String& name);
 		void setCursor(const String& name);
 
 

+ 130 - 0
MBansheeEngine/Cursor.cs

@@ -0,0 +1,130 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace BansheeEngine
+{
+    public static class Cursor
+    {
+        public static Vector2I ScreenPosition
+        {
+            get
+            {
+                Vector2I value;
+                Internal_GetScreenPosition(out value);
+                return value;
+            }
+
+            set
+            {
+                Internal_SetScreenPosition(value);
+            }
+        }
+
+        public static void Hide()
+        {
+            Internal_Hide();
+        }
+
+        public static void Show()
+        {
+            Internal_Show();
+        }
+
+        public static void ClipToRect(Rect2I area)
+        {
+            Internal_ClipToRect(area);
+        }
+
+        public static void ClipDisable()
+        {
+            Internal_ClipDisable();
+        }
+
+        public static void SetCursor(string name)
+        {
+            Internal_SetCursorStr(name);
+        }
+
+        public static void SetCursor(CursorType type)
+        {
+            Internal_SetCursor(type);
+        }
+
+        public static void SetCursorIcon(string name, PixelData iconData, Vector2I hotspot)
+        {
+            Internal_SetCursorIconStr(name, iconData, hotspot);
+        }
+
+        public static void SetCursorIcon(CursorType type, PixelData iconData, Vector2I hotspot)
+        {
+            Internal_SetCursorIcon(type, iconData, hotspot);
+        }
+
+        public static void ClearCursorIcon(string name)
+        {
+            Internal_ClearCursorIconStr(name);
+        }
+
+        public static void ClearCursorIcon(CursorType type)
+        {
+            Internal_ClearCursorIcon(type);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetScreenPosition(out Vector2I value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetScreenPosition(Vector2I value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Hide();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Show();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_ClipToRect(Rect2I value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_ClipDisable();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetCursorStr(string name);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetCursor(CursorType cursor);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetCursorIconStr(string name, PixelData iconData, Vector2I hotspot);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetCursorIcon(CursorType cursor, PixelData iconData, Vector2I hotspot);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_ClearCursorIconStr(string name);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_ClearCursorIcon(CursorType cursor);
+    }
+
+    // Note: Do not modify indexes, they need to match C++ enum CursorType
+	public enum CursorType
+	{
+		Arrow,
+		ArrowDrag,
+		ArrowLeftRight,
+		Wait,
+		IBeam,
+		SizeNESW,
+		SizeNS,
+		SizeNWSE,
+		SizeWE,
+		Deny,
+
+		// Keep at the end
+		Count
+	};
+}

+ 2 - 0
MBansheeEngine/MBansheeEngine.csproj

@@ -44,6 +44,7 @@
   <ItemGroup>
   <ItemGroup>
     <Compile Include="BuiltinResources.cs" />
     <Compile Include="BuiltinResources.cs" />
     <Compile Include="Camera.cs" />
     <Compile Include="Camera.cs" />
+    <Compile Include="Cursor.cs" />
     <Compile Include="Debug.cs" />
     <Compile Include="Debug.cs" />
     <Compile Include="Color.cs" />
     <Compile Include="Color.cs" />
     <Compile Include="Component.cs" />
     <Compile Include="Component.cs" />
@@ -91,6 +92,7 @@
     <Compile Include="Math\Rect2.cs" />
     <Compile Include="Math\Rect2.cs" />
     <Compile Include="Math\Rect2I.cs" />
     <Compile Include="Math\Rect2I.cs" />
     <Compile Include="Math\Vector2I.cs" />
     <Compile Include="Math\Vector2I.cs" />
+    <Compile Include="PixelData.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Math\Quaternion.cs" />
     <Compile Include="Math\Quaternion.cs" />

+ 251 - 0
MBansheeEngine/PixelData.cs

@@ -0,0 +1,251 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace BansheeEngine
+{
+    // Do not modify, IDs must match C++ enum PixelFormat
+    public enum PixelFormat
+    {
+        // 8-bit pixel format, all bits red.
+        R8 = 1,
+        // 2 byte pixel format, 1 byte red, 1 byte green.
+        R8G8 = 2,
+        // 24-bit pixel format, 8 bits for red, green and blue.
+        R8G8B8 = 3,
+        // 32-bit pixel format, 8 bits for red, green, blue and alpha.
+        R8G8B8A8 = 8,
+        // DXT1/BC1 format containing opaque RGB or 1-bit alpha RGB. 4 bits per pixel.
+        BC1 = 13,
+        // DXT3/BC2 format containing RGB with premultiplied alpha. 4 bits per pixel.
+        BC1a = 14,
+        // DXT3/BC2 format containing RGB with explicit alpha. 8 bits per pixel.
+        BC2 = 15,
+        // DXT5/BC2 format containing RGB with explicit alpha. 8 bits per pixel. Better alpha gradients than BC2.
+        BC3 = 16,
+        // One channel compressed format. 4 bits per pixel.
+        BC4 = 17,
+        // Two channel compressed format. 8 bits per pixel.
+        BC5 = 18,
+        // Format storing RGB in half (16-bit) floating point format usable for HDR. 8 bits per pixel.
+        BC6H = 19,
+        // Format storing RGB with optional alpha channel. Similar to BC1/BC2/BC3 formats but with higher quality and higher decompress overhead. 8 bits per pixel.
+        BC7 = 20,
+        // 16-bit pixel format, 16 bits (float) for red
+        Float16_R = 21,
+        // 32-bit, 2-channel s10e5 floating point pixel format, 16-bit red, 16-bit green
+        Float16_RG = 22,
+        // 48-bit pixel format, 16 bits (float) for red, 16 bits (float) for green, 16 bits (float) for blue
+        Float16_RGB = 23,
+        // 64-bit pixel format, 16 bits (float) for red, 16 bits (float) for green, 16 bits (float) for blue, 16 bits (float) for alpha
+        Float16_RGBA = 24,
+        // 32-bit pixel format, 32 bits (float) for red
+        Float32_R = 25,
+        // 64-bit, 2-channel floating point pixel format, 32-bit red, 32-bit green
+        Float32_RG = 26,
+        // 96-bit pixel format, 32 bits (float) for red, 32 bits (float) for green, 32 bits (float) for blue
+        Float32_RGB = 27,
+        // 128-bit pixel format, 32 bits (float) for red, 32 bits (float) for green, 32 bits (float) for blue, 32 bits (float) for alpha
+        Float32_RGBA = 28,
+        // Depth stencil format, 32bit depth, 8bit stencil + 24 unused
+        D32_S8X24 = 29,
+        // Depth stencil fomrat, 24bit depth + 8bit stencil
+        D24S8 = 30,
+        // Depth format, 32bits
+        D32 = 31,
+        // Depth format, 16bits
+        D16 = 32
+    };
+
+    public sealed class PixelData : ScriptObject
+    {
+        public PixelVolume Extents
+        {
+            get
+            {
+                PixelVolume volume;
+                Internal_GetExtents(mCachedPtr, out volume);
+                return volume;
+            }
+        }
+
+        public PixelFormat Format
+        {
+            get
+            {
+                PixelFormat format;
+                Internal_GetFormat(mCachedPtr, out format);
+                return format;
+            }
+        }
+
+        public int RawRowPitch
+        {
+            get
+            {
+                int rowPitch;
+                Internal_GetRowPitch(mCachedPtr, out rowPitch);
+                return rowPitch;
+            }
+        }
+
+        public int RawSlicePitch
+        {
+            get
+            {
+                int slicePitch;
+                Internal_GetSlicePitch(mCachedPtr, out slicePitch);
+                return slicePitch;
+            }
+        }
+
+        public int RawSize
+        {
+            get
+            {
+                int size;
+                Internal_GetSize(mCachedPtr, out size);
+                return size;
+            }
+        }
+
+        public bool RawIsConsecutive
+        {
+            get
+            {
+                bool isConsecutive;
+                Internal_GetIsConsecutive(mCachedPtr, out isConsecutive);
+                return isConsecutive;
+            }
+        }
+
+        public PixelData(PixelVolume volume, PixelFormat format)
+        {
+            Internal_CreateInstance(this, volume, format);
+        }
+
+        public PixelData(int width, int height, PixelFormat format)
+        {
+            Internal_CreateInstance(this, new PixelVolume(0, 0, width, height), format);
+        }
+
+        public PixelData(int width, int height, int depth, PixelFormat format)
+        {
+            Internal_CreateInstance(this, new PixelVolume(0, 0, 0, width, height, depth), format);
+        }
+
+        public Color GetPixel(int x, int y, int z = 0)
+        {
+            Color pixel;
+            Internal_GetPixel(mCachedPtr, x, y, z, out pixel);
+            return pixel;
+        }
+
+        public void SetPixel(Color color, int x, int y, int z = 0)
+        {
+            Internal_SetPixel(mCachedPtr, x, y, z, color);
+        }
+
+        public Color[] GetPixels()
+        {
+            Color[] pixels;
+            Internal_GetPixels(mCachedPtr, out pixels);
+            return pixels;
+        }
+
+        public void SetPixels(Color[] pixels)
+        {
+            Internal_SetPixels(mCachedPtr, pixels);
+        }
+
+        public byte[] GetRawPixels()
+        {
+            byte[] pixels;
+            Internal_GetRawPixels(mCachedPtr, out pixels);
+            return pixels;
+        }
+
+        public void SetRawPixels(byte[] pixels)
+        {
+            Internal_SetRawPixels(mCachedPtr, pixels);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(PixelData instance, PixelVolume volume, PixelFormat format);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetPixel(IntPtr thisPtr, int x, int y, int z, out Color value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetPixel(IntPtr thisPtr, int x, int y, int z, Color value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetPixels(IntPtr thisPtr, out Color[] value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetPixels(IntPtr thisPtr, Color[] value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetRawPixels(IntPtr thisPtr, out byte[] value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetRawPixels(IntPtr thisPtr, byte[] value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetExtents(IntPtr thisPtr, out PixelVolume value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetFormat(IntPtr thisPtr, out PixelFormat value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetRowPitch(IntPtr thisPtr, out int value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetSlicePitch(IntPtr thisPtr, out int value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetSize(IntPtr thisPtr, out int value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_GetIsConsecutive(IntPtr thisPtr, out bool value);
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct PixelVolume
+    {
+        private int left, top, right, bottom, front, back;
+
+        public int Left { get { return left; } }
+        public int Right { get { return right; } }
+        public int Top { get { return top; } }
+        public int Bottom { get { return bottom; } }
+        public int Front { get { return front; } }
+        public int Back { get { return back; } }
+        public int Width { get { return right - left; } }
+        public int Height { get { return bottom - top; } }
+        public int Depth { get { return back - front; } }
+
+        public PixelVolume(int left, int top, int right, int bottom)
+        {
+            this.left = left;
+            this.right = right;
+            this.top = top;
+            this.bottom = bottom;
+            this.front = 0;
+            this.back = 1;
+        }
+
+        public PixelVolume(int left, int top, int front, int right, int bottom, int back)
+        {
+            this.left = left;
+            this.right = right;
+            this.top = top;
+            this.bottom = bottom;
+            this.front = front;
+            this.back = back;
+        }
+    };
+}

+ 20 - 0
SBansheeEngine/Include/BsScriptColor.h

@@ -0,0 +1,20 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsScriptObject.h"
+#include "BsColor.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptColor : public ScriptObject <ScriptColor>
+	{
+	public:
+		SCRIPT_OBJ(BansheeEngineAssemblyName, "BansheeEngine", "Color")
+
+		static Color unbox(MonoObject* obj);
+		static MonoObject* box(const Color& value);
+
+	private:
+		ScriptColor(MonoObject* instance);
+	};
+}

+ 31 - 0
SBansheeEngine/Include/BsScriptCursor.h

@@ -0,0 +1,31 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsScriptObject.h"
+#include "BsRect2I.h"
+#include "BsVector2I.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptCursor : public ScriptObject <ScriptCursor>
+	{
+	public:
+		SCRIPT_OBJ(BansheeEngineAssemblyName, "BansheeEngine", "Cursor")
+
+	private:
+		static void internal_getScreenPosition(Vector2I* value);
+		static void internal_setScreenPosition(Vector2I value);
+		static void internal_hide();
+		static void internal_show();
+		static void internal_clipToRect(Rect2I value);
+		static void internal_clipDisable();
+		static void internal_setCursorStr(MonoString* name);
+		static void internal_setCursor(CursorType cursor);
+		static void internal_setCursorIconStr(MonoString* name, MonoObject* iconData, Vector2I hotspot);
+		static void internal_setCursorIcon(CursorType cursor, MonoObject* iconData, Vector2I hotspot);
+		static void internal_clearCursorIconStr(MonoString* name);
+		static void internal_clearCursorIcon(CursorType cursor);
+
+		ScriptCursor(MonoObject* instance);
+	};
+}

+ 39 - 0
SBansheeEngine/Include/BsScriptPixelData.h

@@ -0,0 +1,39 @@
+#pragma once
+
+#include "BsScriptEnginePrerequisites.h"
+#include "BsScriptObject.h"
+#include "BsPixelData.h"
+#include "BsColor.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BE_EXPORT ScriptPixelData : public ScriptObject <ScriptPixelData>
+	{
+	public:
+		SCRIPT_OBJ(BansheeEngineAssemblyName, "BansheeEngine", "PixelData")
+
+		PixelDataPtr getInternalValue() const { return mPixelData; }
+
+	private:
+		ScriptPixelData(MonoObject* managedInstance, const PixelDataPtr& pixelData);
+		~ScriptPixelData();
+
+		static void internal_createInstance(MonoObject* instance, PixelVolume volume, PixelFormat format);
+		static void internal_getPixel(ScriptPixelData* thisPtr, int x, int y, int z, Color* value);
+		static void internal_setPixel(ScriptPixelData* thisPtr, int x, int y, int z, Color value);
+		static void internal_getPixels(ScriptPixelData* thisPtr, MonoArray** value);
+		static void internal_setPixels(ScriptPixelData* thisPtr, MonoArray* value);
+		static void internal_getRawPixels(ScriptPixelData* thisPtr, MonoArray** value);
+		static void internal_setRawPixels(ScriptPixelData* thisPtr, MonoArray* value);
+		static void internal_getExtents(ScriptPixelData* thisPtr, PixelVolume* value);
+		static void internal_getFormat(ScriptPixelData* thisPtr, PixelFormat* value);
+		static void internal_getRowPitch(ScriptPixelData* thisPtr, int* value);
+		static void internal_getSlicePitch(ScriptPixelData* thisPtr, int* value);
+		static void internal_getSize(ScriptPixelData* thisPtr, int* value);
+		static void internal_getIsConsecutive(ScriptPixelData* thisPtr, bool* value);
+
+		static bool checkIsLocked(ScriptPixelData* thisPtr);
+
+		PixelDataPtr mPixelData;
+	};
+}

+ 6 - 0
SBansheeEngine/SBansheeEngine.vcxproj

@@ -244,7 +244,9 @@
     <ClInclude Include="Include\BsManagedSerializableObject.h" />
     <ClInclude Include="Include\BsManagedSerializableObject.h" />
     <ClInclude Include="Include\BsRuntimeScriptObjects.h" />
     <ClInclude Include="Include\BsRuntimeScriptObjects.h" />
     <ClInclude Include="Include\BsScriptCamera.h" />
     <ClInclude Include="Include\BsScriptCamera.h" />
+    <ClInclude Include="Include\BsScriptColor.h" />
     <ClInclude Include="Include\BsScriptComponent.h" />
     <ClInclude Include="Include\BsScriptComponent.h" />
+    <ClInclude Include="Include\BsScriptCursor.h" />
     <ClInclude Include="Include\BsScriptDebug.h" />
     <ClInclude Include="Include\BsScriptDebug.h" />
     <ClInclude Include="Include\BsScriptEnginePrerequisites.h" />
     <ClInclude Include="Include\BsScriptEnginePrerequisites.h" />
     <ClInclude Include="Include\BsScriptGameObject.h" />
     <ClInclude Include="Include\BsScriptGameObject.h" />
@@ -274,6 +276,7 @@
     <ClInclude Include="Include\BsScriptManagedResource.h" />
     <ClInclude Include="Include\BsScriptManagedResource.h" />
     <ClInclude Include="Include\BsScriptObject.h" />
     <ClInclude Include="Include\BsScriptObject.h" />
     <ClInclude Include="Include\BsScriptObjectImpl.h" />
     <ClInclude Include="Include\BsScriptObjectImpl.h" />
+    <ClInclude Include="Include\BsScriptPixelData.h" />
     <ClInclude Include="Include\BsScriptResource.h" />
     <ClInclude Include="Include\BsScriptResource.h" />
     <ClInclude Include="Include\BsScriptResourceManager.h" />
     <ClInclude Include="Include\BsScriptResourceManager.h" />
     <ClInclude Include="Include\BsScriptSceneObject.h" />
     <ClInclude Include="Include\BsScriptSceneObject.h" />
@@ -301,7 +304,9 @@
     <ClCompile Include="Source\BsManagedResourceMetaData.cpp" />
     <ClCompile Include="Source\BsManagedResourceMetaData.cpp" />
     <ClCompile Include="Source\BsRuntimeScriptObjects.cpp" />
     <ClCompile Include="Source\BsRuntimeScriptObjects.cpp" />
     <ClCompile Include="Source\BsScriptCamera.cpp" />
     <ClCompile Include="Source\BsScriptCamera.cpp" />
+    <ClCompile Include="Source\BsScriptColor.cpp" />
     <ClCompile Include="Source\BsScriptComponent.cpp" />
     <ClCompile Include="Source\BsScriptComponent.cpp" />
+    <ClCompile Include="Source\BsScriptCursor.cpp" />
     <ClCompile Include="Source\BsScriptDebug.cpp" />
     <ClCompile Include="Source\BsScriptDebug.cpp" />
     <ClCompile Include="Source\BsScriptEnginePlugin.cpp" />
     <ClCompile Include="Source\BsScriptEnginePlugin.cpp" />
     <ClCompile Include="Source\BsScriptGameObjectManager.cpp" />
     <ClCompile Include="Source\BsScriptGameObjectManager.cpp" />
@@ -329,6 +334,7 @@
     <ClCompile Include="Source\BsScriptManagedResource.cpp" />
     <ClCompile Include="Source\BsScriptManagedResource.cpp" />
     <ClCompile Include="Source\BsScriptObject.cpp" />
     <ClCompile Include="Source\BsScriptObject.cpp" />
     <ClCompile Include="Source\BsScriptObjectImpl.cpp" />
     <ClCompile Include="Source\BsScriptObjectImpl.cpp" />
+    <ClCompile Include="Source\BsScriptPixelData.cpp" />
     <ClCompile Include="Source\BsScriptResourceManager.cpp" />
     <ClCompile Include="Source\BsScriptResourceManager.cpp" />
     <ClCompile Include="Source\BsScriptSceneObject.cpp" />
     <ClCompile Include="Source\BsScriptSceneObject.cpp" />
     <ClCompile Include="Source\BsManagedSerializableArray.cpp" />
     <ClCompile Include="Source\BsManagedSerializableArray.cpp" />

+ 18 - 0
SBansheeEngine/SBansheeEngine.vcxproj.filters

@@ -234,6 +234,15 @@
     <ClInclude Include="Include\BsScriptVirtualButton.h">
     <ClInclude Include="Include\BsScriptVirtualButton.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptCursor.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsScriptPixelData.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsScriptColor.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptTexture2D.cpp">
     <ClCompile Include="Source\BsScriptTexture2D.cpp">
@@ -401,5 +410,14 @@
     <ClCompile Include="Source\BsScriptVirtualButton.cpp">
     <ClCompile Include="Source\BsScriptVirtualButton.cpp">
       <Filter>Source Files</Filter>
       <Filter>Source Files</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptCursor.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsScriptPixelData.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsScriptColor.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 26 - 0
SBansheeEngine/Source/BsScriptColor.cpp

@@ -0,0 +1,26 @@
+#include "BsScriptColor.h"
+#include "BsMonoManager.h"
+#include "BsMonoClass.h"
+#include "BsMonoUtil.h"
+
+namespace BansheeEngine
+{
+	ScriptColor::ScriptColor(MonoObject* instance)
+		:ScriptObject(instance)
+	{ }
+
+	void ScriptColor::initRuntimeData()
+	{ }
+
+	MonoObject* ScriptColor::box(const Color& value)
+	{
+		// We're casting away const but it's fine since structs are passed by value anyway
+		return mono_value_box(MonoManager::instance().getDomain(),
+			metaData.scriptClass->_getInternalClass(), (void*)&value);
+	}
+
+	Color ScriptColor::unbox(MonoObject* obj)
+	{
+		return *(Color*)mono_object_unbox(obj);
+	}
+}

+ 109 - 0
SBansheeEngine/Source/BsScriptCursor.cpp

@@ -0,0 +1,109 @@
+#include "BsScriptCursor.h"
+#include "BsMonoManager.h"
+#include "BsMonoClass.h"
+#include "BsMonoUtil.h"
+#include "BsCursor.h"
+#include "BsScriptPixelData.h"
+
+namespace BansheeEngine
+{
+	ScriptCursor::ScriptCursor(MonoObject* instance)
+		:ScriptObject(instance)
+	{ }
+
+	void ScriptCursor::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_GetScreenPosition", &ScriptCursor::internal_getScreenPosition);
+		metaData.scriptClass->addInternalCall("Internal_SetScreenPosition", &ScriptCursor::internal_setScreenPosition);
+		metaData.scriptClass->addInternalCall("Internal_Hide", &ScriptCursor::internal_hide);
+		metaData.scriptClass->addInternalCall("Internal_Show", &ScriptCursor::internal_show);
+		metaData.scriptClass->addInternalCall("Internal_ClipToRect", &ScriptCursor::internal_clipToRect);
+		metaData.scriptClass->addInternalCall("Internal_ClipDisable", &ScriptCursor::internal_clipDisable);
+		metaData.scriptClass->addInternalCall("Internal_SetCursor", &ScriptCursor::internal_setCursor);
+		metaData.scriptClass->addInternalCall("Internal_SetCursorStr", &ScriptCursor::internal_setCursorStr);
+		metaData.scriptClass->addInternalCall("Internal_SetCursorIcon", &ScriptCursor::internal_setCursorIcon);
+		metaData.scriptClass->addInternalCall("Internal_SetCursorIconStr", &ScriptCursor::internal_setCursorIconStr);
+		metaData.scriptClass->addInternalCall("Internal_ClearCursorIcon", &ScriptCursor::internal_clearCursorIcon);
+		metaData.scriptClass->addInternalCall("Internal_ClearCursorIconStr", &ScriptCursor::internal_clearCursorIconStr);
+	}
+
+	void ScriptCursor::internal_getScreenPosition(Vector2I* value)
+	{
+		Cursor::instance().getScreenPosition();
+	}
+
+	void ScriptCursor::internal_setScreenPosition(Vector2I value)
+	{
+		Cursor::instance().setScreenPosition(value);
+	}
+
+	void ScriptCursor::internal_hide()
+	{
+		Cursor::instance().hide();
+	}
+
+	void ScriptCursor::internal_show()
+	{
+		Cursor::instance().show();
+	}
+
+	void ScriptCursor::internal_clipToRect(Rect2I value)
+	{
+		Cursor::instance().clipToRect(value);
+	}
+
+	void ScriptCursor::internal_clipDisable()
+	{
+		Cursor::instance().clipDisable();
+	}
+
+	void ScriptCursor::internal_setCursorStr(MonoString* name)
+	{
+		String nameStr = MonoUtil::monoToString(name);
+		Cursor::instance().setCursor(nameStr);
+	}
+
+	void ScriptCursor::internal_setCursor(CursorType cursor)
+	{
+		Cursor::instance().setCursor(cursor);
+	}
+
+	void ScriptCursor::internal_setCursorIconStr(MonoString* name, MonoObject* iconData, Vector2I hotspot)
+	{
+		String nameStr = MonoUtil::monoToString(name);
+
+		ScriptPixelData* scriptPixelData = ScriptPixelData::toNative(iconData);
+
+		if (scriptPixelData != nullptr)
+		{
+			PixelDataPtr pixelData = scriptPixelData->getInternalValue();
+			Cursor::instance().setCursorIcon(nameStr, *pixelData, hotspot);
+		}
+		else
+			Cursor::instance().clearCursorIcon(nameStr);
+	}
+
+	void ScriptCursor::internal_setCursorIcon(CursorType cursor, MonoObject* iconData, Vector2I hotspot)
+	{
+		ScriptPixelData* scriptPixelData = ScriptPixelData::toNative(iconData);
+
+		if (scriptPixelData != nullptr)
+		{
+			PixelDataPtr pixelData = scriptPixelData->getInternalValue();
+			Cursor::instance().setCursorIcon(cursor, *pixelData, hotspot);
+		}
+		else
+			Cursor::instance().clearCursorIcon(cursor);
+	}
+
+	void ScriptCursor::internal_clearCursorIconStr(MonoString* name)
+	{
+		String nameStr = MonoUtil::monoToString(name);
+		Cursor::instance().clearCursorIcon(nameStr);
+	}
+
+	void ScriptCursor::internal_clearCursorIcon(CursorType cursor)
+	{
+		Cursor::instance().clearCursorIcon(cursor);
+	}
+}

+ 295 - 0
SBansheeEngine/Source/BsScriptPixelData.cpp

@@ -0,0 +1,295 @@
+#include "BsScriptPixelData.h"
+#include "BsScriptMeta.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+#include "BsMonoUtil.h"
+#include "BsPixelUtil.h"
+#include "BsScriptColor.h"
+
+namespace BansheeEngine
+{
+	ScriptPixelData::ScriptPixelData(MonoObject* managedInstance, const PixelDataPtr& pixelData)
+		:ScriptObject(managedInstance), mPixelData(pixelData)
+	{
+
+	}
+
+	ScriptPixelData::~ScriptPixelData()
+	{
+
+	}
+
+	void ScriptPixelData::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptPixelData::internal_createInstance);
+		metaData.scriptClass->addInternalCall("Internal_GetPixel", &ScriptPixelData::internal_getPixel);
+		metaData.scriptClass->addInternalCall("Internal_SetPixel", &ScriptPixelData::internal_setPixel);
+		metaData.scriptClass->addInternalCall("Internal_GetPixels", &ScriptPixelData::internal_getPixels);
+		metaData.scriptClass->addInternalCall("Internal_SetPixels", &ScriptPixelData::internal_setPixels);
+		metaData.scriptClass->addInternalCall("Internal_GetRawPixels", &ScriptPixelData::internal_getRawPixels);
+		metaData.scriptClass->addInternalCall("Internal_SetRawPixels", &ScriptPixelData::internal_setRawPixels);
+		metaData.scriptClass->addInternalCall("Internal_GetExtents", &ScriptPixelData::internal_getExtents);
+		metaData.scriptClass->addInternalCall("Internal_GetFormat", &ScriptPixelData::internal_getFormat);
+		metaData.scriptClass->addInternalCall("Internal_GetRowPitch", &ScriptPixelData::internal_getRowPitch);
+		metaData.scriptClass->addInternalCall("Internal_GetSlicePitch", &ScriptPixelData::internal_getSlicePitch);
+		metaData.scriptClass->addInternalCall("Internal_GetSize", &ScriptPixelData::internal_getSize);
+		metaData.scriptClass->addInternalCall("Internal_GetIsConsecutive", &ScriptPixelData::internal_getIsConsecutive);
+	}
+
+	void ScriptPixelData::internal_createInstance(MonoObject* instance, PixelVolume volume, PixelFormat format)
+	{
+		PixelDataPtr pixelData = bs_shared_ptr<PixelData>(volume, format);
+		pixelData->allocateInternalBuffer();
+
+		ScriptPixelData* scriptPixelData = new (bs_alloc<ScriptPixelData>()) ScriptPixelData(instance, pixelData);
+	}
+
+	void ScriptPixelData::internal_getPixel(ScriptPixelData* thisPtr, int x, int y, int z, Color* value)
+	{
+		if (!checkIsLocked(thisPtr))
+			*value = thisPtr->mPixelData->getColorAt(x, y, z);
+		else
+			*value = Color();
+	}
+
+	void ScriptPixelData::internal_setPixel(ScriptPixelData* thisPtr, int x, int y, int z, Color value)
+	{
+		if (!checkIsLocked(thisPtr))
+			thisPtr->mPixelData->setColorAt(value, x, y, z);
+	}
+
+	void ScriptPixelData::internal_getPixels(ScriptPixelData* thisPtr, MonoArray** value)
+	{
+		if (!checkIsLocked(thisPtr))
+			return;
+
+		PixelDataPtr pixelData = thisPtr->mPixelData;
+		PixelVolume pixelVolume = pixelData->getExtents();
+		UINT32 depth = pixelVolume.getDepth();
+		UINT32 height = pixelVolume.getHeight();
+		UINT32 width = pixelVolume.getWidth();
+
+		::MonoClass* colorClass = ScriptColor::getMetaData()->scriptClass->_getInternalClass();
+		UINT32 totalNumElements = width * height * depth;
+		MonoArray* colorArray = mono_array_new(MonoManager::instance().getDomain(),
+			colorClass, totalNumElements);
+
+		PixelFormat format = pixelData->getFormat();
+		UINT32 pixelSize = PixelUtil::getNumElemBytes(format);
+		UINT8* data = pixelData->getData();
+
+		UINT32 rowPitch = pixelData->getRowPitch();
+		UINT32 slicePitch = pixelData->getSlicePitch();
+
+		// Note: Can I copy bytes more directly?
+		for (UINT32 z = 0; z < depth; z++)
+		{
+			UINT32 zArrayIdx = z * width * height;
+			UINT32 zDataIdx = z * slicePitch * pixelSize;
+
+			for (UINT32 y = 0; y < height; y++)
+			{
+				UINT32 yArrayIdx = y * width;
+				UINT32 yDataIdx = y * rowPitch * pixelSize;
+
+				for (UINT32 x = 0; x < width; x++)
+				{
+					UINT32 arrayIdx = x + yArrayIdx + zArrayIdx;
+					UINT32 dataIdx = x * pixelSize + yDataIdx + zDataIdx;
+
+					UINT8* dest = data + dataIdx;
+					mono_array_set(colorArray, Color, arrayIdx, *(Color*)dest);
+				}
+			}
+		}
+
+		*value = colorArray;
+
+	}
+
+	void ScriptPixelData::internal_setPixels(ScriptPixelData* thisPtr, MonoArray* value)
+	{
+		if (!checkIsLocked(thisPtr))
+			return;
+
+		PixelDataPtr pixelData = thisPtr->mPixelData;
+		PixelVolume pixelVolume = pixelData->getExtents();
+		UINT32 depth = pixelVolume.getDepth();
+		UINT32 height = pixelVolume.getHeight();
+		UINT32 width = pixelVolume.getWidth();
+
+		UINT32 arrayLen = (UINT32)mono_array_length(value);
+		UINT32 totalNumElements = width * height * depth;
+		if (arrayLen != totalNumElements)
+		{
+			LOGERR("Unable to set colors, invalid array size.")
+			return;
+		}
+
+		PixelFormat format = pixelData->getFormat();
+		UINT32 pixelSize = PixelUtil::getNumElemBytes(format);
+		UINT8* data = pixelData->getData();
+
+		UINT32 rowPitch = pixelData->getRowPitch();
+		UINT32 slicePitch = pixelData->getSlicePitch();
+
+		for (UINT32 z = 0; z < depth; z++)
+		{
+			UINT32 zArrayIdx = z * width * height;
+			UINT32 zDataIdx = z * slicePitch * pixelSize;
+
+			for (UINT32 y = 0; y < height; y++)
+			{
+				UINT32 yArrayIdx = y * width;
+				UINT32 yDataIdx = y * rowPitch * pixelSize;
+
+				for (UINT32 x = 0; x < width; x++)
+				{
+					UINT32 arrayIdx = x + yArrayIdx + zArrayIdx;
+					UINT32 dataIdx = x * pixelSize + yDataIdx + zDataIdx;
+
+					UINT8* dest = data + dataIdx;
+
+					Color color = mono_array_get(value, Color, arrayIdx);
+					PixelUtil::packColor(color, format, dest);
+				}
+			}
+		}
+	}
+
+	void ScriptPixelData::internal_getRawPixels(ScriptPixelData* thisPtr, MonoArray** value)
+	{
+		if (!checkIsLocked(thisPtr))
+			return;
+
+		PixelDataPtr pixelData = thisPtr->mPixelData;
+		PixelVolume pixelVolume = pixelData->getExtents();
+		UINT32 depth = pixelVolume.getDepth();
+		UINT32 height = pixelVolume.getHeight();
+		UINT32 width = pixelVolume.getWidth();
+
+		MonoArray* byteArray = mono_array_new(MonoManager::instance().getDomain(),
+			mono_get_byte_class(), pixelData->getSize());
+
+		PixelFormat format = pixelData->getFormat();
+		UINT32 pixelSize = PixelUtil::getNumElemBytes(format);
+		UINT8* data = pixelData->getData();
+
+		UINT32 rowPitch = pixelData->getRowPitch();
+		UINT32 slicePitch = pixelData->getSlicePitch();
+
+		// Note: Can I copy bytes more directly?
+		for (UINT32 z = 0; z < depth; z++)
+		{
+			UINT32 zArrayIdx = z * width * height;
+			UINT32 zDataIdx = z * slicePitch * pixelSize;
+
+			for (UINT32 y = 0; y < height; y++)
+			{
+				UINT32 yArrayIdx = y * width;
+				UINT32 yDataIdx = y * rowPitch * pixelSize;
+
+				for (UINT32 x = 0; x < width; x++)
+				{
+					UINT32 arrayIdx = x + yArrayIdx + zArrayIdx;
+					UINT32 dataIdx = x * pixelSize + yDataIdx + zDataIdx;
+
+					UINT8* dest = data + dataIdx;
+					mono_array_set(byteArray, char, arrayIdx, *dest);
+				}
+			}
+		}
+
+		*value = byteArray;
+	}
+
+	void ScriptPixelData::internal_setRawPixels(ScriptPixelData* thisPtr, MonoArray* value)
+	{
+		if (!checkIsLocked(thisPtr))
+			return;
+
+		PixelDataPtr pixelData = thisPtr->mPixelData;
+		PixelVolume pixelVolume = pixelData->getExtents();
+		UINT32 depth = pixelVolume.getDepth();
+		UINT32 height = pixelVolume.getHeight();
+		UINT32 width = pixelVolume.getWidth();
+
+		UINT32 arrayLen = (UINT32)mono_array_length(value);
+		if (pixelData->getSize() != arrayLen)
+		{
+			LOGERR("Unable to set colors, invalid array size.")
+			return;
+		}
+
+		PixelFormat format = pixelData->getFormat();
+		UINT32 pixelSize = PixelUtil::getNumElemBytes(format);
+		UINT8* data = pixelData->getData();
+
+		UINT32 rowPitch = pixelData->getRowPitch();
+		UINT32 slicePitch = pixelData->getSlicePitch();
+
+		// Note: Can I copy bytes more directly?
+		for (UINT32 z = 0; z < depth; z++)
+		{
+			UINT32 zArrayIdx = z * width * height;
+			UINT32 zDataIdx = z * slicePitch * pixelSize;
+
+			for (UINT32 y = 0; y < height; y++)
+			{
+				UINT32 yArrayIdx = y * width;
+				UINT32 yDataIdx = y * rowPitch * pixelSize;
+
+				for (UINT32 x = 0; x < width; x++)
+				{
+					UINT32 arrayIdx = x + yArrayIdx + zArrayIdx;
+					UINT32 dataIdx = x * pixelSize + yDataIdx + zDataIdx;
+
+					UINT8* dest = data + dataIdx;
+					*dest = mono_array_get(value, char, arrayIdx);
+				}
+			}
+		}
+	}
+
+	void ScriptPixelData::internal_getExtents(ScriptPixelData* thisPtr, PixelVolume* value)
+	{
+		*value = thisPtr->mPixelData->getExtents();
+	}
+
+	void ScriptPixelData::internal_getFormat(ScriptPixelData* thisPtr, PixelFormat* value)
+	{
+		*value = thisPtr->mPixelData->getFormat();
+	}
+
+	void ScriptPixelData::internal_getRowPitch(ScriptPixelData* thisPtr, int* value)
+	{
+		*value = thisPtr->mPixelData->getRowPitch();
+	}
+
+	void ScriptPixelData::internal_getSlicePitch(ScriptPixelData* thisPtr, int* value)
+	{
+		*value = thisPtr->mPixelData->getSlicePitch();
+	}
+
+	void ScriptPixelData::internal_getSize(ScriptPixelData* thisPtr, int* value)
+	{
+		*value = thisPtr->mPixelData->getSize();
+	}
+
+	void ScriptPixelData::internal_getIsConsecutive(ScriptPixelData* thisPtr, bool* value)
+	{
+		*value = thisPtr->mPixelData->isConsecutive();
+	}
+
+	bool ScriptPixelData::checkIsLocked(ScriptPixelData* thisPtr)
+	{
+		if (thisPtr->mPixelData->isLocked())
+		{
+			LOGWRN("Attempting to access a locked pixel data buffer.");
+			return true;
+		}
+
+		return false;
+	}
+}

+ 45 - 6
SceneView.txt

@@ -1,15 +1,54 @@
+2. Extend C++ Texture so it keeps a CPU cached copy if we want it (PixelData per face, per mip)
+  - Texture::readCPUData(face, mip). Return null if not supported by texture.
+3. Figure out how to port AsyncOp to C#
+4. Write a C# interface for Texture, Texture2D, Texture3D, TextureCube
+  - Port PixelFormat to C#: Only a subset of actual formats? Only IDs not meta-data.
+  - Texture: width, height, format, numMipmaps, usage, sRGB, sampleCount
+  - Texture2D: GetPixels(int mip), SetPixels(int mip), AsyncOp GetGPUPixels(int mip)
+  - Texture3D: depth, GetPixels(int mip), SetPixels(int mip), AsyncOp GetGPUPixels(int mip)
+  - TextureCube: GetPixels(CubeFace face, int mip), SetPixels(CubeFace face, int mip), AsyncOp GetGPUPixels(CubeFace face, int mip)
+
+-------------
+
+Get rid of multisample hint from Texture and move it to RenderTarget (RENDER_TEXTURE_DESC actually)
+ - Seems they only use it for some kind of qality hint
+ - Possibly replace it with an enum if I can't remove it?
+
+-------------
+
+Optionally port PixelUtility to compressing, converting, generating mipmaps, applying gamma to PixelData
+ - Also getMaxMimaps and other methods for retrieving pixel format information
+
+
+
+
+
+
+
+WEEKEND END
+-----------------------
 
 
  GIZMO TODO:
  GIZMO TODO:
   - Make a C# wrapper for Renderable
   - Make a C# wrapper for Renderable
 
 
- - Do I handle it gracefully if user tries to access destroyed component or scene object?
-  - I don't, at least not with SceneObject. I will try to access HSceneObject handle even if its
-    destroyed. Add a check.
-
 Refactor GizmoManager and HandleManager so they accept a CameraHandler
 Refactor GizmoManager and HandleManager so they accept a CameraHandler
+ - I need to ensure scene CameraHandler has proper position/rotation before being passed to handle and gizmo manager
+ - Delete SceneViewLocator, I don't think it's used anywhere
+
+Tomorrow:
+ - Figure out how to deal with Textures, especially reading them
+ - Move handle/gizmo manager to CameraHandler
+ - Finish up Cursor
+
 Port SceneCameraController to C#
 Port SceneCameraController to C#
- - Will need a C# Cursor and SceneObject C# interface will also likely need to be completed (SceneObject doesn't have Destroy() among other things)
+ - Will need a C# Cursor
 Port RenderTexture to C# and likely extend Texture2D so it accepts renderable flags. While at it add TextureCube and Texture3D as well.
 Port RenderTexture to C# and likely extend Texture2D so it accepts renderable flags. While at it add TextureCube and Texture3D as well.
+ - Actually Texture2D doesn't seem to be implemented at all. Will also need to add PixelData wrapper.
+ - Will I need to add support for readable textures? e.g. what happens when you try to read a texture from C#?
+   - Almost certainly. It's very useful to be able to read textures.
+   - I can't sync the threads when reading, it would be too slow. Have an AsyncOp similar to c++ code? 
+   - Also DX11 already creates a temporary staging buffer when reading from a texture, so keeping yet another CPU
+     copy seems like a waste.
 Ensure that EditorWindow resize callback works properly.
 Ensure that EditorWindow resize callback works properly.
  - Perhaps add OnResizeEnd callback that can be used for updating the render texture
  - Perhaps add OnResizeEnd callback that can be used for updating the render texture
 Create a C# wrapper around ProjectSettings
 Create a C# wrapper around ProjectSettings
@@ -38,7 +77,7 @@ LATER:
  - Need a way to render text for gizmos and handles, and in scene in general
  - Need a way to render text for gizmos and handles, and in scene in general
  - Add drag to select
  - Add drag to select
  - Need a better system to catch broken shaders. DX11 just draws nothing with depth, DX9 draws all white.
  - Need a better system to catch broken shaders. DX11 just draws nothing with depth, DX9 draws all white.
- - The bounds I retrieve from GUIUtility are relative to the entire window, not just the current widget. Another reason to move editor widgets to their own GUIWidget.
+ - The bounds I retrieve from GUIUtility are relative to the entire window, not just the current widget.
  - Set up Application::getPrimaryViewport so it returns a valid viewport otherwise C# Camera won't work properly
  - Set up Application::getPrimaryViewport so it returns a valid viewport otherwise C# Camera won't work properly
 
 
 ---------------------------------------------------------------------
 ---------------------------------------------------------------------