Ver Fonte

A lot more work on C# scene window
- Dock manager properly prunes invalid windows when loading layout
- C# editor window receives an event when focus changes
- Retrieving VirtualInput configuration works
- Fixed GUI rendering so it properly separates sprite materials for different GUI widgets
- Fixed invalid exceptions when representing multisampling with just 1 sample
- Fixed an issue with reading mono field visibility
- Changes some simple types from class to struct and made them serializable

Marko Pintera há 11 anos atrás
pai
commit
d61a7ecffd
58 ficheiros alterados com 632 adições e 318 exclusões
  1. 1 0
      BansheeEditor/Include/BsDockManagerLayout.h
  2. 2 1
      BansheeEditor/Include/BsEditorWidget.h
  3. 17 0
      BansheeEditor/Include/BsEditorWidgetManager.h
  4. 5 3
      BansheeEditor/Include/BsSceneViewHandler.h
  5. 3 0
      BansheeEditor/Source/BsDockManager.cpp
  6. 53 0
      BansheeEditor/Source/BsDockManagerLayout.cpp
  7. 12 4
      BansheeEditor/Source/BsEditorWidget.cpp
  8. 32 0
      BansheeEditor/Source/BsEditorWidgetManager.cpp
  9. 2 2
      BansheeEditor/Source/BsGUIColor.cpp
  10. 33 28
      BansheeEditor/Source/BsSceneViewHandler.cpp
  11. 22 9
      BansheeEngine/Include/BsGUIMaterialManager.h
  12. 6 1
      BansheeEngine/Include/BsImageSprite.h
  13. 6 1
      BansheeEngine/Include/BsTextSprite.h
  14. 3 3
      BansheeEngine/Source/BsGUIButtonBase.cpp
  15. 1 0
      BansheeEngine/Source/BsGUIElementBase.cpp
  16. 2 2
      BansheeEngine/Source/BsGUIInputBox.cpp
  17. 5 1
      BansheeEngine/Source/BsGUIInputCaret.cpp
  18. 5 1
      BansheeEngine/Source/BsGUIInputSelection.cpp
  19. 1 1
      BansheeEngine/Source/BsGUILabel.cpp
  20. 36 15
      BansheeEngine/Source/BsGUIMaterialManager.cpp
  21. 1 1
      BansheeEngine/Source/BsGUIRenderTexture.cpp
  22. 1 1
      BansheeEngine/Source/BsGUIScrollBar.cpp
  23. 1 1
      BansheeEngine/Source/BsGUIScrollBarHandle.cpp
  24. 1 1
      BansheeEngine/Source/BsGUITexture.cpp
  25. 5 5
      BansheeEngine/Source/BsImageSprite.cpp
  26. 3 3
      BansheeEngine/Source/BsTextSprite.cpp
  27. 3 3
      BansheeGLRenderSystem/Source/BsGLTexture.cpp
  28. 1 1
      BansheeMono/Source/BsMonoField.cpp
  29. 3 0
      BansheeRenderer/Source/BsBansheeRenderer.cpp
  30. 8 8
      MBansheeEditor/DbgGizmo.cs
  31. 3 3
      MBansheeEditor/DebugCameraHandle.cs
  32. 14 5
      MBansheeEditor/EditorWindow.cs
  33. 5 5
      MBansheeEditor/Scene/DefaultHandleManager.cs
  34. 2 2
      MBansheeEditor/Scene/Handles.cs
  35. 48 45
      MBansheeEditor/Scene/SceneCamera.cs
  36. 22 6
      MBansheeEditor/Scene/SceneViewHandler.cs
  37. 38 20
      MBansheeEditor/Scene/SceneWindow.cs
  38. 16 16
      MBansheeEngine/Math/AABox.cs
  39. 26 24
      MBansheeEngine/Math/BsRect3.cs
  40. 7 0
      MBansheeEngine/Math/Degree.cs
  41. 0 1
      MBansheeEngine/Math/MathEx.cs
  42. 7 1
      MBansheeEngine/Math/Matrix3.cs
  43. 7 1
      MBansheeEngine/Math/Matrix4.cs
  44. 6 1
      MBansheeEngine/Math/Quaternion.cs
  45. 8 1
      MBansheeEngine/Math/Radian.cs
  46. 8 3
      MBansheeEngine/Math/Ray.cs
  47. 7 2
      MBansheeEngine/Math/Rect2.cs
  48. 7 2
      MBansheeEngine/Math/Rect2I.cs
  49. 16 14
      MBansheeEngine/SceneObject.cs
  50. 5 2
      SBansheeEditor/Include/BsScriptEditorWindow.h
  51. 5 3
      SBansheeEditor/Include/BsScriptSceneViewHandler.h
  52. 14 4
      SBansheeEditor/Source/BsScriptEditorWindow.cpp
  53. 19 7
      SBansheeEditor/Source/BsScriptSceneViewHandler.cpp
  54. 1 1
      SBansheeEngine/Include/BsScriptSceneObject.h
  55. 47 47
      SBansheeEngine/Source/BsScriptCameraHandler.cpp
  56. 3 2
      SBansheeEngine/Source/BsScriptInputConfiguration.cpp
  57. 5 4
      SBansheeEngine/Source/BsScriptSceneObject.cpp
  58. 12 0
      TODO.txt

+ 1 - 0
BansheeEditor/Include/BsDockManagerLayout.h

@@ -33,6 +33,7 @@ namespace BansheeEngine
 		~DockManagerLayout();
 		~DockManagerLayout();
 
 
 		Entry& getRootEntry() { return mRootEntry; }
 		Entry& getRootEntry() { return mRootEntry; }
+		void pruneInvalidLeaves();
 
 
 	private:
 	private:
 		Entry mRootEntry;
 		Entry mRootEntry;

+ 2 - 1
BansheeEditor/Include/BsEditorWidget.h

@@ -22,7 +22,7 @@ namespace BansheeEngine
 		void _setSize(UINT32 width, UINT32 height);
 		void _setSize(UINT32 width, UINT32 height);
 		void _setPosition(INT32 x, INT32 y);
 		void _setPosition(INT32 x, INT32 y);
 		void _changeParent(EditorWidgetContainer* parent);
 		void _changeParent(EditorWidgetContainer* parent);
-		void _setHasFocus(bool focus) { mHasFocus = focus; }
+		void _setHasFocus(bool focus);
 		EditorWidgetContainer* _getParent() const { return mParent; }
 		EditorWidgetContainer* _getParent() const { return mParent; }
 
 
 		Vector2I screenToWidgetPos(const Vector2I& screenPos) const;
 		Vector2I screenToWidgetPos(const Vector2I& screenPos) const;
@@ -38,6 +38,7 @@ namespace BansheeEngine
 		Event<void(UINT32, UINT32)> onResized;
 		Event<void(UINT32, UINT32)> onResized;
 		Event<void(INT32, INT32)> onMoved;
 		Event<void(INT32, INT32)> onMoved;
 		Event<void(EditorWidgetContainer*)> onParentChanged;
 		Event<void(EditorWidgetContainer*)> onParentChanged;
+		Event<void(bool)> onFocusChanged;
 	protected:
 	protected:
 		friend class EditorWidgetManager;
 		friend class EditorWidgetManager;
 
 

+ 17 - 0
BansheeEditor/Include/BsEditorWidgetManager.h

@@ -41,6 +41,11 @@ namespace BansheeEngine
 		 */
 		 */
 		EditorWidgetBase* create(const String& name, EditorWidgetContainer& parentContainer);
 		EditorWidgetBase* create(const String& name, EditorWidgetContainer& parentContainer);
 
 
+		/**
+		 * @brief	Checks if the provided name represents a widget that can be created.
+		 */
+		bool isValidWidget(const String& name) const;
+
 		/**
 		/**
 		 * @brief	Closes the given widget.
 		 * @brief	Closes the given widget.
 		 */
 		 */
@@ -83,10 +88,22 @@ namespace BansheeEngine
 		 */
 		 */
 		void onPointerPressed(const PointerEvent& event);
 		void onPointerPressed(const PointerEvent& event);
 
 
+		/**
+		 * @brief	Triggered whenever a window gains focus.
+		 */
+		void onFocusGained(const RenderWindow& window);
+
+		/**
+		 * @brief	Triggered whenever a window loses focus.
+		 */
+		void onFocusLost(const RenderWindow& window);
+
 		Map<String, EditorWidgetBase*> mActiveWidgets;
 		Map<String, EditorWidgetBase*> mActiveWidgets;
 		Map<String, std::function<EditorWidgetBase*(EditorWidgetContainer&)>> mCreateCallbacks;
 		Map<String, std::function<EditorWidgetBase*(EditorWidgetContainer&)>> mCreateCallbacks;
 
 
 		HEvent mOnPointerPressedConn;
 		HEvent mOnPointerPressedConn;
+		HEvent mOnFocusLostConn;
+		HEvent mOnFocusGainedConn;
 
 
 		static Stack<std::pair<String, std::function<EditorWidgetBase*(EditorWidgetContainer&)>>> QueuedCreateCallbacks;
 		static Stack<std::pair<String, std::function<EditorWidgetBase*(EditorWidgetContainer&)>>> QueuedCreateCallbacks;
 	};
 	};

+ 5 - 3
BansheeEditor/Include/BsSceneViewHandler.h

@@ -7,12 +7,14 @@ namespace BansheeEngine
 	class BS_ED_EXPORT SceneViewHandler
 	class BS_ED_EXPORT SceneViewHandler
 	{
 	{
 	public:
 	public:
-		SceneViewHandler(const EditorWidgetBase* parentWidget, const SPtr<CameraHandler>& camera);
+		SceneViewHandler(EditorWidgetBase* parentWidget, const SPtr<CameraHandler>& camera);
 		virtual ~SceneViewHandler();
 		virtual ~SceneViewHandler();
 
 
 		void update(const Vector2I& position, const Vector2I& delta);
 		void update(const Vector2I& position, const Vector2I& delta);
-		void pointerPressed(const Vector2I& position);
-		void pointerReleased(const Vector2I& position, bool controlHeld);
+		void trySelectHandle(const Vector2I& position);
+		bool isHandleActive() const;
+		void clearHandleSelection();
+		void pickObject(const Vector2I& position, bool additive);
 
 
 	protected:
 	protected:
 		void render(const Viewport* viewport, DrawList& drawList);
 		void render(const Viewport* viewport, DrawList& drawList);

+ 3 - 0
BansheeEditor/Source/BsDockManager.cpp

@@ -693,6 +693,9 @@ namespace BansheeEngine
 			}
 			}
 		};
 		};
 
 
+		// Prune layout by removing invalid leafs (ones with no widgets, or widgets that no longer exist)
+		layout->pruneInvalidLeaves();
+
 		// Dock elements
 		// Dock elements
 		const DockManagerLayout::Entry* rootEntry = &layout->getRootEntry();
 		const DockManagerLayout::Entry* rootEntry = &layout->getRootEntry();
 		const DockManagerLayout::Entry* leafEntry = GetLeafEntry(rootEntry, 0);
 		const DockManagerLayout::Entry* leafEntry = GetLeafEntry(rootEntry, 0);

+ 53 - 0
BansheeEditor/Source/BsDockManagerLayout.cpp

@@ -1,5 +1,6 @@
 #include "BsDockManagerLayout.h"
 #include "BsDockManagerLayout.h"
 #include "BsDockManagerLayoutRTTI.h"
 #include "BsDockManagerLayoutRTTI.h"
+#include "BsEditorWidgetManager.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -69,6 +70,58 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
+	void DockManagerLayout::pruneInvalidLeaves()
+	{
+		Stack<Entry*> layoutTodo;
+		layoutTodo.push(&mRootEntry);
+
+		while (!layoutTodo.empty())
+		{
+			Entry* curEntry = layoutTodo.top();
+			layoutTodo.pop();
+
+			if (!curEntry->isLeaf)
+			{
+				layoutTodo.push(curEntry->children[0]);
+				layoutTodo.push(curEntry->children[1]);
+			}
+			else
+			{
+				for (INT32 i = 0; i < (INT32)curEntry->widgetNames.size(); i++)
+				{
+					if (!EditorWidgetManager::instance().isValidWidget(curEntry->widgetNames[i]))
+					{
+						curEntry->widgetNames.erase(curEntry->widgetNames.begin() + i);
+						i--;
+					}
+				}
+
+				if (curEntry->widgetNames.size() == 0)
+				{
+					Entry* parent = curEntry->parent;
+					if (parent != nullptr)
+					{
+						Entry* newParent = parent->parent;
+						Entry* otherChild = parent->children[0] == curEntry ? parent->children[1] : parent->children[0];
+
+						if (newParent != nullptr)
+						{
+							if (newParent->children[0] == parent)
+								newParent->children[0] = otherChild;
+							else
+								newParent->children[1] = otherChild;
+						}
+
+						otherChild->parent = newParent;
+
+						bs_delete(parent);
+						bs_delete(curEntry);
+					}
+				}
+			}
+		}
+	}
+
 	/************************************************************************/
 	/************************************************************************/
 	/* 								RTTI		                     		*/
 	/* 								RTTI		                     		*/
 	/************************************************************************/
 	/************************************************************************/

+ 12 - 4
BansheeEditor/Source/BsEditorWidget.cpp

@@ -69,6 +69,16 @@ namespace BansheeEngine
 		doOnResized(width, height);
 		doOnResized(width, height);
 	}
 	}
 
 
