Browse Source

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 10 years ago
parent
commit
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);
+        }
+    }
+}