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

Fixed a crash due to the GUI input box tracking an out of range selection
Prevent SceneObject transform GUI from updating when it has input focus

BearishSun пре 9 година
родитељ
комит
1b2c049393

+ 3 - 3
Build/VS2015/BansheeCore.vcxproj.filters

@@ -752,9 +752,6 @@
     <ClInclude Include="..\..\Source\BansheeCore\Include\BsPhysicsCommon.h">
       <Filter>Header Files\Physics</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\BansheeCore\Include\BsPhysicsMeshRTTI.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\BansheeCore\Include\BsShaderDefines.h">
       <Filter>Header Files\Material</Filter>
     </ClInclude>
@@ -764,6 +761,9 @@
     <ClInclude Include="..\..\Source\BansheeCore\Include\BsShaderImportOptionsRTTI.h">
       <Filter>Header Files\RTTI</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\Source\BansheeCore\Include\BsPhysicsMeshRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\Source\BansheeCore\Source\BsCoreApplication.cpp">

+ 400 - 388
Build/VS2015/SBansheeEditor.vcxproj.filters

@@ -1,389 +1,401 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
-      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorPrerequisites.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorWindow.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIIntField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIFloatField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUITextField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIToggleField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIColorField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIVector2Field.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIVector3Field.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIVector4Field.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsGUIGameObjectField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIGameObjectField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsGUIResourceField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIResourceField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptProjectLibrary.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsEditorScriptManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGizmos.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGizmoManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptSelection.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleDrawing.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleSlider.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleSliderLine.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleSliderPlane.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleSliderDisc.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorUtility.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleSliderManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorSettings.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptModalWindow.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptBrowseDialog.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptDragDropManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptImportOptions.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptCodeEditor.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorApplication.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptPlatformInfo.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptBuildManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsMenuItemManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorBuiltin.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptDropDownWindow.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptOSDropTarget.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptFolderMonitor.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUISceneTreeView.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorTestSuite.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptUnitTests.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptPrefabUtility.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsGUITextureField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUITextureField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptUndoRedo.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsEditorResourceLoader.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptProjectSettings.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsEditorScriptLibrary.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptInspectorUtility.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIListBoxField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIEnumField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUISliderField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsToolbarItemManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorInput.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorVirtualInput.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptSceneGrid.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptSceneSelection.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptSceneGizmos.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptSceneHandles.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorPlugin.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorWindow.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIIntField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIFloatField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUITextField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIToggleField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIColorField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIVector2Field.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIVector3Field.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIVector4Field.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsGUIGameObjectField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIGameObjectField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsGUIResourceField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIResourceField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptProjectLibrary.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsEditorScriptManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGizmos.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGizmoManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptSelection.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleDrawing.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleSlider.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleSliderLine.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleSliderPlane.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleSliderDisc.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorUtility.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleSliderManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorSettings.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptModalWindow.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptBrowseDialog.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptDragDropManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptImportOptions.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptCodeEditor.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorApplication.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptPlatformInfo.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptBuildManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsMenuItemManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorBuiltin.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptDropDownWindow.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptOSDropTarget.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptFolderMonitor.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUISceneTreeView.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorTestSuite.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptUnitTests.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptPrefabUtility.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsGUITextureField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUITextureField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptUndoRedo.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsEditorResourceLoader.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptProjectSettings.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsEditorScriptLibrary.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptInspectorUtility.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIListBoxField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIEnumField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUISliderField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsToolbarItemManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorInput.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorVirtualInput.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptSceneGrid.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptSceneSelection.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptSceneGizmos.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptSceneHandles.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-  </ItemGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Header Files\Wrappers">
+      <UniqueIdentifier>{eb60c74c-163f-4706-b256-c8031cb5ff8b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Wrappers\GUI">
+      <UniqueIdentifier>{296f0e79-ff4e-4f90-8f71-afd7e26e87e1}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Wrappers">
+      <UniqueIdentifier>{e0255fa4-4a90-4abe-bff0-2b4694c44adf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Wrappers\GUI">
+      <UniqueIdentifier>{71b44666-325b-4251-a2b2-c7fdf57e6059}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorPrerequisites.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsGUIGameObjectField.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsGUIResourceField.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsEditorScriptManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptDragDropManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsMenuItemManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsGUITextureField.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsEditorResourceLoader.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsEditorScriptLibrary.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsToolbarItemManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptCodeEditor.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptBrowseDialog.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptBuildManager.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptDropDownWindow.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorApplication.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorBuiltin.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorInput.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorSettings.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorTestSuite.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorUtility.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorVirtualInput.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptEditorWindow.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptFolderMonitor.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGizmos.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIColorField.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIEnumField.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIFloatField.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIGameObjectField.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIIntField.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIListBoxField.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIResourceField.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUISceneTreeView.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUISliderField.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUITextField.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUITextureField.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIToggleField.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIVector2Field.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIVector3Field.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGUIVector4Field.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptUnitTests.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptUndoRedo.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptSelection.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptSceneSelection.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptSceneHandles.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptSceneGrid.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptSceneGizmos.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptProjectSettings.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptProjectLibrary.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptPrefabUtility.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptPlatformInfo.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptOSDropTarget.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptModalWindow.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptInspectorUtility.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptImportOptions.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleSliderPlane.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleSliderManager.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleSliderLine.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleSliderDisc.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleSlider.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptHandleDrawing.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEditor\Include\BsScriptGizmoManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorPlugin.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsGUIGameObjectField.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsGUIResourceField.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsEditorScriptManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGizmoManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsMenuItemManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsGUITextureField.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsEditorResourceLoader.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsEditorScriptLibrary.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsToolbarItemManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIColorField.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIEnumField.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIFloatField.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIGameObjectField.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIIntField.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIListBoxField.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIResourceField.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUISceneTreeView.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUISliderField.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUITextField.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUITextureField.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIToggleField.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIVector2Field.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIVector3Field.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGUIVector4Field.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptBrowseDialog.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptBuildManager.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptCodeEditor.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptDragDropManager.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptDropDownWindow.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorApplication.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorBuiltin.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorInput.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorSettings.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorTestSuite.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorUtility.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorVirtualInput.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptEditorWindow.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptFolderMonitor.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptGizmos.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleDrawing.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleSlider.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleSliderDisc.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleSliderLine.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleSliderManager.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptHandleSliderPlane.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptImportOptions.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptInspectorUtility.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptModalWindow.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptOSDropTarget.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptPlatformInfo.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptPrefabUtility.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptProjectLibrary.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptProjectSettings.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptSceneGizmos.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptSceneGrid.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptSceneHandles.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptSceneSelection.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptSelection.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptUndoRedo.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEditor\Source\BsScriptUnitTests.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+  </ItemGroup>
 </Project>

+ 814 - 808
Build/VS2015/SBansheeEngine.vcxproj.filters

@@ -1,809 +1,815 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="Source Files">
-      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
-      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
-    </Filter>
-    <Filter Include="Header Files">
-      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
-      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
-    </Filter>
-    <Filter Include="Header Files\GUI">
-      <UniqueIdentifier>{90896fa0-9186-412e-bad6-b57e3ae7c060}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\GUI">
-      <UniqueIdentifier>{a412791a-7e2f-4aea-a34f-6c2ad7f1246c}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Serialization">
-      <UniqueIdentifier>{97b82061-c2d8-49e4-8840-80ff956f2cc0}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Serialization">
-      <UniqueIdentifier>{10d91e2d-e560-4081-ac15-bc6753ca2a7e}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Serialization\RTTI">
-      <UniqueIdentifier>{3225801f-fe74-4e07-aa59-37ad5d5ac1da}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\RTTI">
-      <UniqueIdentifier>{cff4d9c9-b006-4675-a58e-6a0e449ff8d5}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Physics">
-      <UniqueIdentifier>{8355a19c-b7b7-49a0-a8dd-baec11b88e28}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Physics">
-      <UniqueIdentifier>{9eb1c24d-26f9-4036-bf91-978b7a78966e}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptFont.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptObject.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSpriteTexture.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptTexture2D.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptEnginePrerequisites.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptStringTable.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptHString.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedComponent.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptComponent.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptResource.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGameObject.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptResourceManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGameObjectManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSceneObject.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIButton.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIContent.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIElementStateStyle.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIElementStyle.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIFixedSpace.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIFlexibleSpace.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIInputBox.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUILabel.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUILayout.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIListBox.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIScrollArea.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUITexture.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIToggle.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIToggleGroup.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableArrayRTTI.h">
-      <Filter>Header Files\Serialization\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableDictionaryRTTI.h">
-      <Filter>Header Files\Serialization\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableListRTTI.h">
-      <Filter>Header Files\Serialization\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableObjectRTTI.h">
-      <Filter>Header Files\Serialization\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableArray.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableDictionary.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableList.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableObject.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableFieldRTTI.h">
-      <Filter>Header Files\Serialization\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableObjectInfoRTTI.h">
-      <Filter>Header Files\Serialization\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableField.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableObjectInfo.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableObject.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableField.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptDebug.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableArray.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableProperty.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptObjectImpl.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIElement.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUILayoutUtility.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedResource.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedResourceMetaData.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedComponentRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedResourceRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedResourceMetaDataRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptManagedResource.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedResourceManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableList.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableDictionary.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptInput.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptInputConfiguration.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptVirtualInput.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptVector2I.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptVirtualButton.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCursor.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPixelData.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptColor.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptAsyncOp.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptTexture.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptTextureCube.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptTexture3D.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPixelUtility.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptRenderTarget.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptRenderTexture.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptRenderTexture2D.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptTime.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIRenderTexture.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptObjectManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptAssemblyManager.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUISlider.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIProgressBar.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPlainText.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptScriptCode.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptBuiltin.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptShader.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptMaterial.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptMesh.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptMeshData.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptVector.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptBoneWeight.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptContextMenu.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableDiff.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableDiffRTTI.h">
-      <Filter>Header Files\Serialization\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedDiff.h">
-      <Filter>Header Files\Serialization</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPrefab.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptScene.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptProfilerOverlayInternal.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptStringTableManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUISkin.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptResources.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsEngineScriptLibrary.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCamera.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptRenderable.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptLight.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptFontBitmap.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableUtility.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptShaderInclude.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptLogEntry.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIContentImages.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsPlayInEditorManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptResourceRef.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIWidget.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUI.h">
-      <Filter>Header Files\GUI</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPhysicsMaterial.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPhysicsMesh.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCollider.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCollisionData.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPhysicsQueryHit.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptRigidbody.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptBoxCollider.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSphereCollider.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCapsuleCollider.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPlaneCollider.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptMeshCollider.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptJointCommon.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptControllerCollision.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCharacterController.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptJoint.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptDistanceJoint.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Source\BsScriptHingeJoint.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Source\BsScriptSliderJoint.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Source\BsScriptSphericalJoint.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Source\BsScriptFixedJoint.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Source\BsScriptD6Joint.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPhysics.h">
-      <Filter>Header Files\Physics</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptTexture2D.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptFont.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSpriteTexture.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptEnginePlugin.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptHString.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptStringTable.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedComponent.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptComponent.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptResourceManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGameObjectManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSceneObject.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIButton.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIContent.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIElementStateStyle.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIElementStyle.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIFixedSpace.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIFlexibleSpace.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIInputBox.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUILabel.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUILayout.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIListBox.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIScrollArea.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUITexture.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIToggle.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIToggleGroup.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableArray.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableDictionary.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableField.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableList.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableObject.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableObjectInfo.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableObject.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableField.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptDebug.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableArray.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableProperty.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptObjectImpl.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptObject.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIElement.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUILayoutUtility.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedResource.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedResourceMetaData.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptManagedResource.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedResourceManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableList.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableDictionary.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptInput.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptInputConfiguration.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptVirtualInput.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptVector2I.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptVirtualButton.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCursor.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPixelData.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptColor.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptAsyncOp.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptTexture.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptTextureCube.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptTexture3D.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPixelUtility.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptRenderTarget.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptRenderTexture.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptRenderTexture2D.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptTime.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIRenderTexture.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptObjectManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptResource.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGameObject.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptAssemblyManager.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUISlider.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIProgressBar.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPlainText.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptScriptCode.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptBuiltin.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptShader.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptMaterial.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptMesh.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptMeshData.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptVector.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptBoneWeight.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptContextMenu.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableDiff.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedDiff.cpp">
-      <Filter>Source Files\Serialization</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPrefab.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptScene.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptProfilerOverlayInternal.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptStringTableManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUISkin.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptResources.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsEngineScriptLibrary.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCamera.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptRenderable.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptLight.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptFontBitmap.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableUtility.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptShaderInclude.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptLogEntry.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIContentImages.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsPlayInEditorManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptResourceRef.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIWidget.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUI.cpp">
-      <Filter>Source Files\GUI</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPhysicsMaterial.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPhysicsMesh.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCollider.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCollisionData.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPhysicsQueryHit.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptRigidbody.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptBoxCollider.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSphereCollider.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCapsuleCollider.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPlaneCollider.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptMeshCollider.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptJointCommon.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptControllerCollision.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCharacterController.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptJoint.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptDistanceJoint.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptHingeJoint.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSliderJoint.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptFixedJoint.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSphericalJoint.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptD6Joint.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPhysics.cpp">
-      <Filter>Source Files\Physics</Filter>
-    </ClCompile>
-  </ItemGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Header Files\Serialization">
+      <UniqueIdentifier>{97b82061-c2d8-49e4-8840-80ff956f2cc0}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Serialization">
+      <UniqueIdentifier>{10d91e2d-e560-4081-ac15-bc6753ca2a7e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Serialization\RTTI">
+      <UniqueIdentifier>{3225801f-fe74-4e07-aa59-37ad5d5ac1da}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\RTTI">
+      <UniqueIdentifier>{cff4d9c9-b006-4675-a58e-6a0e449ff8d5}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Wrappers">
+      <UniqueIdentifier>{beddd517-49bb-4a3a-a200-31f490620231}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Wrappers\Physics">
+      <UniqueIdentifier>{8355a19c-b7b7-49a0-a8dd-baec11b88e28}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Wrappers\GUI">
+      <UniqueIdentifier>{90896fa0-9186-412e-bad6-b57e3ae7c060}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Wrappers">
+      <UniqueIdentifier>{45f5c7ec-9c9f-4154-8451-ff3a9ef6a020}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Wrappers\Physics">
+      <UniqueIdentifier>{9eb1c24d-26f9-4036-bf91-978b7a78966e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Wrappers\GUI">
+      <UniqueIdentifier>{a412791a-7e2f-4aea-a34f-6c2ad7f1246c}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptObject.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptEnginePrerequisites.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedComponent.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptResourceManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGameObjectManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIButton.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIContent.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIElementStateStyle.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIElementStyle.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIFixedSpace.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIFlexibleSpace.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIInputBox.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUILabel.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUILayout.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIListBox.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIScrollArea.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUITexture.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIToggle.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIToggleGroup.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableArrayRTTI.h">
+      <Filter>Header Files\Serialization\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableDictionaryRTTI.h">
+      <Filter>Header Files\Serialization\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableListRTTI.h">
+      <Filter>Header Files\Serialization\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableObjectRTTI.h">
+      <Filter>Header Files\Serialization\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableArray.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableDictionary.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableList.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableObject.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableFieldRTTI.h">
+      <Filter>Header Files\Serialization\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableObjectInfoRTTI.h">
+      <Filter>Header Files\Serialization\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableField.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableObjectInfo.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptObjectImpl.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIElement.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUILayoutUtility.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedResource.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedResourceMetaData.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedComponentRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedResourceRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedResourceMetaDataRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedResourceManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIRenderTexture.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptObjectManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptAssemblyManager.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUISlider.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIProgressBar.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableDiff.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedSerializableDiffRTTI.h">
+      <Filter>Header Files\Serialization\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsManagedDiff.h">
+      <Filter>Header Files\Serialization</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptStringTableManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUISkin.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsEngineScriptLibrary.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsPlayInEditorManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIWidget.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUI.h">
+      <Filter>Header Files\Wrappers\GUI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCollider.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCollisionData.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPhysicsQueryHit.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptRigidbody.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptBoxCollider.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSphereCollider.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCapsuleCollider.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPlaneCollider.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptMeshCollider.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptJointCommon.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptControllerCollision.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCharacterController.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptJoint.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptDistanceJoint.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Source\BsScriptHingeJoint.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Source\BsScriptSliderJoint.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Source\BsScriptSphericalJoint.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Source\BsScriptFixedJoint.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Source\BsScriptD6Joint.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPhysics.h">
+      <Filter>Header Files\Wrappers\Physics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptAsyncOp.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptBoneWeight.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptBuiltin.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCamera.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptColor.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptComponent.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptContextMenu.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptCursor.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptDebug.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptFont.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptFontBitmap.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGameObject.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptGUIContentImages.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptHString.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptInput.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptInputConfiguration.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptLight.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptLogEntry.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptManagedResource.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptMaterial.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptMesh.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptMeshData.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPhysicsMaterial.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPhysicsMesh.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPixelData.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPixelUtility.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPlainText.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptPrefab.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptProfilerOverlayInternal.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptRenderable.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptRenderTarget.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptRenderTexture.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptRenderTexture2D.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptResource.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptVirtualInput.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptVirtualButton.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptVector2I.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptVector.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptTime.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptTextureCube.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptTexture3D.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptTexture2D.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptTexture.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptStringTable.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSpriteTexture.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptShaderInclude.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptShader.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableUtility.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableProperty.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableObject.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableList.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableField.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableDictionary.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptScriptCode.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSerializableArray.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptSceneObject.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptScene.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptResources.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\Source\SBansheeEngine\Include\BsScriptResourceRef.h">
+      <Filter>Header Files\Wrappers</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptEnginePlugin.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedComponent.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptResourceManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGameObjectManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIButton.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIContent.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIElementStateStyle.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIElementStyle.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIFixedSpace.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIFlexibleSpace.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIInputBox.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUILabel.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUILayout.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIListBox.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIScrollArea.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUITexture.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIToggle.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIToggleGroup.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableArray.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableDictionary.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableField.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableList.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableObject.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableObjectInfo.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptObjectImpl.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptObject.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIElement.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUILayoutUtility.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedResource.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedResourceMetaData.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedResourceManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIRenderTexture.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptObjectManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptAssemblyManager.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUISlider.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIProgressBar.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedSerializableDiff.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsManagedDiff.cpp">
+      <Filter>Source Files\Serialization</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptStringTableManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUISkin.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsEngineScriptLibrary.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsPlayInEditorManager.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIWidget.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUI.cpp">
+      <Filter>Source Files\Wrappers\GUI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCollider.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCollisionData.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPhysicsQueryHit.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptRigidbody.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptBoxCollider.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSphereCollider.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCapsuleCollider.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPlaneCollider.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptMeshCollider.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptJointCommon.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptControllerCollision.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCharacterController.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptJoint.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptDistanceJoint.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptHingeJoint.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSliderJoint.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptFixedJoint.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSphericalJoint.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptD6Joint.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPhysics.cpp">
+      <Filter>Source Files\Wrappers\Physics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptAsyncOp.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptBoneWeight.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptBuiltin.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCamera.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptColor.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptComponent.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptContextMenu.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptCursor.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptDebug.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptFont.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptFontBitmap.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGameObject.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptGUIContentImages.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptHString.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptInput.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptInputConfiguration.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptLight.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptLogEntry.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptManagedResource.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptMaterial.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptMesh.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptMeshData.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPhysicsMaterial.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPhysicsMesh.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPixelData.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPixelUtility.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPlainText.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptPrefab.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptProfilerOverlayInternal.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptVirtualInput.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptVirtualButton.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptVector2I.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptVector.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptTime.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptTextureCube.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptTexture3D.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptTexture2D.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptTexture.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptStringTable.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSpriteTexture.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptShaderInclude.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptShader.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableUtility.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableProperty.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableObject.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableList.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableField.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableDictionary.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSerializableArray.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptScriptCode.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptSceneObject.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptScene.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptResources.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptResourceRef.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptResource.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptRenderTexture2D.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptRenderTexture.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptRenderTarget.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\Source\SBansheeEngine\Source\BsScriptRenderable.cpp">
+      <Filter>Source Files\Wrappers</Filter>
+    </ClCompile>
+  </ItemGroup>
 </Project>

+ 1269 - 1266
Source/BansheeEngine/Source/BsGUIInputBox.cpp

@@ -1,1267 +1,1270 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsGUIInputBox.h"
-#include "BsGUIManager.h"
-#include "BsImageSprite.h"
-#include "BsGUISkin.h"
-#include "BsSpriteTexture.h"
-#include "BsTextSprite.h"
-#include "BsGUIDimensions.h"
-#include "BsGUITextInputEvent.h"
-#include "BsGUIMouseEvent.h"
-#include "BsGUICommandEvent.h"
-#include "BsGUIInputCaret.h"
-#include "BsGUIInputSelection.h"
-#include "BsGUIContextMenu.h"
-#include "BsGUIHelper.h"
-
-namespace BansheeEngine
-{
-	VirtualButton GUIInputBox::mCopyVB = VirtualButton("Copy");
-	VirtualButton GUIInputBox::mPasteVB = VirtualButton("Paste");
-	VirtualButton GUIInputBox::mCutVB = VirtualButton("Cut");
-	VirtualButton GUIInputBox::mSelectAllVB = VirtualButton("SelectAll");
-
-	const String& GUIInputBox::getGUITypeName()
-	{
-		static String name = "InputBox";
-		return name;
-	}
-
-	GUIInputBox::GUIInputBox(const String& styleName, const GUIDimensions& dimensions, bool multiline)
-		:GUIElement(styleName, dimensions), mDragInProgress(false),
-		mCaretShown(false), mSelectionShown(false), mIsMultiline(multiline), mHasFocus(false), mIsMouseOver(false),
-		mState(State::Normal)
-	{
-		mImageSprite = bs_new<ImageSprite>();
-		mTextSprite = bs_new<TextSprite>();
-	}
-
-	GUIInputBox::~GUIInputBox()
-	{
-		bs_delete(mTextSprite);
-		bs_delete(mImageSprite);
-	}
-
-	GUIInputBox* GUIInputBox::create(bool multiline, const String& styleName)
-	{
-		return new (bs_alloc<GUIInputBox>()) GUIInputBox(getStyleName<GUIInputBox>(styleName), GUIDimensions::create(), multiline);
-	}
-
-	GUIInputBox* GUIInputBox::create(bool multiline, const GUIOptions& options, const String& styleName)
-	{
-		return new (bs_alloc<GUIInputBox>()) GUIInputBox(getStyleName<GUIInputBox>(styleName), GUIDimensions::create(options), multiline);
-	}
-
-	GUIInputBox* GUIInputBox::create(const GUIOptions& options, const String& styleName)
-	{
-		return new (bs_alloc<GUIInputBox>()) GUIInputBox(getStyleName<GUIInputBox>(styleName), GUIDimensions::create(options), false);
-	}
-
-	void GUIInputBox::setText(const WString& text)
-	{
-		if (mText == text)
-			return;
-
-		bool filterOkay = true;
-		if(mFilter != nullptr)
-		{
-			filterOkay = mFilter(text);
-		}
-
-		if(filterOkay)
-		{
-			Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-
-			WString oldText = mText;
-			mText = text;
-
-			if (mHasFocus)
-			{
-				TEXT_SPRITE_DESC textDesc = getTextDesc();
-				Vector2I offset = getTextOffset();
-
-				gGUIManager().getInputCaretTool()->updateText(this, textDesc);
-				gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
-
-				if (mText.size() > 0)
-					gGUIManager().getInputCaretTool()->moveCaretToChar((UINT32)mText.size() - 1, CARET_AFTER);
-				else
-					gGUIManager().getInputCaretTool()->moveCaretToChar(0, CARET_BEFORE);
-
-				scrollTextToCaret();
-			}
-
-			Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-			if (origSize != newSize)
-				_markLayoutAsDirty();
-			else
-				_markContentAsDirty();
-		}
-	}
-
-	UINT32 GUIInputBox::_getNumRenderElements() const
-	{
-		UINT32 numElements = mImageSprite->getNumRenderElements();
-		numElements += mTextSprite->getNumRenderElements();
-
-		if(mCaretShown && gGUIManager().getCaretBlinkState())
-			numElements += gGUIManager().getInputCaretTool()->getSprite()->getNumRenderElements();
-
-		if(mSelectionShown)
-		{
-			const Vector<ImageSprite*>& sprites = gGUIManager().getInputSelectionTool()->getSprites();
-			for(auto& selectionSprite : sprites)
-			{
-				numElements += selectionSprite->getNumRenderElements();
-			}
-		}
-
-		return numElements;
-	}
-
-	const SpriteMaterialInfo& GUIInputBox::_getMaterial(UINT32 renderElementIdx) const
-	{
-		UINT32 localRenderElementIdx;
-		Sprite* sprite = renderElemToSprite(renderElementIdx, localRenderElementIdx);
-
-		return sprite->getMaterialInfo(localRenderElementIdx);
-	}
-
-	UINT32 GUIInputBox::_getNumQuads(UINT32 renderElementIdx) const
-	{
-		UINT32 localRenderElementIdx;
-		Sprite* sprite = renderElemToSprite(renderElementIdx, localRenderElementIdx);
-
-		return sprite->getNumQuads(localRenderElementIdx);
-	}
-
-	void GUIInputBox::updateRenderElementsInternal()
-	{		
-		mImageDesc.width = mLayoutData.area.width;
-		mImageDesc.height = mLayoutData.area.height;
-		mImageDesc.borderLeft = _getStyle()->border.left;
-		mImageDesc.borderRight = _getStyle()->border.right;
-		mImageDesc.borderTop = _getStyle()->border.top;
-		mImageDesc.borderBottom = _getStyle()->border.bottom;
-		mImageDesc.color = getTint();
-
-		const HSpriteTexture& activeTex = getActiveTexture();
-		if(SpriteTexture::checkIsLoaded(activeTex))
-		{
-			mImageDesc.texture = activeTex.getInternalPtr();
-		}
-
-		mImageSprite->update(mImageDesc, (UINT64)_getParentWidget());
-
-		TEXT_SPRITE_DESC textDesc = getTextDesc();
-		mTextSprite->update(textDesc, (UINT64)_getParentWidget());
-
-		if(mCaretShown && gGUIManager().getCaretBlinkState())
-		{
-			gGUIManager().getInputCaretTool()->updateText(this, textDesc); // TODO - These shouldn't be here. Only call this when one of these parameters changes.
-			gGUIManager().getInputCaretTool()->updateSprite();
-		}
-
-		if(mSelectionShown)
-		{
-			gGUIManager().getInputSelectionTool()->updateText(this, textDesc); // TODO - These shouldn't be here. Only call this when one of these parameters changes.
-			gGUIManager().getInputSelectionTool()->updateSprite();
-		}
-
-		// When text bounds are reduced the scroll needs to be adjusted so that
-		// input box isn't filled with mostly empty space.
-		Vector2I offset(mLayoutData.area.x, mLayoutData.area.y);
-		clampScrollToBounds(mTextSprite->getBounds(offset, Rect2I()));
-
-		GUIElement::updateRenderElementsInternal();
-	}
-
-	void GUIInputBox::updateClippedBounds()
-	{
-		Vector2I offset(mLayoutData.area.x, mLayoutData.area.y);
-		mClippedBounds = mImageSprite->getBounds(offset, mLayoutData.getLocalClipRect());
-	}
-
-	Sprite* GUIInputBox::renderElemToSprite(UINT32 renderElemIdx, UINT32& localRenderElemIdx) const
-	{
-		UINT32 oldNumElements = 0;
-		UINT32 newNumElements = oldNumElements + mTextSprite->getNumRenderElements();
-		if(renderElemIdx < newNumElements)
-		{
-			localRenderElemIdx = renderElemIdx - oldNumElements;
-			return mTextSprite;
-		}
-
-		oldNumElements = newNumElements;
-		newNumElements += mImageSprite->getNumRenderElements();
-
-		if(renderElemIdx < newNumElements)
-		{
-			localRenderElemIdx = renderElemIdx - oldNumElements;
-			return mImageSprite;
-		}
-
-		if(mCaretShown && gGUIManager().getCaretBlinkState())
-		{
-			oldNumElements = newNumElements;
-			newNumElements += gGUIManager().getInputCaretTool()->getSprite()->getNumRenderElements();
-
-			if(renderElemIdx < newNumElements)
-			{
-				localRenderElemIdx = renderElemIdx - oldNumElements;
-				return gGUIManager().getInputCaretTool()->getSprite();
-			}
-		}
-
-		if(mSelectionShown)
-		{
-			const Vector<ImageSprite*>& sprites = gGUIManager().getInputSelectionTool()->getSprites();
-			for(auto& selectionSprite : sprites)
-			{
-				oldNumElements = newNumElements;
-				newNumElements += selectionSprite->getNumRenderElements();
-
-				if(renderElemIdx < newNumElements)
-				{
-					localRenderElemIdx = renderElemIdx - oldNumElements;
-					return selectionSprite;
-				}
-			}
-		}
-
-		localRenderElemIdx = renderElemIdx;
-		return nullptr;
-	}
-
-	Vector2I GUIInputBox::renderElemToOffset(UINT32 renderElemIdx) const
-	{
-		UINT32 oldNumElements = 0;
-		UINT32 newNumElements = oldNumElements + mTextSprite->getNumRenderElements();
-		if(renderElemIdx < newNumElements)
-			return getTextOffset();
-
-		oldNumElements = newNumElements;
-		newNumElements += mImageSprite->getNumRenderElements();
-
-		if(renderElemIdx < newNumElements)
-			return Vector2I(mLayoutData.area.x, mLayoutData.area.y);;
-
-		if(mCaretShown && gGUIManager().getCaretBlinkState())
-		{
-			oldNumElements = newNumElements;
-			newNumElements += gGUIManager().getInputCaretTool()->getSprite()->getNumRenderElements();
-
-			if(renderElemIdx < newNumElements)
-				return gGUIManager().getInputCaretTool()->getSpriteOffset();
-		}
-
-		if(mSelectionShown)
-		{
-			UINT32 spriteIdx = 0;
-			const Vector<ImageSprite*>& sprites = gGUIManager().getInputSelectionTool()->getSprites();
-			for(auto& selectionSprite : sprites)
-			{
-				oldNumElements = newNumElements;
-				newNumElements += selectionSprite->getNumRenderElements();
-
-				if(renderElemIdx < newNumElements)
-					return gGUIManager().getInputSelectionTool()->getSelectionSpriteOffset(spriteIdx);
-
-				spriteIdx++;
-			}
-		}
-
-		return Vector2I();
-	}
-
-	Rect2I GUIInputBox::renderElemToClipRect(UINT32 renderElemIdx) const
-	{
-		UINT32 oldNumElements = 0;
-		UINT32 newNumElements = oldNumElements + mTextSprite->getNumRenderElements();
-		if(renderElemIdx < newNumElements)
-			return getTextClipRect();
-
-		oldNumElements = newNumElements;
-		newNumElements += mImageSprite->getNumRenderElements();
-
-		if(renderElemIdx < newNumElements)
-			return mLayoutData.getLocalClipRect();
-
-		if(mCaretShown && gGUIManager().getCaretBlinkState())
-		{
-			oldNumElements = newNumElements;
-			newNumElements += gGUIManager().getInputCaretTool()->getSprite()->getNumRenderElements();
-
-			if(renderElemIdx < newNumElements)
-			{
-				return gGUIManager().getInputCaretTool()->getSpriteClipRect(getTextClipRect());
-			}
-		}
-
-		if(mSelectionShown)
-		{
-			UINT32 spriteIdx = 0;
-			const Vector<ImageSprite*>& sprites = gGUIManager().getInputSelectionTool()->getSprites();
-			for(auto& selectionSprite : sprites)
-			{
-				oldNumElements = newNumElements;
-				newNumElements += selectionSprite->getNumRenderElements();
-
-				if(renderElemIdx < newNumElements)
-					return gGUIManager().getInputSelectionTool()->getSelectionSpriteClipRect(spriteIdx, getTextClipRect());
-
-				spriteIdx++;
-			}
-		}
-
-		return Rect2I();
-	}
-
-	Vector2I GUIInputBox::_getOptimalSize() const
-	{
-		UINT32 imageWidth = 0;
-		UINT32 imageHeight = 0;
-
-		const HSpriteTexture& activeTex = getActiveTexture();
-		if(SpriteTexture::checkIsLoaded(activeTex))
-		{
-			imageWidth = activeTex->getWidth();
-			imageHeight = activeTex->getHeight();
-		}
-
-		Vector2I contentSize = GUIHelper::calcOptimalContentsSize(mText, *_getStyle(), _getDimensions());
-		UINT32 contentWidth = std::max(imageWidth, (UINT32)contentSize.x);
-		UINT32 contentHeight = std::max(imageHeight, (UINT32)contentSize.y);
-
-		return Vector2I(contentWidth, contentHeight);
-	}
-
-	Vector2I GUIInputBox::_getTextInputOffset() const
-	{
-		return mTextOffset;	
-	}
-
-	Rect2I GUIInputBox::_getTextInputRect() const
-	{
-		Rect2I textBounds = getCachedContentBounds();
-		textBounds.x -= mLayoutData.area.x;
-		textBounds.y -= mLayoutData.area.y;
-
-		return textBounds;
-	}
-
-	UINT32 GUIInputBox::_getRenderElementDepth(UINT32 renderElementIdx) const
-	{
-		UINT32 localRenderElementIdx;
-		Sprite* sprite = renderElemToSprite(renderElementIdx, localRenderElementIdx);
-
-		if(sprite == mImageSprite)
-			return _getDepth() + 3;
-		else if(sprite == mTextSprite)
-			return _getDepth() + 1;
-		else if(sprite == gGUIManager().getInputCaretTool()->getSprite())
-			return _getDepth();
-		else // Selection sprites
-			return _getDepth() + 2;
-	}
-
-	UINT32 GUIInputBox::_getRenderElementDepthRange() const
-	{
-		return 4;
-	}
-
-	bool GUIInputBox::_hasCustomCursor(const Vector2I position, CursorType& type) const
-	{
-		if(_isInBounds(position) && !_isDisabled())
-		{
-			type = CursorType::IBeam;
-			return true;
-		}
-
-		return false;
-	}
-
-	void GUIInputBox::_fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, UINT32 maxNumQuads, 
-		UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const
-	{
-		UINT32 localRenderElementIdx;
-		Sprite* sprite = renderElemToSprite(renderElementIdx, localRenderElementIdx);
-		Vector2I offset = renderElemToOffset(renderElementIdx);
-		Rect2I clipRect = renderElemToClipRect(renderElementIdx);
-
-		sprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, vertexStride, indexStride, localRenderElementIdx, offset, clipRect);
-	}
-
-	bool GUIInputBox::_mouseEvent(const GUIMouseEvent& ev)
-	{
-		if(ev.getType() == GUIMouseEventType::MouseOver)
-		{
-			if (!_isDisabled())
-			{
-				if (!mHasFocus)
-				{
-					Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-					mState = State::Hover;
-					Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-
-					if (origSize != newSize)
-						_markLayoutAsDirty();
-					else
-						_markContentAsDirty();
-				}
-
-				mIsMouseOver = true;
-			}
-
-			return true;
-		}
-		else if(ev.getType() == GUIMouseEventType::MouseOut)
-		{
-			if (!_isDisabled())
-			{
-				if (!mHasFocus)
-				{
-					Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-					mState = State::Normal;
-					Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-
-					if (origSize != newSize)
-						_markLayoutAsDirty();
-					else
-						_markContentAsDirty();
-				}
-
-				mIsMouseOver = false;
-			}
-
-			return true;
-		}
-		else if(ev.getType() == GUIMouseEventType::MouseDoubleClick && ev.getButton() == GUIMouseButton::Left)
-		{
-			if (!_isDisabled())
-			{
-				showSelection(0);
-				gGUIManager().getInputSelectionTool()->selectAll();
-
-				_markContentAsDirty();
-			}
-
-			return true;
-		}
-		else if(ev.getType() == GUIMouseEventType::MouseDown && ev.getButton() == GUIMouseButton::Left)
-		{
-			if (!_isDisabled())
-			{
-				if (ev.isShiftDown())
-				{
-					if (!mSelectionShown)
-						showSelection(gGUIManager().getInputCaretTool()->getCaretPos());
-				}
-				else
-				{
-					clearSelection();
-					showCaret();
-				}
-
-				if (mText.size() > 0)
-					gGUIManager().getInputCaretTool()->moveCaretToPos(ev.getPosition());
-				else
-					gGUIManager().getInputCaretTool()->moveCaretToStart();
-
-				if (ev.isShiftDown())
-					gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
-
-				scrollTextToCaret();
-				_markContentAsDirty();
-			}
-
-			return true;
-		}
-		else if(ev.getType() == GUIMouseEventType::MouseDragStart)
-		{
-			if (!_isDisabled())
-			{
-				if (!ev.isShiftDown())
-				{
-					mDragInProgress = true;
-
-					UINT32 caretPos = gGUIManager().getInputCaretTool()->getCaretPos();
-					showSelection(caretPos);
-					gGUIManager().getInputSelectionTool()->selectionDragStart(caretPos);
-					_markContentAsDirty();
-
-					return true;
-				}
-			}
-		}
-		else if(ev.getType() == GUIMouseEventType::MouseDragEnd)
-		{
-			if (!_isDisabled())
-			{
-				if (!ev.isShiftDown())
-				{
-					mDragInProgress = false;
-
-					gGUIManager().getInputSelectionTool()->selectionDragEnd();
-					_markContentAsDirty();
-					return true;
-				}
-			}
-		}
-		else if(ev.getType() == GUIMouseEventType::MouseDrag)
-		{
-			if (!_isDisabled())
-			{
-				if (!ev.isShiftDown())
-				{
-					if (mText.size() > 0)
-						gGUIManager().getInputCaretTool()->moveCaretToPos(ev.getPosition());
-					else
-						gGUIManager().getInputCaretTool()->moveCaretToStart();
-
-					gGUIManager().getInputSelectionTool()->selectionDragUpdate(gGUIManager().getInputCaretTool()->getCaretPos());
-
-					scrollTextToCaret();
-					_markContentAsDirty();
-					return true;
-				}
-			}
-		}
-
-		return false;
-	}
-
-	bool GUIInputBox::_textInputEvent(const GUITextInputEvent& ev)
-	{
-		if (_isDisabled())
-			return false;
-
-		Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-
-		if(mSelectionShown)
-			deleteSelectedText(true);
-
-		UINT32 charIdx = gGUIManager().getInputCaretTool()->getCharIdxAtCaretPos();
-
-		bool filterOkay = true;
-		if(mFilter != nullptr)
-		{
-			WString newText = mText;
-			newText.insert(newText.begin() + charIdx, ev.getInputChar());
-
-			filterOkay = mFilter(newText);
-		}
-
-		if(filterOkay)
-		{
-			insertChar(charIdx, ev.getInputChar());
-
-			gGUIManager().getInputCaretTool()->moveCaretToChar(charIdx, CARET_AFTER);
-			scrollTextToCaret();
-
-			if(!onValueChanged.empty())
-				onValueChanged(mText);
-		}
-
-		Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-		if (origSize != newSize)
-			_markLayoutAsDirty();
-		else
-			_markContentAsDirty();
-
-		return true;
-	}
-
-	bool GUIInputBox::_commandEvent(const GUICommandEvent& ev)
-	{
-		if (_isDisabled())
-			return false;
-
-		bool baseReturn = GUIElement::_commandEvent(ev);
-
-		if(ev.getType() == GUICommandEventType::Redraw)
-		{
-			_markContentAsDirty();
-			return true;
-		}
-
-		if(ev.getType() == GUICommandEventType::FocusGained)
-		{
-			Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-			mState = State::Focused;
-
-			showSelection(0);
-			gGUIManager().getInputSelectionTool()->selectAll();
-
-			mHasFocus = true;
-
-			Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-			if (origSize != newSize)
-				_markLayoutAsDirty();
-			else
-				_markContentAsDirty();
-
-			return true;
-		}
-		
-		if(ev.getType() == GUICommandEventType::FocusLost)
-		{
-			Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-			mState = State::Normal;
-
-			hideCaret();
-			clearSelection();
-
-			mHasFocus = false;
-
-			Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-			if (origSize != newSize)
-				_markLayoutAsDirty();
-			else
-				_markContentAsDirty();
-
-			return true;
-		}
-		
-		if(ev.getType() == GUICommandEventType::Backspace)
-		{
-			if(mText.size() > 0)
-			{
-				Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-				if(mSelectionShown)
-				{
-					deleteSelectedText();
-				}
-				else
-				{
-					UINT32 charIdx = gGUIManager().getInputCaretTool()->getCharIdxAtCaretPos() - 1;
-
-					if(charIdx < (UINT32)mText.size())
-					{
-						bool filterOkay = true;
-						if(mFilter != nullptr)
-						{
-							WString newText = mText;
-							newText.erase(charIdx, 1);
-
-							filterOkay = mFilter(newText);
-						}
-
-						if(filterOkay)
-						{
-							eraseChar(charIdx);
-
-							if (charIdx > 0)
-							{
-								charIdx--;
-
-								gGUIManager().getInputCaretTool()->moveCaretToChar(charIdx, CARET_AFTER);
-							}
-							else
-								gGUIManager().getInputCaretTool()->moveCaretToChar(charIdx, CARET_BEFORE);
-
-							scrollTextToCaret();
-
-							if(!onValueChanged.empty())
-								onValueChanged(mText);
-						}
-					}
-				}
-
-				Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-				if (origSize != newSize)
-					_markLayoutAsDirty();
-				else
-					_markContentAsDirty();
-			}
-
-			return true;
-		}
-
-		if(ev.getType() == GUICommandEventType::Delete)
-		{
-			if(mText.size() > 0)
-			{
-				Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-				if(mSelectionShown)
-				{
-					deleteSelectedText();
-				}
-				else
-				{
-					UINT32 charIdx = gGUIManager().getInputCaretTool()->getCharIdxAtCaretPos();
-					if(charIdx < (UINT32)mText.size())
-					{
-						bool filterOkay = true;
-						if(mFilter != nullptr)
-						{
-							WString newText = mText;
-							newText.erase(charIdx, 1);
-
-							filterOkay = mFilter(newText);
-						}
-
-						if(filterOkay)
-						{
-							eraseChar(charIdx);
-
-							if(charIdx > 0)
-								charIdx--;
-
-							gGUIManager().getInputCaretTool()->moveCaretToChar(charIdx, CARET_AFTER);
-
-							scrollTextToCaret();
-
-							if(!onValueChanged.empty())
-								onValueChanged(mText);
-						}
-					}
-				}
-
-				Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-				if (origSize != newSize)
-					_markLayoutAsDirty();
-				else
-					_markContentAsDirty();
-			}
-
-			return true;
-		}
-
-		if(ev.getType() == GUICommandEventType::MoveLeft)
-		{
-			if(mSelectionShown)
-			{
-				UINT32 selStart = gGUIManager().getInputSelectionTool()->getSelectionStart();
-				clearSelection();
-
-				if (!mCaretShown)
-					showCaret();
-
-				if(selStart > 0)
-					gGUIManager().getInputCaretTool()->moveCaretToChar(selStart - 1, CARET_AFTER);
-				else
-					gGUIManager().getInputCaretTool()->moveCaretToChar(0, CARET_BEFORE);
-			}
-			else
-				gGUIManager().getInputCaretTool()->moveCaretLeft();
-
-			scrollTextToCaret();
-			_markContentAsDirty();
-			return true;
-		}
-
-		if(ev.getType() == GUICommandEventType::SelectLeft)
-		{
-			if(!mSelectionShown)
-				showSelection(gGUIManager().getInputCaretTool()->getCaretPos());
-
-			gGUIManager().getInputCaretTool()->moveCaretLeft();
-			gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
-
-			scrollTextToCaret();
-			_markContentAsDirty();
-			return true;
-		}
-
-		if(ev.getType() == GUICommandEventType::MoveRight)
-		{
-			if(mSelectionShown)
-			{
-				UINT32 selEnd = gGUIManager().getInputSelectionTool()->getSelectionEnd();
-				clearSelection();
-
-				if (!mCaretShown)
-					showCaret();
-
-				if(selEnd > 0)
-					gGUIManager().getInputCaretTool()->moveCaretToChar(selEnd - 1, CARET_AFTER);
-				else
-					gGUIManager().getInputCaretTool()->moveCaretToChar(0, CARET_BEFORE);
-			}
-			else
-				gGUIManager().getInputCaretTool()->moveCaretRight();
-
-			scrollTextToCaret();
-			_markContentAsDirty();
-			return true;
-		}
-
-		if(ev.getType() == GUICommandEventType::SelectRight)
-		{
-			if(!mSelectionShown)
-				showSelection(gGUIManager().getInputCaretTool()->getCaretPos());
-
-			gGUIManager().getInputCaretTool()->moveCaretRight();
-			gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
-
-			scrollTextToCaret();
-			_markContentAsDirty();
-			return true;
-		}
-
-		if(ev.getType() == GUICommandEventType::MoveUp)
-		{
-			if (mSelectionShown)
-				clearSelection();
-
-			if (!mCaretShown)
-				showCaret();
-
-			gGUIManager().getInputCaretTool()->moveCaretUp();
-
-			scrollTextToCaret();
-			_markContentAsDirty();
-			return true;
-		}
-
-		if(ev.getType() == GUICommandEventType::SelectUp)
-		{
-			if(!mSelectionShown)
-				showSelection(gGUIManager().getInputCaretTool()->getCaretPos());;
-
-			gGUIManager().getInputCaretTool()->moveCaretUp();
-			gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
-
-			scrollTextToCaret();
-			_markContentAsDirty();
-			return true;
-		}
-
-		if(ev.getType() == GUICommandEventType::MoveDown)
-		{
-			if (mSelectionShown)
-				clearSelection();
-
-			if (!mCaretShown)
-				showCaret();
-
-			gGUIManager().getInputCaretTool()->moveCaretDown();
-
-			scrollTextToCaret();
-			_markContentAsDirty();
-			return true;
-		}
-
-		if(ev.getType() == GUICommandEventType::SelectDown)
-		{
-			if(!mSelectionShown)
-				showSelection(gGUIManager().getInputCaretTool()->getCaretPos());
-
-			gGUIManager().getInputCaretTool()->moveCaretDown();
-			gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
-
-			scrollTextToCaret();
-			_markContentAsDirty();
-			return true;
-		}
-
-		if(ev.getType() == GUICommandEventType::Return)
-		{
-			if (mIsMultiline)
-			{
-				Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-
-				if (mSelectionShown)
-					deleteSelectedText();
-
-				UINT32 charIdx = gGUIManager().getInputCaretTool()->getCharIdxAtCaretPos();
-
-				bool filterOkay = true;
-				if (mFilter != nullptr)
-				{
-					WString newText = mText;
-					newText.insert(newText.begin() + charIdx, '\n');
-
-					filterOkay = mFilter(newText);
-				}
-
-				if (filterOkay)
-				{
-					insertChar(charIdx, '\n');
-
-					gGUIManager().getInputCaretTool()->moveCaretRight();
-					scrollTextToCaret();
-
-					if (!onValueChanged.empty())
-						onValueChanged(mText);
-				}
-
-				Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-				if (origSize != newSize)
-					_markLayoutAsDirty();
-				else
-					_markContentAsDirty();
-
-				return true;
-			}
-		}
-
-		if (ev.getType() == GUICommandEventType::Confirm)
-		{
-			onConfirm();
-			return true;
-		}
-
-		return baseReturn;
-	}
-
-	bool GUIInputBox::_virtualButtonEvent(const GUIVirtualButtonEvent& ev)
-	{
-		if (_isDisabled())
-			return false;
-
-		if(ev.getButton() == mCutVB)
-		{
-			cutText();
-
-			return true;
-		}
-		else if(ev.getButton() == mCopyVB)
-		{
-			copyText();
-
-			return true;
-		}
-		else if(ev.getButton() == mPasteVB)
-		{
-			pasteText();
-			return true;
-		}
-		else if(ev.getButton() == mSelectAllVB)
-		{
-			showSelection(0);
-			gGUIManager().getInputSelectionTool()->selectAll();
-			_markContentAsDirty();
-
-			return true;
-		}
-
-		return false;
-	}
-
-	void GUIInputBox::showCaret()
-	{
-		mCaretShown = true;
-
-		TEXT_SPRITE_DESC textDesc = getTextDesc();
-		Vector2I offset = getTextOffset();
-		gGUIManager().getInputCaretTool()->updateText(this, textDesc);
-	}
-
-	void GUIInputBox::hideCaret()
-	{
-		mCaretShown = false;
-	}
-
-	void GUIInputBox::showSelection(UINT32 anchorCaretPos)
-	{
-		TEXT_SPRITE_DESC textDesc = getTextDesc();
-		Vector2I offset = getTextOffset();
-		gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
-
-		gGUIManager().getInputSelectionTool()->showSelection(anchorCaretPos);
-		mSelectionShown = true;
-	}
-
-	void GUIInputBox::clearSelection()
-	{
-		gGUIManager().getInputSelectionTool()->clearSelection();
-		mSelectionShown = false;
-	}
-
-	void GUIInputBox::scrollTextToCaret()
-	{
-		TEXT_SPRITE_DESC textDesc = getTextDesc();
-
-		Vector2I textOffset = getTextOffset();
-		Vector2I caretPos = gGUIManager().getInputCaretTool()->getCaretPosition(textOffset);
-		UINT32 caretHeight = gGUIManager().getInputCaretTool()->getCaretHeight();
-		UINT32 caretWidth = 1;
-
-		INT32 left = textOffset.x - mTextOffset.x;
-		// Include caret width here because we don't want to scroll if just the caret is outside the bounds
-		// (Possible if the text width is exactly the maximum width)
-		INT32 right = left + (INT32)textDesc.width + caretWidth; 
-		INT32 top = textOffset.y - mTextOffset.y;
-		INT32 bottom = top + (INT32)textDesc.height;
-
-		// If caret is too high to display we don't want the offset to keep adjusting itself
-		caretHeight = std::min(caretHeight, (UINT32)(bottom - top));
-		INT32 caretRight = caretPos.x + (INT32)caretWidth;
-		INT32 caretBottom = caretPos.y + (INT32)caretHeight;
-
-		Vector2I offset;
-		if(caretPos.x < left)
-		{
-			offset.x = left - caretPos.x;
-		}
-		else if(caretRight > right)
-		{
-			offset.x = -(caretRight - right);
-		}
-
-		if(caretPos.y < top)
-		{
-			offset.y = top - caretPos.y;
-		}
-		else if(caretBottom > bottom)
-		{
-			offset.y = -(caretBottom - bottom);
-		}
-
-		mTextOffset += offset;
-
-		gGUIManager().getInputCaretTool()->updateText(this, textDesc);
-		gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
-	}
-
-	void GUIInputBox::clampScrollToBounds(Rect2I unclippedTextBounds)
-	{
-		Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-		TEXT_SPRITE_DESC textDesc = getTextDesc();
-
-		Vector2I newTextOffset;
-		INT32 maxScrollableWidth = std::max(0, (INT32)unclippedTextBounds.width - (INT32)textDesc.width);
-		INT32 maxScrollableHeight = std::max(0, (INT32)unclippedTextBounds.height - (INT32)textDesc.height);
-		newTextOffset.x = Math::clamp(mTextOffset.x, -maxScrollableWidth, 0);
-		newTextOffset.y = Math::clamp(mTextOffset.y, -maxScrollableHeight, 0);
-
-		if(newTextOffset != mTextOffset)
-		{
-			mTextOffset = newTextOffset;
-
-			gGUIManager().getInputCaretTool()->updateText(this, textDesc);
-			gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
-		}
-	}
-
-	void GUIInputBox::insertString(UINT32 charIdx, const WString& string)
-	{
-		mText.insert(mText.begin() + charIdx, string.begin(), string.end());
-
-		TEXT_SPRITE_DESC textDesc = getTextDesc();
-		Vector2I offset = getTextOffset();
-
-		gGUIManager().getInputCaretTool()->updateText(this, textDesc);
-		gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
-	}
-
-	void GUIInputBox::insertChar(UINT32 charIdx, UINT32 charCode)
-	{
-		mText.insert(mText.begin() + charIdx, charCode);
-
-		TEXT_SPRITE_DESC textDesc = getTextDesc();
-		Vector2I offset = getTextOffset();
-
-		gGUIManager().getInputCaretTool()->updateText(this, textDesc);
-		gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
-	}
-
-	void GUIInputBox::eraseChar(UINT32 charIdx)
-	{
-		mText.erase(charIdx, 1);
-
-		TEXT_SPRITE_DESC textDesc = getTextDesc();
-		Vector2I offset = getTextOffset();
-
-		gGUIManager().getInputCaretTool()->updateText(this, textDesc);
-		gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
-	}
-
-	void GUIInputBox::deleteSelectedText(bool internal)
-	{
-		UINT32 selStart = gGUIManager().getInputSelectionTool()->getSelectionStart();
-		UINT32 selEnd = gGUIManager().getInputSelectionTool()->getSelectionEnd();
-
-		bool filterOkay = true;
-		if (!internal && mFilter != nullptr)
-		{
-			WString newText = mText;
-			newText.erase(newText.begin() + selStart, newText.begin() + selEnd);
-
-			filterOkay = mFilter(newText);
-		}
-
-		if (!mCaretShown)
-			showCaret();
-
-		if(filterOkay)
-		{
-			mText.erase(mText.begin() + selStart, mText.begin() + selEnd);
-
-			TEXT_SPRITE_DESC textDesc = getTextDesc();
-			Vector2I offset = getTextOffset();
-			gGUIManager().getInputCaretTool()->updateText(this, textDesc);
-			gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
-
-			if(selStart > 0)
-			{
-				UINT32 newCaretPos = selStart - 1;
-				gGUIManager().getInputCaretTool()->moveCaretToChar(newCaretPos, CARET_AFTER);
-			}
-			else
-			{
-				gGUIManager().getInputCaretTool()->moveCaretToChar(0, CARET_BEFORE);
-			}
-
-			scrollTextToCaret();
-
-			if (!internal)
-				onValueChanged(mText);
-		}
-
-		clearSelection();
-	}
-
-	WString GUIInputBox::getSelectedText()
-	{
-		UINT32 selStart = gGUIManager().getInputSelectionTool()->getSelectionStart();
-		UINT32 selEnd = gGUIManager().getInputSelectionTool()->getSelectionEnd();
-
-		return mText.substr(selStart, selEnd - selStart);
-
-		mText.erase(mText.begin() + selStart, mText.begin() + gGUIManager().getInputSelectionTool()->getSelectionEnd());
-	}
-
-	Vector2I GUIInputBox::getTextOffset() const
-	{
-		Rect2I textBounds = getCachedContentBounds();
-		return Vector2I(textBounds.x, textBounds.y) + mTextOffset;
-	}
-
-	Rect2I GUIInputBox::getTextClipRect() const
-	{
-		Rect2I contentClipRect = getCachedContentClipRect();
-		return Rect2I(contentClipRect.x - mTextOffset.x, contentClipRect.y - mTextOffset.y, contentClipRect.width, contentClipRect.height);
-	}
-
-	TEXT_SPRITE_DESC GUIInputBox::getTextDesc() const
-	{
-		TEXT_SPRITE_DESC textDesc;
-		textDesc.text = mText;
-		textDesc.font = _getStyle()->font;
-		textDesc.fontSize = _getStyle()->fontSize;
-		textDesc.color = getTint() * getActiveTextColor();
-
-		Rect2I textBounds = getCachedContentBounds();
-		textDesc.width = textBounds.width;
-		textDesc.height = textBounds.height;
-		textDesc.horzAlign = _getStyle()->textHorzAlign;
-		textDesc.vertAlign = _getStyle()->textVertAlign;
-		textDesc.wordWrap = mIsMultiline;
-
-		return textDesc;
-	}
-
-	const HSpriteTexture& GUIInputBox::getActiveTexture() const
-	{
-		switch(mState)
-		{
-		case State::Focused:
-			return _getStyle()->focused.texture;
-		case State::Hover:
-			return _getStyle()->hover.texture;
-		case State::Normal:
-			return _getStyle()->normal.texture;
-		}
-
-		return _getStyle()->normal.texture;
-	}
-
-	Color GUIInputBox::getActiveTextColor() const
-	{
-		switch (mState)
-		{
-		case State::Focused:
-			return _getStyle()->focused.textColor;
-		case State::Hover:
-			return _getStyle()->hover.textColor;
-		case State::Normal:
-			return _getStyle()->normal.textColor;
-		}
-
-		return _getStyle()->normal.textColor;
-	}
-
-	GUIContextMenuPtr GUIInputBox::_getContextMenu() const
-	{
-		static GUIContextMenuPtr contextMenu;
-
-		if (contextMenu == nullptr)
-		{
-			contextMenu = bs_shared_ptr_new<GUIContextMenu>();
-
-			contextMenu->addMenuItem(L"Cut", std::bind(&GUIInputBox::cutText, const_cast<GUIInputBox*>(this)), 0);
-			contextMenu->addMenuItem(L"Copy", std::bind(&GUIInputBox::copyText, const_cast<GUIInputBox*>(this)), 0);
-			contextMenu->addMenuItem(L"Paste", std::bind(&GUIInputBox::pasteText, const_cast<GUIInputBox*>(this)), 0);
-
-			contextMenu->setLocalizedName(L"Cut", HString(L"Cut"));
-			contextMenu->setLocalizedName(L"Copy", HString(L"Copy"));
-			contextMenu->setLocalizedName(L"Paste", HString(L"Paste"));
-		}
-
-		if (!_isDisabled())
-			return contextMenu;
-
-		return nullptr;
-	}
-
-	void GUIInputBox::cutText()
-	{
-		Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-
-		copyText();
-		deleteSelectedText();
-
-		Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-		if (origSize != newSize)
-			_markLayoutAsDirty();
-		else
-			_markContentAsDirty();
-	}
-
-	void GUIInputBox::copyText()
-	{
-		PlatformUtility::copyToClipboard(getSelectedText());
-	}
-
-	void GUIInputBox::pasteText()
-	{
-		if (mSelectionShown)
-			deleteSelectedText(true);
-
-		WString textInClipboard = PlatformUtility::copyFromClipboard();
-		UINT32 charIdx = gGUIManager().getInputCaretTool()->getCharIdxAtCaretPos();
-
-		bool filterOkay = true;
-		if(mFilter != nullptr)
-		{
-			WString newText = mText;
-			newText.insert(newText.begin() + charIdx, textInClipboard.begin(), textInClipboard.end());
-
-			filterOkay = mFilter(newText);
-		}
-
-		if(filterOkay)
-		{
-			Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-			insertString(charIdx, textInClipboard);
-
-			if(textInClipboard.size() > 0)
-				gGUIManager().getInputCaretTool()->moveCaretToChar(charIdx + ((UINT32)textInClipboard.size() - 1), CARET_AFTER);
-
-			scrollTextToCaret();
-
-			Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
-			if (origSize != newSize)
-				_markLayoutAsDirty();
-			else
-				_markContentAsDirty();
-
-			if(!onValueChanged.empty())
-				onValueChanged(mText);
-		}
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsGUIInputBox.h"
+#include "BsGUIManager.h"
+#include "BsImageSprite.h"
+#include "BsGUISkin.h"
+#include "BsSpriteTexture.h"
+#include "BsTextSprite.h"
+#include "BsGUIDimensions.h"
+#include "BsGUITextInputEvent.h"
+#include "BsGUIMouseEvent.h"
+#include "BsGUICommandEvent.h"
+#include "BsGUIInputCaret.h"
+#include "BsGUIInputSelection.h"
+#include "BsGUIContextMenu.h"
+#include "BsGUIHelper.h"
+
+namespace BansheeEngine
+{
+	VirtualButton GUIInputBox::mCopyVB = VirtualButton("Copy");
+	VirtualButton GUIInputBox::mPasteVB = VirtualButton("Paste");
+	VirtualButton GUIInputBox::mCutVB = VirtualButton("Cut");
+	VirtualButton GUIInputBox::mSelectAllVB = VirtualButton("SelectAll");
+
+	const String& GUIInputBox::getGUITypeName()
+	{
+		static String name = "InputBox";
+		return name;
+	}
+
+	GUIInputBox::GUIInputBox(const String& styleName, const GUIDimensions& dimensions, bool multiline)
+		:GUIElement(styleName, dimensions), mDragInProgress(false),
+		mCaretShown(false), mSelectionShown(false), mIsMultiline(multiline), mHasFocus(false), mIsMouseOver(false),
+		mState(State::Normal)
+	{
+		mImageSprite = bs_new<ImageSprite>();
+		mTextSprite = bs_new<TextSprite>();
+	}
+
+	GUIInputBox::~GUIInputBox()
+	{
+		bs_delete(mTextSprite);
+		bs_delete(mImageSprite);
+	}
+
+	GUIInputBox* GUIInputBox::create(bool multiline, const String& styleName)
+	{
+		return new (bs_alloc<GUIInputBox>()) GUIInputBox(getStyleName<GUIInputBox>(styleName), GUIDimensions::create(), multiline);
+	}
+
+	GUIInputBox* GUIInputBox::create(bool multiline, const GUIOptions& options, const String& styleName)
+	{
+		return new (bs_alloc<GUIInputBox>()) GUIInputBox(getStyleName<GUIInputBox>(styleName), GUIDimensions::create(options), multiline);
+	}
+
+	GUIInputBox* GUIInputBox::create(const GUIOptions& options, const String& styleName)
+	{
+		return new (bs_alloc<GUIInputBox>()) GUIInputBox(getStyleName<GUIInputBox>(styleName), GUIDimensions::create(options), false);
+	}
+
+	void GUIInputBox::setText(const WString& text)
+	{
+		if (mText == text)
+			return;
+
+		bool filterOkay = true;
+		if(mFilter != nullptr)
+		{
+			filterOkay = mFilter(text);
+		}
+
+		if(filterOkay)
+		{
+			Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+
+			WString oldText = mText;
+			mText = text;
+
+			if (mHasFocus)
+			{
+				TEXT_SPRITE_DESC textDesc = getTextDesc();
+				Vector2I offset = getTextOffset();
+
+				gGUIManager().getInputCaretTool()->updateText(this, textDesc);
+				gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
+
+				if (mText.size() > 0)
+					gGUIManager().getInputCaretTool()->moveCaretToChar((UINT32)mText.size() - 1, CARET_AFTER);
+				else
+					gGUIManager().getInputCaretTool()->moveCaretToChar(0, CARET_BEFORE);
+
+				if (mSelectionShown)
+					gGUIManager().getInputSelectionTool()->selectAll();
+
+				scrollTextToCaret();
+			}
+
+			Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+			if (origSize != newSize)
+				_markLayoutAsDirty();
+			else
+				_markContentAsDirty();
+		}
+	}
+
+	UINT32 GUIInputBox::_getNumRenderElements() const
+	{
+		UINT32 numElements = mImageSprite->getNumRenderElements();
+		numElements += mTextSprite->getNumRenderElements();
+
+		if(mCaretShown && gGUIManager().getCaretBlinkState())
+			numElements += gGUIManager().getInputCaretTool()->getSprite()->getNumRenderElements();
+
+		if(mSelectionShown)
+		{
+			const Vector<ImageSprite*>& sprites = gGUIManager().getInputSelectionTool()->getSprites();
+			for(auto& selectionSprite : sprites)
+			{
+				numElements += selectionSprite->getNumRenderElements();
+			}
+		}
+
+		return numElements;
+	}
+
+	const SpriteMaterialInfo& GUIInputBox::_getMaterial(UINT32 renderElementIdx) const
+	{
+		UINT32 localRenderElementIdx;
+		Sprite* sprite = renderElemToSprite(renderElementIdx, localRenderElementIdx);
+
+		return sprite->getMaterialInfo(localRenderElementIdx);
+	}
+
+	UINT32 GUIInputBox::_getNumQuads(UINT32 renderElementIdx) const
+	{
+		UINT32 localRenderElementIdx;
+		Sprite* sprite = renderElemToSprite(renderElementIdx, localRenderElementIdx);
+
+		return sprite->getNumQuads(localRenderElementIdx);
+	}
+
+	void GUIInputBox::updateRenderElementsInternal()
+	{		
+		mImageDesc.width = mLayoutData.area.width;
+		mImageDesc.height = mLayoutData.area.height;
+		mImageDesc.borderLeft = _getStyle()->border.left;
+		mImageDesc.borderRight = _getStyle()->border.right;
+		mImageDesc.borderTop = _getStyle()->border.top;
+		mImageDesc.borderBottom = _getStyle()->border.bottom;
+		mImageDesc.color = getTint();
+
+		const HSpriteTexture& activeTex = getActiveTexture();
+		if(SpriteTexture::checkIsLoaded(activeTex))
+		{
+			mImageDesc.texture = activeTex.getInternalPtr();
+		}
+
+		mImageSprite->update(mImageDesc, (UINT64)_getParentWidget());
+
+		TEXT_SPRITE_DESC textDesc = getTextDesc();
+		mTextSprite->update(textDesc, (UINT64)_getParentWidget());
+
+		if(mCaretShown && gGUIManager().getCaretBlinkState())
+		{
+			gGUIManager().getInputCaretTool()->updateText(this, textDesc); // TODO - These shouldn't be here. Only call this when one of these parameters changes.
+			gGUIManager().getInputCaretTool()->updateSprite();
+		}
+
+		if(mSelectionShown)
+		{
+			gGUIManager().getInputSelectionTool()->updateText(this, textDesc); // TODO - These shouldn't be here. Only call this when one of these parameters changes.
+			gGUIManager().getInputSelectionTool()->updateSprite();
+		}
+
+		// When text bounds are reduced the scroll needs to be adjusted so that
+		// input box isn't filled with mostly empty space.
+		Vector2I offset(mLayoutData.area.x, mLayoutData.area.y);
+		clampScrollToBounds(mTextSprite->getBounds(offset, Rect2I()));
+
+		GUIElement::updateRenderElementsInternal();
+	}
+
+	void GUIInputBox::updateClippedBounds()
+	{
+		Vector2I offset(mLayoutData.area.x, mLayoutData.area.y);
+		mClippedBounds = mImageSprite->getBounds(offset, mLayoutData.getLocalClipRect());
+	}
+
+	Sprite* GUIInputBox::renderElemToSprite(UINT32 renderElemIdx, UINT32& localRenderElemIdx) const
+	{
+		UINT32 oldNumElements = 0;
+		UINT32 newNumElements = oldNumElements + mTextSprite->getNumRenderElements();
+		if(renderElemIdx < newNumElements)
+		{
+			localRenderElemIdx = renderElemIdx - oldNumElements;
+			return mTextSprite;
+		}
+
+		oldNumElements = newNumElements;
+		newNumElements += mImageSprite->getNumRenderElements();
+
+		if(renderElemIdx < newNumElements)
+		{
+			localRenderElemIdx = renderElemIdx - oldNumElements;
+			return mImageSprite;
+		}
+
+		if(mCaretShown && gGUIManager().getCaretBlinkState())
+		{
+			oldNumElements = newNumElements;
+			newNumElements += gGUIManager().getInputCaretTool()->getSprite()->getNumRenderElements();
+
+			if(renderElemIdx < newNumElements)
+			{
+				localRenderElemIdx = renderElemIdx - oldNumElements;
+				return gGUIManager().getInputCaretTool()->getSprite();
+			}
+		}
+
+		if(mSelectionShown)
+		{
+			const Vector<ImageSprite*>& sprites = gGUIManager().getInputSelectionTool()->getSprites();
+			for(auto& selectionSprite : sprites)
+			{
+				oldNumElements = newNumElements;
+				newNumElements += selectionSprite->getNumRenderElements();
+
+				if(renderElemIdx < newNumElements)
+				{
+					localRenderElemIdx = renderElemIdx - oldNumElements;
+					return selectionSprite;
+				}
+			}
+		}
+
+		localRenderElemIdx = renderElemIdx;
+		return nullptr;
+	}
+
+	Vector2I GUIInputBox::renderElemToOffset(UINT32 renderElemIdx) const
+	{
+		UINT32 oldNumElements = 0;
+		UINT32 newNumElements = oldNumElements + mTextSprite->getNumRenderElements();
+		if(renderElemIdx < newNumElements)
+			return getTextOffset();
+
+		oldNumElements = newNumElements;
+		newNumElements += mImageSprite->getNumRenderElements();
+
+		if(renderElemIdx < newNumElements)
+			return Vector2I(mLayoutData.area.x, mLayoutData.area.y);;
+
+		if(mCaretShown && gGUIManager().getCaretBlinkState())
+		{
+			oldNumElements = newNumElements;
+			newNumElements += gGUIManager().getInputCaretTool()->getSprite()->getNumRenderElements();
+
+			if(renderElemIdx < newNumElements)
+				return gGUIManager().getInputCaretTool()->getSpriteOffset();
+		}
+
+		if(mSelectionShown)
+		{
+			UINT32 spriteIdx = 0;
+			const Vector<ImageSprite*>& sprites = gGUIManager().getInputSelectionTool()->getSprites();
+			for(auto& selectionSprite : sprites)
+			{
+				oldNumElements = newNumElements;
+				newNumElements += selectionSprite->getNumRenderElements();
+
+				if(renderElemIdx < newNumElements)
+					return gGUIManager().getInputSelectionTool()->getSelectionSpriteOffset(spriteIdx);
+
+				spriteIdx++;
+			}
+		}
+
+		return Vector2I();
+	}
+
+	Rect2I GUIInputBox::renderElemToClipRect(UINT32 renderElemIdx) const
+	{
+		UINT32 oldNumElements = 0;
+		UINT32 newNumElements = oldNumElements + mTextSprite->getNumRenderElements();
+		if(renderElemIdx < newNumElements)
+			return getTextClipRect();
+
+		oldNumElements = newNumElements;
+		newNumElements += mImageSprite->getNumRenderElements();
+
+		if(renderElemIdx < newNumElements)
+			return mLayoutData.getLocalClipRect();
+
+		if(mCaretShown && gGUIManager().getCaretBlinkState())
+		{
+			oldNumElements = newNumElements;
+			newNumElements += gGUIManager().getInputCaretTool()->getSprite()->getNumRenderElements();
+
+			if(renderElemIdx < newNumElements)
+			{
+				return gGUIManager().getInputCaretTool()->getSpriteClipRect(getTextClipRect());
+			}
+		}
+
+		if(mSelectionShown)
+		{
+			UINT32 spriteIdx = 0;
+			const Vector<ImageSprite*>& sprites = gGUIManager().getInputSelectionTool()->getSprites();
+			for(auto& selectionSprite : sprites)
+			{
+				oldNumElements = newNumElements;
+				newNumElements += selectionSprite->getNumRenderElements();
+
+				if(renderElemIdx < newNumElements)
+					return gGUIManager().getInputSelectionTool()->getSelectionSpriteClipRect(spriteIdx, getTextClipRect());
+
+				spriteIdx++;
+			}
+		}
+
+		return Rect2I();
+	}
+
+	Vector2I GUIInputBox::_getOptimalSize() const
+	{
+		UINT32 imageWidth = 0;
+		UINT32 imageHeight = 0;
+
+		const HSpriteTexture& activeTex = getActiveTexture();
+		if(SpriteTexture::checkIsLoaded(activeTex))
+		{
+			imageWidth = activeTex->getWidth();
+			imageHeight = activeTex->getHeight();
+		}
+
+		Vector2I contentSize = GUIHelper::calcOptimalContentsSize(mText, *_getStyle(), _getDimensions());
+		UINT32 contentWidth = std::max(imageWidth, (UINT32)contentSize.x);
+		UINT32 contentHeight = std::max(imageHeight, (UINT32)contentSize.y);
+
+		return Vector2I(contentWidth, contentHeight);
+	}
+
+	Vector2I GUIInputBox::_getTextInputOffset() const
+	{
+		return mTextOffset;	
+	}
+
+	Rect2I GUIInputBox::_getTextInputRect() const
+	{
+		Rect2I textBounds = getCachedContentBounds();
+		textBounds.x -= mLayoutData.area.x;
+		textBounds.y -= mLayoutData.area.y;
+
+		return textBounds;
+	}
+
+	UINT32 GUIInputBox::_getRenderElementDepth(UINT32 renderElementIdx) const
+	{
+		UINT32 localRenderElementIdx;
+		Sprite* sprite = renderElemToSprite(renderElementIdx, localRenderElementIdx);
+
+		if(sprite == mImageSprite)
+			return _getDepth() + 3;
+		else if(sprite == mTextSprite)
+			return _getDepth() + 1;
+		else if(sprite == gGUIManager().getInputCaretTool()->getSprite())
+			return _getDepth();
+		else // Selection sprites
+			return _getDepth() + 2;
+	}
+
+	UINT32 GUIInputBox::_getRenderElementDepthRange() const
+	{
+		return 4;
+	}
+
+	bool GUIInputBox::_hasCustomCursor(const Vector2I position, CursorType& type) const
+	{
+		if(_isInBounds(position) && !_isDisabled())
+		{
+			type = CursorType::IBeam;
+			return true;
+		}
+
+		return false;
+	}
+
+	void GUIInputBox::_fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, UINT32 maxNumQuads, 
+		UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const
+	{
+		UINT32 localRenderElementIdx;
+		Sprite* sprite = renderElemToSprite(renderElementIdx, localRenderElementIdx);
+		Vector2I offset = renderElemToOffset(renderElementIdx);
+		Rect2I clipRect = renderElemToClipRect(renderElementIdx);
+
+		sprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, vertexStride, indexStride, localRenderElementIdx, offset, clipRect);
+	}
+
+	bool GUIInputBox::_mouseEvent(const GUIMouseEvent& ev)
+	{
+		if(ev.getType() == GUIMouseEventType::MouseOver)
+		{
+			if (!_isDisabled())
+			{
+				if (!mHasFocus)
+				{
+					Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+					mState = State::Hover;
+					Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+
+					if (origSize != newSize)
+						_markLayoutAsDirty();
+					else
+						_markContentAsDirty();
+				}
+
+				mIsMouseOver = true;
+			}
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseOut)
+		{
+			if (!_isDisabled())
+			{
+				if (!mHasFocus)
+				{
+					Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+					mState = State::Normal;
+					Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+
+					if (origSize != newSize)
+						_markLayoutAsDirty();
+					else
+						_markContentAsDirty();
+				}
+
+				mIsMouseOver = false;
+			}
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDoubleClick && ev.getButton() == GUIMouseButton::Left)
+		{
+			if (!_isDisabled())
+			{
+				showSelection(0);
+				gGUIManager().getInputSelectionTool()->selectAll();
+
+				_markContentAsDirty();
+			}
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDown && ev.getButton() == GUIMouseButton::Left)
+		{
+			if (!_isDisabled())
+			{
+				if (ev.isShiftDown())
+				{
+					if (!mSelectionShown)
+						showSelection(gGUIManager().getInputCaretTool()->getCaretPos());
+				}
+				else
+				{
+					clearSelection();
+					showCaret();
+				}
+
+				if (mText.size() > 0)
+					gGUIManager().getInputCaretTool()->moveCaretToPos(ev.getPosition());
+				else
+					gGUIManager().getInputCaretTool()->moveCaretToStart();
+
+				if (ev.isShiftDown())
+					gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
+
+				scrollTextToCaret();
+				_markContentAsDirty();
+			}
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDragStart)
+		{
+			if (!_isDisabled())
+			{
+				if (!ev.isShiftDown())
+				{
+					mDragInProgress = true;
+
+					UINT32 caretPos = gGUIManager().getInputCaretTool()->getCaretPos();
+					showSelection(caretPos);
+					gGUIManager().getInputSelectionTool()->selectionDragStart(caretPos);
+					_markContentAsDirty();
+
+					return true;
+				}
+			}
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDragEnd)
+		{
+			if (!_isDisabled())
+			{
+				if (!ev.isShiftDown())
+				{
+					mDragInProgress = false;
+
+					gGUIManager().getInputSelectionTool()->selectionDragEnd();
+					_markContentAsDirty();
+					return true;
+				}
+			}
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDrag)
+		{
+			if (!_isDisabled())
+			{
+				if (!ev.isShiftDown())
+				{
+					if (mText.size() > 0)
+						gGUIManager().getInputCaretTool()->moveCaretToPos(ev.getPosition());
+					else
+						gGUIManager().getInputCaretTool()->moveCaretToStart();
+
+					gGUIManager().getInputSelectionTool()->selectionDragUpdate(gGUIManager().getInputCaretTool()->getCaretPos());
+
+					scrollTextToCaret();
+					_markContentAsDirty();
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
+
+	bool GUIInputBox::_textInputEvent(const GUITextInputEvent& ev)
+	{
+		if (_isDisabled())
+			return false;
+
+		Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+
+		if(mSelectionShown)
+			deleteSelectedText(true);
+
+		UINT32 charIdx = gGUIManager().getInputCaretTool()->getCharIdxAtCaretPos();
+
+		bool filterOkay = true;
+		if(mFilter != nullptr)
+		{
+			WString newText = mText;
+			newText.insert(newText.begin() + charIdx, ev.getInputChar());
+
+			filterOkay = mFilter(newText);
+		}
+
+		if(filterOkay)
+		{
+			insertChar(charIdx, ev.getInputChar());
+
+			gGUIManager().getInputCaretTool()->moveCaretToChar(charIdx, CARET_AFTER);
+			scrollTextToCaret();
+
+			if(!onValueChanged.empty())
+				onValueChanged(mText);
+		}
+
+		Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+		if (origSize != newSize)
+			_markLayoutAsDirty();
+		else
+			_markContentAsDirty();
+
+		return true;
+	}
+
+	bool GUIInputBox::_commandEvent(const GUICommandEvent& ev)
+	{
+		if (_isDisabled())
+			return false;
+
+		bool baseReturn = GUIElement::_commandEvent(ev);
+
+		if(ev.getType() == GUICommandEventType::Redraw)
+		{
+			_markContentAsDirty();
+			return true;
+		}
+
+		if(ev.getType() == GUICommandEventType::FocusGained)
+		{
+			Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+			mState = State::Focused;
+
+			showSelection(0);
+			gGUIManager().getInputSelectionTool()->selectAll();
+
+			mHasFocus = true;
+
+			Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+			if (origSize != newSize)
+				_markLayoutAsDirty();
+			else
+				_markContentAsDirty();
+
+			return true;
+		}
+		
+		if(ev.getType() == GUICommandEventType::FocusLost)
+		{
+			Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+			mState = State::Normal;
+
+			hideCaret();
+			clearSelection();
+
+			mHasFocus = false;
+
+			Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+			if (origSize != newSize)
+				_markLayoutAsDirty();
+			else
+				_markContentAsDirty();
+
+			return true;
+		}
+		
+		if(ev.getType() == GUICommandEventType::Backspace)
+		{
+			if(mText.size() > 0)
+			{
+				Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+				if(mSelectionShown)
+				{
+					deleteSelectedText();
+				}
+				else
+				{
+					UINT32 charIdx = gGUIManager().getInputCaretTool()->getCharIdxAtCaretPos() - 1;
+
+					if(charIdx < (UINT32)mText.size())
+					{
+						bool filterOkay = true;
+						if(mFilter != nullptr)
+						{
+							WString newText = mText;
+							newText.erase(charIdx, 1);
+
+							filterOkay = mFilter(newText);
+						}
+
+						if(filterOkay)
+						{
+							eraseChar(charIdx);
+
+							if (charIdx > 0)
+							{
+								charIdx--;
+
+								gGUIManager().getInputCaretTool()->moveCaretToChar(charIdx, CARET_AFTER);
+							}
+							else
+								gGUIManager().getInputCaretTool()->moveCaretToChar(charIdx, CARET_BEFORE);
+
+							scrollTextToCaret();
+
+							if(!onValueChanged.empty())
+								onValueChanged(mText);
+						}
+					}
+				}
+
+				Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+				if (origSize != newSize)
+					_markLayoutAsDirty();
+				else
+					_markContentAsDirty();
+			}
+
+			return true;
+		}
+
+		if(ev.getType() == GUICommandEventType::Delete)
+		{
+			if(mText.size() > 0)
+			{
+				Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+				if(mSelectionShown)
+				{
+					deleteSelectedText();
+				}
+				else
+				{
+					UINT32 charIdx = gGUIManager().getInputCaretTool()->getCharIdxAtCaretPos();
+					if(charIdx < (UINT32)mText.size())
+					{
+						bool filterOkay = true;
+						if(mFilter != nullptr)
+						{
+							WString newText = mText;
+							newText.erase(charIdx, 1);
+
+							filterOkay = mFilter(newText);
+						}
+
+						if(filterOkay)
+						{
+							eraseChar(charIdx);
+
+							if(charIdx > 0)
+								charIdx--;
+
+							gGUIManager().getInputCaretTool()->moveCaretToChar(charIdx, CARET_AFTER);
+
+							scrollTextToCaret();
+
+							if(!onValueChanged.empty())
+								onValueChanged(mText);
+						}
+					}
+				}
+
+				Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+				if (origSize != newSize)
+					_markLayoutAsDirty();
+				else
+					_markContentAsDirty();
+			}
+
+			return true;
+		}
+
+		if(ev.getType() == GUICommandEventType::MoveLeft)
+		{
+			if(mSelectionShown)
+			{
+				UINT32 selStart = gGUIManager().getInputSelectionTool()->getSelectionStart();
+				clearSelection();
+
+				if (!mCaretShown)
+					showCaret();
+
+				if(selStart > 0)
+					gGUIManager().getInputCaretTool()->moveCaretToChar(selStart - 1, CARET_AFTER);
+				else
+					gGUIManager().getInputCaretTool()->moveCaretToChar(0, CARET_BEFORE);
+			}
+			else
+				gGUIManager().getInputCaretTool()->moveCaretLeft();
+
+			scrollTextToCaret();
+			_markContentAsDirty();
+			return true;
+		}
+
+		if(ev.getType() == GUICommandEventType::SelectLeft)
+		{
+			if(!mSelectionShown)
+				showSelection(gGUIManager().getInputCaretTool()->getCaretPos());
+
+			gGUIManager().getInputCaretTool()->moveCaretLeft();
+			gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
+
+			scrollTextToCaret();
+			_markContentAsDirty();
+			return true;
+		}
+
+		if(ev.getType() == GUICommandEventType::MoveRight)
+		{
+			if(mSelectionShown)
+			{
+				UINT32 selEnd = gGUIManager().getInputSelectionTool()->getSelectionEnd();
+				clearSelection();
+
+				if (!mCaretShown)
+					showCaret();
+
+				if(selEnd > 0)
+					gGUIManager().getInputCaretTool()->moveCaretToChar(selEnd - 1, CARET_AFTER);
+				else
+					gGUIManager().getInputCaretTool()->moveCaretToChar(0, CARET_BEFORE);
+			}
+			else
+				gGUIManager().getInputCaretTool()->moveCaretRight();
+
+			scrollTextToCaret();
+			_markContentAsDirty();
+			return true;
+		}
+
+		if(ev.getType() == GUICommandEventType::SelectRight)
+		{
+			if(!mSelectionShown)
+				showSelection(gGUIManager().getInputCaretTool()->getCaretPos());
+
+			gGUIManager().getInputCaretTool()->moveCaretRight();
+			gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
+
+			scrollTextToCaret();
+			_markContentAsDirty();
+			return true;
+		}
+
+		if(ev.getType() == GUICommandEventType::MoveUp)
+		{
+			if (mSelectionShown)
+				clearSelection();
+
+			if (!mCaretShown)
+				showCaret();
+
+			gGUIManager().getInputCaretTool()->moveCaretUp();
+
+			scrollTextToCaret();
+			_markContentAsDirty();
+			return true;
+		}
+
+		if(ev.getType() == GUICommandEventType::SelectUp)
+		{
+			if(!mSelectionShown)
+				showSelection(gGUIManager().getInputCaretTool()->getCaretPos());;
+
+			gGUIManager().getInputCaretTool()->moveCaretUp();
+			gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
+
+			scrollTextToCaret();
+			_markContentAsDirty();
+			return true;
+		}
+
+		if(ev.getType() == GUICommandEventType::MoveDown)
+		{
+			if (mSelectionShown)
+				clearSelection();
+
+			if (!mCaretShown)
+				showCaret();
+
+			gGUIManager().getInputCaretTool()->moveCaretDown();
+
+			scrollTextToCaret();
+			_markContentAsDirty();
+			return true;
+		}
+
+		if(ev.getType() == GUICommandEventType::SelectDown)
+		{
+			if(!mSelectionShown)
+				showSelection(gGUIManager().getInputCaretTool()->getCaretPos());
+
+			gGUIManager().getInputCaretTool()->moveCaretDown();
+			gGUIManager().getInputSelectionTool()->moveSelectionToCaret(gGUIManager().getInputCaretTool()->getCaretPos());
+
+			scrollTextToCaret();
+			_markContentAsDirty();
+			return true;
+		}
+
+		if(ev.getType() == GUICommandEventType::Return)
+		{
+			if (mIsMultiline)
+			{
+				Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+
+				if (mSelectionShown)
+					deleteSelectedText();
+
+				UINT32 charIdx = gGUIManager().getInputCaretTool()->getCharIdxAtCaretPos();
+
+				bool filterOkay = true;
+				if (mFilter != nullptr)
+				{
+					WString newText = mText;
+					newText.insert(newText.begin() + charIdx, '\n');
+
+					filterOkay = mFilter(newText);
+				}
+
+				if (filterOkay)
+				{
+					insertChar(charIdx, '\n');
+
+					gGUIManager().getInputCaretTool()->moveCaretRight();
+					scrollTextToCaret();
+
+					if (!onValueChanged.empty())
+						onValueChanged(mText);
+				}
+
+				Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+				if (origSize != newSize)
+					_markLayoutAsDirty();
+				else
+					_markContentAsDirty();
+
+				return true;
+			}
+		}
+
+		if (ev.getType() == GUICommandEventType::Confirm)
+		{
+			onConfirm();
+			return true;
+		}
+
+		return baseReturn;
+	}
+
+	bool GUIInputBox::_virtualButtonEvent(const GUIVirtualButtonEvent& ev)
+	{
+		if (_isDisabled())
+			return false;
+
+		if(ev.getButton() == mCutVB)
+		{
+			cutText();
+
+			return true;
+		}
+		else if(ev.getButton() == mCopyVB)
+		{
+			copyText();
+
+			return true;
+		}
+		else if(ev.getButton() == mPasteVB)
+		{
+			pasteText();
+			return true;
+		}
+		else if(ev.getButton() == mSelectAllVB)
+		{
+			showSelection(0);
+			gGUIManager().getInputSelectionTool()->selectAll();
+			_markContentAsDirty();
+
+			return true;
+		}
+
+		return false;
+	}
+
+	void GUIInputBox::showCaret()
+	{
+		mCaretShown = true;
+
+		TEXT_SPRITE_DESC textDesc = getTextDesc();
+		Vector2I offset = getTextOffset();
+		gGUIManager().getInputCaretTool()->updateText(this, textDesc);
+	}
+
+	void GUIInputBox::hideCaret()
+	{
+		mCaretShown = false;
+	}
+
+	void GUIInputBox::showSelection(UINT32 anchorCaretPos)
+	{
+		TEXT_SPRITE_DESC textDesc = getTextDesc();
+		Vector2I offset = getTextOffset();
+		gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
+
+		gGUIManager().getInputSelectionTool()->showSelection(anchorCaretPos);
+		mSelectionShown = true;
+	}
+
+	void GUIInputBox::clearSelection()
+	{
+		gGUIManager().getInputSelectionTool()->clearSelection();
+		mSelectionShown = false;
+	}
+
+	void GUIInputBox::scrollTextToCaret()
+	{
+		TEXT_SPRITE_DESC textDesc = getTextDesc();
+
+		Vector2I textOffset = getTextOffset();
+		Vector2I caretPos = gGUIManager().getInputCaretTool()->getCaretPosition(textOffset);
+		UINT32 caretHeight = gGUIManager().getInputCaretTool()->getCaretHeight();
+		UINT32 caretWidth = 1;
+
+		INT32 left = textOffset.x - mTextOffset.x;
+		// Include caret width here because we don't want to scroll if just the caret is outside the bounds
+		// (Possible if the text width is exactly the maximum width)
+		INT32 right = left + (INT32)textDesc.width + caretWidth; 
+		INT32 top = textOffset.y - mTextOffset.y;
+		INT32 bottom = top + (INT32)textDesc.height;
+
+		// If caret is too high to display we don't want the offset to keep adjusting itself
+		caretHeight = std::min(caretHeight, (UINT32)(bottom - top));
+		INT32 caretRight = caretPos.x + (INT32)caretWidth;
+		INT32 caretBottom = caretPos.y + (INT32)caretHeight;
+
+		Vector2I offset;
+		if(caretPos.x < left)
+		{
+			offset.x = left - caretPos.x;
+		}
+		else if(caretRight > right)
+		{
+			offset.x = -(caretRight - right);
+		}
+
+		if(caretPos.y < top)
+		{
+			offset.y = top - caretPos.y;
+		}
+		else if(caretBottom > bottom)
+		{
+			offset.y = -(caretBottom - bottom);
+		}
+
+		mTextOffset += offset;
+
+		gGUIManager().getInputCaretTool()->updateText(this, textDesc);
+		gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
+	}
+
+	void GUIInputBox::clampScrollToBounds(Rect2I unclippedTextBounds)
+	{
+		Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+		TEXT_SPRITE_DESC textDesc = getTextDesc();
+
+		Vector2I newTextOffset;
+		INT32 maxScrollableWidth = std::max(0, (INT32)unclippedTextBounds.width - (INT32)textDesc.width);
+		INT32 maxScrollableHeight = std::max(0, (INT32)unclippedTextBounds.height - (INT32)textDesc.height);
+		newTextOffset.x = Math::clamp(mTextOffset.x, -maxScrollableWidth, 0);
+		newTextOffset.y = Math::clamp(mTextOffset.y, -maxScrollableHeight, 0);
+
+		if(newTextOffset != mTextOffset)
+		{
+			mTextOffset = newTextOffset;
+
+			gGUIManager().getInputCaretTool()->updateText(this, textDesc);
+			gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
+		}
+	}
+
+	void GUIInputBox::insertString(UINT32 charIdx, const WString& string)
+	{
+		mText.insert(mText.begin() + charIdx, string.begin(), string.end());
+
+		TEXT_SPRITE_DESC textDesc = getTextDesc();
+		Vector2I offset = getTextOffset();
+
+		gGUIManager().getInputCaretTool()->updateText(this, textDesc);
+		gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
+	}
+
+	void GUIInputBox::insertChar(UINT32 charIdx, UINT32 charCode)
+	{
+		mText.insert(mText.begin() + charIdx, charCode);
+
+		TEXT_SPRITE_DESC textDesc = getTextDesc();
+		Vector2I offset = getTextOffset();
+
+		gGUIManager().getInputCaretTool()->updateText(this, textDesc);
+		gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
+	}
+
+	void GUIInputBox::eraseChar(UINT32 charIdx)
+	{
+		mText.erase(charIdx, 1);
+
+		TEXT_SPRITE_DESC textDesc = getTextDesc();
+		Vector2I offset = getTextOffset();
+
+		gGUIManager().getInputCaretTool()->updateText(this, textDesc);
+		gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
+	}
+
+	void GUIInputBox::deleteSelectedText(bool internal)
+	{
+		UINT32 selStart = gGUIManager().getInputSelectionTool()->getSelectionStart();
+		UINT32 selEnd = gGUIManager().getInputSelectionTool()->getSelectionEnd();
+
+		bool filterOkay = true;
+		if (!internal && mFilter != nullptr)
+		{
+			WString newText = mText;
+			newText.erase(newText.begin() + selStart, newText.begin() + selEnd);
+
+			filterOkay = mFilter(newText);
+		}
+
+		if (!mCaretShown)
+			showCaret();
+
+		if(filterOkay)
+		{
+			mText.erase(mText.begin() + selStart, mText.begin() + selEnd);
+
+			TEXT_SPRITE_DESC textDesc = getTextDesc();
+			Vector2I offset = getTextOffset();
+			gGUIManager().getInputCaretTool()->updateText(this, textDesc);
+			gGUIManager().getInputSelectionTool()->updateText(this, textDesc);
+
+			if(selStart > 0)
+			{
+				UINT32 newCaretPos = selStart - 1;
+				gGUIManager().getInputCaretTool()->moveCaretToChar(newCaretPos, CARET_AFTER);
+			}
+			else
+			{
+				gGUIManager().getInputCaretTool()->moveCaretToChar(0, CARET_BEFORE);
+			}
+
+			scrollTextToCaret();
+
+			if (!internal)
+				onValueChanged(mText);
+		}
+
+		clearSelection();
+	}
+
+	WString GUIInputBox::getSelectedText()
+	{
+		UINT32 selStart = gGUIManager().getInputSelectionTool()->getSelectionStart();
+		UINT32 selEnd = gGUIManager().getInputSelectionTool()->getSelectionEnd();
+
+		return mText.substr(selStart, selEnd - selStart);
+
+		mText.erase(mText.begin() + selStart, mText.begin() + gGUIManager().getInputSelectionTool()->getSelectionEnd());
+	}
+
+	Vector2I GUIInputBox::getTextOffset() const
+	{
+		Rect2I textBounds = getCachedContentBounds();
+		return Vector2I(textBounds.x, textBounds.y) + mTextOffset;
+	}
+
+	Rect2I GUIInputBox::getTextClipRect() const
+	{
+		Rect2I contentClipRect = getCachedContentClipRect();
+		return Rect2I(contentClipRect.x - mTextOffset.x, contentClipRect.y - mTextOffset.y, contentClipRect.width, contentClipRect.height);
+	}
+
+	TEXT_SPRITE_DESC GUIInputBox::getTextDesc() const
+	{
+		TEXT_SPRITE_DESC textDesc;
+		textDesc.text = mText;
+		textDesc.font = _getStyle()->font;
+		textDesc.fontSize = _getStyle()->fontSize;
+		textDesc.color = getTint() * getActiveTextColor();
+
+		Rect2I textBounds = getCachedContentBounds();
+		textDesc.width = textBounds.width;
+		textDesc.height = textBounds.height;
+		textDesc.horzAlign = _getStyle()->textHorzAlign;
+		textDesc.vertAlign = _getStyle()->textVertAlign;
+		textDesc.wordWrap = mIsMultiline;
+
+		return textDesc;
+	}
+
+	const HSpriteTexture& GUIInputBox::getActiveTexture() const
+	{
+		switch(mState)
+		{
+		case State::Focused:
+			return _getStyle()->focused.texture;
+		case State::Hover:
+			return _getStyle()->hover.texture;
+		case State::Normal:
+			return _getStyle()->normal.texture;
+		}
+
+		return _getStyle()->normal.texture;
+	}
+
+	Color GUIInputBox::getActiveTextColor() const
+	{
+		switch (mState)
+		{
+		case State::Focused:
+			return _getStyle()->focused.textColor;
+		case State::Hover:
+			return _getStyle()->hover.textColor;
+		case State::Normal:
+			return _getStyle()->normal.textColor;
+		}
+
+		return _getStyle()->normal.textColor;
+	}
+
+	GUIContextMenuPtr GUIInputBox::_getContextMenu() const
+	{
+		static GUIContextMenuPtr contextMenu;
+
+		if (contextMenu == nullptr)
+		{
+			contextMenu = bs_shared_ptr_new<GUIContextMenu>();
+
+			contextMenu->addMenuItem(L"Cut", std::bind(&GUIInputBox::cutText, const_cast<GUIInputBox*>(this)), 0);
+			contextMenu->addMenuItem(L"Copy", std::bind(&GUIInputBox::copyText, const_cast<GUIInputBox*>(this)), 0);
+			contextMenu->addMenuItem(L"Paste", std::bind(&GUIInputBox::pasteText, const_cast<GUIInputBox*>(this)), 0);
+
+			contextMenu->setLocalizedName(L"Cut", HString(L"Cut"));
+			contextMenu->setLocalizedName(L"Copy", HString(L"Copy"));
+			contextMenu->setLocalizedName(L"Paste", HString(L"Paste"));
+		}
+
+		if (!_isDisabled())
+			return contextMenu;
+
+		return nullptr;
+	}
+
+	void GUIInputBox::cutText()
+	{
+		Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+
+		copyText();
+		deleteSelectedText();
+
+		Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+		if (origSize != newSize)
+			_markLayoutAsDirty();
+		else
+			_markContentAsDirty();
+	}
+
+	void GUIInputBox::copyText()
+	{
+		PlatformUtility::copyToClipboard(getSelectedText());
+	}
+
+	void GUIInputBox::pasteText()
+	{
+		if (mSelectionShown)
+			deleteSelectedText(true);
+
+		WString textInClipboard = PlatformUtility::copyFromClipboard();
+		UINT32 charIdx = gGUIManager().getInputCaretTool()->getCharIdxAtCaretPos();
+
+		bool filterOkay = true;
+		if(mFilter != nullptr)
+		{
+			WString newText = mText;
+			newText.insert(newText.begin() + charIdx, textInClipboard.begin(), textInClipboard.end());
+
+			filterOkay = mFilter(newText);
+		}
+
+		if(filterOkay)
+		{
+			Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+			insertString(charIdx, textInClipboard);
+
+			if(textInClipboard.size() > 0)
+				gGUIManager().getInputCaretTool()->moveCaretToChar(charIdx + ((UINT32)textInClipboard.size() - 1), CARET_AFTER);
+
+			scrollTextToCaret();
+
+			Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
+			if (origSize != newSize)
+				_markLayoutAsDirty();
+			else
+				_markContentAsDirty();
+
+			if(!onValueChanged.empty())
+				onValueChanged(mText);
+		}
+	}
 }

+ 312 - 312
Source/BansheeEngine/Source/BsGUIInputTool.cpp

@@ -1,313 +1,313 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsGUIInputTool.h"
-#include "BsGUIElement.h"
-#include "BsMath.h"
-#include "BsVector2.h"
-#include "BsFont.h"
-
-namespace BansheeEngine
-{
-	GUIInputTool::GUIInputTool()
-		:mQuads(nullptr), mNumQuads(0), mElement(nullptr)
-	{ }
-
-	GUIInputTool::~GUIInputTool()
-	{ }
-
-	void GUIInputTool::updateText(const GUIElement* element, const TEXT_SPRITE_DESC& textDesc)
-	{
-		mElement = element;
-		mTextDesc = textDesc;
-
-		mLineDescs.clear();
-
-		bs_frame_mark();
-		{
-			TextData<FrameAlloc> textData(mTextDesc.text, mTextDesc.font, mTextDesc.fontSize,
-				mTextDesc.width, mTextDesc.height, mTextDesc.wordWrap, mTextDesc.wordBreak);
-
-			UINT32 numLines = textData.getNumLines();
-			UINT32 numPages = textData.getNumPages();
-
-			mNumQuads = 0;
-			for (UINT32 i = 0; i < numPages; i++)
-				mNumQuads += textData.getNumQuadsForPage(i);
-
-			if (mQuads != nullptr)
-				bs_delete(mQuads);
-
-			mQuads = bs_newN<Vector2>(mNumQuads * 4);
-
-			TextSprite::genTextQuads(textData, mTextDesc.width, mTextDesc.height, mTextDesc.horzAlign, mTextDesc.vertAlign, mTextDesc.anchor,
-				mQuads, nullptr, nullptr, mNumQuads);
-
-			UINT32 numVerts = mNumQuads * 4;
-
-			// Store cached line data
-			UINT32 curCharIdx = 0;
-			UINT32 curLineIdx = 0;
-
-			Vector2I* alignmentOffsets = bs_frame_new<Vector2I>(numLines);
-			TextSprite::getAlignmentOffsets(textData, mTextDesc.width, mTextDesc.height, mTextDesc.horzAlign, 
-				mTextDesc.vertAlign, alignmentOffsets);
-
-			for (UINT32 i = 0; i < numLines; i++)
-			{
-				const TextDataBase::TextLine& line = textData.getLine(i);
-
-				// Line has a newline char only if it wasn't created by word wrap and it isn't the last line
-				bool hasNewline = line.hasNewlineChar() && (curLineIdx != (numLines - 1));
-
-				UINT32 startChar = curCharIdx;
-				UINT32 endChar = curCharIdx + line.getNumChars() + (hasNewline ? 1 : 0);
-				UINT32 lineHeight = line.getYOffset();
-				INT32 lineYStart = alignmentOffsets[curLineIdx].y;
-
-				GUIInputLineDesc lineDesc(startChar, endChar, lineHeight, lineYStart, hasNewline);
-				mLineDescs.push_back(lineDesc);
-
-				curCharIdx = lineDesc.getEndChar();
-				curLineIdx++;
-			}
-
-			bs_frame_delete(alignmentOffsets);
-		}
-		bs_frame_clear();
-	}
-
-	Vector2I GUIInputTool::getTextOffset() const
-	{
-		Vector2I offset(mElement->_getLayoutData().area.x, mElement->_getLayoutData().area.y);
-
-		return offset + mElement->_getTextInputOffset() + Vector2I(mElement->_getTextInputRect().x, mElement->_getTextInputRect().y);
-	}
-
-	Rect2I GUIInputTool::getCharRect(UINT32 charIdx) const
-	{
-		Rect2I charRect = getLocalCharRect(charIdx);
-		Vector2I textOffset = getTextOffset();
-
-		charRect.x += textOffset.x;
-		charRect.y += textOffset.y;
-
-		return charRect;
-	}
-
-	Rect2I GUIInputTool::getLocalCharRect(UINT32 charIdx) const
-	{
-		UINT32 lineIdx = getLineForChar(charIdx);
-
-		// If char is newline we don't have any geometry to return
-		const GUIInputLineDesc& lineDesc = getLineDesc(lineIdx);
-		if(lineDesc.isNewline(charIdx))
-			return Rect2I();
-
-		UINT32 numNewlineChars = 0;
-		for(UINT32 i = 0; i < lineIdx; i++)
-			numNewlineChars += (getLineDesc(i).hasNewlineChar() ? 1 : 0);
-
-		UINT32 quadIdx = charIdx - numNewlineChars;
-		if(quadIdx >= 0 && quadIdx < mNumQuads)
-		{
-			UINT32 vertIdx = quadIdx * 4;
-
-			Rect2I charRect;
-			charRect.x = Math::roundToInt(mQuads[vertIdx + 0].x);
-			charRect.y = Math::roundToInt(mQuads[vertIdx + 0].y);
-			charRect.width = Math::roundToInt(mQuads[vertIdx + 3].x - charRect.x);
-			charRect.height = Math::roundToInt(mQuads[vertIdx + 3].y - charRect.y);
-
-			return charRect;
-		}
-
-		BS_EXCEPT(InternalErrorException, "Invalid character index: " + toString(charIdx));
-		return Rect2I();
-	}
-
-	INT32 GUIInputTool::getCharIdxAtPos(const Vector2I& pos) const
-	{
-		Vector2 vecPos((float)pos.x, (float)pos.y);
-
-		UINT32 lineStartChar = 0;
-		UINT32 lineEndChar = 0;
-		UINT32 numNewlineChars = 0;
-		UINT32 lineIdx = 0;
-		for(auto& line : mLineDescs)
-		{
-			INT32 lineStart = line.getLineYStart() + getTextOffset().y;
-			if(pos.y >= lineStart && pos.y < (lineStart + (INT32)line.getLineHeight()))
-			{
-				lineStartChar = line.getStartChar();
-				lineEndChar = line.getEndChar(false);
-				break;
-			}
-
-			// Newline chars count in the startChar/endChar variables, but don't actually exist in the buffers
-			// so we need to filter them out
-			numNewlineChars += (line.hasNewlineChar() ? 1 : 0); 
-
-			lineIdx++;
-		}
-
-		UINT32 lineStartQuad = lineStartChar - numNewlineChars;
-		UINT32 lineEndQuad = lineEndChar - numNewlineChars;
-
-		float nearestDist = std::numeric_limits<float>::max();
-		UINT32 nearestChar = 0;
-		bool foundChar = false;
-
-		Vector2I textOffset = getTextOffset();
-		for(UINT32 i = lineStartQuad; i < lineEndQuad; i++)
-		{
-			UINT32 curVert = i * 4;
-
-			float centerX = mQuads[curVert + 0].x + mQuads[curVert + 1].x;
-			centerX *= 0.5f;
-			centerX += textOffset.x;
-
-			float dist = Math::abs(centerX - vecPos.x);
-			if(dist < nearestDist)
-			{
-				nearestChar = i + numNewlineChars;
-				nearestDist = dist;
-				foundChar = true;
-			}
-		}
-
-		if(!foundChar)
-			return -1;
-
-		return nearestChar;
-	}
-
-	UINT32 GUIInputTool::getLineForChar(UINT32 charIdx, bool newlineCountsOnNextLine) const
-	{
-		UINT32 idx = 0;
-		for(auto& line : mLineDescs)
-		{
-			if((charIdx >= line.getStartChar() && charIdx < line.getEndChar()) || 
-				(charIdx == line.getStartChar() && line.getStartChar() == line.getEndChar()))
-			{
-				if(line.isNewline(charIdx) && newlineCountsOnNextLine)
-					return idx + 1; // Incrementing is safe because next line must exist, since we just found a newline char
-
-				return idx;
-			}
-
-			idx++;
-		}
-
-		BS_EXCEPT(InternalErrorException, "Invalid character index: " + toString(charIdx));
-		return 0;
-	}
-
-	UINT32 GUIInputTool::getCharIdxAtInputIdx(UINT32 inputIdx) const
-	{
-		if(mTextDesc.text.size() == 0)
-			return 0;
-
-		UINT32 numLines = getNumLines();
-		UINT32 curPos = 0;
-		UINT32 curCharIdx = 0;
-		for(UINT32 i = 0; i < numLines; i++)
-		{
-			const GUIInputLineDesc& lineDesc = getLineDesc(i);
-
-			if(curPos == inputIdx)
-				return lineDesc.getStartChar();
-
-			curPos++; // Move past line start position
-
-			UINT32 numChars = lineDesc.getEndChar() - lineDesc.getStartChar();
-			UINT32 numCaretPositions = lineDesc.getEndChar(false) - lineDesc.getStartChar();
-			if(inputIdx >= (curPos + numCaretPositions))
-			{
-				curCharIdx += numChars;
-				curPos += numCaretPositions;
-				continue;
-			}
-
-			UINT32 diff = inputIdx - curPos; 
-			curCharIdx += diff + 1; // Character after the caret
-
-			return curCharIdx;
-		}
-
-		return 0;
-	}
-
-	bool GUIInputTool::isNewline(UINT32 inputIdx) const
-	{
-		if(mTextDesc.text.size() == 0)
-			return true;
-
-		UINT32 numLines = getNumLines();
-		UINT32 curPos = 0;
-		for(UINT32 i = 0; i < numLines; i++)
-		{
-			const GUIInputLineDesc& lineDesc = getLineDesc(i);
-
-			if(curPos == inputIdx)
-				return true;
-
-			UINT32 numChars = lineDesc.getEndChar(false) - lineDesc.getStartChar();
-			curPos += numChars;
-		}
-
-		return false;
-	}
-
-	bool GUIInputTool::isNewlineChar(UINT32 charIdx) const
-	{
-		if(mTextDesc.text[charIdx] == '\n')
-			return true;
-
-		return false;
-	}
-
-	bool GUIInputTool::isDescValid() const
-	{
-		// We we have some text but line descs are empty we may assume
-		// something went wrong when creating the line descs, therefore it is
-		// not valid and no text is displayed.
-		if(mTextDesc.text.size() > 0)
-			return mLineDescs.size() > 0;
-
-		return true;
-	}
-
-	GUIInputLineDesc::GUIInputLineDesc(UINT32 startChar, UINT32 endChar, UINT32 lineHeight, INT32 lineYStart, bool includesNewline)
-		:mStartChar(startChar), mEndChar(endChar), mLineHeight(lineHeight), mLineYStart(lineYStart), mIncludesNewline(includesNewline)
-	{
-
-	}
-
-	UINT32 GUIInputLineDesc::getEndChar(bool includeNewline) const
-	{
-		if(mIncludesNewline)
-		{
-			if(includeNewline)
-				return mEndChar;
-			else
-			{
-				if(mEndChar > 0)
-					return mEndChar - 1;
-				else
-					return mStartChar;
-			}
-		}
-		else
-			return mEndChar;
-	}
-
-	bool GUIInputLineDesc::isNewline(UINT32 charIdx) const
-	{
-		if(mIncludesNewline)
-		{
-			return (mEndChar - 1) == charIdx;
-		}
-		else
-			return false;
-	}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsGUIInputTool.h"
+#include "BsGUIElement.h"
+#include "BsMath.h"
+#include "BsVector2.h"
+#include "BsFont.h"
+
+namespace BansheeEngine
+{
+	GUIInputTool::GUIInputTool()
+		:mQuads(nullptr), mNumQuads(0), mElement(nullptr)
+	{ }
+
+	GUIInputTool::~GUIInputTool()
+	{ }
+
+	void GUIInputTool::updateText(const GUIElement* element, const TEXT_SPRITE_DESC& textDesc)
+	{
+		mElement = element;
+		mTextDesc = textDesc;
+
+		mLineDescs.clear();
+
+		bs_frame_mark();
+		{
+			TextData<FrameAlloc> textData(mTextDesc.text, mTextDesc.font, mTextDesc.fontSize,
+				mTextDesc.width, mTextDesc.height, mTextDesc.wordWrap, mTextDesc.wordBreak);
+
+			UINT32 numLines = textData.getNumLines();
+			UINT32 numPages = textData.getNumPages();
+
+			mNumQuads = 0;
+			for (UINT32 i = 0; i < numPages; i++)
+				mNumQuads += textData.getNumQuadsForPage(i);
+
+			if (mQuads != nullptr)
+				bs_delete(mQuads);
+
+			mQuads = bs_newN<Vector2>(mNumQuads * 4);
+
+			TextSprite::genTextQuads(textData, mTextDesc.width, mTextDesc.height, mTextDesc.horzAlign, mTextDesc.vertAlign, mTextDesc.anchor,
+				mQuads, nullptr, nullptr, mNumQuads);
+
+			UINT32 numVerts = mNumQuads * 4;
+
+			// Store cached line data
+			UINT32 curCharIdx = 0;
+			UINT32 curLineIdx = 0;
+
+			Vector2I* alignmentOffsets = bs_frame_new<Vector2I>(numLines);
+			TextSprite::getAlignmentOffsets(textData, mTextDesc.width, mTextDesc.height, mTextDesc.horzAlign, 
+				mTextDesc.vertAlign, alignmentOffsets);
+
+			for (UINT32 i = 0; i < numLines; i++)
+			{
+				const TextDataBase::TextLine& line = textData.getLine(i);
+
+				// Line has a newline char only if it wasn't created by word wrap and it isn't the last line
+				bool hasNewline = line.hasNewlineChar() && (curLineIdx != (numLines - 1));
+
+				UINT32 startChar = curCharIdx;
+				UINT32 endChar = curCharIdx + line.getNumChars() + (hasNewline ? 1 : 0);
+				UINT32 lineHeight = line.getYOffset();
+				INT32 lineYStart = alignmentOffsets[curLineIdx].y;
+
+				GUIInputLineDesc lineDesc(startChar, endChar, lineHeight, lineYStart, hasNewline);
+				mLineDescs.push_back(lineDesc);
+
+				curCharIdx = lineDesc.getEndChar();
+				curLineIdx++;
+			}
+
+			bs_frame_delete(alignmentOffsets);
+		}
+		bs_frame_clear();
+	}
+
+	Vector2I GUIInputTool::getTextOffset() const
+	{
+		Vector2I offset(mElement->_getLayoutData().area.x, mElement->_getLayoutData().area.y);
+
+		return offset + mElement->_getTextInputOffset() + Vector2I(mElement->_getTextInputRect().x, mElement->_getTextInputRect().y);
+	}
+
+	Rect2I GUIInputTool::getCharRect(UINT32 charIdx) const
+	{
+		Rect2I charRect = getLocalCharRect(charIdx);
+		Vector2I textOffset = getTextOffset();
+
+		charRect.x += textOffset.x;
+		charRect.y += textOffset.y;
+
+		return charRect;
+	}
+
+	Rect2I GUIInputTool::getLocalCharRect(UINT32 charIdx) const
+	{
+		UINT32 lineIdx = getLineForChar(charIdx);
+
+		// If char is newline we don't have any geometry to return
+		const GUIInputLineDesc& lineDesc = getLineDesc(lineIdx);
+		if(lineDesc.isNewline(charIdx))
+			return Rect2I();
+
+		UINT32 numNewlineChars = 0;
+		for(UINT32 i = 0; i < lineIdx; i++)
+			numNewlineChars += (getLineDesc(i).hasNewlineChar() ? 1 : 0);
+
+		UINT32 quadIdx = charIdx - numNewlineChars;
+		if(quadIdx >= 0 && quadIdx < mNumQuads)
+		{
+			UINT32 vertIdx = quadIdx * 4;
+
+			Rect2I charRect;
+			charRect.x = Math::roundToInt(mQuads[vertIdx + 0].x);
+			charRect.y = Math::roundToInt(mQuads[vertIdx + 0].y);
+			charRect.width = Math::roundToInt(mQuads[vertIdx + 3].x - charRect.x);
+			charRect.height = Math::roundToInt(mQuads[vertIdx + 3].y - charRect.y);
+
+			return charRect;
+		}
+
+		LOGERR("Invalid character index: " + toString(charIdx));
+		return Rect2I();
+	}
+
+	INT32 GUIInputTool::getCharIdxAtPos(const Vector2I& pos) const
+	{
+		Vector2 vecPos((float)pos.x, (float)pos.y);
+
+		UINT32 lineStartChar = 0;
+		UINT32 lineEndChar = 0;
+		UINT32 numNewlineChars = 0;
+		UINT32 lineIdx = 0;
+		for(auto& line : mLineDescs)
+		{
+			INT32 lineStart = line.getLineYStart() + getTextOffset().y;
+			if(pos.y >= lineStart && pos.y < (lineStart + (INT32)line.getLineHeight()))
+			{
+				lineStartChar = line.getStartChar();
+				lineEndChar = line.getEndChar(false);
+				break;
+			}
+
+			// Newline chars count in the startChar/endChar variables, but don't actually exist in the buffers
+			// so we need to filter them out
+			numNewlineChars += (line.hasNewlineChar() ? 1 : 0); 
+
+			lineIdx++;
+		}
+
+		UINT32 lineStartQuad = lineStartChar - numNewlineChars;
+		UINT32 lineEndQuad = lineEndChar - numNewlineChars;
+
+		float nearestDist = std::numeric_limits<float>::max();
+		UINT32 nearestChar = 0;
+		bool foundChar = false;
+
+		Vector2I textOffset = getTextOffset();
+		for(UINT32 i = lineStartQuad; i < lineEndQuad; i++)
+		{
+			UINT32 curVert = i * 4;
+
+			float centerX = mQuads[curVert + 0].x + mQuads[curVert + 1].x;
+			centerX *= 0.5f;
+			centerX += textOffset.x;
+
+			float dist = Math::abs(centerX - vecPos.x);
+			if(dist < nearestDist)
+			{
+				nearestChar = i + numNewlineChars;
+				nearestDist = dist;
+				foundChar = true;
+			}
+		}
+
+		if(!foundChar)
+			return -1;
+
+		return nearestChar;
+	}
+
+	UINT32 GUIInputTool::getLineForChar(UINT32 charIdx, bool newlineCountsOnNextLine) const
+	{
+		UINT32 idx = 0;
+		for(auto& line : mLineDescs)
+		{
+			if((charIdx >= line.getStartChar() && charIdx < line.getEndChar()) || 
+				(charIdx == line.getStartChar() && line.getStartChar() == line.getEndChar()))
+			{
+				if(line.isNewline(charIdx) && newlineCountsOnNextLine)
+					return idx + 1; // Incrementing is safe because next line must exist, since we just found a newline char
+
+				return idx;
+			}
+
+			idx++;
+		}
+
+		LOGERR("Invalid character index: " + toString(charIdx));
+		return 0;
+	}
+
+	UINT32 GUIInputTool::getCharIdxAtInputIdx(UINT32 inputIdx) const
+	{
+		if(mTextDesc.text.size() == 0)
+			return 0;
+
+		UINT32 numLines = getNumLines();
+		UINT32 curPos = 0;
+		UINT32 curCharIdx = 0;
+		for(UINT32 i = 0; i < numLines; i++)
+		{
+			const GUIInputLineDesc& lineDesc = getLineDesc(i);
+
+			if(curPos == inputIdx)
+				return lineDesc.getStartChar();
+
+			curPos++; // Move past line start position
+
+			UINT32 numChars = lineDesc.getEndChar() - lineDesc.getStartChar();
+			UINT32 numCaretPositions = lineDesc.getEndChar(false) - lineDesc.getStartChar();
+			if(inputIdx >= (curPos + numCaretPositions))
+			{
+				curCharIdx += numChars;
+				curPos += numCaretPositions;
+				continue;
+			}
+
+			UINT32 diff = inputIdx - curPos; 
+			curCharIdx += diff + 1; // Character after the caret
+
+			return curCharIdx;
+		}
+
+		return 0;
+	}
+
+	bool GUIInputTool::isNewline(UINT32 inputIdx) const
+	{
+		if(mTextDesc.text.size() == 0)
+			return true;
+
+		UINT32 numLines = getNumLines();
+		UINT32 curPos = 0;
+		for(UINT32 i = 0; i < numLines; i++)
+		{
+			const GUIInputLineDesc& lineDesc = getLineDesc(i);
+
+			if(curPos == inputIdx)
+				return true;
+
+			UINT32 numChars = lineDesc.getEndChar(false) - lineDesc.getStartChar();
+			curPos += numChars;
+		}
+
+		return false;
+	}
+
+	bool GUIInputTool::isNewlineChar(UINT32 charIdx) const
+	{
+		if(mTextDesc.text[charIdx] == '\n')
+			return true;
+
+		return false;
+	}
+
+	bool GUIInputTool::isDescValid() const
+	{
+		// We we have some text but line descs are empty we may assume
+		// something went wrong when creating the line descs, therefore it is
+		// not valid and no text is displayed.
+		if(mTextDesc.text.size() > 0)
+			return mLineDescs.size() > 0;
+
+		return true;
+	}
+
+	GUIInputLineDesc::GUIInputLineDesc(UINT32 startChar, UINT32 endChar, UINT32 lineHeight, INT32 lineYStart, bool includesNewline)
+		:mStartChar(startChar), mEndChar(endChar), mLineHeight(lineHeight), mLineYStart(lineYStart), mIncludesNewline(includesNewline)
+	{
+
+	}
+
+	UINT32 GUIInputLineDesc::getEndChar(bool includeNewline) const
+	{
+		if(mIncludesNewline)
+		{
+			if(includeNewline)
+				return mEndChar;
+			else
+			{
+				if(mEndChar > 0)
+					return mEndChar - 1;
+				else
+					return mStartChar;
+			}
+		}
+		else
+			return mEndChar;
+	}
+
+	bool GUIInputLineDesc::isNewline(UINT32 charIdx) const
+	{
+		if(mIncludesNewline)
+		{
+			return (mEndChar - 1) == charIdx;
+		}
+		else
+			return false;
+	}
 }

+ 880 - 865
Source/MBansheeEditor/Inspector/InspectorWindow.cs

@@ -1,865 +1,880 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Collections.Generic;
-using System.Data.Common;
-using System.IO;
-using BansheeEngine;
-
-namespace BansheeEditor
-{
-    /// <summary>
-    /// Displays GUI for a <see cref="SceneObject"/> or for a <see cref="Resource"/>. Scene object's transform values
-    /// are displayed, along with all their components and their fields.
-    /// </summary>
-    internal sealed class InspectorWindow : EditorWindow
-    {
-        /// <summary>
-        /// Type of objects displayed in the window.
-        /// </summary>
-        private enum InspectorType
-        {
-            SceneObject,
-            Resource,
-            Multiple,
-            None
-        }
-
-        /// <summary>
-        /// Inspector GUI elements for a single <see cref="Component"/> in a <see cref="SceneObject"/>.
-        /// </summary>
-        private class InspectorComponent
-        {
-            public GUIToggle foldout;
-            public GUIButton removeBtn;
-            public GUILayout title;
-            public GUIPanel panel;
-            public Inspector inspector;
-            public UInt64 instanceId;
-        }
-
-        /// <summary>
-        /// Inspector GUI elements for a <see cref="Resource"/>
-        /// </summary>
-        private class InspectorResource
-        {
-            public GUIPanel panel;
-            public Inspector inspector;
-        }
-
-        private static readonly Color HIGHLIGHT_COLOR = new Color(1.0f, 1.0f, 1.0f, 0.5f);
-        private const int RESOURCE_TITLE_HEIGHT = 30;
-        private const int COMPONENT_SPACING = 10;
-        private const int PADDING = 5;
-
-        private List<InspectorComponent> inspectorComponents = new List<InspectorComponent>();
-        private InspectorPersistentData persistentData;
-        private InspectorResource inspectorResource;
-        private GUIScrollArea inspectorScrollArea;
-        private GUILayout inspectorLayout;
-        private GUIPanel highlightPanel;
-        private GUITexture scrollAreaHighlight;
-
-        private SceneObject activeSO;
-        private InspectableState modifyState;
-        private int undoCommandIdx = -1;
-        private GUITextBox soNameInput;
-        private GUIToggle soActiveToggle;
-        private GUILayout soPrefabLayout;
-        private bool soHasPrefab;
-        private GUIFloatField soPosX;
-        private GUIFloatField soPosY;
-        private GUIFloatField soPosZ;
-        private GUIFloatField soRotX;
-        private GUIFloatField soRotY;
-        private GUIFloatField soRotZ;
-        private GUIFloatField soScaleX;
-        private GUIFloatField soScaleY;
-        private GUIFloatField soScaleZ;
-
-        private Rect2I[] dropAreas = new Rect2I[0];
-
-        private InspectorType currentType = InspectorType.None;
-        private Resource activeResource;
-
-        /// <summary>
-        /// Opens the inspector window from the menu bar.
-        /// </summary>
-        [MenuItem("Windows/Inspector", ButtonModifier.CtrlAlt, ButtonCode.I, 6000)]
-        private static void OpenInspectorWindow()
-        {
-            OpenWindow<InspectorWindow>();
-        }
-
-        /// <summary>
-        /// Name of the inspector window to display on the window title.
-        /// </summary>
-        /// <returns>Name of the inspector window to display on the window title.</returns>
-        protected override LocString GetDisplayName()
-        {
-            return new LocEdString("Inspector");
-        }
-
-        /// <summary>
-        /// Sets a resource whose GUI is to be displayed in the inspector. Clears any previous contents of the window.
-        /// </summary>
-        /// <param name="resourcePath">Resource path relative to the project of the resource to inspect.</param>
-        private void SetObjectToInspect(String resourcePath)
-        {
-            activeResource = ProjectLibrary.Load<Resource>(resourcePath);
-
-            if (activeResource == null)
-                return;
-
-            currentType = InspectorType.Resource;
-
-            inspectorScrollArea = new GUIScrollArea();
-            GUI.AddElement(inspectorScrollArea);
-            inspectorLayout = inspectorScrollArea.Layout;
-
-            GUIPanel titlePanel = inspectorLayout.AddPanel();
-            titlePanel.SetHeight(RESOURCE_TITLE_HEIGHT);
-
-            GUILayoutY titleLayout = titlePanel.AddLayoutY();
-            titleLayout.SetPosition(PADDING, PADDING);
-
-            string name = Path.GetFileNameWithoutExtension(resourcePath);
-            string type = activeResource.GetType().Name;
-
-            LocString title = new LocEdString(name + " (" + type + ")");
-            GUILabel titleLabel = new GUILabel(title);
-
-            titleLayout.AddFlexibleSpace();
-            GUILayoutX titleLabelLayout = titleLayout.AddLayoutX();
-            titleLabelLayout.AddElement(titleLabel);
-            titleLayout.AddFlexibleSpace();
-
-            GUIPanel titleBgPanel = titlePanel.AddPanel(1);
-
-            GUITexture titleBg = new GUITexture(null, EditorStyles.InspectorTitleBg);
-            titleBgPanel.AddElement(titleBg);
-
-            inspectorLayout.AddSpace(COMPONENT_SPACING);
-
-            inspectorResource = new InspectorResource();
-            inspectorResource.panel = inspectorLayout.AddPanel();
-
-            var persistentProperties = persistentData.GetProperties(activeResource.UUID);
-
-            inspectorResource.inspector = InspectorUtility.GetInspector(activeResource.GetType());
-            inspectorResource.inspector.Initialize(inspectorResource.panel, activeResource, persistentProperties);
-
-            inspectorLayout.AddFlexibleSpace();
-        }
-
-        /// <summary>
-        /// Sets a scene object whose GUI is to be displayed in the inspector. Clears any previous contents of the window.
-        /// </summary>
-        /// <param name="so">Scene object to inspect.</param>
-        private void SetObjectToInspect(SceneObject so)
-        {
-            if (so == null)
-                return;
-
-            currentType = InspectorType.SceneObject;
-            activeSO = so;
-
-            inspectorScrollArea = new GUIScrollArea();
-            scrollAreaHighlight = new GUITexture(Builtin.WhiteTexture);
-            scrollAreaHighlight.SetTint(HIGHLIGHT_COLOR);
-            scrollAreaHighlight.Active = false;
-
-            GUI.AddElement(inspectorScrollArea);
-            GUIPanel inspectorPanel = inspectorScrollArea.Layout.AddPanel();
-            inspectorLayout = inspectorPanel.AddLayoutY();
-            highlightPanel = inspectorPanel.AddPanel(-1);
-            highlightPanel.AddElement(scrollAreaHighlight);
-
-            // SceneObject fields
-            CreateSceneObjectFields();
-            RefreshSceneObjectFields(true);
-
-            // Components
-            Component[] allComponents = so.GetComponents();
-            for (int i = 0; i < allComponents.Length; i++)
-            {
-                inspectorLayout.AddSpace(COMPONENT_SPACING);
-
-                InspectorComponent data = new InspectorComponent();
-                data.instanceId = allComponents[i].InstanceId;
-
-                data.foldout = new GUIToggle(allComponents[i].GetType().Name, EditorStyles.Foldout);
-                data.removeBtn = new GUIButton(new GUIContent(EditorBuiltin.XBtnIcon), GUIOption.FixedWidth(30));
-
-                data.title = inspectorLayout.AddLayoutX();
-                data.title.AddElement(data.foldout);
-                data.title.AddElement(data.removeBtn);
-                data.panel = inspectorLayout.AddPanel();
-
-                var persistentProperties = persistentData.GetProperties(allComponents[i].InstanceId);
-
-                data.inspector = InspectorUtility.GetInspector(allComponents[i].GetType());
-                data.inspector.Initialize(data.panel, allComponents[i], persistentProperties);
-
-                bool isExpanded = data.inspector.Persistent.GetBool(data.instanceId + "_Expanded", true);
-                data.foldout.Value = isExpanded;
-
-                if (!isExpanded)
-                    data.inspector.SetVisible(false);
-
-                Type curComponentType = allComponents[i].GetType();
-                data.foldout.OnToggled += (bool expanded) => OnComponentFoldoutToggled(data, expanded);
-                data.removeBtn.OnClick += () => OnComponentRemoveClicked(curComponentType);
-
-                inspectorComponents.Add(data);
-            }
-
-            inspectorLayout.AddFlexibleSpace();
-
-            UpdateDropAreas();
-        }
-
-        /// <summary>
-        /// Creates GUI elements required for displaying <see cref="SceneObject"/> fields like name, prefab data and 
-        /// transform (position, rotation, scale). Assumes that necessary inspector scroll area layout has already been 
-        /// created.
-        /// </summary>
-        private void CreateSceneObjectFields()
-        {
-            GUIPanel sceneObjectPanel = inspectorLayout.AddPanel();
-            sceneObjectPanel.SetHeight(GetTitleBounds().height);
-
-            GUILayoutY sceneObjectLayout = sceneObjectPanel.AddLayoutY();
-            sceneObjectLayout.SetPosition(PADDING, PADDING);
-
-            GUIPanel sceneObjectBgPanel = sceneObjectPanel.AddPanel(1);
-
-            GUILayoutX nameLayout = sceneObjectLayout.AddLayoutX();
-            soActiveToggle = new GUIToggle("");
-            soActiveToggle.OnToggled += OnSceneObjectActiveStateToggled;
-            GUILabel nameLbl = new GUILabel(new LocEdString("Name"), GUIOption.FixedWidth(50));
-            soNameInput = new GUITextBox(false, GUIOption.FlexibleWidth(180));
-            soNameInput.Text = activeSO.Name;
-            soNameInput.OnChanged += OnSceneObjectRename;
-            soNameInput.OnConfirmed += OnModifyConfirm;
-            soNameInput.OnFocusLost += OnModifyConfirm;
-
-            nameLayout.AddElement(soActiveToggle);
-            nameLayout.AddSpace(3);
-            nameLayout.AddElement(nameLbl);
-            nameLayout.AddElement(soNameInput);
-            nameLayout.AddFlexibleSpace();
-
-            soPrefabLayout = sceneObjectLayout.AddLayoutX();
-
-            GUILayoutX positionLayout = sceneObjectLayout.AddLayoutX();
-            GUILabel positionLbl = new GUILabel(new LocEdString("Position"), GUIOption.FixedWidth(50));
-            soPosX = new GUIFloatField(new LocEdString("X"), 10, "", GUIOption.FixedWidth(60));
-            soPosY = new GUIFloatField(new LocEdString("Y"), 10, "", GUIOption.FixedWidth(60));
-            soPosZ = new GUIFloatField(new LocEdString("Z"), 10, "", GUIOption.FixedWidth(60));
-
-            soPosX.OnChanged += (x) => OnPositionChanged(0, x);
-            soPosY.OnChanged += (y) => OnPositionChanged(1, y);
-            soPosZ.OnChanged += (z) => OnPositionChanged(2, z);
-
-            soPosX.OnConfirmed += OnModifyConfirm;
-            soPosY.OnConfirmed += OnModifyConfirm;
-            soPosZ.OnConfirmed += OnModifyConfirm;
-
-            soPosX.OnFocusLost += OnModifyConfirm;
-            soPosY.OnFocusLost += OnModifyConfirm;
-            soPosZ.OnFocusLost += OnModifyConfirm;
-
-            positionLayout.AddElement(positionLbl);
-            positionLayout.AddElement(soPosX);
-            positionLayout.AddSpace(10);
-            positionLayout.AddFlexibleSpace();
-            positionLayout.AddElement(soPosY);
-            positionLayout.AddSpace(10);
-            positionLayout.AddFlexibleSpace();
-            positionLayout.AddElement(soPosZ);
-            positionLayout.AddFlexibleSpace();
-
-            GUILayoutX rotationLayout = sceneObjectLayout.AddLayoutX();
-            GUILabel rotationLbl = new GUILabel(new LocEdString("Rotation"), GUIOption.FixedWidth(50));
-            soRotX = new GUIFloatField(new LocEdString("X"), 10, "", GUIOption.FixedWidth(60));
-            soRotY = new GUIFloatField(new LocEdString("Y"), 10, "", GUIOption.FixedWidth(60));
-            soRotZ = new GUIFloatField(new LocEdString("Z"), 10, "", GUIOption.FixedWidth(60));
-
-            soRotX.OnChanged += (x) => OnRotationChanged(0, x);
-            soRotY.OnChanged += (y) => OnRotationChanged(1, y);
-            soRotZ.OnChanged += (z) => OnRotationChanged(2, z);
-
-            soRotX.OnConfirmed += OnModifyConfirm;
-            soRotY.OnConfirmed += OnModifyConfirm;
-            soRotZ.OnConfirmed += OnModifyConfirm;
-
-            soRotX.OnFocusLost += OnModifyConfirm;
-            soRotY.OnFocusLost += OnModifyConfirm;
-            soRotZ.OnFocusLost += OnModifyConfirm;
-
-            rotationLayout.AddElement(rotationLbl);
-            rotationLayout.AddElement(soRotX);
-            rotationLayout.AddSpace(10);
-            rotationLayout.AddFlexibleSpace();
-            rotationLayout.AddElement(soRotY);
-            rotationLayout.AddSpace(10);
-            rotationLayout.AddFlexibleSpace();
-            rotationLayout.AddElement(soRotZ);
-            rotationLayout.AddFlexibleSpace();
-
-            GUILayoutX scaleLayout = sceneObjectLayout.AddLayoutX();
-            GUILabel scaleLbl = new GUILabel(new LocEdString("Scale"), GUIOption.FixedWidth(50));
-            soScaleX = new GUIFloatField(new LocEdString("X"), 10, "", GUIOption.FixedWidth(60));
-            soScaleY = new GUIFloatField(new LocEdString("Y"), 10, "", GUIOption.FixedWidth(60));
-            soScaleZ = new GUIFloatField(new LocEdString("Z"), 10, "", GUIOption.FixedWidth(60));
-
-            soScaleX.OnChanged += (x) => OnScaleChanged(0, x);
-            soScaleY.OnChanged += (y) => OnScaleChanged(1, y);
-            soScaleZ.OnChanged += (z) => OnScaleChanged(2, z);
-
-            soScaleX.OnConfirmed += OnModifyConfirm;
-            soScaleY.OnConfirmed += OnModifyConfirm;
-            soScaleZ.OnConfirmed += OnModifyConfirm;
-
-            soScaleX.OnFocusLost += OnModifyConfirm;
-            soScaleY.OnFocusLost += OnModifyConfirm;
-            soScaleZ.OnFocusLost += OnModifyConfirm;
-
-            scaleLayout.AddElement(scaleLbl);
-            scaleLayout.AddElement(soScaleX);
-            scaleLayout.AddSpace(10);
-            scaleLayout.AddFlexibleSpace();
-            scaleLayout.AddElement(soScaleY);
-            scaleLayout.AddSpace(10);
-            scaleLayout.AddFlexibleSpace();
-            scaleLayout.AddElement(soScaleZ);
-            scaleLayout.AddFlexibleSpace();
-
-            sceneObjectLayout.AddFlexibleSpace();
-
-            GUITexture titleBg = new GUITexture(null, EditorStyles.InspectorTitleBg);
-            sceneObjectBgPanel.AddElement(titleBg);
-        }
-
-        /// <summary>
-        /// Updates contents of the scene object specific fields (name, position, rotation, etc.)
-        /// </summary>
-        /// <param name="forceUpdate">If true, the GUI elements will be updated regardless of whether a change was
-        ///                           detected or not.</param>
-        private void RefreshSceneObjectFields(bool forceUpdate)
-        {
-            if (activeSO == null)
-                return;
-
-            soNameInput.Text = activeSO.Name;
-            soActiveToggle.Value = activeSO.Active;
-
-            SceneObject prefabParent = PrefabUtility.GetPrefabParent(activeSO);
-
-            // Ignore prefab parent if scene root, we only care for non-root prefab instances
-            bool hasPrefab = prefabParent != null && prefabParent.Parent != null;
-            if (soHasPrefab != hasPrefab || forceUpdate)
-            {
-                int numChildren = soPrefabLayout.ChildCount;
-                for (int i = 0; i < numChildren; i++)
-                    soPrefabLayout.GetChild(0).Destroy();
-
-                GUILabel prefabLabel =new GUILabel(new LocEdString("Prefab"), GUIOption.FixedWidth(50));
-                soPrefabLayout.AddElement(prefabLabel);
-
-                if (hasPrefab)
-                {
-                    GUIButton btnApplyPrefab = new GUIButton(new LocEdString("Apply"), GUIOption.FixedWidth(60));
-                    GUIButton btnRevertPrefab = new GUIButton(new LocEdString("Revert"), GUIOption.FixedWidth(60));
-                    GUIButton btnBreakPrefab = new GUIButton(new LocEdString("Break"), GUIOption.FixedWidth(60));
-
-                    btnApplyPrefab.OnClick += () => PrefabUtility.ApplyPrefab(activeSO);
-                    btnRevertPrefab.OnClick += () =>
-                    {
-                        UndoRedo.RecordSO(activeSO, true, "Reverting \"" + activeSO.Name + "\" to prefab.");
-
-                        PrefabUtility.RevertPrefab(activeSO);
-                        EditorApplication.SetSceneDirty();
-                    };
-                    btnBreakPrefab.OnClick += () =>
-                    {
-                        UndoRedo.BreakPrefab(activeSO, "Breaking prefab link for " + activeSO.Name);
-
-                        EditorApplication.SetSceneDirty();
-                    };
-
-                    soPrefabLayout.AddElement(btnApplyPrefab);
-                    soPrefabLayout.AddElement(btnRevertPrefab);
-                    soPrefabLayout.AddElement(btnBreakPrefab);
-                }
-                else
-                {
-                    GUILabel noPrefabLabel = new GUILabel("None");
-                    soPrefabLayout.AddElement(noPrefabLabel);
-                }
-
-                soHasPrefab = hasPrefab;
-            }
-
-            Vector3 position;
-            Vector3 angles;
-            if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
-            {
-                position = activeSO.Position;
-                angles = activeSO.Rotation.ToEuler();
-            }
-            else
-            {
-                position = activeSO.LocalPosition;
-                angles = activeSO.LocalRotation.ToEuler();
-            }
-
-            Vector3 scale = activeSO.LocalScale;
-
-            soPosX.Value = position.x;
-            soPosY.Value = position.y;
-            soPosZ.Value = position.z;
-
-            soRotX.Value = angles.x;
-            soRotY.Value = angles.y;
-            soRotZ.Value = angles.z;
-
-            soScaleX.Value = scale.x;
-            soScaleY.Value = scale.y;
-            soScaleZ.Value = scale.z;
-        }
-
-        private void OnInitialize()
-        {
-            Selection.OnSelectionChanged += OnSelectionChanged;
-
-            const string soName = "InspectorPersistentData";
-            SceneObject so = Scene.Root.FindChild(soName);
-            if (so == null)
-                so = new SceneObject(soName, true);
-
-            persistentData = so.GetComponent<InspectorPersistentData>();
-            if (persistentData == null)
-                persistentData = so.AddComponent<InspectorPersistentData>();
-
-            OnSelectionChanged(new SceneObject[0], new string[0]);
-        }
-
-        private void OnDestroy()
-        {
-            Selection.OnSelectionChanged -= OnSelectionChanged;
-        }
-
-        private void OnEditorUpdate()
-        {
-            if (currentType == InspectorType.SceneObject)
-            {
-                Component[] allComponents = activeSO.GetComponents();
-                bool requiresRebuild = allComponents.Length != inspectorComponents.Count;
-
-                if (!requiresRebuild)
-                {
-                    for (int i = 0; i < inspectorComponents.Count; i++)
-                    {
-                        if (inspectorComponents[i].instanceId != allComponents[i].InstanceId)
-                        {
-                            requiresRebuild = true;
-                            break;
-                        }
-                    }
-                }
-
-                if (requiresRebuild)
-                {
-                    SceneObject so = activeSO;
-                    Clear();
-                    SetObjectToInspect(so);
-                }
-                else
-                {
-                    RefreshSceneObjectFields(false);
-
-                    InspectableState componentModifyState = InspectableState.NotModified;
-                    for (int i = 0; i < inspectorComponents.Count; i++)
-                        componentModifyState |= inspectorComponents[i].inspector.Refresh();
-
-                    if (componentModifyState.HasFlag(InspectableState.ModifyInProgress))
-                        EditorApplication.SetSceneDirty();
-
-                    modifyState |= componentModifyState;
-                }
-            }
-            else if (currentType == InspectorType.Resource)
-            {
-                inspectorResource.inspector.Refresh();
-            }
-
-            // Detect drag and drop
-            bool isValidDrag = false;
-
-            if (activeSO != null)
-            {
-                if ((DragDrop.DragInProgress || DragDrop.DropInProgress) && DragDrop.Type == DragDropType.Resource)
-                {
-                    Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition);
-                    Vector2I scrollPos = windowPos;
-                    Rect2I contentBounds = inspectorLayout.Bounds;
-                    scrollPos.x -= contentBounds.x;
-                    scrollPos.y -= contentBounds.y;
-
-                    bool isInBounds = false;
-                    Rect2I dropArea = new Rect2I();
-                    foreach (var bounds in dropAreas)
-                    {
-                        if (bounds.Contains(scrollPos))
-                        {
-                            isInBounds = true;
-                            dropArea = bounds;
-                            break;
-                        }
-                    }
-
-                    Type draggedComponentType = null;
-                    if (isInBounds)
-                    {
-                        ResourceDragDropData dragData = DragDrop.Data as ResourceDragDropData;
-                        if (dragData != null)
-                        {
-                            foreach (var resPath in dragData.Paths)
-                            {
-                                ResourceMeta meta = ProjectLibrary.GetMeta(resPath);
-                                if (meta != null)
-                                {
-                                    if (meta.ResType == ResourceType.ScriptCode)
-                                    {
-                                        ScriptCode scriptFile = ProjectLibrary.Load<ScriptCode>(resPath);
-
-                                        if (scriptFile != null)
-                                        {
-                                            Type[] scriptTypes = scriptFile.Types;
-                                            foreach (var type in scriptTypes)
-                                            {
-                                                if (type.IsSubclassOf(typeof (Component)))
-                                                {
-                                                    draggedComponentType = type;
-                                                    isValidDrag = true;
-                                                    break;
-                                                }
-                                            }
-
-                                            if (draggedComponentType != null)
-                                                break;
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-
-                    if (isValidDrag)
-                    {
-                        scrollAreaHighlight.Bounds = dropArea;
-
-                        if (DragDrop.DropInProgress)
-                        {
-                            activeSO.AddComponent(draggedComponentType);
-
-                            modifyState = InspectableState.Modified;
-                            EditorApplication.SetSceneDirty();
-                        }
-                    }
-                }               
-            }
-
-            if (scrollAreaHighlight != null)
-                scrollAreaHighlight.Active = isValidDrag;
-        }
-
-        /// <summary>
-        /// Triggered when the user selects a new resource or a scene object, or deselects everything.
-        /// </summary>
-        /// <param name="objects">A set of new scene objects that were selected.</param>
-        /// <param name="paths">A set of absolute resource paths that were selected.</param>
-        private void OnSelectionChanged(SceneObject[] objects, string[] paths)
-        {
-            if (currentType == InspectorType.SceneObject && modifyState == InspectableState.NotModified)
-                UndoRedo.PopCommand(undoCommandIdx);
-
-            Clear();
-            modifyState = InspectableState.NotModified;
-
-            if (objects.Length == 0 && paths.Length == 0)
-            {
-                currentType = InspectorType.None;
-                inspectorScrollArea = new GUIScrollArea();
-                GUI.AddElement(inspectorScrollArea);
-                inspectorLayout = inspectorScrollArea.Layout;
-
-                inspectorLayout.AddFlexibleSpace();
-                GUILayoutX layoutMsg = inspectorLayout.AddLayoutX();
-                layoutMsg.AddFlexibleSpace();
-                layoutMsg.AddElement(new GUILabel(new LocEdString("No object selected")));
-                layoutMsg.AddFlexibleSpace();
-                inspectorLayout.AddFlexibleSpace();
-            }
-            else if ((objects.Length + paths.Length) > 1)
-            {
-                currentType = InspectorType.None;
-                inspectorScrollArea = new GUIScrollArea();
-                GUI.AddElement(inspectorScrollArea);
-                inspectorLayout = inspectorScrollArea.Layout;
-
-                inspectorLayout.AddFlexibleSpace();
-                GUILayoutX layoutMsg = inspectorLayout.AddLayoutX();
-                layoutMsg.AddFlexibleSpace();
-                layoutMsg.AddElement(new GUILabel(new LocEdString("Multiple objects selected")));
-                layoutMsg.AddFlexibleSpace();
-                inspectorLayout.AddFlexibleSpace();
-            }
-            else if (objects.Length == 1)
-            {
-                if (objects[0] != null)
-                {
-                    UndoRedo.RecordSO(objects[0]);
-                    undoCommandIdx = UndoRedo.TopCommandId;
-
-                    SetObjectToInspect(objects[0]);
-                }
-            }
-            else if (paths.Length == 1)
-            {
-                SetObjectToInspect(paths[0]);
-            }
-        }
-
-        /// <summary>
-        /// Triggered when the user closes or expands a component foldout, making the component fields visible or hidden.
-        /// </summary>
-        /// <param name="inspectorData">Contains GUI data for the component that was toggled.</param>
-        /// <param name="expanded">Determines whether to display or hide component contents.</param>
-        private void OnComponentFoldoutToggled(InspectorComponent inspectorData, bool expanded)
-        {
-            inspectorData.inspector.Persistent.SetBool(inspectorData.instanceId + "_Expanded", expanded);
-            inspectorData.inspector.SetVisible(expanded);
-        }
-
-        /// <summary>
-        /// Triggered when the user clicks the component remove button. Removes that component from the active scene object.
-        /// </summary>
-        /// <param name="componentType">Type of the component to remove.</param>
-        private void OnComponentRemoveClicked(Type componentType)
-        {
-            if (activeSO != null)
-            {
-                activeSO.RemoveComponent(componentType);
-
-                modifyState = InspectableState.Modified;
-                EditorApplication.SetSceneDirty();
-            }
-        }
-
-        /// <summary>
-        /// Destroys all inspector GUI elements.
-        /// </summary>
-        internal void Clear()
-        {
-            for (int i = 0; i < inspectorComponents.Count; i++)
-            {
-                inspectorComponents[i].foldout.Destroy();
-                inspectorComponents[i].removeBtn.Destroy();
-                inspectorComponents[i].inspector.Destroy();
-            }
-
-            inspectorComponents.Clear();
-
-            if (inspectorResource != null)
-            {
-                inspectorResource.inspector.Destroy();
-                inspectorResource = null;
-            }
-
-            if (inspectorScrollArea != null)
-            {
-                inspectorScrollArea.Destroy();
-                inspectorScrollArea = null;
-            }
-
-            if (scrollAreaHighlight != null)
-            {
-                scrollAreaHighlight.Destroy();
-                scrollAreaHighlight = null;
-            }
-
-            if (highlightPanel != null)
-            {
-                highlightPanel.Destroy();
-                highlightPanel = null;
-            }
-
-            activeSO = null;
-            soNameInput = null;
-            soActiveToggle = null;
-            soPrefabLayout = null;
-            soHasPrefab = false;
-            soPosX = null;
-            soPosY = null;
-            soPosZ = null;
-            soRotX = null;
-            soRotY = null;
-            soRotZ = null;
-            soScaleX = null;
-            soScaleY = null;
-            soScaleZ = null;
-            dropAreas = new Rect2I[0];
-
-            activeResource = null;
-            currentType = InspectorType.None;
-        }
-
-        /// <summary>
-        /// Returns the size of the title bar area that is displayed for <see cref="SceneObject"/> specific fields.
-        /// </summary>
-        /// <returns>Area of the title bar, relative to the window.</returns>
-        private Rect2I GetTitleBounds()
-        {
-            return new Rect2I(0, 0, Width, 115);
-        }
-
-        /// <summary>
-        /// Triggered when the user changes the name of the currently active scene object.
-        /// </summary>
-        private void OnSceneObjectRename(string name)
-        {
-            if (activeSO != null)
-            {
-                activeSO.Name = name;
-
-                modifyState |= InspectableState.ModifyInProgress;
-                EditorApplication.SetSceneDirty();
-            }
-        }
-
-        /// <summary>
-        /// Triggered when the user changes the active state of the scene object.
-        /// </summary>
-        /// <param name="active">True if the object is active, false otherwise.</param>
-        private void OnSceneObjectActiveStateToggled(bool active)
-        {
-            if (activeSO != null)
-                activeSO.Active = active;
-        }
-
-        /// <summary>
-        /// Triggered when the scene object modification is confirmed by the user.
-        /// </summary>
-        private void OnModifyConfirm()
-        {
-            if (modifyState.HasFlag(InspectableState.ModifyInProgress))
-                modifyState = InspectableState.Modified;
-        }
-
-        /// <summary>
-        /// Triggered when the position value in the currently active <see cref="SceneObject"/> changes. Updates the 
-        /// necessary GUI elements.
-        /// </summary>
-        /// <param name="idx">Index of the coordinate that was changed.</param>
-        /// <param name="value">New value of the field.</param>
-        private void OnPositionChanged(int idx, float value)
-        {
-            if (activeSO == null)
-                return;
-
-            if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
-            {
-                Vector3 position = activeSO.Position;
-                position[idx] = value;
-                activeSO.Position = position;
-            }
-            else
-            {
-                Vector3 position = activeSO.LocalPosition;
-                position[idx] = value;
-                activeSO.LocalPosition = position;
-            }
-
-            modifyState = InspectableState.ModifyInProgress;
-            EditorApplication.SetSceneDirty();
-        }
-
-        /// <summary>
-        /// Triggered when the rotation value in the currently active <see cref="SceneObject"/> changes. Updates the 
-        /// necessary GUI elements.
-        /// </summary>
-        /// <param name="idx">Index of the euler angle that was changed (0 - X, 1 - Y, 2 - Z).</param>
-        /// <param name="value">New value of the field.</param>
-        private void OnRotationChanged(int idx, float value)
-        {
-            if (activeSO == null)
-                return;
-
-            if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
-            {
-                Vector3 angles = activeSO.Rotation.ToEuler();
-                angles[idx] = value;
-                activeSO.Rotation = Quaternion.FromEuler(angles);
-            }
-            else
-            {
-                Vector3 angles = activeSO.LocalRotation.ToEuler();
-                angles[idx] = value;
-                activeSO.LocalRotation = Quaternion.FromEuler(angles);
-            }
-
-            modifyState = InspectableState.ModifyInProgress;
-            EditorApplication.SetSceneDirty();
-        }
-
-        /// <summary>
-        /// Triggered when the scale value in the currently active <see cref="SceneObject"/> changes. Updates the 
-        /// necessary GUI elements.
-        /// </summary>
-        /// <param name="idx">Index of the coordinate that was changed.</param>
-        /// <param name="value">New value of the field.</param>
-        private void OnScaleChanged(int idx, float value)
-        {
-            if (activeSO == null)
-                return;
-
-            Vector3 scale = activeSO.LocalScale;
-            scale[idx] = value;
-            activeSO.LocalScale = scale;
-
-            modifyState = InspectableState.ModifyInProgress;
-            EditorApplication.SetSceneDirty();
-        }
-
-        /// <inheritdoc/>
-        protected override void WindowResized(int width, int height)
-        {
-            base.WindowResized(width, height);
-
-            UpdateDropAreas();
-        }
-
-        /// <summary>
-        /// Updates drop areas used for dragging and dropping components on the inspector.
-        /// </summary>
-        private void UpdateDropAreas()
-        {
-            if (activeSO == null)
-                return;
-
-            Rect2I contentBounds = inspectorLayout.Bounds;
-            dropAreas = new Rect2I[inspectorComponents.Count + 1];
-            int yOffset = GetTitleBounds().height;
-            for (int i = 0; i < inspectorComponents.Count; i++)
-            {
-                dropAreas[i] = new Rect2I(0, yOffset, contentBounds.width, COMPONENT_SPACING);
-                yOffset += inspectorComponents[i].title.Bounds.height + inspectorComponents[i].panel.Bounds.height + COMPONENT_SPACING;
-            }
-
-            dropAreas[dropAreas.Length - 1] = new Rect2I(0, yOffset, contentBounds.width, contentBounds.height - yOffset);
-        }
-    }
-}
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Collections.Generic;
+using System.Data.Common;
+using System.IO;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /// <summary>
+    /// Displays GUI for a <see cref="SceneObject"/> or for a <see cref="Resource"/>. Scene object's transform values
+    /// are displayed, along with all their components and their fields.
+    /// </summary>
+    internal sealed class InspectorWindow : EditorWindow
+    {
+        /// <summary>
+        /// Type of objects displayed in the window.
+        /// </summary>
+        private enum InspectorType
+        {
+            SceneObject,
+            Resource,
+            Multiple,
+            None
+        }
+
+        /// <summary>
+        /// Inspector GUI elements for a single <see cref="Component"/> in a <see cref="SceneObject"/>.
+        /// </summary>
+        private class InspectorComponent
+        {
+            public GUIToggle foldout;
+            public GUIButton removeBtn;
+            public GUILayout title;
+            public GUIPanel panel;
+            public Inspector inspector;
+            public UInt64 instanceId;
+        }
+
+        /// <summary>
+        /// Inspector GUI elements for a <see cref="Resource"/>
+        /// </summary>
+        private class InspectorResource
+        {
+            public GUIPanel panel;
+            public Inspector inspector;
+        }
+
+        private static readonly Color HIGHLIGHT_COLOR = new Color(1.0f, 1.0f, 1.0f, 0.5f);
+        private const int RESOURCE_TITLE_HEIGHT = 30;
+        private const int COMPONENT_SPACING = 10;
+        private const int PADDING = 5;
+
+        private List<InspectorComponent> inspectorComponents = new List<InspectorComponent>();
+        private InspectorPersistentData persistentData;
+        private InspectorResource inspectorResource;
+        private GUIScrollArea inspectorScrollArea;
+        private GUILayout inspectorLayout;
+        private GUIPanel highlightPanel;
+        private GUITexture scrollAreaHighlight;
+
+        private SceneObject activeSO;
+        private InspectableState modifyState;
+        private int undoCommandIdx = -1;
+        private GUITextBox soNameInput;
+        private GUIToggle soActiveToggle;
+        private GUILayout soPrefabLayout;
+        private bool soHasPrefab;
+        private GUIFloatField soPosX;
+        private GUIFloatField soPosY;
+        private GUIFloatField soPosZ;
+        private GUIFloatField soRotX;
+        private GUIFloatField soRotY;
+        private GUIFloatField soRotZ;
+        private GUIFloatField soScaleX;
+        private GUIFloatField soScaleY;
+        private GUIFloatField soScaleZ;
+
+        private Rect2I[] dropAreas = new Rect2I[0];
+
+        private InspectorType currentType = InspectorType.None;
+        private Resource activeResource;
+
+        /// <summary>
+        /// Opens the inspector window from the menu bar.
+        /// </summary>
+        [MenuItem("Windows/Inspector", ButtonModifier.CtrlAlt, ButtonCode.I, 6000)]
+        private static void OpenInspectorWindow()
+        {
+            OpenWindow<InspectorWindow>();
+        }
+
+        /// <summary>
+        /// Name of the inspector window to display on the window title.
+        /// </summary>
+        /// <returns>Name of the inspector window to display on the window title.</returns>
+        protected override LocString GetDisplayName()
+        {
+            return new LocEdString("Inspector");
+        }
+
+        /// <summary>
+        /// Sets a resource whose GUI is to be displayed in the inspector. Clears any previous contents of the window.
+        /// </summary>
+        /// <param name="resourcePath">Resource path relative to the project of the resource to inspect.</param>
+        private void SetObjectToInspect(String resourcePath)
+        {
+            activeResource = ProjectLibrary.Load<Resource>(resourcePath);
+
+            if (activeResource == null)
+                return;
+
+            currentType = InspectorType.Resource;
+
+            inspectorScrollArea = new GUIScrollArea();
+            GUI.AddElement(inspectorScrollArea);
+            inspectorLayout = inspectorScrollArea.Layout;
+
+            GUIPanel titlePanel = inspectorLayout.AddPanel();
+            titlePanel.SetHeight(RESOURCE_TITLE_HEIGHT);
+
+            GUILayoutY titleLayout = titlePanel.AddLayoutY();
+            titleLayout.SetPosition(PADDING, PADDING);
+
+            string name = Path.GetFileNameWithoutExtension(resourcePath);
+            string type = activeResource.GetType().Name;
+
+            LocString title = new LocEdString(name + " (" + type + ")");
+            GUILabel titleLabel = new GUILabel(title);
+
+            titleLayout.AddFlexibleSpace();
+            GUILayoutX titleLabelLayout = titleLayout.AddLayoutX();
+            titleLabelLayout.AddElement(titleLabel);
+            titleLayout.AddFlexibleSpace();
+
+            GUIPanel titleBgPanel = titlePanel.AddPanel(1);
+
+            GUITexture titleBg = new GUITexture(null, EditorStyles.InspectorTitleBg);
+            titleBgPanel.AddElement(titleBg);
+
+            inspectorLayout.AddSpace(COMPONENT_SPACING);
+
+            inspectorResource = new InspectorResource();
+            inspectorResource.panel = inspectorLayout.AddPanel();
+
+            var persistentProperties = persistentData.GetProperties(activeResource.UUID);
+
+            inspectorResource.inspector = InspectorUtility.GetInspector(activeResource.GetType());
+            inspectorResource.inspector.Initialize(inspectorResource.panel, activeResource, persistentProperties);
+
+            inspectorLayout.AddFlexibleSpace();
+        }
+
+        /// <summary>
+        /// Sets a scene object whose GUI is to be displayed in the inspector. Clears any previous contents of the window.
+        /// </summary>
+        /// <param name="so">Scene object to inspect.</param>
+        private void SetObjectToInspect(SceneObject so)
+        {
+            if (so == null)
+                return;
+
+            currentType = InspectorType.SceneObject;
+            activeSO = so;
+
+            inspectorScrollArea = new GUIScrollArea();
+            scrollAreaHighlight = new GUITexture(Builtin.WhiteTexture);
+            scrollAreaHighlight.SetTint(HIGHLIGHT_COLOR);
+            scrollAreaHighlight.Active = false;
+
+            GUI.AddElement(inspectorScrollArea);
+            GUIPanel inspectorPanel = inspectorScrollArea.Layout.AddPanel();
+            inspectorLayout = inspectorPanel.AddLayoutY();
+            highlightPanel = inspectorPanel.AddPanel(-1);
+            highlightPanel.AddElement(scrollAreaHighlight);
+
+            // SceneObject fields
+            CreateSceneObjectFields();
+            RefreshSceneObjectFields(true);
+
+            // Components
+            Component[] allComponents = so.GetComponents();
+            for (int i = 0; i < allComponents.Length; i++)
+            {
+                inspectorLayout.AddSpace(COMPONENT_SPACING);
+
+                InspectorComponent data = new InspectorComponent();
+                data.instanceId = allComponents[i].InstanceId;
+
+                data.foldout = new GUIToggle(allComponents[i].GetType().Name, EditorStyles.Foldout);
+                data.removeBtn = new GUIButton(new GUIContent(EditorBuiltin.XBtnIcon), GUIOption.FixedWidth(30));
+
+                data.title = inspectorLayout.AddLayoutX();
+                data.title.AddElement(data.foldout);
+                data.title.AddElement(data.removeBtn);
+                data.panel = inspectorLayout.AddPanel();
+
+                var persistentProperties = persistentData.GetProperties(allComponents[i].InstanceId);
+
+                data.inspector = InspectorUtility.GetInspector(allComponents[i].GetType());
+                data.inspector.Initialize(data.panel, allComponents[i], persistentProperties);
+
+                bool isExpanded = data.inspector.Persistent.GetBool(data.instanceId + "_Expanded", true);
+                data.foldout.Value = isExpanded;
+
+                if (!isExpanded)
+                    data.inspector.SetVisible(false);
+
+                Type curComponentType = allComponents[i].GetType();
+                data.foldout.OnToggled += (bool expanded) => OnComponentFoldoutToggled(data, expanded);
+                data.removeBtn.OnClick += () => OnComponentRemoveClicked(curComponentType);
+
+                inspectorComponents.Add(data);
+            }
+
+            inspectorLayout.AddFlexibleSpace();
+
+            UpdateDropAreas();
+        }
+
+        /// <summary>
+        /// Creates GUI elements required for displaying <see cref="SceneObject"/> fields like name, prefab data and 
+        /// transform (position, rotation, scale). Assumes that necessary inspector scroll area layout has already been 
+        /// created.
+        /// </summary>
+        private void CreateSceneObjectFields()
+        {
+            GUIPanel sceneObjectPanel = inspectorLayout.AddPanel();
+            sceneObjectPanel.SetHeight(GetTitleBounds().height);
+
+            GUILayoutY sceneObjectLayout = sceneObjectPanel.AddLayoutY();
+            sceneObjectLayout.SetPosition(PADDING, PADDING);
+
+            GUIPanel sceneObjectBgPanel = sceneObjectPanel.AddPanel(1);
+
+            GUILayoutX nameLayout = sceneObjectLayout.AddLayoutX();
+            soActiveToggle = new GUIToggle("");
+            soActiveToggle.OnToggled += OnSceneObjectActiveStateToggled;
+            GUILabel nameLbl = new GUILabel(new LocEdString("Name"), GUIOption.FixedWidth(50));
+            soNameInput = new GUITextBox(false, GUIOption.FlexibleWidth(180));
+            soNameInput.Text = activeSO.Name;
+            soNameInput.OnChanged += OnSceneObjectRename;
+            soNameInput.OnConfirmed += OnModifyConfirm;
+            soNameInput.OnFocusLost += OnModifyConfirm;
+
+            nameLayout.AddElement(soActiveToggle);
+            nameLayout.AddSpace(3);
+            nameLayout.AddElement(nameLbl);
+            nameLayout.AddElement(soNameInput);
+            nameLayout.AddFlexibleSpace();
+
+            soPrefabLayout = sceneObjectLayout.AddLayoutX();
+
+            GUILayoutX positionLayout = sceneObjectLayout.AddLayoutX();
+            GUILabel positionLbl = new GUILabel(new LocEdString("Position"), GUIOption.FixedWidth(50));
+            soPosX = new GUIFloatField(new LocEdString("X"), 10, "", GUIOption.FixedWidth(60));
+            soPosY = new GUIFloatField(new LocEdString("Y"), 10, "", GUIOption.FixedWidth(60));
+            soPosZ = new GUIFloatField(new LocEdString("Z"), 10, "", GUIOption.FixedWidth(60));
+
+            soPosX.OnChanged += (x) => OnPositionChanged(0, x);
+            soPosY.OnChanged += (y) => OnPositionChanged(1, y);
+            soPosZ.OnChanged += (z) => OnPositionChanged(2, z);
+
+            soPosX.OnConfirmed += OnModifyConfirm;
+            soPosY.OnConfirmed += OnModifyConfirm;
+            soPosZ.OnConfirmed += OnModifyConfirm;
+
+            soPosX.OnFocusLost += OnModifyConfirm;
+            soPosY.OnFocusLost += OnModifyConfirm;
+            soPosZ.OnFocusLost += OnModifyConfirm;
+
+            positionLayout.AddElement(positionLbl);
+            positionLayout.AddElement(soPosX);
+            positionLayout.AddSpace(10);
+            positionLayout.AddFlexibleSpace();
+            positionLayout.AddElement(soPosY);
+            positionLayout.AddSpace(10);
+            positionLayout.AddFlexibleSpace();
+            positionLayout.AddElement(soPosZ);
+            positionLayout.AddFlexibleSpace();
+
+            GUILayoutX rotationLayout = sceneObjectLayout.AddLayoutX();
+            GUILabel rotationLbl = new GUILabel(new LocEdString("Rotation"), GUIOption.FixedWidth(50));
+            soRotX = new GUIFloatField(new LocEdString("X"), 10, "", GUIOption.FixedWidth(60));
+            soRotY = new GUIFloatField(new LocEdString("Y"), 10, "", GUIOption.FixedWidth(60));
+            soRotZ = new GUIFloatField(new LocEdString("Z"), 10, "", GUIOption.FixedWidth(60));
+
+            soRotX.OnChanged += (x) => OnRotationChanged(0, x);
+            soRotY.OnChanged += (y) => OnRotationChanged(1, y);
+            soRotZ.OnChanged += (z) => OnRotationChanged(2, z);
+
+            soRotX.OnConfirmed += OnModifyConfirm;
+            soRotY.OnConfirmed += OnModifyConfirm;
+            soRotZ.OnConfirmed += OnModifyConfirm;
+
+            soRotX.OnFocusLost += OnModifyConfirm;
+            soRotY.OnFocusLost += OnModifyConfirm;
+            soRotZ.OnFocusLost += OnModifyConfirm;
+
+            rotationLayout.AddElement(rotationLbl);
+            rotationLayout.AddElement(soRotX);
+            rotationLayout.AddSpace(10);
+            rotationLayout.AddFlexibleSpace();
+            rotationLayout.AddElement(soRotY);
+            rotationLayout.AddSpace(10);
+            rotationLayout.AddFlexibleSpace();
+            rotationLayout.AddElement(soRotZ);
+            rotationLayout.AddFlexibleSpace();
+
+            GUILayoutX scaleLayout = sceneObjectLayout.AddLayoutX();
+            GUILabel scaleLbl = new GUILabel(new LocEdString("Scale"), GUIOption.FixedWidth(50));
+            soScaleX = new GUIFloatField(new LocEdString("X"), 10, "", GUIOption.FixedWidth(60));
+            soScaleY = new GUIFloatField(new LocEdString("Y"), 10, "", GUIOption.FixedWidth(60));
+            soScaleZ = new GUIFloatField(new LocEdString("Z"), 10, "", GUIOption.FixedWidth(60));
+
+            soScaleX.OnChanged += (x) => OnScaleChanged(0, x);
+            soScaleY.OnChanged += (y) => OnScaleChanged(1, y);
+            soScaleZ.OnChanged += (z) => OnScaleChanged(2, z);
+
+            soScaleX.OnConfirmed += OnModifyConfirm;
+            soScaleY.OnConfirmed += OnModifyConfirm;
+            soScaleZ.OnConfirmed += OnModifyConfirm;
+
+            soScaleX.OnFocusLost += OnModifyConfirm;
+            soScaleY.OnFocusLost += OnModifyConfirm;
+            soScaleZ.OnFocusLost += OnModifyConfirm;
+
+            scaleLayout.AddElement(scaleLbl);
+            scaleLayout.AddElement(soScaleX);
+            scaleLayout.AddSpace(10);
+            scaleLayout.AddFlexibleSpace();
+            scaleLayout.AddElement(soScaleY);
+            scaleLayout.AddSpace(10);
+            scaleLayout.AddFlexibleSpace();
+            scaleLayout.AddElement(soScaleZ);
+            scaleLayout.AddFlexibleSpace();
+
+            sceneObjectLayout.AddFlexibleSpace();
+
+            GUITexture titleBg = new GUITexture(null, EditorStyles.InspectorTitleBg);
+            sceneObjectBgPanel.AddElement(titleBg);
+        }
+
+        /// <summary>
+        /// Updates contents of the scene object specific fields (name, position, rotation, etc.)
+        /// </summary>
+        /// <param name="forceUpdate">If true, the GUI elements will be updated regardless of whether a change was
+        ///                           detected or not.</param>
+        private void RefreshSceneObjectFields(bool forceUpdate)
+        {
+            if (activeSO == null)
+                return;
+
+            soNameInput.Text = activeSO.Name;
+            soActiveToggle.Value = activeSO.Active;
+
+            SceneObject prefabParent = PrefabUtility.GetPrefabParent(activeSO);
+
+            // Ignore prefab parent if scene root, we only care for non-root prefab instances
+            bool hasPrefab = prefabParent != null && prefabParent.Parent != null;
+            if (soHasPrefab != hasPrefab || forceUpdate)
+            {
+                int numChildren = soPrefabLayout.ChildCount;
+                for (int i = 0; i < numChildren; i++)
+                    soPrefabLayout.GetChild(0).Destroy();
+
+                GUILabel prefabLabel =new GUILabel(new LocEdString("Prefab"), GUIOption.FixedWidth(50));
+                soPrefabLayout.AddElement(prefabLabel);
+
+                if (hasPrefab)
+                {
+                    GUIButton btnApplyPrefab = new GUIButton(new LocEdString("Apply"), GUIOption.FixedWidth(60));
+                    GUIButton btnRevertPrefab = new GUIButton(new LocEdString("Revert"), GUIOption.FixedWidth(60));
+                    GUIButton btnBreakPrefab = new GUIButton(new LocEdString("Break"), GUIOption.FixedWidth(60));
+
+                    btnApplyPrefab.OnClick += () => PrefabUtility.ApplyPrefab(activeSO);
+                    btnRevertPrefab.OnClick += () =>
+                    {
+                        UndoRedo.RecordSO(activeSO, true, "Reverting \"" + activeSO.Name + "\" to prefab.");
+
+                        PrefabUtility.RevertPrefab(activeSO);
+                        EditorApplication.SetSceneDirty();
+                    };
+                    btnBreakPrefab.OnClick += () =>
+                    {
+                        UndoRedo.BreakPrefab(activeSO, "Breaking prefab link for " + activeSO.Name);
+
+                        EditorApplication.SetSceneDirty();
+                    };
+
+                    soPrefabLayout.AddElement(btnApplyPrefab);
+                    soPrefabLayout.AddElement(btnRevertPrefab);
+                    soPrefabLayout.AddElement(btnBreakPrefab);
+                }
+                else
+                {
+                    GUILabel noPrefabLabel = new GUILabel("None");
+                    soPrefabLayout.AddElement(noPrefabLabel);
+                }
+
+                soHasPrefab = hasPrefab;
+            }
+
+            Vector3 position;
+            Vector3 angles;
+            if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
+            {
+                position = activeSO.Position;
+                angles = activeSO.Rotation.ToEuler();
+            }
+            else
+            {
+                position = activeSO.LocalPosition;
+                angles = activeSO.LocalRotation.ToEuler();
+            }
+
+            Vector3 scale = activeSO.LocalScale;
+
+            if(!soPosX.HasInputFocus)
+                soPosX.Value = position.x;
+
+            if (!soPosY.HasInputFocus)
+                soPosY.Value = position.y;
+
+            if (!soPosZ.HasInputFocus)
+                soPosZ.Value = position.z;
+
+            if (!soRotX.HasInputFocus)
+                soRotX.Value = angles.x;
+
+            if (!soRotY.HasInputFocus)
+                soRotY.Value = angles.y;
+
+            if (!soRotZ.HasInputFocus)
+                soRotZ.Value = angles.z;
+
+            if (!soScaleX.HasInputFocus)
+                soScaleX.Value = scale.x;
+
+            if (!soScaleY.HasInputFocus)
+                soScaleY.Value = scale.y;
+
+            if (!soScaleZ.HasInputFocus)
+                soScaleZ.Value = scale.z;
+        }
+
+        private void OnInitialize()
+        {
+            Selection.OnSelectionChanged += OnSelectionChanged;
+
+            const string soName = "InspectorPersistentData";
+            SceneObject so = Scene.Root.FindChild(soName);
+            if (so == null)
+                so = new SceneObject(soName, true);
+
+            persistentData = so.GetComponent<InspectorPersistentData>();
+            if (persistentData == null)
+                persistentData = so.AddComponent<InspectorPersistentData>();
+
+            OnSelectionChanged(new SceneObject[0], new string[0]);
+        }
+
+        private void OnDestroy()
+        {
+            Selection.OnSelectionChanged -= OnSelectionChanged;
+        }
+
+        private void OnEditorUpdate()
+        {
+            if (currentType == InspectorType.SceneObject)
+            {
+                Component[] allComponents = activeSO.GetComponents();
+                bool requiresRebuild = allComponents.Length != inspectorComponents.Count;
+
+                if (!requiresRebuild)
+                {
+                    for (int i = 0; i < inspectorComponents.Count; i++)
+                    {
+                        if (inspectorComponents[i].instanceId != allComponents[i].InstanceId)
+                        {
+                            requiresRebuild = true;
+                            break;
+                        }
+                    }
+                }
+
+                if (requiresRebuild)
+                {
+                    SceneObject so = activeSO;
+                    Clear();
+                    SetObjectToInspect(so);
+                }
+                else
+                {
+                    RefreshSceneObjectFields(false);
+
+                    InspectableState componentModifyState = InspectableState.NotModified;
+                    for (int i = 0; i < inspectorComponents.Count; i++)
+                        componentModifyState |= inspectorComponents[i].inspector.Refresh();
+
+                    if (componentModifyState.HasFlag(InspectableState.ModifyInProgress))
+                        EditorApplication.SetSceneDirty();
+
+                    modifyState |= componentModifyState;
+                }
+            }
+            else if (currentType == InspectorType.Resource)
+            {
+                inspectorResource.inspector.Refresh();
+            }
+
+            // Detect drag and drop
+            bool isValidDrag = false;
+
+            if (activeSO != null)
+            {
+                if ((DragDrop.DragInProgress || DragDrop.DropInProgress) && DragDrop.Type == DragDropType.Resource)
+                {
+                    Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition);
+                    Vector2I scrollPos = windowPos;
+                    Rect2I contentBounds = inspectorLayout.Bounds;
+                    scrollPos.x -= contentBounds.x;
+                    scrollPos.y -= contentBounds.y;
+
+                    bool isInBounds = false;
+                    Rect2I dropArea = new Rect2I();
+                    foreach (var bounds in dropAreas)
+                    {
+                        if (bounds.Contains(scrollPos))
+                        {
+                            isInBounds = true;
+                            dropArea = bounds;
+                            break;
+                        }
+                    }
+
+                    Type draggedComponentType = null;
+                    if (isInBounds)
+                    {
+                        ResourceDragDropData dragData = DragDrop.Data as ResourceDragDropData;
+                        if (dragData != null)
+                        {
+                            foreach (var resPath in dragData.Paths)
+                            {
+                                ResourceMeta meta = ProjectLibrary.GetMeta(resPath);
+                                if (meta != null)
+                                {
+                                    if (meta.ResType == ResourceType.ScriptCode)
+                                    {
+                                        ScriptCode scriptFile = ProjectLibrary.Load<ScriptCode>(resPath);
+
+                                        if (scriptFile != null)
+                                        {
+                                            Type[] scriptTypes = scriptFile.Types;
+                                            foreach (var type in scriptTypes)
+                                            {
+                                                if (type.IsSubclassOf(typeof (Component)))
+                                                {
+                                                    draggedComponentType = type;
+                                                    isValidDrag = true;
+                                                    break;
+                                                }
+                                            }
+
+                                            if (draggedComponentType != null)
+                                                break;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+
+                    if (isValidDrag)
+                    {
+                        scrollAreaHighlight.Bounds = dropArea;
+
+                        if (DragDrop.DropInProgress)
+                        {
+                            activeSO.AddComponent(draggedComponentType);
+
+                            modifyState = InspectableState.Modified;
+                            EditorApplication.SetSceneDirty();
+                        }
+                    }
+                }               
+            }
+
+            if (scrollAreaHighlight != null)
+                scrollAreaHighlight.Active = isValidDrag;
+        }
+
+        /// <summary>
+        /// Triggered when the user selects a new resource or a scene object, or deselects everything.
+        /// </summary>
+        /// <param name="objects">A set of new scene objects that were selected.</param>
+        /// <param name="paths">A set of absolute resource paths that were selected.</param>
+        private void OnSelectionChanged(SceneObject[] objects, string[] paths)
+        {
+            if (currentType == InspectorType.SceneObject && modifyState == InspectableState.NotModified)
+                UndoRedo.PopCommand(undoCommandIdx);
+
+            Clear();
+            modifyState = InspectableState.NotModified;
+
+            if (objects.Length == 0 && paths.Length == 0)
+            {
+                currentType = InspectorType.None;
+                inspectorScrollArea = new GUIScrollArea();
+                GUI.AddElement(inspectorScrollArea);
+                inspectorLayout = inspectorScrollArea.Layout;
+
+                inspectorLayout.AddFlexibleSpace();
+                GUILayoutX layoutMsg = inspectorLayout.AddLayoutX();
+                layoutMsg.AddFlexibleSpace();
+                layoutMsg.AddElement(new GUILabel(new LocEdString("No object selected")));
+                layoutMsg.AddFlexibleSpace();
+                inspectorLayout.AddFlexibleSpace();
+            }
+            else if ((objects.Length + paths.Length) > 1)
+            {
+                currentType = InspectorType.None;
+                inspectorScrollArea = new GUIScrollArea();
+                GUI.AddElement(inspectorScrollArea);
+                inspectorLayout = inspectorScrollArea.Layout;
+
+                inspectorLayout.AddFlexibleSpace();
+                GUILayoutX layoutMsg = inspectorLayout.AddLayoutX();
+                layoutMsg.AddFlexibleSpace();
+                layoutMsg.AddElement(new GUILabel(new LocEdString("Multiple objects selected")));
+                layoutMsg.AddFlexibleSpace();
+                inspectorLayout.AddFlexibleSpace();
+            }
+            else if (objects.Length == 1)
+            {
+                if (objects[0] != null)
+                {
+                    UndoRedo.RecordSO(objects[0]);
+                    undoCommandIdx = UndoRedo.TopCommandId;
+
+                    SetObjectToInspect(objects[0]);
+                }
+            }
+            else if (paths.Length == 1)
+            {
+                SetObjectToInspect(paths[0]);
+            }
+        }
+
+        /// <summary>
+        /// Triggered when the user closes or expands a component foldout, making the component fields visible or hidden.
+        /// </summary>
+        /// <param name="inspectorData">Contains GUI data for the component that was toggled.</param>
+        /// <param name="expanded">Determines whether to display or hide component contents.</param>
+        private void OnComponentFoldoutToggled(InspectorComponent inspectorData, bool expanded)
+        {
+            inspectorData.inspector.Persistent.SetBool(inspectorData.instanceId + "_Expanded", expanded);
+            inspectorData.inspector.SetVisible(expanded);
+        }
+
+        /// <summary>
+        /// Triggered when the user clicks the component remove button. Removes that component from the active scene object.
+        /// </summary>
+        /// <param name="componentType">Type of the component to remove.</param>
+        private void OnComponentRemoveClicked(Type componentType)
+        {
+            if (activeSO != null)
+            {
+                activeSO.RemoveComponent(componentType);
+
+                modifyState = InspectableState.Modified;
+                EditorApplication.SetSceneDirty();
+            }
+        }
+
+        /// <summary>
+        /// Destroys all inspector GUI elements.
+        /// </summary>
+        internal void Clear()
+        {
+            for (int i = 0; i < inspectorComponents.Count; i++)
+            {
+                inspectorComponents[i].foldout.Destroy();
+                inspectorComponents[i].removeBtn.Destroy();
+                inspectorComponents[i].inspector.Destroy();
+            }
+
+            inspectorComponents.Clear();
+
+            if (inspectorResource != null)
+            {
+                inspectorResource.inspector.Destroy();
+                inspectorResource = null;
+            }
+
+            if (inspectorScrollArea != null)
+            {
+                inspectorScrollArea.Destroy();
+                inspectorScrollArea = null;
+            }
+
+            if (scrollAreaHighlight != null)
+            {
+                scrollAreaHighlight.Destroy();
+                scrollAreaHighlight = null;
+            }
+
+            if (highlightPanel != null)
+            {
+                highlightPanel.Destroy();
+                highlightPanel = null;
+            }
+
+            activeSO = null;
+            soNameInput = null;
+            soActiveToggle = null;
+            soPrefabLayout = null;
+            soHasPrefab = false;
+            soPosX = null;
+            soPosY = null;
+            soPosZ = null;
+            soRotX = null;
+            soRotY = null;
+            soRotZ = null;
+            soScaleX = null;
+            soScaleY = null;
+            soScaleZ = null;
+            dropAreas = new Rect2I[0];
+
+            activeResource = null;
+            currentType = InspectorType.None;
+        }
+
+        /// <summary>
+        /// Returns the size of the title bar area that is displayed for <see cref="SceneObject"/> specific fields.
+        /// </summary>
+        /// <returns>Area of the title bar, relative to the window.</returns>
+        private Rect2I GetTitleBounds()
+        {
+            return new Rect2I(0, 0, Width, 115);
+        }
+
+        /// <summary>
+        /// Triggered when the user changes the name of the currently active scene object.
+        /// </summary>
+        private void OnSceneObjectRename(string name)
+        {
+            if (activeSO != null)
+            {
+                activeSO.Name = name;
+
+                modifyState |= InspectableState.ModifyInProgress;
+                EditorApplication.SetSceneDirty();
+            }
+        }
+
+        /// <summary>
+        /// Triggered when the user changes the active state of the scene object.
+        /// </summary>
+        /// <param name="active">True if the object is active, false otherwise.</param>
+        private void OnSceneObjectActiveStateToggled(bool active)
+        {
+            if (activeSO != null)
+                activeSO.Active = active;
+        }
+
+        /// <summary>
+        /// Triggered when the scene object modification is confirmed by the user.
+        /// </summary>
+        private void OnModifyConfirm()
+        {
+            if (modifyState.HasFlag(InspectableState.ModifyInProgress))
+                modifyState = InspectableState.Modified;
+        }
+
+        /// <summary>
+        /// Triggered when the position value in the currently active <see cref="SceneObject"/> changes. Updates the 
+        /// necessary GUI elements.
+        /// </summary>
+        /// <param name="idx">Index of the coordinate that was changed.</param>
+        /// <param name="value">New value of the field.</param>
+        private void OnPositionChanged(int idx, float value)
+        {
+            if (activeSO == null)
+                return;
+
+            if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
+            {
+                Vector3 position = activeSO.Position;
+                position[idx] = value;
+                activeSO.Position = position;
+            }
+            else
+            {
+                Vector3 position = activeSO.LocalPosition;
+                position[idx] = value;
+                activeSO.LocalPosition = position;
+            }
+
+            modifyState = InspectableState.ModifyInProgress;
+            EditorApplication.SetSceneDirty();
+        }
+
+        /// <summary>
+        /// Triggered when the rotation value in the currently active <see cref="SceneObject"/> changes. Updates the 
+        /// necessary GUI elements.
+        /// </summary>
+        /// <param name="idx">Index of the euler angle that was changed (0 - X, 1 - Y, 2 - Z).</param>
+        /// <param name="value">New value of the field.</param>
+        private void OnRotationChanged(int idx, float value)
+        {
+            if (activeSO == null)
+                return;
+
+            if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
+            {
+                Vector3 angles = activeSO.Rotation.ToEuler();
+                angles[idx] = value;
+                activeSO.Rotation = Quaternion.FromEuler(angles);
+            }
+            else
+            {
+                Vector3 angles = activeSO.LocalRotation.ToEuler();
+                angles[idx] = value;
+                activeSO.LocalRotation = Quaternion.FromEuler(angles);
+            }
+
+            modifyState = InspectableState.ModifyInProgress;
+            EditorApplication.SetSceneDirty();
+        }
+
+        /// <summary>
+        /// Triggered when the scale value in the currently active <see cref="SceneObject"/> changes. Updates the 
+        /// necessary GUI elements.
+        /// </summary>
+        /// <param name="idx">Index of the coordinate that was changed.</param>
+        /// <param name="value">New value of the field.</param>
+        private void OnScaleChanged(int idx, float value)
+        {
+            if (activeSO == null)
+                return;
+
+            Vector3 scale = activeSO.LocalScale;
+            scale[idx] = value;
+            activeSO.LocalScale = scale;
+
+            modifyState = InspectableState.ModifyInProgress;
+            EditorApplication.SetSceneDirty();
+        }
+
+        /// <inheritdoc/>
+        protected override void WindowResized(int width, int height)
+        {
+            base.WindowResized(width, height);
+
+            UpdateDropAreas();
+        }
+
+        /// <summary>
+        /// Updates drop areas used for dragging and dropping components on the inspector.
+        /// </summary>
+        private void UpdateDropAreas()
+        {
+            if (activeSO == null)
+                return;
+
+            Rect2I contentBounds = inspectorLayout.Bounds;
+            dropAreas = new Rect2I[inspectorComponents.Count + 1];
+            int yOffset = GetTitleBounds().height;
+            for (int i = 0; i < inspectorComponents.Count; i++)
+            {
+                dropAreas[i] = new Rect2I(0, yOffset, contentBounds.width, COMPONENT_SPACING);
+                yOffset += inspectorComponents[i].title.Bounds.height + inspectorComponents[i].panel.Bounds.height + COMPONENT_SPACING;
+            }
+
+            dropAreas[dropAreas.Length - 1] = new Rect2I(0, yOffset, contentBounds.width, contentBounds.height - yOffset);
+        }
+    }
+}