+	void EditorWidgetBase::_setHasFocus(bool focus) 
+	{ 
+		if (mHasFocus != focus)
+		{
+			mHasFocus = focus;
+
+			onFocusChanged(focus);
+		}
+	}
+
 	Vector2I EditorWidgetBase::screenToWidgetPos(const Vector2I& screenPos) const
 	Vector2I EditorWidgetBase::screenToWidgetPos(const Vector2I& screenPos) const
 	{
 	{
 		EditorWindowBase* parentEditorWindow = mParent->getParentWindow();
 		EditorWindowBase* parentEditorWindow = mParent->getParentWindow();
@@ -95,14 +105,12 @@ namespace BansheeEngine
 
 
 	void EditorWidgetBase::doOnMoved(INT32 x, INT32 y)
 	void EditorWidgetBase::doOnMoved(INT32 x, INT32 y)
 	{
 	{
-		if (!onMoved.empty())
-			onMoved(x, y);
+		onMoved(x, y);
 	}
 	}
 
 
 	void EditorWidgetBase::doOnResized(UINT32 width, UINT32 height)
 	void EditorWidgetBase::doOnResized(UINT32 width, UINT32 height)
 	{
 	{
-		if (!onResized.empty())
-			onResized(width, height);
+		onResized(width, height);
 	}
 	}
 
 
 	void EditorWidgetBase::doOnParentChanged()
 	void EditorWidgetBase::doOnParentChanged()

+ 32 - 0
BansheeEditor/Source/BsEditorWidgetManager.cpp

@@ -9,6 +9,7 @@
 #include "BsException.h"
 #include "BsException.h"
 #include "BsInput.h"
 #include "BsInput.h"
 #include "BsRenderWindow.h"
 #include "BsRenderWindow.h"
+#include "BsRenderWindowManager.h"
 #include "BsVector2I.h"
 #include "BsVector2I.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
@@ -28,11 +29,15 @@ namespace BansheeEngine
 		}
 		}
 
 
 		mOnPointerPressedConn = gInput().onPointerPressed.connect(std::bind(&EditorWidgetManager::onPointerPressed, this, _1));
 		mOnPointerPressedConn = gInput().onPointerPressed.connect(std::bind(&EditorWidgetManager::onPointerPressed, this, _1));
+		mOnFocusLostConn = RenderWindowManager::instance().onFocusLost.connect(std::bind(&EditorWidgetManager::onFocusLost, this, _1));
+		mOnFocusGainedConn = RenderWindowManager::instance().onFocusGained.connect(std::bind(&EditorWidgetManager::onFocusGained, this, _1));
 	}
 	}
 
 
 	EditorWidgetManager::~EditorWidgetManager()
 	EditorWidgetManager::~EditorWidgetManager()
 	{
 	{
 		mOnPointerPressedConn.disconnect();
 		mOnPointerPressedConn.disconnect();
+		mOnFocusLostConn.disconnect();
+		mOnFocusGainedConn.disconnect();
 
 
 		Map<String, EditorWidgetBase*> widgetsCopy = mActiveWidgets;
 		Map<String, EditorWidgetBase*> widgetsCopy = mActiveWidgets;
 
 
@@ -111,6 +116,12 @@ namespace BansheeEngine
 		return newWidget;
 		return newWidget;
 	}
 	}
 
 
+	bool EditorWidgetManager::isValidWidget(const String& name) const
+	{
+		auto iterFindCreate = mCreateCallbacks.find(name);
+		return iterFindCreate != mCreateCallbacks.end();
+	}
+
 	EditorWidgetLayoutPtr EditorWidgetManager::getLayout() const
 	EditorWidgetLayoutPtr EditorWidgetManager::getLayout() const
 	{
 	{
 		auto GetWidgetNamesInContainer = [&] (const EditorWidgetContainer* container)
 		auto GetWidgetNamesInContainer = [&] (const EditorWidgetContainer* container)
@@ -246,6 +257,27 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
+	void EditorWidgetManager::onFocusGained(const RenderWindow& window)
+	{
+		// Do nothing, possibly regain focus on last focused widget?
+	}
+
+	void EditorWidgetManager::onFocusLost(const RenderWindow& window)
+	{
+		for (auto& widgetData : mActiveWidgets)
+		{
+			EditorWidgetBase* widget = widgetData.second;
+			EditorWidgetContainer* parentContainer = widget->_getParent();
+			EditorWindowBase* parentWindow = parentContainer->getParentWindow();
+			RenderWindowPtr parentRenderWindow = parentWindow->_getRenderWindow();
+
+			if (parentRenderWindow.get() != &window)
+				continue;
+
+			widget->_setHasFocus(false);
+		}
+	}
+
 	void EditorWidgetManager::preRegisterWidget(const String& name, std::function<EditorWidgetBase*(EditorWidgetContainer&)> createCallback)
 	void EditorWidgetManager::preRegisterWidget(const String& name, std::function<EditorWidgetBase*(EditorWidgetContainer&)> createCallback)
 	{
 	{
 		QueuedCreateCallbacks.push(std::pair<String, std::function<EditorWidgetBase*(EditorWidgetContainer&)>>(name, createCallback));
 		QueuedCreateCallbacks.push(std::pair<String, std::function<EditorWidgetBase*(EditorWidgetContainer&)>>(name, createCallback));

+ 2 - 2
BansheeEditor/Source/BsGUIColor.cpp

@@ -97,8 +97,8 @@ namespace BansheeEngine
 		mAlphaImageDesc.width = mWidth - mColorImageDesc.width;
 		mAlphaImageDesc.width = mWidth - mColorImageDesc.width;
 		mAlphaImageDesc.height = mHeight;
 		mAlphaImageDesc.height = mHeight;
 
 
-		mColorSprite->update(mColorImageDesc);
-		mAlphaSprite->update(mAlphaImageDesc);
+		mColorSprite->update(mColorImageDesc, (UINT64)_getParentWidget());
+		mAlphaSprite->update(mAlphaImageDesc, (UINT64)_getParentWidget());
 
 
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}

+ 33 - 28
BansheeEditor/Source/BsSceneViewHandler.cpp

@@ -17,8 +17,8 @@ using namespace std::placeholders;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	SceneViewHandler::SceneViewHandler(const EditorWidgetBase* parentWidget, const SPtr<CameraHandler>& camera)
-		:mCamera(camera), mSceneGrid(nullptr)
+	SceneViewHandler::SceneViewHandler(EditorWidgetBase* parentWidget, const SPtr<CameraHandler>& camera)
+		:mCamera(camera), mSceneGrid(nullptr), mParentWidget(parentWidget)
 	{
 	{
 		mRenderCallback = RendererManager::instance().getActive()->onRenderViewport.connect(std::bind(&SceneViewHandler::render, this, _1, _2));
 		mRenderCallback = RendererManager::instance().getActive()->onRenderViewport.connect(std::bind(&SceneViewHandler::render, this, _1, _2));
 		mSceneGrid = bs_new<SceneGrid>();
 		mSceneGrid = bs_new<SceneGrid>();
@@ -44,45 +44,50 @@ namespace BansheeEngine
 		mSceneGrid->update();
 		mSceneGrid->update();
 	}
 	}
 
 
-	void SceneViewHandler::pointerPressed(const Vector2I& position)
+	void SceneViewHandler::trySelectHandle(const Vector2I& position)
 	{
 	{
 		HandleManager::instance().trySelect(mCamera, position);
 		HandleManager::instance().trySelect(mCamera, position);
 	}
 	}
 
 
-	void SceneViewHandler::pointerReleased(const Vector2I& position, bool controlHeld)
+	bool SceneViewHandler::isHandleActive() const
 	{
 	{
-		if (HandleManager::instance().isHandleActive())
-			HandleManager::instance().clearSelection();
-		else
-		{
-			// TODO - Handle multi-selection (i.e. selection rectangle when dragging)
-			HSceneObject pickedObject = ScenePicking::instance().pickClosestObject(mCamera, position, Vector2I(1, 1));
+		return HandleManager::instance().isHandleActive();
+	}
 
 
-			if (pickedObject)
-			{
-				if (controlHeld) // Append to existing selection
-				{
-					Vector<HSceneObject> selectedSOs = Selection::instance().getSceneObjects();
+	void SceneViewHandler::clearHandleSelection()
+	{
+		HandleManager::instance().clearSelection();
+	}
 
 
-					auto iterFind = std::find_if(selectedSOs.begin(), selectedSOs.end(),
-						[&](const HSceneObject& obj) { return obj == pickedObject; }
-					);
+	void SceneViewHandler::pickObject(const Vector2I& position, bool additive)
+	{
+		// TODO - Handle multi-selection (i.e. selection rectangle when dragging)
+		HSceneObject pickedObject = ScenePicking::instance().pickClosestObject(mCamera, position, Vector2I(1, 1));
 
 
-					if (iterFind != selectedSOs.end())
-						selectedSOs.push_back(pickedObject);
+		if (pickedObject)
+		{
+			if (additive) // Append to existing selection
+			{
+				Vector<HSceneObject> selectedSOs = Selection::instance().getSceneObjects();
 
 
-					Selection::instance().setSceneObjects(selectedSOs);
-				}
-				else
-				{
-					Vector<HSceneObject> selectedSOs = { pickedObject };
+				auto iterFind = std::find_if(selectedSOs.begin(), selectedSOs.end(),
+					[&](const HSceneObject& obj) { return obj == pickedObject; }
+				);
 
 
-					Selection::instance().setSceneObjects(selectedSOs);
-				}
+				if (iterFind != selectedSOs.end())
+					selectedSOs.push_back(pickedObject);
+
+				Selection::instance().setSceneObjects(selectedSOs);
 			}
 			}
 			else
 			else
-				Selection::instance().clearSceneSelection();
+			{
+				Vector<HSceneObject> selectedSOs = { pickedObject };
+
+				Selection::instance().setSceneObjects(selectedSOs);
+			}
 		}
 		}
+		else
+			Selection::instance().clearSceneSelection();
 	}
 	}
 
 
 	void SceneViewHandler::render(const Viewport* viewport, DrawList& drawList)
 	void SceneViewHandler::render(const Viewport* viewport, DrawList& drawList)

+ 22 - 9
BansheeEngine/Include/BsGUIMaterialManager.h

@@ -17,33 +17,45 @@ namespace BansheeEngine
 
 
 		/**
 		/**
 		 * @brief	Creates a new material, or returns a reference to an existing one based on
 		 * @brief	Creates a new material, or returns a reference to an existing one based on
-		 * 			the provided primary texture.
+		 * 			the provided primary texture, tint and group id.
 		 * 			
 		 * 			
 		 *			Returned material can be used for text rendering.
 		 *			Returned material can be used for text rendering.
 		 *			
 		 *			
 		 *			Make sure to release all materials with a call to "releaseMaterial()".
 		 *			Make sure to release all materials with a call to "releaseMaterial()".
+		 *
+		 *  @note	Group ID allows you to force the system to return different materials even if texture and tint could
+		 *			otherwise be shared. Sometimes you need this if you know other material properties (like world transform)
+		 *			won't be shared.
 		 */
 		 */
-		const GUIMaterialInfo& requestTextMaterial(const HTexture& texture, const Color& tint) const;
+		const GUIMaterialInfo& requestTextMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
 
 
 		/**
 		/**
 		 * @brief	Creates a new material, or returns a reference to an existing one based on
 		 * @brief	Creates a new material, or returns a reference to an existing one based on
-		 * 			the provided primary texture.
+		 * 			the provided primary texture, tint and group id.
 		 * 			
 		 * 			
 		 *			Returned material can be used for normal image rendering.
 		 *			Returned material can be used for normal image rendering.
 		 *			
 		 *			
 		 *			Make sure to release all materials with a call to "releaseMaterial()".
 		 *			Make sure to release all materials with a call to "releaseMaterial()".
+		 *
+		 *  @note	Group ID allows you to force the system to return different materials even if texture and tint could
+		 *			otherwise be shared. Sometimes you need this if you know other material properties (like world transform)
+		 *			won't be shared.
 		 */
 		 */
-		const GUIMaterialInfo& requestImageMaterial(const HTexture& texture, const Color& tint) const;
+		const GUIMaterialInfo& requestImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
 
 
 		/**
 		/**
 		 * @brief	Creates a new material, or returns a reference to an existing one based on
 		 * @brief	Creates a new material, or returns a reference to an existing one based on
-		 * 			the provided primary texture.
+		 * 			the provided primary texture, tint and group id.
 		 * 			
 		 * 			
 		 *			Returned material can be used for non-transparent image rendering.
 		 *			Returned material can be used for non-transparent image rendering.
 		 *			
 		 *			
 		 *			Make sure to release all materials with a call to "releaseMaterial()".
 		 *			Make sure to release all materials with a call to "releaseMaterial()".
+		 *
+		 * @note	Group ID allows you to force the system to return different materials even if texture and tint could
+		 *			otherwise be shared. Sometimes you need this if you know other material properties (like world transform)
+		 *			won't be shared.
 		 */
 		 */
-		const GUIMaterialInfo& requestNonAlphaImageMaterial(const HTexture& texture, const Color& tint) const;
+		const GUIMaterialInfo& requestNonAlphaImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
 
 
 		/**
 		/**
 		 * @brief	Releases the held reference to the material. This allows us to fully unload a material
 		 * @brief	Releases the held reference to the material. This allows us to fully unload a material
@@ -55,19 +67,19 @@ namespace BansheeEngine
 		 * @brief	Attempts to find an existing text material with the specified color and tint. Returns null
 		 * @brief	Attempts to find an existing text material with the specified color and tint. Returns null
 		 *			if one cannot be found.
 		 *			if one cannot be found.
 		 */
 		 */
-		const GUIMaterialInfo* findExistingTextMaterial(const HTexture& texture, const Color& tint) const;
+		const GUIMaterialInfo* findExistingTextMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
 
 
 		/**
 		/**
 		 * @brief	Attempts to find an existing image material with the specified color and tint. Returns null
 		 * @brief	Attempts to find an existing image material with the specified color and tint. Returns null
 		 *			if one cannot be found.
 		 *			if one cannot be found.
 		 */
 		 */
-		const GUIMaterialInfo* findExistingImageMaterial(const HTexture& texture, const Color& tint) const;
+		const GUIMaterialInfo* findExistingImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
 
 
 		/**
 		/**
 		 * @brief	Attempts to find an existing non-transparent image material with the specified color and tint.
 		 * @brief	Attempts to find an existing non-transparent image material with the specified color and tint.
 		 *			Returns null if one cannot be found.
 		 *			Returns null if one cannot be found.
 		 */
 		 */
-		const GUIMaterialInfo* findExistingNonAlphaImageMaterial(const HTexture& texture, const Color& tint) const;
+		const GUIMaterialInfo* findExistingNonAlphaImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const;
 
 
 		/**
 		/**
 		 * @brief	Releases all internal materials, whether they are used or not.
 		 * @brief	Releases all internal materials, whether they are used or not.
@@ -83,6 +95,7 @@ namespace BansheeEngine
 				:refCount(0)
 				:refCount(0)
 			{ }
 			{ }
 
 
+			UINT64 groupId;
 			GUIMaterialInfo handle;
 			GUIMaterialInfo handle;
 			UINT32 refCount;
 			UINT32 refCount;
 		};
 		};

+ 6 - 1
BansheeEngine/Include/BsImageSprite.h

@@ -46,7 +46,12 @@ namespace BansheeEngine
 
 
 		/**
 		/**
 		 * @brief	Recreates internal sprite data according the specified description structure.
 		 * @brief	Recreates internal sprite data according the specified description structure.
+		 *
+		 * @param	desc	Describes the geometry and material of the sprite.
+		 * @param	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);
+		void update(const IMAGE_SPRITE_DESC& desc, UINT64 groupId);
 	};
 	};
 }
 }

+ 6 - 1
BansheeEngine/Include/BsTextSprite.h

@@ -56,8 +56,13 @@ namespace BansheeEngine
 
 
 		/**
 		/**
 		 * @brief	Recreates internal sprite data according the specified description structure.
 		 * @brief	Recreates internal sprite data according the specified description structure.
+		 *
+		 * @param	desc	Describes the geometry and material of the sprite.
+		 * @param	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 TEXT_SPRITE_DESC& desc);
+		void update(const TEXT_SPRITE_DESC& desc, UINT64 groupId);
 
 
 		/**
 		/**
 		 * @brief	Calculates and returns offset for each individual text line. The offsets provide
 		 * @brief	Calculates and returns offset for each individual text line. The offsets provide

+ 3 - 3
BansheeEngine/Source/BsGUIButtonBase.cpp

@@ -114,9 +114,9 @@ namespace BansheeEngine
 		mImageDesc.borderTop = _getStyle()->border.top;
 		mImageDesc.borderTop = _getStyle()->border.top;
 		mImageDesc.borderBottom = _getStyle()->border.bottom;
 		mImageDesc.borderBottom = _getStyle()->border.bottom;
 
 
-		mImageSprite->update(mImageDesc);
+		mImageSprite->update(mImageDesc, (UINT64)_getParentWidget());
 
 
-		mTextSprite->update(getTextDesc());
+		mTextSprite->update(getTextDesc(), (UINT64)_getParentWidget());
 
 
 		if(mContentImageSprite != nullptr)
 		if(mContentImageSprite != nullptr)
 		{
 		{
@@ -125,7 +125,7 @@ namespace BansheeEngine
 			contentImgDesc.width = mContent.getImage()->getWidth();
 			contentImgDesc.width = mContent.getImage()->getWidth();
 			contentImgDesc.height = mContent.getImage()->getHeight();
 			contentImgDesc.height = mContent.getImage()->getHeight();
 
 
-			mContentImageSprite->update(contentImgDesc);
+			mContentImageSprite->update(contentImgDesc, (UINT64)_getParentWidget());
 		}
 		}
 
 
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();

+ 1 - 0
BansheeEngine/Source/BsGUIElementBase.cpp

@@ -4,6 +4,7 @@
 #include "BsGUILayoutY.h"
 #include "BsGUILayoutY.h"
 #include "BsGUIElement.h"
 #include "BsGUIElement.h"
 #include "BsException.h"
 #include "BsException.h"
+#include "BsGUIWidget.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {

+ 2 - 2
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -143,10 +143,10 @@ namespace BansheeEngine
 			mImageDesc.texture = activeTex.getInternalPtr();
 			mImageDesc.texture = activeTex.getInternalPtr();
 		}
 		}
 
 
-		mImageSprite->update(mImageDesc);
+		mImageSprite->update(mImageDesc, (UINT64)_getParentWidget());
 
 
 		TEXT_SPRITE_DESC textDesc = getTextDesc();
 		TEXT_SPRITE_DESC textDesc = getTextDesc();
-		mTextSprite->update(textDesc);
+		mTextSprite->update(textDesc, (UINT64)_getParentWidget());
 
 
 		if(mCaretShown && gGUIManager().getCaretBlinkState())
 		if(mCaretShown && gGUIManager().getCaretBlinkState())
 		{
 		{

+ 5 - 1
BansheeEngine/Source/BsGUIInputCaret.cpp

@@ -52,7 +52,11 @@ namespace BansheeEngine
 		mCaretDesc.height = getCaretHeight();
 		mCaretDesc.height = getCaretHeight();
 		mCaretDesc.texture = GUIManager::instance().getCaretTexture().getInternalPtr();
 		mCaretDesc.texture = GUIManager::instance().getCaretTexture().getInternalPtr();
 
 
-		mCaretSprite->update(mCaretDesc);
+		GUIWidget* widget = nullptr;
+		if (mElement != nullptr)
+			widget = mElement->_getParentWidget();
+
+		mCaretSprite->update(mCaretDesc, (UINT64)widget);
 	}
 	}
 
 
 	void GUIInputCaret::moveCaretToStart()
 	void GUIInputCaret::moveCaretToStart()

+ 5 - 1
BansheeEngine/Source/BsGUIInputSelection.cpp

@@ -38,6 +38,10 @@ namespace BansheeEngine
 			}
 			}
 		}
 		}
 
 
+		const GUIWidget* widget = nullptr;
+		if (mElement != nullptr)
+			widget = mElement->_getParentWidget();
+
 		UINT32 idx = 0;
 		UINT32 idx = 0;
 		for(auto& sprite : mSprites)
 		for(auto& sprite : mSprites)
 		{
 		{
@@ -46,7 +50,7 @@ namespace BansheeEngine
 			desc.height = mSelectionRects[idx].height;
 			desc.height = mSelectionRects[idx].height;
 			desc.texture = GUIManager::instance().getTextSelectionTexture().getInternalPtr();
 			desc.texture = GUIManager::instance().getTextSelectionTexture().getInternalPtr();
 
 
-			sprite->update(desc);
+			sprite->update(desc, (UINT64)widget);
 			idx++;
 			idx++;
 		}
 		}
 	}
 	}

+ 1 - 1
BansheeEngine/Source/BsGUILabel.cpp

@@ -49,7 +49,7 @@ namespace BansheeEngine
 		mDesc.height = mHeight;
 		mDesc.height = mHeight;
 		mDesc.text = mContent.getText();
 		mDesc.text = mContent.getText();
 
 
-		mTextSprite->update(mDesc);
+		mTextSprite->update(mDesc, (UINT64)_getParentWidget());
 
 
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}

+ 36 - 15
BansheeEngine/Source/BsGUIMaterialManager.cpp

@@ -12,15 +12,16 @@ namespace BansheeEngine
 		SAMPLER_STATE_DESC ssDesc;
 		SAMPLER_STATE_DESC ssDesc;
 		ssDesc.magFilter = FO_POINT;
 		ssDesc.magFilter = FO_POINT;
 		ssDesc.minFilter = FO_POINT;
 		ssDesc.minFilter = FO_POINT;
-		ssDesc.mipFilter = FO_POINT;

+		ssDesc.mipFilter = FO_POINT;
+
 		mGUISamplerState = SamplerState::create(ssDesc);
 		mGUISamplerState = SamplerState::create(ssDesc);
 	}
 	}
 
 
-	const GUIMaterialInfo& GUIMaterialManager::requestTextMaterial(const HTexture& texture, const Color& tint) const
+	const GUIMaterialInfo& GUIMaterialManager::requestTextMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
 	{
 	{
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 
 
-		const GUIMaterialInfo* matInfo = findExistingTextMaterial(texture, tint);
+		const GUIMaterialInfo* matInfo = findExistingTextMaterial(groupId, texture, tint);
 		if(matInfo != nullptr)
 		if(matInfo != nullptr)
 			return *matInfo;
 			return *matInfo;
 
 
@@ -32,16 +33,17 @@ namespace BansheeEngine
 		guiMat.handle.mainTexSampler.set(mGUISamplerState);
 		guiMat.handle.mainTexSampler.set(mGUISamplerState);
 		guiMat.handle.mainTexture.set(texture);
 		guiMat.handle.mainTexture.set(texture);
 		guiMat.handle.tint.set(vecColor);
 		guiMat.handle.tint.set(vecColor);
-		guiMat.refCount = 1;		
+		guiMat.refCount = 1;
+		guiMat.groupId = groupId;
 
 
 		return guiMat.handle;
 		return guiMat.handle;
 	}
 	}
 
 
-	const GUIMaterialInfo& GUIMaterialManager::requestImageMaterial(const HTexture& texture, const Color& tint) const
+	const GUIMaterialInfo& GUIMaterialManager::requestImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
 	{
 	{
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 
 
-		const GUIMaterialInfo* matInfo = findExistingImageMaterial(texture, tint);
+		const GUIMaterialInfo* matInfo = findExistingImageMaterial(groupId, texture, tint);
 		if(matInfo != nullptr)
 		if(matInfo != nullptr)
 			return *matInfo;
 			return *matInfo;
 
 
@@ -53,16 +55,17 @@ namespace BansheeEngine
 		guiMat.handle.mainTexSampler.set(mGUISamplerState);
 		guiMat.handle.mainTexSampler.set(mGUISamplerState);
 		guiMat.handle.mainTexture.set(texture);
 		guiMat.handle.mainTexture.set(texture);
 		guiMat.handle.tint.set(vecColor);
 		guiMat.handle.tint.set(vecColor);
-		guiMat.refCount = 1;		
+		guiMat.refCount = 1;
+		guiMat.groupId = groupId;
 
 
 		return guiMat.handle;
 		return guiMat.handle;
 	}
 	}
 
 
-	const GUIMaterialInfo& GUIMaterialManager::requestNonAlphaImageMaterial(const HTexture& texture, const Color& tint) const
+	const GUIMaterialInfo& GUIMaterialManager::requestNonAlphaImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
 	{
 	{
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 
 
-		const GUIMaterialInfo* matInfo = findExistingNonAlphaImageMaterial(texture, tint);
+		const GUIMaterialInfo* matInfo = findExistingNonAlphaImageMaterial(groupId, texture, tint);
 		if (matInfo != nullptr)
 		if (matInfo != nullptr)
 			return *matInfo;
 			return *matInfo;
 
 
@@ -75,17 +78,18 @@ namespace BansheeEngine
 		guiMat.handle.mainTexture.set(texture);
 		guiMat.handle.mainTexture.set(texture);
 		guiMat.handle.tint.set(vecColor);
 		guiMat.handle.tint.set(vecColor);
 		guiMat.refCount = 1;
 		guiMat.refCount = 1;
+		guiMat.groupId = groupId;
 
 
 		return guiMat.handle;
 		return guiMat.handle;
 	}
 	}
 
 
-	const GUIMaterialInfo* GUIMaterialManager::findExistingTextMaterial(const HTexture& texture, const Color& tint) const
+	const GUIMaterialInfo* GUIMaterialManager::findExistingTextMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
 	{
 	{
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 
 
 		for(auto& matHandle : mTextMaterials)
 		for(auto& matHandle : mTextMaterials)
 		{
 		{
-			if(matHandle.handle.mainTexture.get() == texture && matHandle.handle.tint.get() == vecColor)
+			if (matHandle.handle.mainTexture.get() == texture && matHandle.handle.tint.get() == vecColor && matHandle.groupId == groupId)
 			{
 			{
 				matHandle.refCount++;
 				matHandle.refCount++;
 				return &matHandle.handle;
 				return &matHandle.handle;
@@ -95,13 +99,13 @@ namespace BansheeEngine
 		return nullptr;
 		return nullptr;
 	}
 	}
 
 
-	const GUIMaterialInfo* GUIMaterialManager::findExistingImageMaterial(const HTexture& texture, const Color& tint) const
+	const GUIMaterialInfo* GUIMaterialManager::findExistingImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
 	{
 	{
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 
 
 		for(auto& matHandle : mImageMaterials)
 		for(auto& matHandle : mImageMaterials)
 		{
 		{
-			if(matHandle.handle.mainTexture.get() == texture && matHandle.handle.tint.get() == vecColor)
+			if (matHandle.handle.mainTexture.get() == texture && matHandle.handle.tint.get() == vecColor && matHandle.groupId == groupId)
 			{
 			{
 				matHandle.refCount++;
 				matHandle.refCount++;
 				return &matHandle.handle;
 				return &matHandle.handle;
@@ -111,13 +115,13 @@ namespace BansheeEngine
 		return nullptr;
 		return nullptr;
 	}
 	}
 
 
-	const GUIMaterialInfo* GUIMaterialManager::findExistingNonAlphaImageMaterial(const HTexture& texture, const Color& tint) const
+	const GUIMaterialInfo* GUIMaterialManager::findExistingNonAlphaImageMaterial(UINT64 groupId, const HTexture& texture, const Color& tint) const
 	{
 	{
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 		Vector4 vecColor(tint.r, tint.g, tint.b, tint.a);
 
 
 		for (auto& matHandle : mNonAlphaImageMaterials)
 		for (auto& matHandle : mNonAlphaImageMaterials)
 		{
 		{
-			if (matHandle.handle.mainTexture.get() == texture && matHandle.handle.tint.get() == vecColor)
+			if (matHandle.handle.mainTexture.get() == texture && matHandle.handle.tint.get() == vecColor && matHandle.groupId == groupId)
 			{
 			{
 				matHandle.refCount++;
 				matHandle.refCount++;
 				return &matHandle.handle;
 				return &matHandle.handle;
@@ -162,11 +166,28 @@ namespace BansheeEngine
 
 
 			i++;
 			i++;
 		}
 		}
+
+		i = 0;
+		for (auto& matHandle : mNonAlphaImageMaterials)
+		{
+			if (&matHandle.handle == &material)
+			{
+				if (--matHandle.refCount == 0)
+				{
+					mNonAlphaImageMaterials.erase(mNonAlphaImageMaterials.begin() + i);
+					released = true;
+					break;
+				}
+			}
+
+			i++;
+		}
 	}
 	}
 
 
 	void GUIMaterialManager::clearMaterials()
 	void GUIMaterialManager::clearMaterials()
 	{
 	{
 		mTextMaterials.clear();
 		mTextMaterials.clear();
 		mImageMaterials.clear();
 		mImageMaterials.clear();
+		mNonAlphaImageMaterials.clear();
 	}
 	}
 }
 }

+ 1 - 1
BansheeEngine/Source/BsGUIRenderTexture.cpp

@@ -73,7 +73,7 @@ namespace BansheeEngine
 		mDesc.height = mHeight;
 		mDesc.height = mHeight;
 		mDesc.transparent = false;
 		mDesc.transparent = false;
 
 
-		mImageSprite->update(mDesc);
+		mImageSprite->update(mDesc, (UINT64)_getParentWidget());
 
 
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}

+ 1 - 1
BansheeEngine/Source/BsGUIScrollBar.cpp

@@ -91,7 +91,7 @@ namespace BansheeEngine
 		desc.width = mWidth;
 		desc.width = mWidth;
 		desc.height = mHeight;
 		desc.height = mHeight;
 
 
-		mImageSprite->update(desc);
+		mImageSprite->update(desc, (UINT64)_getParentWidget());
 
 
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}

+ 1 - 1
BansheeEngine/Source/BsGUIScrollBarHandle.cpp

@@ -104,7 +104,7 @@ namespace BansheeEngine
 			desc.height = mHandleSize;
 			desc.height = mHandleSize;
 		}
 		}
 
 
-		mImageSprite->update(desc);
+		mImageSprite->update(desc, (UINT64)_getParentWidget());
 		
 		
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}

+ 1 - 1
BansheeEngine/Source/BsGUITexture.cpp

@@ -191,7 +191,7 @@ namespace BansheeEngine
 			break;
 			break;
 		}
 		}
 
 
-		mImageSprite->update(mDesc);
+		mImageSprite->update(mDesc, (UINT64)_getParentWidget());
 		
 		
 		GUIElement::updateRenderElementsInternal();
 		GUIElement::updateRenderElementsInternal();
 	}
 	}

+ 5 - 5
BansheeEngine/Source/BsImageSprite.cpp

@@ -13,7 +13,7 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	void ImageSprite::update(const IMAGE_SPRITE_DESC& desc)
+	void ImageSprite::update(const IMAGE_SPRITE_DESC& desc, UINT64 groupId)
 	{
 	{
 		const FontData* fontData = nullptr;
 		const FontData* fontData = nullptr;
 		if(desc.texture == nullptr || desc.texture->getTexture() == nullptr)
 		if(desc.texture == nullptr || desc.texture->getTexture() == nullptr)
@@ -64,9 +64,9 @@ namespace BansheeEngine
 				const GUIMaterialInfo* matInfo = nullptr;
 				const GUIMaterialInfo* matInfo = nullptr;
 				
 				
 				if (desc.transparent)
 				if (desc.transparent)
-					matInfo = GUIMaterialManager::instance().findExistingImageMaterial(tex, desc.color);
+					matInfo = GUIMaterialManager::instance().findExistingImageMaterial(groupId, tex, desc.color);
 				else
 				else
-					matInfo = GUIMaterialManager::instance().findExistingNonAlphaImageMaterial(tex, desc.color);
+					matInfo = GUIMaterialManager::instance().findExistingNonAlphaImageMaterial(groupId, tex, desc.color);
 
 
 				if(matInfo == nullptr)
 				if(matInfo == nullptr)
 				{
 				{
@@ -85,9 +85,9 @@ namespace BansheeEngine
 			if (getNewMaterial)
 			if (getNewMaterial)
 			{
 			{
 				if (desc.transparent)
 				if (desc.transparent)
-					renderElem.matInfo = GUIMaterialManager::instance().requestImageMaterial(tex, desc.color);
+					renderElem.matInfo = GUIMaterialManager::instance().requestImageMaterial(groupId, tex, desc.color);
 				else
 				else
-					renderElem.matInfo = GUIMaterialManager::instance().requestNonAlphaImageMaterial(tex, desc.color);
+					renderElem.matInfo = GUIMaterialManager::instance().requestNonAlphaImageMaterial(groupId, tex, desc.color);
 			}
 			}
 
 
 			texPage++;
 			texPage++;

+ 3 - 3
BansheeEngine/Source/BsTextSprite.cpp

@@ -13,7 +13,7 @@ namespace BansheeEngine
 
 
 	}
 	}
 
 
-	void TextSprite::update(const TEXT_SPRITE_DESC& desc)
+	void TextSprite::update(const TEXT_SPRITE_DESC& desc, UINT64 groupId)
 	{
 	{
 		TextData textData(desc.text, desc.font, desc.fontSize, desc.width, desc.height, desc.wordWrap);
 		TextData textData(desc.text, desc.font, desc.fontSize, desc.width, desc.height, desc.wordWrap);
 
 
@@ -76,7 +76,7 @@ namespace BansheeEngine
 				getNewMaterial = true;
 				getNewMaterial = true;
 			else
 			else
 			{
 			{
-				const GUIMaterialInfo* matInfo = GUIMaterialManager::instance().findExistingImageMaterial(tex, desc.color);
+				const GUIMaterialInfo* matInfo = GUIMaterialManager::instance().findExistingTextMaterial(groupId, tex, desc.color);
 				if(matInfo == nullptr)
 				if(matInfo == nullptr)
 				{
 				{
 					getNewMaterial = true;
 					getNewMaterial = true;
@@ -92,7 +92,7 @@ namespace BansheeEngine
 			}
 			}
 
 
 			if(getNewMaterial)
 			if(getNewMaterial)
-				cachedElem.matInfo = GUIMaterialManager::instance().requestTextMaterial(tex, desc.color);
+				cachedElem.matInfo = GUIMaterialManager::instance().requestTextMaterial(groupId, tex, desc.color);
 
 
 			texPage++;
 			texPage++;
 		}
 		}

+ 3 - 3
BansheeGLRenderSystem/Source/BsGLTexture.cpp

@@ -189,7 +189,7 @@ namespace BansheeEngine
 
 
 	PixelData GLTextureCore::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
 	PixelData GLTextureCore::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
 	{
 	{
-		if (mProperties.getMultisampleCount() > 0)
+		if (mProperties.getMultisampleCount() > 1)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
 
 		if(mLockedBuffer != nullptr)
 		if(mLockedBuffer != nullptr)
@@ -219,7 +219,7 @@ namespace BansheeEngine
 
 
 	void GLTextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
 	void GLTextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
 	{
 	{
-		if (mProperties.getMultisampleCount() > 0)
+		if (mProperties.getMultisampleCount() > 1)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
 
 		getBuffer(face, mipLevel)->download(dest);
 		getBuffer(face, mipLevel)->download(dest);
@@ -227,7 +227,7 @@ namespace BansheeEngine
 
 
 	void GLTextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
 	void GLTextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
 	{
 	{
-		if (mProperties.getMultisampleCount() > 0)
+		if (mProperties.getMultisampleCount() > 1)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
 
 		getBuffer(face, mipLevel)->upload(src, src.getExtents());
 		getBuffer(face, mipLevel)->upload(src, src.getExtents());

+ 1 - 1
BansheeMono/Source/BsMonoField.cpp

@@ -76,7 +76,7 @@ namespace BansheeEngine
 
 
 	MonoFieldVisibility MonoField::getVisibility()
 	MonoFieldVisibility MonoField::getVisibility()
 	{
 	{
-		uint32_t flags = mono_field_get_flags(mField);
+		uint32_t flags = mono_field_get_flags(mField) & MONO_FIELD_ATTR_FIELD_ACCESS_MASK;
 
 
 		if(flags == MONO_FIELD_ATTR_PRIVATE)
 		if(flags == MONO_FIELD_ATTR_PRIVATE)
 			return MonoFieldVisibility::Private;
 			return MonoFieldVisibility::Private;

+ 3 - 0
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -217,6 +217,9 @@ namespace BansheeEngine
 			const CameraHandlerCore* camera = cameraData.first;
 			const CameraHandlerCore* camera = cameraData.first;
 			SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
 			SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
 
 
+			if (renderTarget == nullptr)
+				continue;
+
 			auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(), [&](const RenderTargetData& x) { return x.target == renderTarget; });
 			auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(), [&](const RenderTargetData& x) { return x.target == renderTarget; });
 			if (findIter != mRenderTargets.end())
 			if (findIter != mRenderTargets.end())
 			{
 			{

+ 8 - 8
MBansheeEditor/DbgGizmo.cs

@@ -20,15 +20,15 @@ namespace BansheeEditor
                 iconTexture = new SpriteTexture(iconTex);
                 iconTexture = new SpriteTexture(iconTex);
             }
             }
 
 
-            Gizmos.DrawCube(target.sceneObject.Position, new Vector3(1, 1, 1));
-            Gizmos.DrawSphere(target.sceneObject.Position + 2 * Vector3.xAxis, 1.0f);
-            Gizmos.DrawWireCube(target.sceneObject.Position + 4 * Vector3.xAxis, new Vector3(1, 1, 1));
-            Gizmos.DrawWireSphere(target.sceneObject.Position + 6 * Vector3.xAxis, 1.0f);
-            Gizmos.DrawLine(target.sceneObject.Position + 7.5f * Vector3.xAxis,
-                target.sceneObject.Position + 8.5f * Vector3.xAxis);
-            Gizmos.DrawFrustum(target.sceneObject.Position + 10 * Vector3.xAxis, 1920.0f / 1080.0f, 90, 1.0f, 1000.0f);
+            Gizmos.DrawCube(target.sceneObject.position, new Vector3(1, 1, 1));
+            Gizmos.DrawSphere(target.sceneObject.position + 2 * Vector3.xAxis, 1.0f);
+            Gizmos.DrawWireCube(target.sceneObject.position + 4 * Vector3.xAxis, new Vector3(1, 1, 1));
+            Gizmos.DrawWireSphere(target.sceneObject.position + 6 * Vector3.xAxis, 1.0f);
+            Gizmos.DrawLine(target.sceneObject.position + 7.5f * Vector3.xAxis,
+                target.sceneObject.position + 8.5f * Vector3.xAxis);
+            Gizmos.DrawFrustum(target.sceneObject.position + 10 * Vector3.xAxis, 1920.0f / 1080.0f, 90, 1.0f, 1000.0f);
 
 
-            Gizmos.DrawIcon(target.sceneObject.Position + new Vector3(0, 10, 0), iconTexture, false);
+            Gizmos.DrawIcon(target.sceneObject.position + new Vector3(0, 10, 0), iconTexture, false);
         }
         }
     }
     }
 }
 }

+ 3 - 3
MBansheeEditor/DebugCameraHandle.cs

@@ -18,7 +18,7 @@ namespace BansheeEditor
 
 
         protected override void PreInput()
         protected override void PreInput()
         {
         {
-            xAxis.Position = target.sceneObject.Position;
+            xAxis.Position = target.sceneObject.position;
         }
         }
 
 
         protected override void PostInput()
         protected override void PostInput()
@@ -28,14 +28,14 @@ namespace BansheeEditor
 
 
         protected override void Draw()
         protected override void Draw()
         {
         {
-            Vector3 end = target.sceneObject.Position + Vector3.xAxis * 5;
+            Vector3 end = target.sceneObject.position + Vector3.xAxis * 5;
 
 
             if (xAxis.State == HandleSlider.StateType.Active)
             if (xAxis.State == HandleSlider.StateType.Active)
                 HandleDrawing.SetColor(Color.white);
                 HandleDrawing.SetColor(Color.white);
             else
             else
                 HandleDrawing.SetColor(Color.green);
                 HandleDrawing.SetColor(Color.green);
 
 
-            HandleDrawing.DrawLine(target.sceneObject.Position, end);
+            HandleDrawing.DrawLine(target.sceneObject.position, end);
         }
         }
     }
     }
 }
 }

+ 14 - 5
MBansheeEditor/EditorWindow.cs

@@ -19,12 +19,16 @@ namespace BansheeEditor
 
 
         public Vector2I ScreenToWindowPos(Vector2I screenPos)
         public Vector2I ScreenToWindowPos(Vector2I screenPos)
         {
         {
-            return Internal_ScreenToWindowPos(mCachedPtr, screenPos);
+            Vector2I windowPos;
+            Internal_ScreenToWindowPos(mCachedPtr, screenPos, out windowPos);
+            return windowPos;
         }
         }
 
 
-        public Vector2I WindowToScreenPos(Vector2I screenPos)
+        public Vector2I WindowToScreenPos(Vector2I windowPos)
         {
         {
-            return Internal_WindowToScreenPos(mCachedPtr, screenPos);
+            Vector2I screenPos;
+            Internal_WindowToScreenPos(mCachedPtr, windowPos, out screenPos);
+            return screenPos;
         }
         }
 
 
         protected EditorWindow()
         protected EditorWindow()
@@ -37,6 +41,11 @@ namespace BansheeEditor
             GUI.SetArea(0, 0, width, height);
             GUI.SetArea(0, 0, width, height);
         }
         }
 
 
+        protected virtual void FocusChanged(bool inFocus)
+        {
+            
+        }
+
         internal GUIPanel CreatePanel(int x, int y, int width, int height)
         internal GUIPanel CreatePanel(int x, int y, int width, int height)
         {
         {
             GUIPanel newPanel = new GUIPanel();
             GUIPanel newPanel = new GUIPanel();
@@ -63,9 +72,9 @@ namespace BansheeEditor
         private static extern bool Internal_HasFocus(IntPtr nativeInstance);
         private static extern bool Internal_HasFocus(IntPtr nativeInstance);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern Vector2I Internal_ScreenToWindowPos(IntPtr nativeInstance, Vector2I position);
+        private static extern void Internal_ScreenToWindowPos(IntPtr nativeInstance, Vector2I position, out Vector2I windowPos);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern Vector2I Internal_WindowToScreenPos(IntPtr nativeInstance, Vector2I position);
+        private static extern void Internal_WindowToScreenPos(IntPtr nativeInstance, Vector2I position, out Vector2I screenPos);
     }
     }
 }
 }

+ 5 - 5
MBansheeEditor/Scene/DefaultHandleManager.cs

@@ -10,7 +10,7 @@ namespace BansheeEditor
             public HandledObject(SceneObject so)
             public HandledObject(SceneObject so)
             {
             {
                 this.so = so;
                 this.so = so;
-                initialPosition = so.Position;
+                initialPosition = so.position;
             }
             }
 
 
             public SceneObject so;
             public SceneObject so;
@@ -68,11 +68,11 @@ namespace BansheeEditor
                 if (EditorApplication.HandleCoordinateMode == HandleCoordinateMode.World)
                 if (EditorApplication.HandleCoordinateMode == HandleCoordinateMode.World)
                     rotation = Quaternion.identity;
                     rotation = Quaternion.identity;
                 else
                 else
-                    rotation = selectedSceneObjects[0].Rotation; // We don't average rotation in case of multi-selection
+                    rotation = selectedSceneObjects[0].rotation; // We don't average rotation in case of multi-selection
 
 
                 Vector3 position;
                 Vector3 position;
                 if (EditorApplication.HandlePositionMode == HandlePositionMode.Pivot)
                 if (EditorApplication.HandlePositionMode == HandlePositionMode.Pivot)
-                    position = selectedSceneObjects[0].Position; // Just take pivot from the first one, no averaging
+                    position = selectedSceneObjects[0].position; // Just take pivot from the first one, no averaging
                 else
                 else
                 {
                 {
                     List<SceneObject> flatenedHierarchy = new List<SceneObject>();
                     List<SceneObject> flatenedHierarchy = new List<SceneObject>();
@@ -82,7 +82,7 @@ namespace BansheeEditor
                     }
                     }
 
 
                     AABox selectionBounds = EditorUtility.CalculateBounds(flatenedHierarchy.ToArray());
                     AABox selectionBounds = EditorUtility.CalculateBounds(flatenedHierarchy.ToArray());
-                    position = selectionBounds.Center;
+                    position = selectionBounds.center;
                 }
                 }
 
 
                 activeHandle.Position = position;
                 activeHandle.Position = position;
@@ -125,7 +125,7 @@ namespace BansheeEditor
                             MoveHandle moveHandle = (MoveHandle) activeHandle;
                             MoveHandle moveHandle = (MoveHandle) activeHandle;
 
 
                             foreach (var selectedObj in activeSelection)
                             foreach (var selectedObj in activeSelection)
-                                selectedObj.so.Position = selectedObj.initialPosition + moveHandle.Delta;
+                                selectedObj.so.position = selectedObj.initialPosition + moveHandle.Delta;
                         }
                         }
 
 
                             break;
                             break;

+ 2 - 2
MBansheeEditor/Scene/Handles.cs

@@ -51,10 +51,10 @@ namespace BansheeEditor
 
 
         public static float GetHandleSize(Camera camera, Vector3 position)
         public static float GetHandleSize(Camera camera, Vector3 position)
         {
         {
-            Vector3 cameraPos = camera.sceneObject.Position;
+            Vector3 cameraPos = camera.sceneObject.position;
 
 
 		    Vector3 diff = position - cameraPos;
 		    Vector3 diff = position - cameraPos;
-		    float distAlongViewDir = Vector3.Dot(diff, camera.sceneObject.Rotation.Forward);
+		    float distAlongViewDir = Vector3.Dot(diff, camera.sceneObject.rotation.Forward);
 
 
 		    return EditorSettings.DefaultHandleSize / Math.Max(distAlongViewDir, 0.0001f);
 		    return EditorSettings.DefaultHandleSize / Math.Max(distAlongViewDir, 0.0001f);
         }
         }

+ 48 - 45
MBansheeEditor/Scene/SceneCamera.cs

@@ -34,8 +34,8 @@ namespace BansheeEditor
         private VirtualAxis verticalAxis;
         private VirtualAxis verticalAxis;
 
 
         private float currentSpeed;
         private float currentSpeed;
-        private Degree pitch;
         private Degree yaw;
         private Degree yaw;
+        private Radian pitch;
         private bool lastButtonState;
         private bool lastButtonState;
 
 
         public SceneCamera()
         public SceneCamera()
@@ -51,7 +51,7 @@ namespace BansheeEditor
         }
         }
 
 
         private void Update()
         private void Update()
-	    {
+        {
             // TODO - Only move if scene view is focused
             // TODO - Only move if scene view is focused
 
 
 		    bool goingForward = VirtualInput.IsButtonHeld(moveForwardBtn);
 		    bool goingForward = VirtualInput.IsButtonHeld(moveForwardBtn);
@@ -61,62 +61,65 @@ namespace BansheeEditor
 		    bool fastMove = VirtualInput.IsButtonHeld(fastMoveBtn);
 		    bool fastMove = VirtualInput.IsButtonHeld(fastMoveBtn);
 		    bool camRotating = VirtualInput.IsButtonHeld(rotateBtn);
 		    bool camRotating = VirtualInput.IsButtonHeld(rotateBtn);
 
 
-		    if (camRotating != lastButtonState)
-		    {
-		        if (camRotating)
-		            Cursor.Hide();
-		        else
-		            Cursor.Show();
+            if (camRotating != lastButtonState)
+            {
+                if (camRotating)
+                    Cursor.Hide();
+                else
+                    Cursor.Show();
 
 
-			    lastButtonState = camRotating;
-		    }
+                lastButtonState = camRotating;
+            }
 
 
 		    float frameDelta = Time.frameDelta;
 		    float frameDelta = Time.frameDelta;
 		    if (camRotating)
 		    if (camRotating)
 		    {
 		    {
-			    yaw += new Degree(VirtualInput.GetAxisValue(horizontalAxis) * RotationalSpeed * frameDelta);
-			    pitch += new Degree(VirtualInput.GetAxisValue(verticalAxis) * RotationalSpeed * frameDelta);
+		        float horzValue = VirtualInput.GetAxisValue(horizontalAxis);
+                float vertValue = VirtualInput.GetAxisValue(verticalAxis);
+
+                yaw += new Degree(horzValue * RotationalSpeed * frameDelta);
+                pitch += new Degree(vertValue * RotationalSpeed * frameDelta);
 
 
-			    yaw = MathEx.WrapAngle(yaw);
+                yaw = MathEx.WrapAngle(yaw);
                 pitch = MathEx.WrapAngle(pitch);
                 pitch = MathEx.WrapAngle(pitch);
 
 
 		        Quaternion yRot = Quaternion.FromAxisAngle(Vector3.yAxis, yaw);
 		        Quaternion yRot = Quaternion.FromAxisAngle(Vector3.yAxis, yaw);
                 Quaternion xRot = Quaternion.FromAxisAngle(Vector3.xAxis, pitch);
                 Quaternion xRot = Quaternion.FromAxisAngle(Vector3.xAxis, pitch);
 
 
-			    Quaternion camRot = yRot * xRot;
-		        camRot.Normalize();
+                Quaternion camRot = yRot * xRot;
+                camRot.Normalize();
 
 
-		        sceneObject.Rotate(camRot);
+                sceneObject.rotation = camRot;
 		    }
 		    }
 
 
-		    Vector3 direction = Vector3.zero;
-		    if (goingForward) direction += sceneObject.Forward;
-		    if (goingBack) direction -= sceneObject.Forward;
-		    if (goingRight) direction += sceneObject.Right;
-		    if (goingLeft) direction -= sceneObject.Right;
-
-		    if (direction.sqrdMagnitude != 0)
-		    {
-		        direction.Normalize();
-
-			    float multiplier = 1.0f;
-			    if (fastMove)
-				    multiplier = FastModeMultiplier;
-
-			    currentSpeed = MathEx.Clamp(currentSpeed + Acceleration * frameDelta, StartSpeed, TopSpeed);
-			    currentSpeed *= multiplier;
-		    }
-		    else
-		    {
-			    currentSpeed = 0.0f;
-		    }
-
-		    const float tooSmall = 0.0001f;
-		    if (currentSpeed > tooSmall)
-		    {
-			    Vector3 velocity = direction * currentSpeed;
-			    sceneObject.Move(velocity * frameDelta);
-		    }
-	    }
+            Vector3 direction = Vector3.zero;
+            if (goingForward) direction += sceneObject.forward;
+            if (goingBack) direction -= sceneObject.forward;
+            if (goingRight) direction += sceneObject.right;
+            if (goingLeft) direction -= sceneObject.right;
+
+            if (direction.sqrdMagnitude != 0)
+            {
+                direction.Normalize();
+
+                float multiplier = 1.0f;
+                if (fastMove)
+                    multiplier = FastModeMultiplier;
+
+                currentSpeed = MathEx.Clamp(currentSpeed + Acceleration * frameDelta, StartSpeed, TopSpeed);
+                currentSpeed *= multiplier;
+            }
+            else
+            {
+                currentSpeed = 0.0f;
+            }
+
+            const float tooSmall = 0.0001f;
+            if (currentSpeed > tooSmall)
+            {
+                Vector3 velocity = direction * currentSpeed;
+                sceneObject.Move(velocity * frameDelta);
+            }
+        }
     }
     }
 }
 }

+ 22 - 6
MBansheeEditor/Scene/SceneViewHandler.cs

@@ -20,14 +20,24 @@ namespace BansheeEditor
             Internal_Update(mCachedPtr, pointerPos, inputDelta);
             Internal_Update(mCachedPtr, pointerPos, inputDelta);
         }
         }
 
 
-        internal void PointerPressed(Vector2I pointerPos)
+        internal void TrySelectHandle(Vector2I pointerPos)
         {
         {
-            Internal_PointerPressed(mCachedPtr, pointerPos);
+            Internal_TrySelectHandle(mCachedPtr, pointerPos);
         }
         }
 
 
-        internal void PointerReleased(Vector2I pointerPos, bool controlHeld)
+        internal bool IsHandleActive()
         {
         {
-            Internal_PointerReleased(mCachedPtr, pointerPos, controlHeld);
+            return Internal_IsHandleActive(mCachedPtr);
+        }
+
+        internal void ClearHandleSelection()
+        {
+            Internal_ClearHandleSelection(mCachedPtr);
+        }
+
+        internal void PickObject(Vector2I pointerPos, bool controlHeld)
+        {
+            Internal_PickObject(mCachedPtr, pointerPos, controlHeld);
         }
         }
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
@@ -37,9 +47,15 @@ namespace BansheeEditor
         private static extern void Internal_Update(IntPtr thisPtr, Vector2I pointerPos, Vector2I inputDelta);
         private static extern void Internal_Update(IntPtr thisPtr, Vector2I pointerPos, Vector2I inputDelta);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_PointerPressed(IntPtr thisPtr, Vector2I pointerPos);
+        private static extern void Internal_TrySelectHandle(IntPtr thisPtr, Vector2I pointerPos);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_IsHandleActive(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_ClearHandleSelection(IntPtr thisPtr);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_PointerReleased(IntPtr thisPtr, Vector2I pointerPos, bool controlHeld);
+        private static extern void Internal_PickObject(IntPtr thisPtr, Vector2I pointerPos, bool controlHeld);
     }
     }
 }
 }

+ 38 - 20
MBansheeEditor/Scene/SceneWindow.cs

@@ -47,19 +47,36 @@ namespace BansheeEditor
 
 
         private void EditorUpdate()
         private void EditorUpdate()
         {
         {
-            if (Input.IsButtonDown(ButtonCode.MouseLeft))
+            if (HasFocus)
             {
             {
-                sceneViewHandler.PointerPressed(Input.PointerPosition);
+                if (Input.IsButtonDown(ButtonCode.MouseLeft))
+                {
+                    sceneViewHandler.TrySelectHandle(Input.PointerPosition);
 
 
-                Vector2I scenePos;
-                if (ScreenToScenePos(Input.PointerPosition, out scenePos))
-                    dragActive = true;
-            }
-            else if (Input.IsButtonUp(ButtonCode.MouseLeft))
-            {
-                bool ctrlHeld = Input.IsButtonHeld(ButtonCode.LeftControl) || Input.IsButtonHeld(ButtonCode.RightControl);
-                sceneViewHandler.PointerReleased(Input.PointerPosition, ctrlHeld);
-                dragActive = false;
+                    Vector2I scenePos;
+                    if (ScreenToScenePos(Input.PointerPosition, out scenePos))
+                        dragActive = true;
+                }
+                else if (Input.IsButtonUp(ButtonCode.MouseLeft))
+                {
+                    bool ctrlHeld = Input.IsButtonHeld(ButtonCode.LeftControl) || Input.IsButtonHeld(ButtonCode.RightControl);
+
+                    if(sceneViewHandler.IsHandleActive())
+                        sceneViewHandler.ClearHandleSelection();
+                    else
+                        sceneViewHandler.PickObject(Input.PointerPosition, ctrlHeld);
+
+                    dragActive = false;
+                }
+
+                if (!dragActive)
+                {
+                    Vector2I scenePos;
+                    if (ScreenToScenePos(Input.PointerPosition, out scenePos))
+                    {
+                        sceneViewHandler.Update(scenePos, Input.PointerDelta);
+                    }
+                }
             }
             }
 
 
             if (dragActive)
             if (dragActive)
@@ -68,14 +85,6 @@ namespace BansheeEditor
                 ScreenToScenePos(Input.PointerPosition, out scenePos);
                 ScreenToScenePos(Input.PointerPosition, out scenePos);
                 sceneViewHandler.Update(scenePos, Input.PointerDelta);
                 sceneViewHandler.Update(scenePos, Input.PointerDelta);
             }
             }
-            else
-            {
-                Vector2I scenePos;
-                if (ScreenToScenePos(Input.PointerPosition, out scenePos))
-                {
-                    sceneViewHandler.Update(scenePos, Input.PointerDelta);
-                }
-            }
         }
         }
 
 
         protected override void WindowResized(int width, int height)
         protected override void WindowResized(int width, int height)
@@ -85,6 +94,15 @@ namespace BansheeEditor
             base.WindowResized(width, height);
             base.WindowResized(width, height);
         }
         }
 
 
+        protected override void FocusChanged(bool inFocus)
+        {
+            if (!inFocus)
+            {
+                sceneViewHandler.ClearHandleSelection();
+                dragActive = false;
+            }
+        }
+
         private void UpdateRenderTexture(int width, int height)
         private void UpdateRenderTexture(int width, int height)
 	    {
 	    {
 		    width = Math.Max(20, width);
 		    width = Math.Max(20, width);
@@ -100,7 +118,7 @@ namespace BansheeEditor
 		        camera.target = renderTexture;
 		        camera.target = renderTexture;
 		        camera.viewportRect = new Rect2(0.0f, 0.0f, 1.0f, 1.0f);
 		        camera.viewportRect = new Rect2(0.0f, 0.0f, 1.0f, 1.0f);
 
 
-			    sceneCameraSO.Position = new Vector3(0, 0.5f, 1);
+			    sceneCameraSO.position = new Vector3(0, 0.5f, 1);
 			    sceneCameraSO.LookAt(new Vector3(0, 0, 0));
 			    sceneCameraSO.LookAt(new Vector3(0, 0, 0));
 
 
 		        camera.priority = 1;
 		        camera.priority = 1;

+ 16 - 16
MBansheeEngine/Math/AABox.cs

@@ -5,43 +5,43 @@ namespace BansheeEngine
     [StructLayout(LayoutKind.Sequential), SerializeObject]
     [StructLayout(LayoutKind.Sequential), SerializeObject]
 	public struct AABox
 	public struct AABox
 	{
 	{
-        private Vector3 minimum;
-		private Vector3 maximum;
+        private Vector3 _minimum;
+		private Vector3 _maximum;
 
 
-        public Vector3 Minimum
+        public Vector3 minimum
         {
         {
-            get { return minimum; }
-            set { minimum = value; }
+            get { return _minimum; }
+            set { _minimum = value; }
         }
         }
 
 
-        public Vector3 Maximum
+        public Vector3 maximum
         {
         {
-            get { return maximum; }
-            set { maximum = value; }
+            get { return _maximum; }
+            set { _maximum = value; }
         }
         }
 
 
-        public Vector3 Center
+        public Vector3 center
         {
         {
             get 
             get 
             { 		
             { 		
-                return new Vector3((maximum.x + minimum.x) * 0.5f,
-			            (maximum.y + minimum.y) * 0.5f,
-			            (maximum.z + minimum.z) * 0.5f);
+                return new Vector3((_maximum.x + _minimum.x) * 0.5f,
+			            (_maximum.y + _minimum.y) * 0.5f,
+			            (_maximum.z + _minimum.z) * 0.5f);
             }
             }
         }
         }
 
 
-	    public Vector3 Size
+	    public Vector3 size
 	    {
 	    {
 	        get
 	        get
 	        {
 	        {
-	            return maximum - minimum;
+	            return _maximum - _minimum;
 	        }
 	        }
 	    }
 	    }
 
 
         public AABox(Vector3 min, Vector3 max)
         public AABox(Vector3 min, Vector3 max)
         {
         {
-            minimum = min;
-            maximum = max;
+            _minimum = min;
+            _maximum = max;
         }
         }
 	};
 	};
 }
 }

+ 26 - 24
MBansheeEngine/Math/BsRect3.cs

@@ -3,49 +3,51 @@
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
     [StructLayout(LayoutKind.Sequential), SerializeObject]
     [StructLayout(LayoutKind.Sequential), SerializeObject]
-	public class Rect3
+	public struct Rect3
 	{
 	{
         public Rect3(Vector3 center, Vector3[] axes, float[] extents)
         public Rect3(Vector3 center, Vector3[] axes, float[] extents)
         {
         {
-            this.center = center;
-            this.axes[0] = axes[0];
-            this.axes[1] = axes[1];
-            this.extents[0] = extents[0];
-            this.extents[1] = extents[1];
+            this._center = center;
+            _axisHorz = axes[0];
+            _axisVert = axes[1];
+            _extentHorz = extents[0];
+            _extentVert = extents[1];
         }
         }
 
 
-        public Vector3 Center
+        public Vector3 center
         {
         {
-            get { return center; }
-            set { center = value; }
+            get { return _center; }
+            set { _center = value; }
         }
         }
 
 
-        public Vector3 AxisHorz
+        public Vector3 axisHorz
         {
         {
-            get { return axes[0]; }
-            set { axes[0] = value; }
+            get { return _axisHorz; }
+            set { _axisHorz = value; }
         }
         }
 
 
-        public Vector3 AxisVert
+        public Vector3 axisVert
         {
         {
-            get { return axes[1]; }
-            set { axes[1] = value; }
+            get { return _axisVert; }
+            set { _axisVert = value; }
         }
         }
 
 
-        public float ExtentHorz
+        public float extentHorz
         {
         {
-            get { return extents[0]; }
-            set { extents[0] = value; }
+            get { return _extentHorz; }
+            set { _extentHorz = value; }
         }
         }
 
 
-        public float ExtentVert
+        public float extentVert
         {
         {
-            get { return extents[1]; }
-            set { extents[1] = value; }
+            get { return _extentVert; }
+            set { _extentVert = value; }
         }
         }
 
 
-		private Vector3 center;
-        private Vector3[] axes = new Vector3[2];
-        private float[] extents = new float[2];
+		private Vector3 _center;
+        private Vector3 _axisHorz;
+        private Vector3 _axisVert;
+        private float _extentHorz;
+        private float _extentVert;
 	};
 	};
 }
 }

+ 7 - 0
MBansheeEngine/Math/Degree.cs

@@ -1,10 +1,12 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
+using System.Runtime.InteropServices;
 using System.Text;
 using System.Text;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
 	public struct Degree
 	public struct Degree
 	{
 	{
         readonly float value;
         readonly float value;
@@ -140,5 +142,10 @@ namespace BansheeEngine
         {
         {
             return value.GetHashCode();
             return value.GetHashCode();
         }
         }
+
+        public override string ToString()
+        {
+            return value.ToString();
+        }
 	};
 	};
 }
 }

+ 0 - 1
MBansheeEngine/Math/MathEx.cs

@@ -265,7 +265,6 @@ namespace BansheeEngine
         public static Degree WrapAngle(Degree angle)
         public static Degree WrapAngle(Degree angle)
         {
         {
             const float inv360 = 1.0f/360.0f;
             const float inv360 = 1.0f/360.0f;
-
             float angleVal = angle.GetDegrees();
             float angleVal = angle.GetDegrees();
             float wrapCount = MathEx.Floor(MathEx.Abs(angleVal*inv360));
             float wrapCount = MathEx.Floor(MathEx.Abs(angleVal*inv360));
 
 

+ 7 - 1
MBansheeEngine/Math/Matrix3.cs

@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-    [StructLayout(LayoutKind.Sequential)]
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
     public struct Matrix3
     public struct Matrix3
     {
     {
         private struct EulerAngleOrderData
         private struct EulerAngleOrderData
@@ -509,5 +509,11 @@ namespace BansheeEngine
         {
         {
             return quat.ToRotationMatrix();
             return quat.ToRotationMatrix();
         }
         }
+
+        public override string ToString()
+        {
+            return String.Format("({0}, {1}, {2},\n{3}, {4}, {5}\n{6}, {7}, {8})",
+                m00, m01, m02, m10, m11, m12, m20, m21, m22);
+        }
     }
     }
 }
 }

+ 7 - 1
MBansheeEngine/Math/Matrix4.cs

@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-    [StructLayout(LayoutKind.Sequential)]
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
     public struct Matrix4
     public struct Matrix4
     {
     {
         public static readonly Matrix4 zero = new Matrix4();
         public static readonly Matrix4 zero = new Matrix4();
@@ -490,5 +490,11 @@ namespace BansheeEngine
             copy.Transpose();
             copy.Transpose();
             return copy;
             return copy;
         }
         }
+
+        public override string ToString()
+        {
+            return String.Format("({0}, {1}, {2}, {3},\n{4}, {5}, {6}, {7}\n{8}, {9}, {10}, {11}\n{12}, {13}, {14}, {15})",
+                m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33);
+        }
     }
     }
 }
 }

+ 6 - 1
MBansheeEngine/Math/Quaternion.cs

@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-    [StructLayout(LayoutKind.Sequential)]
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
     public struct Quaternion
     public struct Quaternion
     {
     {
         private struct EulerAngleOrderData
         private struct EulerAngleOrderData
@@ -535,5 +535,10 @@ namespace BansheeEngine
 
 
             return false;
             return false;
         }
         }
+
+        public override string ToString()
+        {
+            return String.Format("({0}, {1}, {2}, {3})", x, y, z, w);
+        }
     }
     }
 }
 }

+ 8 - 1
MBansheeEngine/Math/Radian.cs

@@ -1,11 +1,13 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
+using System.Runtime.InteropServices;
 using System.Text;
 using System.Text;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-    public sealed class Radian
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
+    public struct Radian
     {
     {
 		readonly float value;
 		readonly float value;
 
 
@@ -140,5 +142,10 @@ namespace BansheeEngine
         {
         {
             return value.GetHashCode();
             return value.GetHashCode();
         }
         }
+
+        public override string ToString()
+        {
+            return value.ToString();
+        }
     }
     }
 }
 }

+ 8 - 3
MBansheeEngine/Math/Ray.cs

@@ -1,17 +1,17 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
+using System.Runtime.InteropServices;
 using System.Text;
 using System.Text;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-    public class Ray
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
+    public struct Ray
     {
     {
 		public Vector3 origin;
 		public Vector3 origin;
 		public Vector3 direction;
 		public Vector3 direction;
 
 
-        public Ray() {}
-
         public Ray(Vector3 origin, Vector3 direction)
         public Ray(Vector3 origin, Vector3 direction)
         {
         {
             this.origin = origin;
             this.origin = origin;
@@ -42,5 +42,10 @@ namespace BansheeEngine
 
 
             direction = Vector3.Normalize(end - origin);
             direction = Vector3.Normalize(end - origin);
         }
         }
+
+        public override string ToString()
+        {
+            return String.Format("(origin: {0} direction: {1})", origin, direction);
+        }
     };
     };
 }
 }

+ 7 - 2
MBansheeEngine/Math/Rect2.cs

@@ -6,8 +6,8 @@ using System.Text;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-    [StructLayout(LayoutKind.Sequential)]
-    public class Rect2
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
+    public struct Rect2
     {
     {
         public Rect2(float x, float y, float width, float height)
         public Rect2(float x, float y, float width, float height)
         {
         {
@@ -44,6 +44,11 @@ namespace BansheeEngine
             return base.GetHashCode();
             return base.GetHashCode();
         }
         }
 
 
+        public override string ToString()
+        {
+            return String.Format("(x:{0} y:{1} width:{2} height:{3})", x, y, width, height);
+        }
+
         public float x, y, width, height;
         public float x, y, width, height;
     }
     }
 }
 }

+ 7 - 2
MBansheeEngine/Math/Rect2I.cs

@@ -6,8 +6,8 @@ using System.Text;
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-    [StructLayout(LayoutKind.Sequential)]
-    public class Rect2I
+    [StructLayout(LayoutKind.Sequential), SerializeObject]
+    public struct Rect2I
     {
     {
         public Rect2I(int x, int y, int width, int height)
         public Rect2I(int x, int y, int width, int height)
         {
         {
@@ -55,6 +55,11 @@ namespace BansheeEngine
             return base.GetHashCode();
             return base.GetHashCode();
         }
         }
 
 
+        public override string ToString()
+        {
+            return String.Format("(x:{0} y:{1} width:{2} height:{3})", x, y, width, height);
+        }
+
         public int x, y, width, height;
         public int x, y, width, height;
     }
     }
 }
 }

+ 16 - 14
MBansheeEngine/SceneObject.cs

@@ -5,13 +5,13 @@ namespace BansheeEngine
 {
 {
     public sealed class SceneObject : GameObject
     public sealed class SceneObject : GameObject
     {
     {
-        public SceneObject Parent
+        public SceneObject parent
         {
         {
             set { Internal_SetParent(mCachedPtr, value); }
             set { Internal_SetParent(mCachedPtr, value); }
             get { return Internal_GetParent(mCachedPtr); }
             get { return Internal_GetParent(mCachedPtr); }
         }
         }
 
 
-        public Vector3 Position
+        public Vector3 position
         {
         {
             get
             get
             {
             {
@@ -26,7 +26,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 LocalPosition
+        public Vector3 localPosition
         {
         {
             get
             get
             {
             {
@@ -41,7 +41,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Quaternion Rotation
+        public Quaternion rotation
         {
         {
             get
             get
             {
             {
@@ -56,7 +56,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Quaternion LocalRotation
+        public Quaternion localRotation
         {
         {
             get
             get
             {
             {
@@ -71,7 +71,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 Scale
+        public Vector3 scale
         {
         {
             get
             get
             {
             {
@@ -81,7 +81,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 LocalScale
+        public Vector3 localScale
         {
         {
             get
             get
             {
             {
@@ -96,7 +96,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Matrix4 WorldTransform
+        public Matrix4 worldTransform
         {
         {
             get
             get
             {
             {
@@ -106,7 +106,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Matrix4 LocalTransform
+        public Matrix4 localTransform
         {
         {
             get
             get
             {
             {
@@ -116,7 +116,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 Forward
+        public Vector3 forward
         {
         {
             get
             get
             {
             {
@@ -130,7 +130,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 Right
+        public Vector3 right
         {
         {
             get
             get
             {
             {
@@ -140,7 +140,7 @@ namespace BansheeEngine
             }
             }
         }
         }
 
 
-        public Vector3 Up
+        public Vector3 up
         {
         {
             get
             get
             {
             {
@@ -183,7 +183,9 @@ namespace BansheeEngine
 
 
         public int GetNumChildren()
         public int GetNumChildren()
         {
         {
-            return Internal_GetNumChildren(mCachedPtr);
+            int value;
+            Internal_GetNumChildren(mCachedPtr, out value);
+            return value;
         }
         }
 
 
         public SceneObject GetChild(int idx)
         public SceneObject GetChild(int idx)
@@ -246,7 +248,7 @@ namespace BansheeEngine
         private static extern SceneObject Internal_GetParent(IntPtr nativeInstance);
         private static extern SceneObject Internal_GetParent(IntPtr nativeInstance);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern int Internal_GetNumChildren(IntPtr nativeInstance);
+        private static extern void Internal_GetNumChildren(IntPtr nativeInstance, out int value);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern SceneObject Internal_GetChild(IntPtr nativeInstance, int idx);
         private static extern SceneObject Internal_GetChild(IntPtr nativeInstance, int idx);

+ 5 - 2
SBansheeEditor/Include/BsScriptEditorWindow.h

@@ -32,8 +32,8 @@ namespace BansheeEngine
 		static MonoObject* internal_createOrGetInstance(MonoString* ns, MonoString* typeName);
 		static MonoObject* internal_createOrGetInstance(MonoString* ns, MonoString* typeName);
 
 
 		static bool internal_hasFocus(ScriptEditorWindow* thisPtr);
 		static bool internal_hasFocus(ScriptEditorWindow* thisPtr);
-		static Vector2I internal_screenToWindowPos(ScriptEditorWindow* thisPtr, const Vector2I& screenPos);
-		static Vector2I internal_windowToScreenPos(ScriptEditorWindow* thisPtr, const Vector2I& windowPos);
+		static void internal_screenToWindowPos(ScriptEditorWindow* thisPtr, Vector2I screenPos, Vector2I* windowPos);
+		static void internal_windowToScreenPos(ScriptEditorWindow* thisPtr, Vector2I windowPos, Vector2I* screenPos);
 		static UINT32 internal_getWidth(ScriptEditorWindow* thisPtr);
 		static UINT32 internal_getWidth(ScriptEditorWindow* thisPtr);
 		static UINT32 internal_getHeight(ScriptEditorWindow* thisPtr);
 		static UINT32 internal_getHeight(ScriptEditorWindow* thisPtr);
 
 
@@ -42,6 +42,7 @@ namespace BansheeEngine
 		void onWidgetMoved(INT32 x, INT32 y);
 		void onWidgetMoved(INT32 x, INT32 y);
 		void onWidgetResized(UINT32 width, UINT32 height);
 		void onWidgetResized(UINT32 width, UINT32 height);
 		void onWidgetParentChanged(EditorWidgetContainer* newParent);
 		void onWidgetParentChanged(EditorWidgetContainer* newParent);
+		void onFocusChanged(bool inFocus);
 
 
 		void _onManagedInstanceDeleted();
 		void _onManagedInstanceDeleted();
 
 
@@ -51,8 +52,10 @@ namespace BansheeEngine
 		HEvent mOnWidgetMovedConn;
 		HEvent mOnWidgetMovedConn;
 		HEvent mOnWidgetResizedConn;
 		HEvent mOnWidgetResizedConn;
 		HEvent mOnParentChangedConn;
 		HEvent mOnParentChangedConn;
+		HEvent mOnFocusChangedConn;
 
 
 		static MonoMethod* onResizedMethod;
 		static MonoMethod* onResizedMethod;
+		static MonoMethod* onFocusChangedMethod;
 
 
 		// Global editor window management methods
 		// Global editor window management methods
 		static void registerScriptEditorWindow(ScriptEditorWindow* editorWindow);
 		static void registerScriptEditorWindow(ScriptEditorWindow* editorWindow);

+ 5 - 3
SBansheeEditor/Include/BsScriptSceneViewHandler.h

@@ -13,10 +13,12 @@ namespace BansheeEngine
 	private:
 	private:
 		static void internal_Create(MonoObject* managedInstance, ScriptEditorWindow* parentWindow, ScriptCameraHandler* camera);
 		static void internal_Create(MonoObject* managedInstance, ScriptEditorWindow* parentWindow, ScriptCameraHandler* camera);
 		static void internal_Update(ScriptSceneViewHandler* thisPtr, Vector2I inputPos, Vector2I inputDelta);
 		static void internal_Update(ScriptSceneViewHandler* thisPtr, Vector2I inputPos, Vector2I inputDelta);
-		static void internal_PointerPressed(ScriptSceneViewHandler* thisPtr, Vector2I inputPos);
-		static void internal_PointerReleased(ScriptSceneViewHandler* thisPtr, Vector2I inputPos, bool controlPressed);
+		static void internal_TrySelectHandle(ScriptSceneViewHandler* thisPtr, Vector2I inputPos);
+		static bool internal_IsHandleActive(ScriptSceneViewHandler* thisPtr, Vector2I inputPos);
+		static void internal_ClearHandleSelection(ScriptSceneViewHandler* thisPtr, Vector2I inputPos);
+		static void internal_PickObject(ScriptSceneViewHandler* thisPtr, Vector2I inputPos, bool additive);
 
 
-		ScriptSceneViewHandler(MonoObject* object, const EditorWidgetBase* parentWidget, const SPtr<CameraHandler>& camera);
+		ScriptSceneViewHandler(MonoObject* object, EditorWidgetBase* parentWidget, const SPtr<CameraHandler>& camera);
 		~ScriptSceneViewHandler();
 		~ScriptSceneViewHandler();
 
 
 		SceneViewHandler* mHandler;
 		SceneViewHandler* mHandler;

+ 14 - 4
SBansheeEditor/Source/BsScriptEditorWindow.cpp

@@ -17,6 +17,7 @@ namespace BansheeEngine
 {
 {
 	UnorderedMap<String, ScriptEditorWindow::EditorWindowHandle> ScriptEditorWindow::OpenScriptEditorWindows;
 	UnorderedMap<String, ScriptEditorWindow::EditorWindowHandle> ScriptEditorWindow::OpenScriptEditorWindows;
 	MonoMethod* ScriptEditorWindow::onResizedMethod = nullptr;
 	MonoMethod* ScriptEditorWindow::onResizedMethod = nullptr;
+	MonoMethod* ScriptEditorWindow::onFocusChangedMethod = nullptr;
 
 
 	ScriptEditorWindow::ScriptEditorWindow(MonoObject* instance, const String& windowName, const String& displayName, EditorWidgetBase* editorWidget)
 	ScriptEditorWindow::ScriptEditorWindow(MonoObject* instance, const String& windowName, const String& displayName, EditorWidgetBase* editorWidget)
 		:ScriptObject(instance), mName(windowName), mEditorWidget(editorWidget)
 		:ScriptObject(instance), mName(windowName), mEditorWidget(editorWidget)
@@ -24,6 +25,7 @@ namespace BansheeEngine
 		mOnWidgetMovedConn = editorWidget->onMoved.connect(std::bind(&ScriptEditorWindow::onWidgetMoved, this, _1, _2));
 		mOnWidgetMovedConn = editorWidget->onMoved.connect(std::bind(&ScriptEditorWindow::onWidgetMoved, this, _1, _2));
 		mOnWidgetResizedConn = editorWidget->onResized.connect(std::bind(&ScriptEditorWindow::onWidgetResized, this, _1, _2));
 		mOnWidgetResizedConn = editorWidget->onResized.connect(std::bind(&ScriptEditorWindow::onWidgetResized, this, _1, _2));
 		mOnParentChangedConn = editorWidget->onParentChanged.connect(std::bind(&ScriptEditorWindow::onWidgetParentChanged, this, _1));
 		mOnParentChangedConn = editorWidget->onParentChanged.connect(std::bind(&ScriptEditorWindow::onWidgetParentChanged, this, _1));
+		mOnFocusChangedConn = editorWidget->onFocusChanged.connect(std::bind(&ScriptEditorWindow::onFocusChanged, this, _1));
 	}
 	}
 
 
 	ScriptEditorWindow::~ScriptEditorWindow()
 	ScriptEditorWindow::~ScriptEditorWindow()
@@ -32,6 +34,7 @@ namespace BansheeEngine
 		mOnWidgetMovedConn.disconnect();
 		mOnWidgetMovedConn.disconnect();
 		mOnWidgetResizedConn.disconnect();
 		mOnWidgetResizedConn.disconnect();
 		mOnParentChangedConn.disconnect();
 		mOnParentChangedConn.disconnect();
+		mOnFocusChangedConn.disconnect();
 	}
 	}
 
 
 	void ScriptEditorWindow::initRuntimeData()
 	void ScriptEditorWindow::initRuntimeData()
@@ -45,6 +48,7 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_WindowToScreenPos", &ScriptEditorWindow::internal_windowToScreenPos);
 		metaData.scriptClass->addInternalCall("Internal_WindowToScreenPos", &ScriptEditorWindow::internal_windowToScreenPos);
 
 
 		onResizedMethod = metaData.scriptClass->getMethod("WindowResized", 2);
 		onResizedMethod = metaData.scriptClass->getMethod("WindowResized", 2);
+		onFocusChangedMethod = metaData.scriptClass->getMethod("FocusChanged", 1);
 	}
 	}
 
 
 	MonoObject* ScriptEditorWindow::internal_createOrGetInstance(MonoString* ns, MonoString* typeName)
 	MonoObject* ScriptEditorWindow::internal_createOrGetInstance(MonoString* ns, MonoString* typeName)
@@ -78,14 +82,14 @@ namespace BansheeEngine
 		return thisPtr->getEditorWidget()->hasFocus();
 		return thisPtr->getEditorWidget()->hasFocus();
 	}
 	}
 
 
-	Vector2I ScriptEditorWindow::internal_screenToWindowPos(ScriptEditorWindow* thisPtr, const Vector2I& screenPos)
+	void ScriptEditorWindow::internal_screenToWindowPos(ScriptEditorWindow* thisPtr, Vector2I screenPos, Vector2I* windowPos)
 	{
 	{
-		return thisPtr->getEditorWidget()->screenToWidgetPos(screenPos);
+		*windowPos = thisPtr->getEditorWidget()->screenToWidgetPos(screenPos);
 	}
 	}
 
 
-	Vector2I ScriptEditorWindow::internal_windowToScreenPos(ScriptEditorWindow* thisPtr, const Vector2I& windowPos)
+	void ScriptEditorWindow::internal_windowToScreenPos(ScriptEditorWindow* thisPtr, Vector2I windowPos, Vector2I* screenPos)
 	{
 	{
-		return thisPtr->getEditorWidget()->widgetToScreenPos(windowPos);
+		*screenPos = thisPtr->getEditorWidget()->widgetToScreenPos(windowPos);
 	}
 	}
 
 
 	UINT32 ScriptEditorWindow::internal_getWidth(ScriptEditorWindow* thisPtr)
 	UINT32 ScriptEditorWindow::internal_getWidth(ScriptEditorWindow* thisPtr)
@@ -141,6 +145,12 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
+	void ScriptEditorWindow::onFocusChanged(bool inFocus)
+	{
+		void* params[1] = { &inFocus};
+		onFocusChangedMethod->invokeVirtual(mManagedInstance, params);
+	}
+
 	void ScriptEditorWindow::registerManagedEditorWindows()
 	void ScriptEditorWindow::registerManagedEditorWindows()
 	{
 	{
 		MonoAssembly* assembly = MonoManager::instance().getAssembly(BansheeEditorAssemblyName);
 		MonoAssembly* assembly = MonoManager::instance().getAssembly(BansheeEditorAssemblyName);

+ 19 - 7
SBansheeEditor/Source/BsScriptSceneViewHandler.cpp

@@ -10,7 +10,7 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	ScriptSceneViewHandler::ScriptSceneViewHandler(MonoObject* object, const EditorWidgetBase* parentWidget, const SPtr<CameraHandler>& camera)
+	ScriptSceneViewHandler::ScriptSceneViewHandler(MonoObject* object, EditorWidgetBase* parentWidget, const SPtr<CameraHandler>& camera)
 		:ScriptObject(object), mHandler(nullptr)
 		:ScriptObject(object), mHandler(nullptr)
 	{ 
 	{ 
 		mHandler = bs_new<SceneViewHandler>(parentWidget, camera);
 		mHandler = bs_new<SceneViewHandler>(parentWidget, camera);
@@ -25,8 +25,10 @@ namespace BansheeEngine
 	{
 	{
 		metaData.scriptClass->addInternalCall("Internal_Create", &ScriptSceneViewHandler::internal_Create);
 		metaData.scriptClass->addInternalCall("Internal_Create", &ScriptSceneViewHandler::internal_Create);
 		metaData.scriptClass->addInternalCall("Internal_Update", &ScriptSceneViewHandler::internal_Update);
 		metaData.scriptClass->addInternalCall("Internal_Update", &ScriptSceneViewHandler::internal_Update);
-		metaData.scriptClass->addInternalCall("Internal_PointerPressed", &ScriptSceneViewHandler::internal_PointerPressed);
-		metaData.scriptClass->addInternalCall("Internal_PointerReleased", &ScriptSceneViewHandler::internal_PointerReleased);
+		metaData.scriptClass->addInternalCall("Internal_TrySelectHandle", &ScriptSceneViewHandler::internal_TrySelectHandle);
+		metaData.scriptClass->addInternalCall("Internal_IsHandleActive", &ScriptSceneViewHandler::internal_IsHandleActive);
+		metaData.scriptClass->addInternalCall("Internal_ClearHandleSelection", &ScriptSceneViewHandler::internal_ClearHandleSelection);
+		metaData.scriptClass->addInternalCall("Internal_PickObject", &ScriptSceneViewHandler::internal_PickObject);
 	}
 	}
 
 
 	void ScriptSceneViewHandler::internal_Create(MonoObject* managedInstance, ScriptEditorWindow* parentWindow, ScriptCameraHandler* camera)
 	void ScriptSceneViewHandler::internal_Create(MonoObject* managedInstance, ScriptEditorWindow* parentWindow, ScriptCameraHandler* camera)
@@ -41,13 +43,23 @@ namespace BansheeEngine
 		thisPtr->mHandler->update(inputPos, inputDelta);
 		thisPtr->mHandler->update(inputPos, inputDelta);
 	}
 	}
 
 
-	void ScriptSceneViewHandler::internal_PointerPressed(ScriptSceneViewHandler* thisPtr, Vector2I inputPos)
+	void ScriptSceneViewHandler::internal_TrySelectHandle(ScriptSceneViewHandler* thisPtr, Vector2I inputPos)
 	{
 	{
-		thisPtr->mHandler->pointerPressed(inputPos);
+		thisPtr->mHandler->trySelectHandle(inputPos);
 	}
 	}
 
 
-	void ScriptSceneViewHandler::internal_PointerReleased(ScriptSceneViewHandler* thisPtr, Vector2I inputPos, bool controlPressed)
+	bool ScriptSceneViewHandler::internal_IsHandleActive(ScriptSceneViewHandler* thisPtr, Vector2I inputPos)
 	{
 	{
-		thisPtr->mHandler->pointerReleased(inputPos, controlPressed);
+		return thisPtr->mHandler->isHandleActive();
+	}
+
+	void ScriptSceneViewHandler::internal_ClearHandleSelection(ScriptSceneViewHandler* thisPtr, Vector2I inputPos)
+	{
+		thisPtr->mHandler->clearHandleSelection();
+	}
+
+	void ScriptSceneViewHandler::internal_PickObject(ScriptSceneViewHandler* thisPtr, Vector2I inputPos, bool additive)
+	{
+		thisPtr->mHandler->pickObject(inputPos, additive);
 	}
 	}
 }
 }

+ 1 - 1
SBansheeEngine/Include/BsScriptSceneObject.h

@@ -25,7 +25,7 @@ namespace BansheeEngine
 		static void internal_setParent(ScriptSceneObject* nativeInstance, MonoObject* parent);
 		static void internal_setParent(ScriptSceneObject* nativeInstance, MonoObject* parent);
 		static MonoObject* internal_getParent(ScriptSceneObject* nativeInstance);
 		static MonoObject* internal_getParent(ScriptSceneObject* nativeInstance);
 
 
-		static UINT32 internal_getNumChildren(ScriptSceneObject* nativeInstance);
+		static void internal_getNumChildren(ScriptSceneObject* nativeInstance, UINT32* value);
 		static MonoObject* internal_getChild(ScriptSceneObject* nativeInstance, UINT32 idx);
 		static MonoObject* internal_getChild(ScriptSceneObject* nativeInstance, UINT32 idx);
 
 
 		static void internal_getPosition(ScriptSceneObject* nativeInstance, Vector3* value);
 		static void internal_getPosition(ScriptSceneObject* nativeInstance, Vector3* value);

+ 47 - 47
SBansheeEngine/Source/BsScriptCameraHandler.cpp

@@ -34,73 +34,73 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_Create", &ScriptCameraHandler::internal_Create);
 		metaData.scriptClass->addInternalCall("Internal_Create", &ScriptCameraHandler::internal_Create);
 
 
 		metaData.scriptClass->addInternalCall("Internal_GetAspect", &ScriptCameraHandler::internal_GetAspect);
 		metaData.scriptClass->addInternalCall("Internal_GetAspect", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetAspect", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_GetNearClip", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetNearClip", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_SetAspect", &ScriptCameraHandler::internal_SetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetNearClip", &ScriptCameraHandler::internal_GetNearClip);
+		metaData.scriptClass->addInternalCall("Internal_SetNearClip", &ScriptCameraHandler::internal_SetNearClip);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetFarClip", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetFarClip", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetFarClip", &ScriptCameraHandler::internal_GetFarClip);
+		metaData.scriptClass->addInternalCall("Internal_SetFarClip", &ScriptCameraHandler::internal_SetFarClip);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetFieldOfView", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetFieldOfView", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetFieldOfView", &ScriptCameraHandler::internal_GetFieldOfView);
+		metaData.scriptClass->addInternalCall("Internal_SetFieldOfView", &ScriptCameraHandler::internal_SetFieldOfView);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetViewportRect", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetViewportRect", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetViewportRect", &ScriptCameraHandler::internal_GetViewportRect);
+		metaData.scriptClass->addInternalCall("Internal_SetViewportRect", &ScriptCameraHandler::internal_SetViewportRect);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetProjectionType", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetProjectionType", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetProjectionType", &ScriptCameraHandler::internal_GetProjectionType);
+		metaData.scriptClass->addInternalCall("Internal_SetProjectionType", &ScriptCameraHandler::internal_SetProjectionType);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetOrthographicHeight", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetOrthographicHeight", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetOrthographicHeight", &ScriptCameraHandler::internal_GetOrthographicHeight);
+		metaData.scriptClass->addInternalCall("Internal_SetOrthographicHeight", &ScriptCameraHandler::internal_SetOrthographicHeight);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetOrthographicWidth", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetOrthographicWidth", &ScriptCameraHandler::internal_GetOrthographicWidth);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetClearColor", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetClearColor", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetClearColor", &ScriptCameraHandler::internal_GetClearColor);
+		metaData.scriptClass->addInternalCall("Internal_SetClearColor", &ScriptCameraHandler::internal_SetClearColor);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetDepthClearValue", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetDepthClearValue", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetDepthClearValue", &ScriptCameraHandler::internal_GetDepthClearValue);
+		metaData.scriptClass->addInternalCall("Internal_SetDepthClearValue", &ScriptCameraHandler::internal_SetDepthClearValue);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetStencilClearValue", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetStencilClearValue", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetStencilClearValue", &ScriptCameraHandler::internal_GetStencilClearValue);
+		metaData.scriptClass->addInternalCall("Internal_SetStencilClearValue", &ScriptCameraHandler::internal_SetStencilClearValue);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetClearFlags", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetClearFlags", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetClearFlags", &ScriptCameraHandler::internal_GetClearFlags);
+		metaData.scriptClass->addInternalCall("Internal_SetClearFlags", &ScriptCameraHandler::internal_SetClearFlags);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetPriority", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetPriority", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetPriority", &ScriptCameraHandler::internal_GetPriority);
+		metaData.scriptClass->addInternalCall("Internal_SetPriority", &ScriptCameraHandler::internal_SetPriority);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetLayers", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_SetLayers", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetLayers", &ScriptCameraHandler::internal_GetLayers);
+		metaData.scriptClass->addInternalCall("Internal_SetLayers", &ScriptCameraHandler::internal_SetLayers);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetProjMatrix", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_GetProjMatrixInv", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetProjMatrix", &ScriptCameraHandler::internal_GetProjMatrix);
+		metaData.scriptClass->addInternalCall("Internal_GetProjMatrixInv", &ScriptCameraHandler::internal_GetProjMatrixInv);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetViewMatrix", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_GetViewMatrixInv", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetViewMatrix", &ScriptCameraHandler::internal_GetViewMatrix);
+		metaData.scriptClass->addInternalCall("Internal_GetViewMatrixInv", &ScriptCameraHandler::internal_GetViewMatrixInv);
 
 
-		metaData.scriptClass->addInternalCall("Internal_GetWidthPixels", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_GetHeightPixels", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_GetWidthPixels", &ScriptCameraHandler::internal_GetWidthPixels);
+		metaData.scriptClass->addInternalCall("Internal_GetHeightPixels", &ScriptCameraHandler::internal_GetHeightPixels);
 
 
-		metaData.scriptClass->addInternalCall("Internal_WorldToScreen", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_WorldToClip", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_WorldToView", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_WorldToScreen", &ScriptCameraHandler::internal_WorldToScreen);
+		metaData.scriptClass->addInternalCall("Internal_WorldToClip", &ScriptCameraHandler::internal_WorldToClip);
+		metaData.scriptClass->addInternalCall("Internal_WorldToView", &ScriptCameraHandler::internal_WorldToView);
 
 
-		metaData.scriptClass->addInternalCall("Internal_ScreenToWorld", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_ScreenToView", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_ScreenToClip", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_ScreenToWorld", &ScriptCameraHandler::internal_ScreenToWorld);
+		metaData.scriptClass->addInternalCall("Internal_ScreenToView", &ScriptCameraHandler::internal_ScreenToView);
+		metaData.scriptClass->addInternalCall("Internal_ScreenToClip", &ScriptCameraHandler::internal_ScreenToClip);
 
 
-		metaData.scriptClass->addInternalCall("Internal_ViewToWorld", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_ViewToScreen", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_ViewToClip", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_ViewToWorld", &ScriptCameraHandler::internal_ViewToWorld);
+		metaData.scriptClass->addInternalCall("Internal_ViewToScreen", &ScriptCameraHandler::internal_ViewToScreen);
+		metaData.scriptClass->addInternalCall("Internal_ViewToClip", &ScriptCameraHandler::internal_ViewToClip);
 
 
-		metaData.scriptClass->addInternalCall("Internal_ClipToWorld", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_ClipToView", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_ClipToScreen", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_ClipToWorld", &ScriptCameraHandler::internal_ClipToWorld);
+		metaData.scriptClass->addInternalCall("Internal_ClipToView", &ScriptCameraHandler::internal_ClipToView);
+		metaData.scriptClass->addInternalCall("Internal_ClipToScreen", &ScriptCameraHandler::internal_ClipToScreen);
 
 
-		metaData.scriptClass->addInternalCall("Internal_ScreenToWorldRay", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_ProjectPoint", &ScriptCameraHandler::internal_GetAspect);
-		metaData.scriptClass->addInternalCall("Internal_UnprojectPoint", &ScriptCameraHandler::internal_GetAspect);
+		metaData.scriptClass->addInternalCall("Internal_ScreenToWorldRay", &ScriptCameraHandler::internal_ScreenToWorldRay);
+		metaData.scriptClass->addInternalCall("Internal_ProjectPoint", &ScriptCameraHandler::internal_ProjectPoint);
+		metaData.scriptClass->addInternalCall("Internal_UnprojectPoint", &ScriptCameraHandler::internal_UnprojectPoint);
 
 
 		metaData.scriptClass->addInternalCall("Internal_SetRenderTarget", &ScriptCameraHandler::internal_SetRenderTarget);
 		metaData.scriptClass->addInternalCall("Internal_SetRenderTarget", &ScriptCameraHandler::internal_SetRenderTarget);
 
 

+ 3 - 2
SBansheeEngine/Source/BsScriptInputConfiguration.cpp

@@ -40,9 +40,10 @@ namespace BansheeEngine
 
 
 	ScriptInputConfiguration* ScriptInputConfiguration::createScriptInputConfig(const InputConfigurationPtr& inputConfig)
 	ScriptInputConfiguration* ScriptInputConfiguration::createScriptInputConfig(const InputConfigurationPtr& inputConfig)
 	{
 	{
-		MonoObject* instance = metaData.scriptClass->createInstance();
+		MonoObject* instance = metaData.scriptClass->createInstance(false);
 
 
-		return ScriptInputConfiguration::toNative(instance);
+		ScriptInputConfiguration* nativeInstance = new (bs_alloc<ScriptInputConfiguration>()) ScriptInputConfiguration(instance, inputConfig);
+		return nativeInstance;
 	}
 	}
 
 
 	void ScriptInputConfiguration::internal_CreateInstance(MonoObject* object)
 	void ScriptInputConfiguration::internal_CreateInstance(MonoObject* object)

+ 5 - 4
SBansheeEngine/Source/BsScriptSceneObject.cpp

@@ -84,12 +84,12 @@ namespace BansheeEngine
 		return parentScriptSO->getManagedInstance();
 		return parentScriptSO->getManagedInstance();
 	}
 	}
 
 
-	UINT32 ScriptSceneObject::internal_getNumChildren(ScriptSceneObject* nativeInstance)
+	void ScriptSceneObject::internal_getNumChildren(ScriptSceneObject* nativeInstance, UINT32* value)
 	{
 	{
 		if (!checkIfDestroyed(nativeInstance))
 		if (!checkIfDestroyed(nativeInstance))
-			return nativeInstance->mSceneObject->getNumChildren();
+			*value = nativeInstance->mSceneObject->getNumChildren();
 		else
 		else
-			return 0;
+			*value = 0;
 	}
 	}
 
 
 	MonoObject* ScriptSceneObject::internal_getChild(ScriptSceneObject* nativeInstance, UINT32 idx)
 	MonoObject* ScriptSceneObject::internal_getChild(ScriptSceneObject* nativeInstance, UINT32 idx)
@@ -209,7 +209,8 @@ namespace BansheeEngine
 
 
 	void ScriptSceneObject::internal_lookAt(ScriptSceneObject* nativeInstance, Vector3 direction, Vector3 up)
 	void ScriptSceneObject::internal_lookAt(ScriptSceneObject* nativeInstance, Vector3 direction, Vector3 up)
 	{
 	{
-
+		if (!checkIfDestroyed(nativeInstance))
+			nativeInstance->mSceneObject->lookAt(direction, up);
 	}
 	}
 
 
 	void ScriptSceneObject::internal_move(ScriptSceneObject* nativeInstance, Vector3 value)
 	void ScriptSceneObject::internal_move(ScriptSceneObject* nativeInstance, Vector3 value)

+ 12 - 0
TODO.txt

@@ -12,8 +12,20 @@
 
 
 See GDrive/Resources doc for resources refactor
 See GDrive/Resources doc for resources refactor
 
 
+Fix the weird Mono crash that seems to happen in SceneCamera but gets fixed by commenting out various bits of code. However it can be consistently reproduced.
+Scene view initial viewport size isn't valid size
+Screen grid isn't rendered
+Handles aren't properly rendered
+Icon gizmo seems to sometimes get struck to the side of the camera
+Clicking the screen causes a white flash
+
+Other:
+Window resize end callback
+
 Add cutoff plane when rendering discs for rotation handle.
 Add cutoff plane when rendering discs for rotation handle.
 
 
+What happens when I close widgets from C++ code (e.g. due to layout reload or change)? Will C# still try to access them?
+
 C# SceneView:
 C# SceneView:
 Test new Scene window and fix every issue
 Test new Scene window and fix every issue
 Add ProjectWindow and HierarchyWindow to C#
 Add ProjectWindow and HierarchyWindow to C#