Bladeren bron

More work on preparing documentation for doxygen generation

BearishSun 10 jaren geleden
bovenliggende
commit
7c44f4279e

+ 0 - 1
BansheeCore/BansheeCore.vcxproj

@@ -512,7 +512,6 @@
     <ClCompile Include="Source\BsShaderIncludeImporter.cpp" />
     <ClCompile Include="Source\BsShaderIncludeImporter.cpp" />
     <ClCompile Include="Source\BsPixelData.cpp" />
     <ClCompile Include="Source\BsPixelData.cpp" />
     <ClCompile Include="Source\BsPixelUtil.cpp" />
     <ClCompile Include="Source\BsPixelUtil.cpp" />
-    <ClCompile Include="Source\BsPixelVolume.cpp" />
     <ClCompile Include="Source\BsPlatform.cpp" />
     <ClCompile Include="Source\BsPlatform.cpp" />
     <ClCompile Include="Source\BsProfilingManager.cpp" />
     <ClCompile Include="Source\BsProfilingManager.cpp" />
     <ClCompile Include="Source\BsQueryManager.cpp" />
     <ClCompile Include="Source\BsQueryManager.cpp" />

+ 922 - 919
BansheeCore/BansheeCore.vcxproj.filters

@@ -1,920 +1,923 @@
-<?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\Utility">
-      <UniqueIdentifier>{2c09857e-4a4a-480f-8ebb-1661a9ce78dd}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Importer">
-      <UniqueIdentifier>{f1fb2bc5-43c6-476a-89e3-b7de86c5aebe}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Resources">
-      <UniqueIdentifier>{e091a28f-6a0f-44ab-a88f-83e3c970c2f3}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Importer">
-      <UniqueIdentifier>{7ac6e5cb-48f7-4a49-a793-fb2ccfabe895}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Resources">
-      <UniqueIdentifier>{6df1cc13-bf9e-45e7-90ae-337999c702cf}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Scene">
-      <UniqueIdentifier>{327fbccb-fd0d-4fb1-af08-5d00cd7d56a7}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Scene">
-      <UniqueIdentifier>{2211ce11-e426-4aad-a5e6-73727d44bb98}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\RTTI">
-      <UniqueIdentifier>{75249db9-4f2e-43c3-8df4-37250c4b60a2}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Input">
-      <UniqueIdentifier>{7f8e94f3-6990-4723-965a-2b4f9346a7ee}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Input">
-      <UniqueIdentifier>{724588b9-04e2-4e9b-9467-b064ed44f05e}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Material">
-      <UniqueIdentifier>{299ec378-4e67-4818-92f6-ab5ffb9aa9ad}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Material">
-      <UniqueIdentifier>{96caf3fa-c267-4fb4-aaa8-83519666d079}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Renderer">
-      <UniqueIdentifier>{5303462d-20d9-4c00-86b8-162e3a430b07}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Renderer">
-      <UniqueIdentifier>{307618fb-e6a0-41ed-b274-fb1f5f4c6f74}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\RTTI">
-      <UniqueIdentifier>{dc50e07b-6351-4bc2-8bfa-cc3fc1d26c39}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Win32">
-      <UniqueIdentifier>{1d3fe8eb-ec10-4356-90f0-b27f89f01a13}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Text">
-      <UniqueIdentifier>{1daa1a6e-95c0-4e63-b339-4a884773fa64}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Text">
-      <UniqueIdentifier>{96b913ee-4ffb-4c60-9aa9-a51e0faf8060}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Core">
-      <UniqueIdentifier>{62281c40-1fc0-47f6-bc61-ff28314d8e13}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Core">
-      <UniqueIdentifier>{402fe837-7d94-4343-a288-c8308fda8c18}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Platform">
-      <UniqueIdentifier>{d53f502a-b966-4162-a828-af2654f0408f}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Platform">
-      <UniqueIdentifier>{88dfbdf1-6999-424c-ac32-1ffe65b6c9f6}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\RenderAPI">
-      <UniqueIdentifier>{3480589d-111c-44b8-b0f1-a178cd00f31e}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\RenderAPI">
-      <UniqueIdentifier>{e0bdc5fc-afd1-46f9-9e3e-f85ca3e220b8}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Utility">
-      <UniqueIdentifier>{0d63b345-0a58-4df2-9d01-f4da53fc40c9}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Header Files\Localization">
-      <UniqueIdentifier>{df01dcc2-a0b0-48a8-a6fd-59a556cb67f9}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Localization">
-      <UniqueIdentifier>{f8c05475-0bc9-44d9-9702-985ec016f0ba}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Source Files\Win32">
-      <UniqueIdentifier>{86aae89f-a09f-469d-bc37-60c7decba0cb}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="Include\BsRenderStats.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCommonTypes.h">
-      <Filter>Header Files\Utility</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCoreApplication.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsViewport.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsUUID.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPixelVolume.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPixelUtil.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsDeferredCallManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTextData.h">
-      <Filter>Header Files\Text</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsFontManager.h">
-      <Filter>Header Files\Text</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsFontImportOptions.h">
-      <Filter>Header Files\Text</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsFontDesc.h">
-      <Filter>Header Files\Text</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsFont.h">
-      <Filter>Header Files\Text</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsComponent.h">
-      <Filter>Header Files\Scene</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGameObject.h">
-      <Filter>Header Files\Scene</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGameObjectHandle.h">
-      <Filter>Header Files\Scene</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGameObjectManager.h">
-      <Filter>Header Files\Scene</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSceneObject.h">
-      <Filter>Header Files\Scene</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsBlendStateRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsComponentRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsDepthStencilStateRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsFontImportOptionsRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsFontRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGameObjectHandleRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGameObjectRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGpuProgramRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGpuResourceDataRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsImportOptionsRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMaterialRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMeshBaseRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMeshDataRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Source\BsMeshRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPassRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPixelDataRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRasterizerStateRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsResourceHandleRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsResourceManifestRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsResourceRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSamplerStateRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSceneObjectRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsShaderRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTechniqueRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTextureRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVertexDataDescRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVertexDeclarationRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVertexDataDesc.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTransientMesh.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTextureManager.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTexture.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsResources.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsResourceManifest.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsResourceHandle.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsResource.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPixelData.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMeshHeap.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMeshData.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMeshBase.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMesh.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGpuResourceData.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVideoModeInfo.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVertexDeclaration.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVertexData.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsVertexBuffer.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTimerQuery.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTextureView.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSubMesh.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSamplerState.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRenderWindowManager.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRenderWindow.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRenderTexture.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRenderTarget.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRenderStateManager.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRasterizerState.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsQueryManager.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPixelBuffer.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsOcclusionQuery.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMultiRenderTexture.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMeshManager.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsIndexBuffer.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsHardwareBufferManager.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsHardwareBuffer.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGpuProgramManager.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGpuProgram.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGpuParams.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGpuParamDesc.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGpuParamBlockBuffer.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGpuParam.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGpuBufferView.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsGpuBuffer.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsEventQuery.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsDrawOps.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsDepthStencilState.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsBlendState.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRendererManager.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRendererFactory.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\Win32\BsWin32FolderMonitor.h">
-      <Filter>Header Files\Platform</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\Win32\BsWin32DropTarget.h">
-      <Filter>Header Files\Platform</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPlatform.h">
-      <Filter>Header Files\Platform</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsFolderMonitor.h">
-      <Filter>Header Files\Platform</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTechnique.h">
-      <Filter>Header Files\Material</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsShader.h">
-      <Filter>Header Files\Material</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPass.h">
-      <Filter>Header Files\Material</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMaterialManager.h">
-      <Filter>Header Files\Material</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMaterial.h">
-      <Filter>Header Files\Material</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRawInputHandler.h">
-      <Filter>Header Files\Input</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsOSInputHandler.h">
-      <Filter>Header Files\Input</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsInputFwd.h">
-      <Filter>Header Files\Input</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsInput.h">
-      <Filter>Header Files\Input</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSpecificImporter.h">
-      <Filter>Header Files\Importer</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsImportOptions.h">
-      <Filter>Header Files\Importer</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsImporter.h">
-      <Filter>Header Files\Importer</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCoreThreadAccessor.h">
-      <Filter>Header Files\Core</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCoreThread.h">
-      <Filter>Header Files\Core</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCoreObjectManager.h">
-      <Filter>Header Files\Core</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCoreObject.h">
-      <Filter>Header Files\Core</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCommandQueue.h">
-      <Filter>Header Files\Core</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCoreSceneManager.h">
-      <Filter>Header Files\Scene</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCorePrerequisites.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsProfilerCPU.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsProfilerGPU.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsProfilingManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTextureImportOptions.h">
-      <Filter>Header Files\Importer</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsTextureImportOptionsRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsResourceMetaData.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsResourceMetaDataRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsViewportRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMaterialParam.h">
-      <Filter>Header Files\Material</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCoreObjectCore.h">
-      <Filter>Header Files\Core</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsCoreRenderer.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRenderAPI.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRenderAPIManager.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRenderAPIFactory.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRenderAPICapabilities.h">
-      <Filter>Header Files\RenderAPI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsIResourceListener.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsResourceListenerManager.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsUtility.h">
-      <Filter>Header Files\Utility</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSavedResourceData.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsSavedResourceDataRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\Win32\BsWin32Defs.h">
-      <Filter>Header Files\Platform</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\Win32\BSWin32PlatformData.h">
-      <Filter>Header Files\Platform</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\Win32\BsWin32Platform.h">
-      <Filter>Header Files\Platform</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsShaderIncludeImporter.h">
-      <Filter>Header Files\Importer</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsShaderInclude.h">
-      <Filter>Header Files\Resources</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsShaderIncludeRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsShaderManager.h">
-      <Filter>Header Files\Material</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMeshImportOptions.h">
-      <Filter>Header Files\Importer</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMeshImportOptionsRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPrefab.h">
-      <Filter>Header Files\Scene</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPrefabRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPrefabDiff.h">
-      <Filter>Header Files\Scene</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPrefabDiffRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsMeshUtility.h">
-      <Filter>Header Files\Utility</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsPrefabUtility.h">
-      <Filter>Header Files\Scene</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRendererMeshData.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsHString.h">
-      <Filter>Header Files\Localization</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsStringTable.h">
-      <Filter>Header Files\Localization</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsStringTableManager.h">
-      <Filter>Header Files\Localization</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsStringTableRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsIconUtility.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\Win32\BsWin32Window.h">
-      <Filter>Header Files\Win32</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsParamBlocks.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
-    <ClInclude Include="Include\BsRendererUtility.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="Source\BsCoreApplication.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsViewport.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsUUID.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsPixelVolume.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsPixelUtil.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsDrawOps.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsDeferredCallManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsFont.cpp">
-      <Filter>Source Files\Text</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsFontImportOptions.cpp">
-      <Filter>Source Files\Text</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsFontManager.cpp">
-      <Filter>Source Files\Text</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTextData.cpp">
-      <Filter>Source Files\Text</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsComponent.cpp">
-      <Filter>Source Files\Scene</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGameObject.cpp">
-      <Filter>Source Files\Scene</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGameObjectHandle.cpp">
-      <Filter>Source Files\Scene</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGameObjectManager.cpp">
-      <Filter>Source Files\Scene</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsSceneObject.cpp">
-      <Filter>Source Files\Scene</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMaterialRTTI.cpp">
-      <Filter>Source Files\RTTI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGpuResourceData.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMesh.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMeshBase.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMeshData.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMeshHeap.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsPixelData.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsResource.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsResourceHandle.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsResourceManifest.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsResources.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTexture.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTextureManager.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTransientMesh.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsVertexDataDesc.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsBlendState.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsDepthStencilState.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsEventQuery.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGpuBuffer.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGpuBufferView.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGpuParam.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGpuParamBlockBuffer.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGpuParams.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGpuProgram.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsGpuProgramManager.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsHardwareBufferManager.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsIndexBuffer.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMeshManager.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMultiRenderTexture.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsOcclusionQuery.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsPixelBuffer.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsQueryManager.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRasterizerState.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRenderStateManager.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRenderTarget.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRenderTexture.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRenderWindow.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRenderWindowManager.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsSamplerState.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTextureView.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTimerQuery.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsVertexBuffer.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsVertexData.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsVertexDeclaration.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsVideoModeInfo.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRendererManager.cpp">
-      <Filter>Source Files\Renderer</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\Win32\BsWin32FolderMonitor.cpp">
-      <Filter>Source Files\Platform</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMaterial.cpp">
-      <Filter>Source Files\Material</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMaterialManager.cpp">
-      <Filter>Source Files\Material</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsPass.cpp">
-      <Filter>Source Files\Material</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsShader.cpp">
-      <Filter>Source Files\Material</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTechnique.cpp">
-      <Filter>Source Files\Material</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsInput.cpp">
-      <Filter>Source Files\Input</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsOSInputHandler.cpp">
-      <Filter>Source Files\Input</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsImporter.cpp">
-      <Filter>Source Files\Importer</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsImportOptions.cpp">
-      <Filter>Source Files\Importer</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsSpecificImporter.cpp">
-      <Filter>Source Files\Importer</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsCommandQueue.cpp">
-      <Filter>Source Files\Core</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsCoreObject.cpp">
-      <Filter>Source Files\Core</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsCoreObjectManager.cpp">
-      <Filter>Source Files\Core</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsCoreThread.cpp">
-      <Filter>Source Files\Core</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsCoreThreadAccessor.cpp">
-      <Filter>Source Files\Core</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsCoreSceneManager.cpp">
-      <Filter>Source Files\Scene</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsProfilerCPU.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsProfilerGPU.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsProfilingManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsTextureImportOptions.cpp">
-      <Filter>Source Files\Importer</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsResourceMetaData.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMaterialParam.cpp">
-      <Filter>Source Files\Material</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsCoreObjectCore.cpp">
-      <Filter>Source Files\Core</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsCoreRenderer.cpp">
-      <Filter>Source Files\Renderer</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRenderAPI.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRenderAPIManager.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRenderAPICapabilities.cpp">
-      <Filter>Source Files\RenderAPI</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsIResourceListener.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsResourceListenerManager.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsUtility.cpp">
-      <Filter>Source Files\Utility</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsSavedResourceData.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsPlatform.cpp">
-      <Filter>Source Files\Platform</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\Win32\BsWin32Platform.cpp">
-      <Filter>Source Files\Platform</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsShaderIncludeImporter.cpp">
-      <Filter>Source Files\Importer</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsShaderInclude.cpp">
-      <Filter>Source Files\Resources</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsShaderManager.cpp">
-      <Filter>Source Files\Material</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMeshImportOptions.cpp">
-      <Filter>Source Files\Importer</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsPrefab.cpp">
-      <Filter>Source Files\Scene</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsPrefabDiff.cpp">
-      <Filter>Source Files\Scene</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsMeshUtility.cpp">
-      <Filter>Source Files\Utility</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsPrefabUtility.cpp">
-      <Filter>Source Files\Scene</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRendererMeshData.cpp">
-      <Filter>Source Files\Renderer</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsHString.cpp">
-      <Filter>Source Files\Localization</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsStringTable.cpp">
-      <Filter>Source Files\Localization</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsStringTableManager.cpp">
-      <Filter>Source Files\Localization</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsIconUtility.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\Win32\BsWin32Window.cpp">
-      <Filter>Source Files\Win32</Filter>
-    </ClCompile>
-    <ClCompile Include="Source\BsRendererUtility.cpp">
-      <Filter>Source Files\Renderer</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\Utility">
+      <UniqueIdentifier>{2c09857e-4a4a-480f-8ebb-1661a9ce78dd}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Importer">
+      <UniqueIdentifier>{f1fb2bc5-43c6-476a-89e3-b7de86c5aebe}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Resources">
+      <UniqueIdentifier>{e091a28f-6a0f-44ab-a88f-83e3c970c2f3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Importer">
+      <UniqueIdentifier>{7ac6e5cb-48f7-4a49-a793-fb2ccfabe895}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Resources">
+      <UniqueIdentifier>{6df1cc13-bf9e-45e7-90ae-337999c702cf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Scene">
+      <UniqueIdentifier>{327fbccb-fd0d-4fb1-af08-5d00cd7d56a7}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Scene">
+      <UniqueIdentifier>{2211ce11-e426-4aad-a5e6-73727d44bb98}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\RTTI">
+      <UniqueIdentifier>{75249db9-4f2e-43c3-8df4-37250c4b60a2}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Input">
+      <UniqueIdentifier>{7f8e94f3-6990-4723-965a-2b4f9346a7ee}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Input">
+      <UniqueIdentifier>{724588b9-04e2-4e9b-9467-b064ed44f05e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Material">
+      <UniqueIdentifier>{299ec378-4e67-4818-92f6-ab5ffb9aa9ad}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Material">
+      <UniqueIdentifier>{96caf3fa-c267-4fb4-aaa8-83519666d079}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Renderer">
+      <UniqueIdentifier>{5303462d-20d9-4c00-86b8-162e3a430b07}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Renderer">
+      <UniqueIdentifier>{307618fb-e6a0-41ed-b274-fb1f5f4c6f74}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\RTTI">
+      <UniqueIdentifier>{dc50e07b-6351-4bc2-8bfa-cc3fc1d26c39}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Win32">
+      <UniqueIdentifier>{1d3fe8eb-ec10-4356-90f0-b27f89f01a13}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Text">
+      <UniqueIdentifier>{1daa1a6e-95c0-4e63-b339-4a884773fa64}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Text">
+      <UniqueIdentifier>{96b913ee-4ffb-4c60-9aa9-a51e0faf8060}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Platform">
+      <UniqueIdentifier>{d53f502a-b966-4162-a828-af2654f0408f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Platform">
+      <UniqueIdentifier>{88dfbdf1-6999-424c-ac32-1ffe65b6c9f6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\RenderAPI">
+      <UniqueIdentifier>{3480589d-111c-44b8-b0f1-a178cd00f31e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\RenderAPI">
+      <UniqueIdentifier>{e0bdc5fc-afd1-46f9-9e3e-f85ca3e220b8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Utility">
+      <UniqueIdentifier>{0d63b345-0a58-4df2-9d01-f4da53fc40c9}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Localization">
+      <UniqueIdentifier>{df01dcc2-a0b0-48a8-a6fd-59a556cb67f9}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Localization">
+      <UniqueIdentifier>{f8c05475-0bc9-44d9-9702-985ec016f0ba}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Win32">
+      <UniqueIdentifier>{86aae89f-a09f-469d-bc37-60c7decba0cb}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Profiling">
+      <UniqueIdentifier>{4ecc02bc-09b0-4d03-a3c0-0ebb7f154d3c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Profiling">
+      <UniqueIdentifier>{66694132-958f-435a-808f-3c6eb325a322}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\CoreThread">
+      <UniqueIdentifier>{402fe837-7d94-4343-a288-c8308fda8c18}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\CoreThread">
+      <UniqueIdentifier>{62281c40-1fc0-47f6-bc61-ff28314d8e13}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Include\BsCommonTypes.h">
+      <Filter>Header Files\Utility</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCoreApplication.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTextData.h">
+      <Filter>Header Files\Text</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsFontManager.h">
+      <Filter>Header Files\Text</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsFontImportOptions.h">
+      <Filter>Header Files\Text</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsFontDesc.h">
+      <Filter>Header Files\Text</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsFont.h">
+      <Filter>Header Files\Text</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsComponent.h">
+      <Filter>Header Files\Scene</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGameObject.h">
+      <Filter>Header Files\Scene</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGameObjectHandle.h">
+      <Filter>Header Files\Scene</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGameObjectManager.h">
+      <Filter>Header Files\Scene</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSceneObject.h">
+      <Filter>Header Files\Scene</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsBlendStateRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsComponentRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsDepthStencilStateRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsFontImportOptionsRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsFontRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGameObjectHandleRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGameObjectRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuProgramRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuResourceDataRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsImportOptionsRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMaterialRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMeshBaseRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMeshDataRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\BsMeshRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPassRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPixelDataRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRasterizerStateRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsResourceHandleRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsResourceManifestRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsResourceRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSamplerStateRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSceneObjectRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsShaderRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTechniqueRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTextureRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVertexDataDescRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVertexDeclarationRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVertexDataDesc.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTransientMesh.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTextureManager.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTexture.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsResources.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsResourceManifest.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsResourceHandle.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsResource.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPixelData.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMeshHeap.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMeshData.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMeshBase.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMesh.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuResourceData.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVideoModeInfo.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVertexDeclaration.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVertexData.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsVertexBuffer.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTimerQuery.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTextureView.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSubMesh.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSamplerState.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRenderWindowManager.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRenderWindow.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRenderTexture.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRenderTarget.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRenderStateManager.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRasterizerState.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsQueryManager.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPixelBuffer.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsOcclusionQuery.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMultiRenderTexture.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMeshManager.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsIndexBuffer.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsHardwareBufferManager.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsHardwareBuffer.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuProgramManager.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuProgram.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuParams.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuParamDesc.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuParamBlockBuffer.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuParam.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuBufferView.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsGpuBuffer.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsEventQuery.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsDrawOps.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsDepthStencilState.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsBlendState.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRendererManager.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRendererFactory.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\Win32\BsWin32FolderMonitor.h">
+      <Filter>Header Files\Platform</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\Win32\BsWin32DropTarget.h">
+      <Filter>Header Files\Platform</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPlatform.h">
+      <Filter>Header Files\Platform</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsFolderMonitor.h">
+      <Filter>Header Files\Platform</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTechnique.h">
+      <Filter>Header Files\Material</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsShader.h">
+      <Filter>Header Files\Material</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPass.h">
+      <Filter>Header Files\Material</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMaterialManager.h">
+      <Filter>Header Files\Material</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMaterial.h">
+      <Filter>Header Files\Material</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRawInputHandler.h">
+      <Filter>Header Files\Input</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsOSInputHandler.h">
+      <Filter>Header Files\Input</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsInputFwd.h">
+      <Filter>Header Files\Input</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsInput.h">
+      <Filter>Header Files\Input</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSpecificImporter.h">
+      <Filter>Header Files\Importer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsImportOptions.h">
+      <Filter>Header Files\Importer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsImporter.h">
+      <Filter>Header Files\Importer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCoreThreadAccessor.h">
+      <Filter>Header Files\CoreThread</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCoreThread.h">
+      <Filter>Header Files\CoreThread</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCoreObjectManager.h">
+      <Filter>Header Files\CoreThread</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCoreObject.h">
+      <Filter>Header Files\CoreThread</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCommandQueue.h">
+      <Filter>Header Files\CoreThread</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCoreSceneManager.h">
+      <Filter>Header Files\Scene</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCorePrerequisites.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTextureImportOptions.h">
+      <Filter>Header Files\Importer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsTextureImportOptionsRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsResourceMetaData.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsResourceMetaDataRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsViewportRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMaterialParam.h">
+      <Filter>Header Files\Material</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCoreObjectCore.h">
+      <Filter>Header Files\CoreThread</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsCoreRenderer.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRenderAPI.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRenderAPIManager.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRenderAPIFactory.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRenderAPICapabilities.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsUtility.h">
+      <Filter>Header Files\Utility</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSavedResourceData.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsSavedResourceDataRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\Win32\BsWin32Defs.h">
+      <Filter>Header Files\Platform</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\Win32\BSWin32PlatformData.h">
+      <Filter>Header Files\Platform</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\Win32\BsWin32Platform.h">
+      <Filter>Header Files\Platform</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsShaderIncludeImporter.h">
+      <Filter>Header Files\Importer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsShaderInclude.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsShaderIncludeRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsShaderManager.h">
+      <Filter>Header Files\Material</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMeshImportOptions.h">
+      <Filter>Header Files\Importer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMeshImportOptionsRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPrefab.h">
+      <Filter>Header Files\Scene</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPrefabRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPrefabDiff.h">
+      <Filter>Header Files\Scene</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPrefabDiffRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsMeshUtility.h">
+      <Filter>Header Files\Utility</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPrefabUtility.h">
+      <Filter>Header Files\Scene</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRendererMeshData.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsHString.h">
+      <Filter>Header Files\Localization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsStringTable.h">
+      <Filter>Header Files\Localization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsStringTableManager.h">
+      <Filter>Header Files\Localization</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsStringTableRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\Win32\BsWin32Window.h">
+      <Filter>Header Files\Win32</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsParamBlocks.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRendererUtility.h">
+      <Filter>Header Files\Renderer</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsProfilerCPU.h">
+      <Filter>Header Files\Profiling</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsProfilerGPU.h">
+      <Filter>Header Files\Profiling</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsProfilingManager.h">
+      <Filter>Header Files\Profiling</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsRenderStats.h">
+      <Filter>Header Files\Profiling</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsDeferredCallManager.h">
+      <Filter>Header Files\Utility</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsResourceListenerManager.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsIconUtility.h">
+      <Filter>Header Files\Utility</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsIResourceListener.h">
+      <Filter>Header Files\Resources</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsUUID.h">
+      <Filter>Header Files\Utility</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsViewport.h">
+      <Filter>Header Files\RenderAPI</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPixelUtil.h">
+      <Filter>Header Files\Utility</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\BsPixelVolume.h">
+      <Filter>Header Files\Utility</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Source\BsCoreApplication.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsFont.cpp">
+      <Filter>Source Files\Text</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsFontImportOptions.cpp">
+      <Filter>Source Files\Text</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsFontManager.cpp">
+      <Filter>Source Files\Text</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTextData.cpp">
+      <Filter>Source Files\Text</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsComponent.cpp">
+      <Filter>Source Files\Scene</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGameObject.cpp">
+      <Filter>Source Files\Scene</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGameObjectHandle.cpp">
+      <Filter>Source Files\Scene</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGameObjectManager.cpp">
+      <Filter>Source Files\Scene</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsSceneObject.cpp">
+      <Filter>Source Files\Scene</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMaterialRTTI.cpp">
+      <Filter>Source Files\RTTI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGpuResourceData.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMesh.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMeshBase.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMeshData.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMeshHeap.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsPixelData.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsResource.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsResourceHandle.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsResourceManifest.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsResources.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTexture.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTextureManager.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTransientMesh.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsVertexDataDesc.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsBlendState.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsDepthStencilState.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsEventQuery.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGpuBuffer.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGpuBufferView.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGpuParam.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGpuParamBlockBuffer.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGpuParams.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGpuProgram.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsGpuProgramManager.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsHardwareBufferManager.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsIndexBuffer.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMeshManager.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMultiRenderTexture.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsOcclusionQuery.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsPixelBuffer.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsQueryManager.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRasterizerState.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRenderStateManager.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRenderTarget.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRenderTexture.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRenderWindow.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRenderWindowManager.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsSamplerState.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTextureView.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTimerQuery.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsVertexBuffer.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsVertexData.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsVertexDeclaration.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsVideoModeInfo.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRendererManager.cpp">
+      <Filter>Source Files\Renderer</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\Win32\BsWin32FolderMonitor.cpp">
+      <Filter>Source Files\Platform</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMaterial.cpp">
+      <Filter>Source Files\Material</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMaterialManager.cpp">
+      <Filter>Source Files\Material</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsPass.cpp">
+      <Filter>Source Files\Material</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsShader.cpp">
+      <Filter>Source Files\Material</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTechnique.cpp">
+      <Filter>Source Files\Material</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsInput.cpp">
+      <Filter>Source Files\Input</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsOSInputHandler.cpp">
+      <Filter>Source Files\Input</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsImporter.cpp">
+      <Filter>Source Files\Importer</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsImportOptions.cpp">
+      <Filter>Source Files\Importer</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsSpecificImporter.cpp">
+      <Filter>Source Files\Importer</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsCommandQueue.cpp">
+      <Filter>Source Files\CoreThread</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsCoreObject.cpp">
+      <Filter>Source Files\CoreThread</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsCoreObjectManager.cpp">
+      <Filter>Source Files\CoreThread</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsCoreThread.cpp">
+      <Filter>Source Files\CoreThread</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsCoreThreadAccessor.cpp">
+      <Filter>Source Files\CoreThread</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsCoreSceneManager.cpp">
+      <Filter>Source Files\Scene</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsTextureImportOptions.cpp">
+      <Filter>Source Files\Importer</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsResourceMetaData.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMaterialParam.cpp">
+      <Filter>Source Files\Material</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsCoreObjectCore.cpp">
+      <Filter>Source Files\CoreThread</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsCoreRenderer.cpp">
+      <Filter>Source Files\Renderer</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRenderAPI.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRenderAPIManager.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRenderAPICapabilities.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsUtility.cpp">
+      <Filter>Source Files\Utility</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsSavedResourceData.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsPlatform.cpp">
+      <Filter>Source Files\Platform</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\Win32\BsWin32Platform.cpp">
+      <Filter>Source Files\Platform</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsShaderIncludeImporter.cpp">
+      <Filter>Source Files\Importer</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsShaderInclude.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsShaderManager.cpp">
+      <Filter>Source Files\Material</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMeshImportOptions.cpp">
+      <Filter>Source Files\Importer</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsPrefab.cpp">
+      <Filter>Source Files\Scene</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsPrefabDiff.cpp">
+      <Filter>Source Files\Scene</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsMeshUtility.cpp">
+      <Filter>Source Files\Utility</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsPrefabUtility.cpp">
+      <Filter>Source Files\Scene</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRendererMeshData.cpp">
+      <Filter>Source Files\Renderer</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsHString.cpp">
+      <Filter>Source Files\Localization</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsStringTable.cpp">
+      <Filter>Source Files\Localization</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsStringTableManager.cpp">
+      <Filter>Source Files\Localization</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\Win32\BsWin32Window.cpp">
+      <Filter>Source Files\Win32</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsRendererUtility.cpp">
+      <Filter>Source Files\Renderer</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsProfilerCPU.cpp">
+      <Filter>Source Files\Profiling</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsProfilerGPU.cpp">
+      <Filter>Source Files\Profiling</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsProfilingManager.cpp">
+      <Filter>Source Files\Profiling</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsDeferredCallManager.cpp">
+      <Filter>Source Files\Utility</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsResourceListenerManager.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsDrawOps.cpp">
+      <Filter>Source Files\Utility</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsIconUtility.cpp">
+      <Filter>Source Files\Utility</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsUUID.cpp">
+      <Filter>Source Files\Utility</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsIResourceListener.cpp">
+      <Filter>Source Files\Resources</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsViewport.cpp">
+      <Filter>Source Files\RenderAPI</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\BsPixelUtil.cpp">
+      <Filter>Source Files\Utility</Filter>
+    </ClCompile>
+  </ItemGroup>
 </Project>
 </Project>

+ 380 - 394
BansheeCore/Include/BsCommandQueue.h

@@ -1,394 +1,380 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsAsyncOp.h"
-#include <functional>
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Command queue policy that provides no synchonization. Should be used
-	 * 			with command queues that are used on a single thread only.
-	 */
-	class CommandQueueNoSync
-	{
-	public:
-		CommandQueueNoSync() {}
-		virtual ~CommandQueueNoSync() {}
-
-		bool isValidThread(BS_THREAD_ID_TYPE ownerThread) const
-		{
-			return BS_THREAD_CURRENT_ID == ownerThread;
-		}
-
-		void lock() { };
-		void unlock() { }
-	};
-
-	/**
-	 * @brief	Command queue policy that provides synchonization. Should be used
-	 * 			with command queues that are used on multiple threads.
-	 */
-	class CommandQueueSync
-	{
-	public:
-		CommandQueueSync()
-			:mLock(mCommandQueueMutex, BS_DEFER_LOCK)
-		{ }
-		virtual ~CommandQueueSync() {}
-
-		bool isValidThread(BS_THREAD_ID_TYPE ownerThread) const
-		{
-			return true;
-		}
-
-		void lock() 
-		{
-			mLock.lock();
-		};
-
-		void unlock()
-		{
-			mLock.unlock();
-		}
-
-	private:
-		BS_MUTEX(mCommandQueueMutex);
-		BS_LOCK_TYPE mLock;
-	};
-
-	/**
-	 * @brief	Represents a single queued command in the command list. Contains all the data for executing the command
-	 * 			and checking up on the command status.
-	 */
-	struct QueuedCommand
-	{
-#if BS_DEBUG_MODE
-		QueuedCommand(std::function<void(AsyncOp&)> _callback, UINT32 _debugId, const AsyncOpSyncDataPtr& asyncOpSyncData,
-			bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
-			:callbackWithReturnValue(_callback), debugId(_debugId), returnsValue(true), 
-			notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(asyncOpSyncData)
-		{ }
-
-		QueuedCommand(std::function<void()> _callback, UINT32 _debugId, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
-			:callback(_callback), debugId(_debugId), returnsValue(false), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(AsyncOpEmpty())
-		{ }
-
-		UINT32 debugId;
-#else
-		QueuedCommand(std::function<void(AsyncOp&)> _callback, const AsyncOpSyncDataPtr& asyncOpSyncData, 
-			bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
-			:callbackWithReturnValue(_callback), returnsValue(true), notifyWhenComplete(_notifyWhenComplete), 
-			callbackId(_callbackId), asyncOp(asyncOpSyncData)
-		{ }
-
-		QueuedCommand(std::function<void()> _callback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
-			:callback(_callback), returnsValue(false), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(AsyncOpEmpty())
-		{ }
-#endif
-
-		~QueuedCommand()
-		{ }
-
-		QueuedCommand(const QueuedCommand& source)
-		{
-			callback = source.callback;
-			callbackWithReturnValue = source.callbackWithReturnValue;
-			asyncOp = source.asyncOp;
-			returnsValue = source.returnsValue;
-			callbackId = source.callbackId;
-			notifyWhenComplete = source.notifyWhenComplete;
-
-#if BS_DEBUG_MODE
-			debugId = source.debugId;
-#endif
-		}
-
-		QueuedCommand& operator=(const QueuedCommand& rhs)
-		{
-			callback = rhs.callback;
-			callbackWithReturnValue = rhs.callbackWithReturnValue;
-			asyncOp = rhs.asyncOp;
-			returnsValue = rhs.returnsValue;
-			callbackId = rhs.callbackId;
-			notifyWhenComplete = rhs.notifyWhenComplete;
-			
-#if BS_DEBUG_MODE
-			debugId = rhs.debugId;
-#endif
-
-			return *this;
-		}
-
-		std::function<void()> callback;
-		std::function<void(AsyncOp&)> callbackWithReturnValue;
-		AsyncOp asyncOp;
-		bool returnsValue;
-		UINT32 callbackId;
-		bool notifyWhenComplete;
-	};
-
-	/**
-	 * @brief	Contains a list of commands you may queue for later execution on the core thread.
-	 */
-	class BS_CORE_EXPORT CommandQueueBase
-	{
-	public:
-		/**
-		 * @brief	Constructor.
-		 *
-		 * @param	threadId	   	Identifier for the thread the command queue will be getting commands from.					
-		 */
-		CommandQueueBase(BS_THREAD_ID_TYPE threadId);
-		virtual ~CommandQueueBase();
-
-		/**
-		 * @brief	Gets the thread identifier the command queue is used on.
-		 * 			
-		 * @note	If the command queue is using a synchonized access policy generally this
-		 * 			is not relevant as it may be used on multiple threads.
-		 */
-		BS_THREAD_ID_TYPE getThreadId() const { return mMyThreadId; }
-
-		/**
-		 * @brief	Executes all provided commands one by one in order. To get the commands you should call flush().
-		 *
-		 * @param	notifyCallback  	Callback that will be called if a command that has "notifyOnComplete" flag set.
-		 * 								The callback will receive "callbackId" of the command.
-		 */
-		void playbackWithNotify(Queue<QueuedCommand>* commands, std::function<void(UINT32)> notifyCallback);
-
-		/**
-		 * @brief	Executes all provided commands one by one in order. To get the commands you should call flush().
-		 */
-		void playback(Queue<QueuedCommand>* commands);
-
-		/**
-		 * @brief	Allows you to set a breakpoint that will trigger when the specified command is executed.
-		 * 			
-		 * @note	This is helpful when you receive an error on the executing thread and you cannot tell from where was
-		 * 			the command that caused the error queued from. However you can make a note of the queue and command index
-		 * 			and set a breakpoint so that it gets triggered next time you run the program. At that point you can know 
-		 * 			exactly which part of code queued the command by examining the stack trace.
-		 *
-		 * @param	queueIdx  	Zero-based index of the queue the command was queued on.
-		 * @param	commandIdx	Zero-based index of the command.
-		 */
-		static void addBreakpoint(UINT32 queueIdx, UINT32 commandIdx);
-
-		/**
-		 * @brief	Queue up a new command to execute. Make sure the provided function has all of its
-		 * 			parameters properly bound. Last parameter must be unbound and of AsyncOp& type.
-		 * 			This is used to signal that the command is completed, and also for storing the return
-		 * 			value.
-		 * 			
-		 * 			@note	Callback method also needs to call AsyncOp::markAsResolved once it is done
-		 * 			processing. (If it doesn't it will still be called automatically, but the return
-		 * 			value will default to nullptr)
-		 *
-		 * @param	_notifyWhenComplete	(optional) Call the notify method (provided in the call to CommandQueue::playback)
-		 * 								when the command is complete.
-		 * @param	_callbackId			(optional) Identifier for the callback so you can then later find it
-		 * 								if needed.
-		 *
-		 * @return	Async operation object that you can continuously check until the command completes. After
-		 * 			it completes AsyncOp::isResolved will return true and return data will be valid (if
-		 * 			the callback provided any).
-		 */
-		AsyncOp queueReturn(std::function<void(AsyncOp&)> commandCallback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0);
-
-		/**
-		 * @brief	Queue up a new command to execute. Make sure the provided function has all of its
-		 * 			parameters properly bound. Provided command is not expected to return a value. If you
-		 * 			wish to return a value from the callback use the queueReturn which accepts an AsyncOp parameter.
-		 *
-		 * @param	_notifyWhenComplete	(optional) Call the notify method (provided in the call to CommandQueue::playback)
-		 * 								when the command is complete.
-		 * @param	_callbackId		   	(optional) Identifier for the callback so you can then later find
-		 * 								it if needed.
-		 */
-		void queue(std::function<void()> commandCallback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0);
-
-		/**
-		 * @brief	Returns a copy of all queued commands and makes room for new ones. Must be called from the thread
-		 * 			that created the command queue. Returned commands MUST be passed to "playback" method.
-		 */
-		BansheeEngine::Queue<QueuedCommand>* flush();
-
-		/**
-		 * @brief	Cancels all currently queued commands.
-		 */
-		void cancelAll();
-
-		/**
-		 * @brief	Returns true if no commands are queued.
-		 */
-		bool isEmpty();
-
-	protected:
-		/**
-		 * @brief	Helper method that throws an "Invalid thread" exception. Used primarily
-		 * 			so we can avoid including Exception include in this header.
-		 */
-		void throwInvalidThreadException(const String& message) const;
-
-	private:
-		BansheeEngine::Queue<QueuedCommand>* mCommands;
-		Stack<BansheeEngine::Queue<QueuedCommand>*> mEmptyCommandQueues; // List of empty queues for reuse
-
-		AsyncOpSyncDataPtr mAsyncOpSyncData;
-		BS_THREAD_ID_TYPE mMyThreadId;
-
-		// Various variables that allow for easier debugging by allowing us to trigger breakpoints
-		// when a certain command was queued.
-#if BS_DEBUG_MODE
-		struct QueueBreakpoint
-		{
-			class HashFunction
-			{
-			public:
-				size_t operator()(const QueueBreakpoint &key) const;
-			};
-
-			class EqualFunction
-			{
-			public:
-				bool operator()(const QueueBreakpoint &a, const QueueBreakpoint &b) const;
-			};
-
-			QueueBreakpoint(UINT32 _queueIdx, UINT32 _commandIdx)
-				:queueIdx(_queueIdx), commandIdx(_commandIdx)
-			{ }
-
-			UINT32 queueIdx;
-			UINT32 commandIdx;
-
-			inline size_t operator()(const QueueBreakpoint& v) const;
-		};
-
-		UINT32 mMaxDebugIdx;
-		UINT32 mCommandQueueIdx;
-		
-		static UINT32 MaxCommandQueueIdx;
-		static UnorderedSet<QueueBreakpoint, QueueBreakpoint::HashFunction, QueueBreakpoint::EqualFunction> SetBreakpoints;
-		BS_STATIC_MUTEX(CommandQueueBreakpointMutex);
-
-		/**
-		 * @brief	Checks if the specified command has a breakpoint and throw an assert if it does.
-		 */
-		static void breakIfNeeded(UINT32 queueIdx, UINT32 commandIdx);
-#endif
-	};
-
-	/**
-	 * @copydoc CommandQueueBase
-	 * 			
-	 * @brief	Use SyncPolicy to choose whether you want command queue be synchonized or not. Synchonized
-	 * 			command queues may be used across multiple threads and non-synchonized only on one.
-	 */
-	template<class SyncPolicy = CommandQueueNoSync>
-	class CommandQueue : public CommandQueueBase, public SyncPolicy
-	{
-	public:
-		/**
-		 * @copydoc CommandQueueBase::CommandQueueBase
-		 */
-		CommandQueue(BS_THREAD_ID_TYPE threadId)
-			:CommandQueueBase(threadId)
-		{ }
-
-		~CommandQueue() 
-		{ }
-
-		/**
-		 * @copydoc CommandQueueBase::queueReturn
-		 */
-		AsyncOp queueReturn(std::function<void(AsyncOp&)> commandCallback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
-		{
-#if BS_DEBUG_MODE
-#if BS_THREAD_SUPPORT != 0
-			if(!isValidThread(getThreadId()))
-				throwInvalidThreadException("Command queue accessed outside of its creation thread.");
-#endif
-#endif
-
-			lock();
-			AsyncOp asyncOp = CommandQueueBase::queueReturn(commandCallback, _notifyWhenComplete, _callbackId);
-			unlock();
-
-			return asyncOp;
-		}
-
-		/**
-		 * @copydoc CommandQueueBase::queue
-		 */
-		void queue(std::function<void()> commandCallback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
-		{
-#if BS_DEBUG_MODE
-#if BS_THREAD_SUPPORT != 0
-			if(!isValidThread(getThreadId()))
-				throwInvalidThreadException("Command queue accessed outside of its creation thread.");
-#endif
-#endif
-
-			lock();
-			CommandQueueBase::queue(commandCallback, _notifyWhenComplete, _callbackId);
-			unlock();
-		}
-
-		/**
-		 * @copydoc CommandQueueBase::flush
-		 */
-		BansheeEngine::Queue<QueuedCommand>* flush()
-		{
-#if BS_DEBUG_MODE
-#if BS_THREAD_SUPPORT != 0
-			if(!isValidThread(getThreadId()))
-				throwInvalidThreadException("Command queue accessed outside of its creation thread.");
-#endif
-#endif
-
-			lock();
-			BansheeEngine::Queue<QueuedCommand>* commands = CommandQueueBase::flush();
-			unlock();
-
-			return commands;
-		}
-
-		/**
-		 * @copydoc CommandQueueBase::cancelAll
-		 */
-		void cancelAll()
-		{
-#if BS_DEBUG_MODE
-#if BS_THREAD_SUPPORT != 0
-			if(!isValidThread(getThreadId()))
-				throwInvalidThreadException("Command queue accessed outside of its creation thread.");
-#endif
-#endif
-
-			lock();
-			CommandQueueBase::cancelAll();
-			unlock();
-		}
-
-		/**
-		 * @copydoc CommandQueueBase::isEmpty
-		 */
-		bool isEmpty()
-		{
-#if BS_DEBUG_MODE
-#if BS_THREAD_SUPPORT != 0
-			if(!isValidThread(getThreadId()))
-				throwInvalidThreadException("Command queue accessed outside of its creation thread.");
-#endif
-#endif
-
-			lock();
-			bool empty = CommandQueueBase::isEmpty();
-			unlock();
-
-			return empty;
-		}
-	};
-}
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsAsyncOp.h"
+#include <functional>
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup CoreThread
+	 *  @{
+	 */
+
+	/**
+	 * Command queue policy that provides no synchonization. Should be used with command queues that are used on a single 
+	 * thread only.
+	 */
+	class CommandQueueNoSync
+	{
+	public:
+		CommandQueueNoSync() {}
+		virtual ~CommandQueueNoSync() {}
+
+		bool isValidThread(BS_THREAD_ID_TYPE ownerThread) const
+		{
+			return BS_THREAD_CURRENT_ID == ownerThread;
+		}
+
+		void lock() { };
+		void unlock() { }
+	};
+
+	/**
+	 * Command queue policy that provides synchonization. Should be used with command queues that are used on multiple 
+	 * threads.
+	 */
+	class CommandQueueSync
+	{
+	public:
+		CommandQueueSync()
+			:mLock(mCommandQueueMutex, BS_DEFER_LOCK)
+		{ }
+		virtual ~CommandQueueSync() {}
+
+		bool isValidThread(BS_THREAD_ID_TYPE ownerThread) const
+		{
+			return true;
+		}
+
+		void lock() 
+		{
+			mLock.lock();
+		};
+
+		void unlock()
+		{
+			mLock.unlock();
+		}
+
+	private:
+		BS_MUTEX(mCommandQueueMutex);
+		BS_LOCK_TYPE mLock;
+	};
+
+	/**
+	 * Represents a single queued command in the command list. Contains all the data for executing the command and checking 
+	 * up on the command status.
+	 */
+	struct QueuedCommand
+	{
+#if BS_DEBUG_MODE
+		QueuedCommand(std::function<void(AsyncOp&)> _callback, UINT32 _debugId, const AsyncOpSyncDataPtr& asyncOpSyncData,
+			bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
+			:callbackWithReturnValue(_callback), debugId(_debugId), returnsValue(true), 
+			notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(asyncOpSyncData)
+		{ }
+
+		QueuedCommand(std::function<void()> _callback, UINT32 _debugId, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
+			:callback(_callback), debugId(_debugId), returnsValue(false), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(AsyncOpEmpty())
+		{ }
+
+		UINT32 debugId;
+#else
+		QueuedCommand(std::function<void(AsyncOp&)> _callback, const AsyncOpSyncDataPtr& asyncOpSyncData, 
+			bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
+			:callbackWithReturnValue(_callback), returnsValue(true), notifyWhenComplete(_notifyWhenComplete), 
+			callbackId(_callbackId), asyncOp(asyncOpSyncData)
+		{ }
+
+		QueuedCommand(std::function<void()> _callback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
+			:callback(_callback), returnsValue(false), notifyWhenComplete(_notifyWhenComplete), callbackId(_callbackId), asyncOp(AsyncOpEmpty())
+		{ }
+#endif
+
+		~QueuedCommand()
+		{ }
+
+		QueuedCommand(const QueuedCommand& source)
+		{
+			callback = source.callback;
+			callbackWithReturnValue = source.callbackWithReturnValue;
+			asyncOp = source.asyncOp;
+			returnsValue = source.returnsValue;
+			callbackId = source.callbackId;
+			notifyWhenComplete = source.notifyWhenComplete;
+
+#if BS_DEBUG_MODE
+			debugId = source.debugId;
+#endif
+		}
+
+		QueuedCommand& operator=(const QueuedCommand& rhs)
+		{
+			callback = rhs.callback;
+			callbackWithReturnValue = rhs.callbackWithReturnValue;
+			asyncOp = rhs.asyncOp;
+			returnsValue = rhs.returnsValue;
+			callbackId = rhs.callbackId;
+			notifyWhenComplete = rhs.notifyWhenComplete;
+			
+#if BS_DEBUG_MODE
+			debugId = rhs.debugId;
+#endif
+
+			return *this;
+		}
+
+		std::function<void()> callback;
+		std::function<void(AsyncOp&)> callbackWithReturnValue;
+		AsyncOp asyncOp;
+		bool returnsValue;
+		UINT32 callbackId;
+		bool notifyWhenComplete;
+	};
+
+	/** Contains a list of commands you may queue for later execution on the core thread. */
+	class BS_CORE_EXPORT CommandQueueBase
+	{
+	public:
+		/**
+		 * Constructor.
+		 *
+		 * @param[in]	threadId	   	Identifier for the thread the command queue will be getting commands from.					
+		 */
+		CommandQueueBase(BS_THREAD_ID_TYPE threadId);
+		virtual ~CommandQueueBase();
+
+		/**
+		 * Gets the thread identifier the command queue is used on.
+		 * 			
+		 * @note	If the command queue is using a synchonized access policy generally this is not relevant as it may be 
+		 *			used on multiple threads.
+		 */
+		BS_THREAD_ID_TYPE getThreadId() const { return mMyThreadId; }
+
+		/**
+		 * Executes all provided commands one by one in order. To get the commands you should call flush().
+		 *
+		 * @param[in]	notifyCallback  	Callback that will be called if a command that has @p notifyOnComplete flag set.
+		 * 									The callback will receive @p callbackId of the command.
+		 */
+		void playbackWithNotify(Queue<QueuedCommand>* commands, std::function<void(UINT32)> notifyCallback);
+
+		/** Executes all provided commands one by one in order. To get the commands you should call flush(). */
+		void playback(Queue<QueuedCommand>* commands);
+
+		/**
+		 * Allows you to set a breakpoint that will trigger when the specified command is executed.		
+		 *
+		 * @param[in]	queueIdx  	Zero-based index of the queue the command was queued on.
+		 * @param[in]	commandIdx	Zero-based index of the command.
+		 *
+		 * @note	
+		 * This is helpful when you receive an error on the executing thread and you cannot tell from where was the command 
+		 * that caused the error queued from. However you can make a note of the queue and command index and set a 
+		 * breakpoint so that it gets triggered next time you run the program. At that point you can know exactly which part
+		 * of code queued the command by examining the stack trace.
+		 */
+		static void addBreakpoint(UINT32 queueIdx, UINT32 commandIdx);
+
+		/**
+		 * Queue up a new command to execute. Make sure the provided function has all of its parameters properly bound. 
+		 * Last parameter must be unbound and of AsyncOp& type. This is used to signal that the command is completed, and 
+		 * also for storing the return value.		
+		 *
+		 * @param[in]	_notifyWhenComplete	(optional) Call the notify method (provided in the call to playback())
+		 * 									when the command is complete.
+		 * @param[in]	_callbackId			(optional) Identifier for the callback so you can then later find it
+		 * 									if needed.
+		 *
+		 * @return							Async operation object that you can continuously check until the command 
+		 *									completes. After it completes AsyncOp::isResolved() will return true and return 
+		 *									data will be valid (if the callback provided any).
+		 *
+		 * @note	
+		 * Callback method also needs to call AsyncOp::markAsResolved once it is done processing. (If it doesn't it will 
+		 * still be called automatically, but the return value will default to nullptr)
+		 */
+		AsyncOp queueReturn(std::function<void(AsyncOp&)> commandCallback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0);
+
+		/**
+		 * Queue up a new command to execute. Make sure the provided function has all of its parameters properly bound. 
+		 * Provided command is not expected to return a value. If you wish to return a value from the callback use the 
+		 * queueReturn() which accepts an AsyncOp parameter.
+		 *
+		 * @param[in]	_notifyWhenComplete	(optional) Call the notify method (provided in the call to playback())
+		 * 									when the command is complete.
+		 * @param[in]	_callbackId		   	(optional) Identifier for the callback so you can then later find
+		 * 									it if needed.
+		 */
+		void queue(std::function<void()> commandCallback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0);
+
+		/**
+		 * Returns a copy of all queued commands and makes room for new ones. Must be called from the thread that created 
+		 * the command queue. Returned commands must be passed to playback() method.
+		 */
+		Queue<QueuedCommand>* flush();
+
+		/** Cancels all currently queued commands. */
+		void cancelAll();
+
+		/**	Returns true if no commands are queued. */
+		bool isEmpty();
+
+	protected:
+		/**
+		 * Helper method that throws an "Invalid thread" exception. Used primarily so we can avoid including Exception 
+		 * include in this header.
+		 */
+		void throwInvalidThreadException(const String& message) const;
+
+	private:
+		Queue<QueuedCommand>* mCommands;
+		Stack<Queue<QueuedCommand>*> mEmptyCommandQueues; /**< List of empty queues for reuse. */
+
+		AsyncOpSyncDataPtr mAsyncOpSyncData;
+		BS_THREAD_ID_TYPE mMyThreadId;
+
+		// Various variables that allow for easier debugging by allowing us to trigger breakpoints
+		// when a certain command was queued.
+#if BS_DEBUG_MODE
+		struct QueueBreakpoint
+		{
+			class HashFunction
+			{
+			public:
+				size_t operator()(const QueueBreakpoint &key) const;
+			};
+
+			class EqualFunction
+			{
+			public:
+				bool operator()(const QueueBreakpoint &a, const QueueBreakpoint &b) const;
+			};
+
+			QueueBreakpoint(UINT32 _queueIdx, UINT32 _commandIdx)
+				:queueIdx(_queueIdx), commandIdx(_commandIdx)
+			{ }
+
+			UINT32 queueIdx;
+			UINT32 commandIdx;
+
+			inline size_t operator()(const QueueBreakpoint& v) const;
+		};
+
+		UINT32 mMaxDebugIdx;
+		UINT32 mCommandQueueIdx;
+		
+		static UINT32 MaxCommandQueueIdx;
+		static UnorderedSet<QueueBreakpoint, QueueBreakpoint::HashFunction, QueueBreakpoint::EqualFunction> SetBreakpoints;
+		BS_STATIC_MUTEX(CommandQueueBreakpointMutex);
+
+		/** Checks if the specified command has a breakpoint and throw an assert if it does. */
+		static void breakIfNeeded(UINT32 queueIdx, UINT32 commandIdx);
+#endif
+	};
+
+	/**
+	 * @copydoc CommandQueueBase
+	 * 			
+	 * Use SyncPolicy to choose whether you want command queue be synchonized or not. Synchonized command queues may be 
+	 * used across multiple threads and non-synchonized only on one.
+	 */
+	template<class SyncPolicy = CommandQueueNoSync>
+	class CommandQueue : public CommandQueueBase, public SyncPolicy
+	{
+	public:
+		/** @copydoc CommandQueueBase::CommandQueueBase */
+		CommandQueue(BS_THREAD_ID_TYPE threadId)
+			:CommandQueueBase(threadId)
+		{ }
+
+		~CommandQueue() 
+		{ }
+
+		/** @copydoc CommandQueueBase::queueReturn */
+		AsyncOp queueReturn(std::function<void(AsyncOp&)> commandCallback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
+		{
+#if BS_DEBUG_MODE
+#if BS_THREAD_SUPPORT != 0
+			if(!isValidThread(getThreadId()))
+				throwInvalidThreadException("Command queue accessed outside of its creation thread.");
+#endif
+#endif
+
+			lock();
+			AsyncOp asyncOp = CommandQueueBase::queueReturn(commandCallback, _notifyWhenComplete, _callbackId);
+			unlock();
+
+			return asyncOp;
+		}
+
+		/** @copydoc CommandQueueBase::queue */
+		void queue(std::function<void()> commandCallback, bool _notifyWhenComplete = false, UINT32 _callbackId = 0)
+		{
+#if BS_DEBUG_MODE
+#if BS_THREAD_SUPPORT != 0
+			if(!isValidThread(getThreadId()))
+				throwInvalidThreadException("Command queue accessed outside of its creation thread.");
+#endif
+#endif
+
+			lock();
+			CommandQueueBase::queue(commandCallback, _notifyWhenComplete, _callbackId);
+			unlock();
+		}
+
+		/** @copydoc CommandQueueBase::flush */
+		BansheeEngine::Queue<QueuedCommand>* flush()
+		{
+#if BS_DEBUG_MODE
+#if BS_THREAD_SUPPORT != 0
+			if(!isValidThread(getThreadId()))
+				throwInvalidThreadException("Command queue accessed outside of its creation thread.");
+#endif
+#endif
+
+			lock();
+			BansheeEngine::Queue<QueuedCommand>* commands = CommandQueueBase::flush();
+			unlock();
+
+			return commands;
+		}
+
+		/** @copydoc CommandQueueBase::cancelAll */
+		void cancelAll()
+		{
+#if BS_DEBUG_MODE
+#if BS_THREAD_SUPPORT != 0
+			if(!isValidThread(getThreadId()))
+				throwInvalidThreadException("Command queue accessed outside of its creation thread.");
+#endif
+#endif
+
+			lock();
+			CommandQueueBase::cancelAll();
+			unlock();
+		}
+
+		/** @copydoc CommandQueueBase::isEmpty */
+		bool isEmpty()
+		{
+#if BS_DEBUG_MODE
+#if BS_THREAD_SUPPORT != 0
+			if(!isValidThread(getThreadId()))
+				throwInvalidThreadException("Command queue accessed outside of its creation thread.");
+#endif
+#endif
+
+			lock();
+			bool empty = CommandQueueBase::isEmpty();
+			unlock();
+
+			return empty;
+		}
+	};
+
+	/** @} */
+	/** @endcond */
+}

+ 294 - 290
BansheeCore/Include/BsCoreObject.h

@@ -1,290 +1,294 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsCoreObjectCore.h"
-#include "BsAsyncOp.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	This class provides some common functionality that all low-level objects
-	 * 			used on the core thread need to implement.
-	 * 			
-	 * @note	This involves initializing, keeping track of, and releasing GPU resources.
-	 * 			All core GPU objects are initialized on the core thread, and destroyed on the core thread,
-	 * 			so majority of these methods will just schedule object initialization/destruction.
-	 * 			Non-GPU core objects can normally be initialized on the caller thread.
-	 */
-	class BS_CORE_EXPORT CoreObject
-	{
-	protected:
-		/**
-		 * @brief	Values that represent current state of the object
-		 */
-		enum Flags
-		{
-			CGO_DESTROYED = 0x01, /**< Object has been destroyed and shouldn't be used. */
-			CGO_INIT_ON_CORE_THREAD = 0x02 /**< Object requires initialization on core thread. */
-		};
-
-	public:
-		/**
-		 * @brief	Constructs a new core object.
-		 *
-		 * @param	requiresGpuInit	(optional) If true the objects initialize_internal and destroy_internal methods
-		 * 							will be called from the core thread asynchronously. Otherwise they will be called 
-		 * 							by the caller thread synchronously.
-		 */
-		CoreObject(bool requiresGpuInit = true);
-		virtual ~CoreObject();
-
-		/**
-		 * @brief	Frees all the data held by this object.
-		 * 			
-		 * @note	If is created with "CGO_INIT_ON_CORE_THREAD" flag destruction is not done immediately, 
-		 * 			and is instead just scheduled on the core thread. 
-		 * 			Unless called from core thread in which case it is executed immediately.
-		 * 			Objects without "CGO_INIT_ON_CORE_THREAD" flag are destructed immediately.
-		 */
-		virtual void destroy();
-
-		/**
-		 * @brief	Initializes all the internal resources of this object. Should be called by the
-		 * 			factory creation methods automatically after construction and not by user directly.
-		 * 					
-		 * @note	If is created with "CGO_INIT_ON_CORE_THREAD" flag initialization is not done immediately, 
-		 * 			and is instead just scheduled on the core thread. 
-		 * 			Unless called from core thread in which case it is executed immediately.
-		 * 			Objects without "CGO_INIT_ON_CORE_THREAD" flag are initialized immediately.
-		 */
-		virtual void initialize();
-
-		/**
-		 * @brief	Returns true if the object has been destroyed. Destroyed object should not be used.
-		 */
-		bool isDestroyed() const { return (mFlags & CGO_DESTROYED) != 0; }
-
-		/**
-		 * @brief	Blocks the current thread until the resource is fully initialized.
-		 * 			
-		 * @note	If you call this without calling initialize first a deadlock will occur.
-		 * 			You should not call this from core thread.
-		 */
-		void blockUntilCoreInitialized();
-
-		/**
-		 * @brief	Internal method. Sets a shared this pointer to this object. This MUST be called immediately after construction.
-		 *
-		 * @note	Called automatically by the factory creation methods so user should not call this manually.
-		 */
-		void _setThisPtr(std::shared_ptr<CoreObject> ptrThis);
-
-		/**
-		 * @brief	Returns an unique identifier for this object.
-		 */
-		UINT64 getInternalID() const { return mInternalID; }
-
-		/**
-		 * @brief	Internal method. Schedules the object to be destroyed, and then deleted.
-		 */
-		template<class T, class MemAlloc>
-		static void _delete(CoreObject* obj)
-		{
-			if (!obj->isDestroyed())
-				obj->destroy();
-
-			bs_delete<T, MemAlloc>((T*)obj);
-		}
-
-		/**
-		 * @brief	Returns a shared_ptr version of "this" pointer.
-		 */
-		SPtr<CoreObject> getThisPtr() const { return mThis.lock(); }
-
-		/**
-		 * @brief	Returns an object that contains a core thread specific implementation
-		 *			of this CoreObject. 
-		 *
-		 * @note	Thread safe to retrieve, but its data is only valid on the core thread.
-		 */
-		SPtr<CoreObjectCore> getCore() const { return mCoreSpecific; }
-
-		/**
-		 * @brief	Ensures all dirty syncable data is send to the core thread variant of this object.
-		 *
-		 * @note	Call this if you have modified the object and need to make sure core thread has an up
-		 *			to date version. Normally this is done automatically at the end of a frame.
-		 */
-		void syncToCore(CoreAccessor& accessor);
-
-	protected:
-		/**
-		 * @brief	Queues a command to be executed on the core thread, without a return value.
-		 * 			
-		 * @note	Requires a shared pointer to the object this function will be executed on, in order to 
-		 * 			make sure the object is not deleted before the command executes. Can be null if the 
-		 * 			function is static or global.
-		 */
-		static void queueGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void()> func);
-
-		/**
-		 * @brief	Queues a command to be executed on the core thread, with a return value in the form of AsyncOp.
-		 * 			
-		 * @see		AsyncOp
-		 * 			
-		 * @note	Requires a shared pointer to the object this function will be executed on, in order to
-		 * 			make sure the object is not deleted before the command executes. Can be null if the
-		 * 			function is static or global.
-		 */
-		static AsyncOp queueReturnGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void(AsyncOp&)> func);
-
-		bool requiresInitOnCoreThread() const { return (mFlags & CGO_INIT_ON_CORE_THREAD) != 0; }
-		void setIsDestroyed(bool destroyed) { mFlags = destroyed ? mFlags | CGO_DESTROYED : mFlags & ~CGO_DESTROYED; }
-	private:
-		friend class CoreObjectManager;
-
-		volatile UINT8 mFlags;
-		UINT32 mCoreDirtyFlags;
-		UINT64 mInternalID; // ID == 0 is not a valid ID
-		std::weak_ptr<CoreObject> mThis;
-
-		/**
-		 * @brief	Queues object initialization command on the core thread. The command is added to the
-		 * 			primary core thread queue and will be executed as soon as the core thread is ready.
-		 */
-		static void queueInitializeGpuCommand(const SPtr<CoreObjectCore>& obj);
-
-		/**
-		 * @brief	Queues object destruction command on the core thread. The command is added to the
-		 * 			core thread accessor of this thread and will be executed after accessor commands
-		 * 			are submitted and any previously queued commands are executed.
-		 *
-		 * @note	It is up to the caller to ensure no other accessors attempt to use this object.
-		 */
-		static void queueDestroyGpuCommand(const SPtr<CoreObjectCore>& obj);
-
-		/**
-		 * @brief	Helper wrapper method used for queuing commands with no return value on the core thread.
-		 */
-		static void executeGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void()> func);
-
-		/**
-		 * @brief	Helper wrapper method used for queuing commands with a return value on the core thread.
-		 */
-		static void executeReturnGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void(AsyncOp&)> func, AsyncOp& op);
-
-	protected:
-		/************************************************************************/
-		/* 							CORE OBJECT SYNC                      		*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Creates an object that contains core thread specific data and methods
-		 *			for this CoreObject. Can be null if such object is not required.
-		 */
-		virtual SPtr<CoreObjectCore> createCore() const { return nullptr; }
-
-		/**
-		 * @brief	Marks the core data as dirty. This causes the syncToCore()
-		 *			method to trigger the next time objects are synced between core and sim threads.
-		 *
-		 * @param	flags	Optional flags in case you want to signal that only part of the
-		 *					internal data is dirty. syncToCore() will be called regardless
-		 *					and it's up to the implementation to read the flags value if needed.
-		 */
-		void markCoreDirty(UINT32 flags = 0xFFFFFFFF);
-
-		/**
-		 * @brief	Marks the core data as clean. Normally called right after syncToCore()
-		 *			has been called.
-		 */
-		void markCoreClean() { mCoreDirtyFlags = 0; }
-
-		/**
-		 * @brief	Notifies the core object manager that this object is dependant on some other CoreObject(s), and the
-		 * 			dependencies changes since the last call to this method. This will trigger a call to 
-		 * 			::getCoreDependencies to collect the new dependencies.
-		 */
-		void markDependenciesDirty();
-
-		/**
-		 * @brief	Checks is the core dirty flag set. This is used by external systems 
-		 *			to know when internal data has changed and core thread potentially needs to be notified.
-		 */
-		bool isCoreDirty() const { return mCoreDirtyFlags != 0; }
-
-		/**
-		 * @brief	Returns the exact value of the internal flag that signals whether an object needs to be
-		 *			synced with the core thread.
-		 */
-		UINT32 getCoreDirtyFlags() const { return mCoreDirtyFlags; }
-
-		/**
-		 * @brief	Copy internal dirty data to a memory buffer that will be used
-		 *			for updating core thread version of that data.
-		 *
-		 * @note	This generally happens at the end of every sim thread frame. Synced data becomes
-		 *			available to the core thread the start of the next core thread frame.
-		 */
-		virtual CoreSyncData syncToCore(FrameAlloc* allocator) { return CoreSyncData(); }
-
-		/**
-		 * @brief	Populates the provided array with all core objects that this core object depends upon.
-		 */
-		virtual void getCoreDependencies(Vector<CoreObject*>& dependencies) { }
-
-	protected:
-		SPtr<CoreObjectCore> mCoreSpecific;
-	};
-
-	/**
-	 * @brief	Creates a new core object using the specified allocators and returns a shared pointer to it.
-	 *
-	 * @note	All core thread object shared pointers must be created using this method or its overloads
-	 * 			and you should not create them manually.
-	 */
-	template<class Type, class MainAlloc, class PtrDataAlloc, class... Args>
-	std::shared_ptr<Type> bs_core_ptr_new(Args &&...args)
-	{
-		return std::shared_ptr<Type>(bs_new<Type, MainAlloc>(std::forward<Args>(args)...),
-			&CoreObject::_delete<Type, MainAlloc>, StdAlloc<Type, PtrDataAlloc>());
-	}
-
-	/**
-	 * @brief	Creates a new core object using the specified allocator and returns a shared pointer to it.
-	 *
-	 * @note	All core thread object shared pointers must be created using this method or its overloads
-	 * 			and you should not create them manually.
-	 */
-	template<class Type, class MainAlloc, class... Args>
-	std::shared_ptr<Type> bs_core_ptr_new(Args &&...args)
-	{
-		return std::shared_ptr<Type>(bs_new<Type, MainAlloc>(std::forward<Args>(args)...),
-			&CoreObject::_delete<Type, MainAlloc>, StdAlloc<Type, GenAlloc>());
-	}
-
-	/**
-	 * @brief	Creates a new core object and returns a shared pointer to it.
-	 *
-	 * @note	All core thread object shared pointers must be created using this method or its overloads
-	 * 			and you should not create them manually.
-	 */
-	template<class Type, class... Args>
-	std::shared_ptr<Type> bs_core_ptr_new(Args &&...args)
-	{
-		return std::shared_ptr<Type>(bs_new<Type, GenAlloc>(std::forward<Args>(args)...),
-			&CoreObject::_delete<Type, GenAlloc>, StdAlloc<Type, GenAlloc>());
-	}
-
-	/**
-	 * @brief	Creates a core object shared pointer using a previously constructed object.
-	 *
-	 * @note	All core thread object shared pointers must be created using this method or its overloads
-	 * 			and you should not create them manually.
-	 */
-	template<class Type, class MainAlloc = GenAlloc, class PtrDataAlloc = GenAlloc>
-	std::shared_ptr<Type> bs_core_ptr(Type* data)
-	{
-		return std::shared_ptr<Type>(data, &CoreObject::_delete<Type, MainAlloc>, StdAlloc<Type, PtrDataAlloc>());  
-	}
-}
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsCoreObjectCore.h"
+#include "BsAsyncOp.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup CoreThread
+	 *  @{
+	 */
+
+	/**
+	 * Core objects provides functionality for dealing with objects that need to exist on both simulation and core thread.
+	 * It handles cross-thread initialization, destruction as well as syncing data between the two threads.
+	 * 			
+	 * It also provides a standardized way to initialize/destroy objects, and a way to specify dependant CoreObject%s. For
+	 * those purposes it might also be used for objects that only exist on the core thread.
+	 *
+	 * @note	CoreObjectCore is a counterpart to CoreObject that is used exclusively on the core thread. CoreObject on the
+	 *			other hand should be used exclusively on the simulation thread. Types that exist on both threads need to
+	 *			implement both of these.
+	 */
+	class BS_CORE_EXPORT CoreObject
+	{
+	protected:
+		/** Values that represent current state of the core object */
+		enum Flags
+		{
+			CGO_DESTROYED = 0x01, /**< Object has been destroyed and shouldn't be used. */
+			CGO_INIT_ON_CORE_THREAD = 0x02 /**< Object requires initialization on core thread. */
+		};
+
+	public:
+		/**
+		 * Frees all the data held by this object.
+		 * 			
+		 * @note	
+		 * If this object require initialization on core thread destruction is not done immediately, and is 
+		 * instead just scheduled on the core thread. Otherwise the object is destroyed immediately.
+		 */
+		virtual void destroy();
+
+		/**
+		 * Initializes all the internal resources of this object. Must be called right after construction. Generally you
+		 * should call this from a factory method to avoid the issue where user forgets to call it.
+		 * 					
+		 * @note	
+		 * If this object require initialization on core thread initialization is not done immediately, and is instead just 
+		 * scheduled on the core thread. Otherwise the object is initialized immediately.
+		 */
+		virtual void initialize();
+
+		/** Returns true if the object has been destroyed. Destroyed object should not be used. */
+		bool isDestroyed() const { return (mFlags & CGO_DESTROYED) != 0; }
+
+		/**
+		 * Blocks the current thread until the resource is fully initialized.
+		 * 			
+		 * @note	
+		 * If you call this without calling initialize first a deadlock will occur. You should not call this from core thread.
+		 */
+		void blockUntilCoreInitialized();
+
+		/** Returns an unique identifier for this object. */
+		UINT64 getInternalID() const { return mInternalID; }
+
+		/** Returns a shared_ptr version of "this" pointer. */
+		SPtr<CoreObject> getThisPtr() const { return mThis.lock(); }
+
+		/**
+		 * Returns an object that contains a core thread specific implementation of this CoreObject. Null is a valid return
+		 * value in case object requires no core thread implementation.
+		 *
+		 * @note	Thread safe to retrieve, but its data is only valid on the core thread.
+		 */
+		SPtr<CoreObjectCore> getCore() const { return mCoreSpecific; }
+
+		/**
+		 * Ensures all dirty syncable data is send to the core thread counterpart of this object (if any).
+		 *
+		 * @note	Call this if you have modified the object and need to make sure core thread has an up to date version. 
+		 *			Normally this is done automatically at the end of a frame.
+		 */
+		void syncToCore(CoreAccessor& accessor);
+
+		/** @cond INTERNAL */
+
+		/**
+		 * Sets a shared this pointer to this object. This must be called immediately after construction, but before
+		 * initialize().
+		 *
+		 * @note	Internal method.
+		 * @note	This should be called by the factory creation methods so user doesn't have to call it manually.
+		 */
+		void _setThisPtr(std::shared_ptr<CoreObject> ptrThis);
+
+		/**
+		 * Schedules the object to be destroyed, and then deleted.
+		 *
+		 * @note	Internal method.
+		 */
+		template<class T, class MemAlloc>
+		static void _delete(CoreObject* obj)
+		{
+			if (!obj->isDestroyed())
+				obj->destroy();
+
+			bs_delete<T, MemAlloc>((T*)obj);
+		}
+
+		/** @endcond */
+	protected:
+		/**
+		 * Constructs a new core object.
+		 *
+		 * @param[in]	requiresCoreInit	(optional) Determines if the CoreObjectCore counterpart of this object 
+		 *									(if it has any, see createCore()) requires initialization and destruction on the
+		 *									core thread.
+		 */
+		CoreObject(bool requiresCoreInit = true);
+		virtual ~CoreObject();
+
+		/**
+		 * Queues a command to be executed on the core thread, without a return value.
+		 * 			
+		 * @note	
+		 * Requires a shared pointer to the object this function will be executed on, in order to make sure the object is 
+		 * not deleted before the command executes. Can be null if the function is static or global.
+		 */
+		static void queueGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void()> func);
+
+		/**
+		 * Queues a command to be executed on the core thread, with a return value in the form of AsyncOp.
+		 * 			
+		 * @see		AsyncOp
+		 * 			
+		 * @note	
+		 * Requires a shared pointer to the object this function will be executed on, in order to make sure the object is 
+		 * not deleted before the command executes. Can be null if the function is static or global.
+		 */
+		static AsyncOp queueReturnGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void(AsyncOp&)> func);
+
+		bool requiresInitOnCoreThread() const { return (mFlags & CGO_INIT_ON_CORE_THREAD) != 0; }
+		void setIsDestroyed(bool destroyed) { mFlags = destroyed ? mFlags | CGO_DESTROYED : mFlags & ~CGO_DESTROYED; }
+	private:
+		friend class CoreObjectManager;
+
+		volatile UINT8 mFlags;
+		UINT32 mCoreDirtyFlags;
+		UINT64 mInternalID; // ID == 0 is not a valid ID
+		std::weak_ptr<CoreObject> mThis;
+
+		/**
+		 * Queues object initialization command on the core thread. The command is added to the primary core thread queue 
+		 * and will be executed as soon as the core thread is ready.
+		 */
+		static void queueInitializeGpuCommand(const SPtr<CoreObjectCore>& obj);
+
+		/**
+		 * Queues object destruction command on the core thread. The command is added to the core thread accessor of this 
+		 * thread and will be executed after accessor commands are submitted and any previously queued commands are executed.
+		 *
+		 * @note	It is up to the caller to ensure no other accessors attempt to use this object.
+		 */
+		static void queueDestroyGpuCommand(const SPtr<CoreObjectCore>& obj);
+
+		/** Helper wrapper method used for queuing commands with no return value on the core thread. */
+		static void executeGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void()> func);
+
+		/**	Helper wrapper method used for queuing commands with a return value on the core thread. */
+		static void executeReturnGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void(AsyncOp&)> func, AsyncOp& op);
+
+	protected:
+		/************************************************************************/
+		/* 							CORE OBJECT SYNC                      		*/
+		/************************************************************************/
+
+		/**
+		 * Creates an object that contains core thread specific data and methods for this CoreObject. Can be null if such 
+		 * object is not required.
+		 */
+		virtual SPtr<CoreObjectCore> createCore() const { return nullptr; }
+
+		/**
+		 * Marks the core data as dirty. This causes the syncToCore() method to trigger the next time objects are synced 
+		 * between core and sim threads.
+		 *
+		 * @param[in]	flags	(optional)	Flags in case you want to signal that only part of the internal data is dirty. 
+		 *									syncToCore() will be called regardless and it's up to the implementation to read
+		 *									the flags value if needed.
+		 */
+		void markCoreDirty(UINT32 flags = 0xFFFFFFFF);
+
+		/** Marks the core data as clean. Normally called right after syncToCore() has been called. */
+		void markCoreClean() { mCoreDirtyFlags = 0; }
+
+		/**
+		 * Notifies the core object manager that this object is dependant on some other CoreObject(s), and the dependencies
+		 * changed since the last call to this method. This will trigger a call to  getCoreDependencies() to collect the 
+		 * new dependencies.
+		 */
+		void markDependenciesDirty();
+
+		/**
+		 * Checks is the core dirty flag set. This is used by external systems to know when internal data has changed and 
+		 * core thread potentially needs to be notified.
+		 */
+		bool isCoreDirty() const { return mCoreDirtyFlags != 0; }
+
+		/**
+		 * Returns the exact value of the internal flag that signals whether an object needs to be synced with the core thread.
+		 */
+		UINT32 getCoreDirtyFlags() const { return mCoreDirtyFlags; }
+
+		/**
+		 * Copy internal dirty data to a memory buffer that will be used for updating core thread version of that data.
+		 *
+		 * @note	
+		 * This generally happens at the end of every sim thread frame. Synced data becomes available to the core thread 
+		 * the start of the next core thread frame.
+		 */
+		virtual CoreSyncData syncToCore(FrameAlloc* allocator) { return CoreSyncData(); }
+
+		/**
+		 * Populates the provided array with all core objects that this core object depends upon. Dependencies are required
+		 * for syncing to the core thread, so the system can be aware to update the dependant objects if a dependency is
+		 * marked as dirty. (e.g. updating a camera's viewport should also trigger an update on camera so it has
+		 * a chance to potentially update its data).
+		 */
+		virtual void getCoreDependencies(Vector<CoreObject*>& dependencies) { }
+
+	protected:
+		SPtr<CoreObjectCore> mCoreSpecific;
+	};
+
+	/**
+	 * Creates a new core object using the specified allocators and returns a shared pointer to it.
+	 *
+	 * @note	
+	 * All core thread object shared pointers must be created using this method or its overloads and you should not create 
+	 * them manually.
+	 */
+	template<class Type, class MainAlloc, class PtrDataAlloc, class... Args>
+	std::shared_ptr<Type> bs_core_ptr_new(Args &&...args)
+	{
+		return std::shared_ptr<Type>(bs_new<Type, MainAlloc>(std::forward<Args>(args)...),
+			&CoreObject::_delete<Type, MainAlloc>, StdAlloc<Type, PtrDataAlloc>());
+	}
+
+	/**
+	 * Creates a new core object using the specified allocator and returns a shared pointer to it.
+	 *
+	 * @note	
+	 * All core thread object shared pointers must be created using this method or its overloads and you should not create 
+	 * them manually.
+	 */
+	template<class Type, class MainAlloc, class... Args>
+	std::shared_ptr<Type> bs_core_ptr_new(Args &&...args)
+	{
+		return std::shared_ptr<Type>(bs_new<Type, MainAlloc>(std::forward<Args>(args)...),
+			&CoreObject::_delete<Type, MainAlloc>, StdAlloc<Type, GenAlloc>());
+	}
+
+	/**
+	 * Creates a new core object and returns a shared pointer to it.
+	 *
+	 * @note	
+	 * All core thread object shared pointers must be created using this method or its overloads and you should not create 
+	 * them manually.
+	 */
+	template<class Type, class... Args>
+	std::shared_ptr<Type> bs_core_ptr_new(Args &&...args)
+	{
+		return std::shared_ptr<Type>(bs_new<Type, GenAlloc>(std::forward<Args>(args)...),
+			&CoreObject::_delete<Type, GenAlloc>, StdAlloc<Type, GenAlloc>());
+	}
+
+	/**
+	 * Creates a core object shared pointer using a previously constructed object.
+	 *
+	 * @note	
+	 * All core thread object shared pointers must be created using this method or its overloads and you should not create 
+	 * them manually.
+	 */
+	template<class Type, class MainAlloc = GenAlloc, class PtrDataAlloc = GenAlloc>
+	std::shared_ptr<Type> bs_core_ptr(Type* data)
+	{
+		return std::shared_ptr<Type>(data, &CoreObject::_delete<Type, MainAlloc>, StdAlloc<Type, PtrDataAlloc>());  
+	}
+
+	/** @} */
+}
+

+ 90 - 87
BansheeCore/Include/BsCoreObjectCore.h

@@ -1,87 +1,90 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsAsyncOp.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Represents part of a CoreObject that is meant to be used specifically
-	 *			on the core thread. 
-	 *
-	 * @note	Core thread only.
-	 *
-	 *			Different CoreObject implementations should implement this class for their
-	 *			own needs.
-	 */
-	class BS_CORE_EXPORT CoreObjectCore
-	{
-	protected:
-		/**
-		 * @brief	Values that represent current state of the object
-		 */
-		enum Flags
-		{
-			CGCO_INITIALIZED = 0x01, /**< Object has been initialized and can be used. */
-			CGCO_SCHEDULED_FOR_INIT = 0x02 /**< Object has been scheduled for initialization but core thread has not completed it yet. */
-		};
-
-	public:
-		CoreObjectCore();
-		virtual ~CoreObjectCore();
-
-		/**
-		 * @brief	Called on the core thread when the object is first created.
-		 */
-		virtual void initialize();
-
-		/**
-		 * @brief	Internal method. Sets a shared this pointer to this object. This MUST be called immediately after construction.
-		 *
-		 * @note	Called automatically by the factory creation methods so user should not call this manually.
-		 */
-		void _setThisPtr(std::shared_ptr<CoreObjectCore> ptrThis);
-
-		/**
-		 * @brief	Returns a shared_ptr version of "this" pointer.
-		 */
-		SPtr<CoreObjectCore> getThisPtr() const { return mThis.lock(); }
-
-	protected:
-		friend class CoreObjectManager;
-		friend class CoreObject;
-
-		/**
-		 * @brief	Update internal data from provided memory buffer that
-		 *			was populated with data from the sim thread.
-		 *
-		 * @note	This generally happens at the start of a core thread frame. Data used was
-		 *			recorded on the previous sim thread frame.
-		 */
-		virtual void syncToCore(const CoreSyncData& data) { }
-
-		/**
-		 * @brief	Blocks the current thread until the resource is fully initialized.
-		 * 			
-		 * @note	If you call this without calling initialize first a deadlock will occur.
-		 * 			You should not call this from core thread.
-		 */
-		void synchronize();
-
-		/**
-		 * @brief	Returns true if the object has been properly initialized. You are not
-		 * 			allowed to call any methods on the object until it is initialized.
-		 */
-		bool isInitialized() const { return (mFlags & CGCO_INITIALIZED) != 0; }
-		bool isScheduledToBeInitialized() const { return (mFlags & CGCO_SCHEDULED_FOR_INIT) != 0; }
-
-		void setIsInitialized(bool initialized) { mFlags = initialized ? mFlags | CGCO_INITIALIZED : mFlags & ~CGCO_INITIALIZED; }
-		void setScheduledToBeInitialized(bool scheduled) { mFlags = scheduled ? mFlags | CGCO_SCHEDULED_FOR_INIT : mFlags & ~CGCO_SCHEDULED_FOR_INIT; }
-
-		volatile UINT8 mFlags;
-		std::weak_ptr<CoreObjectCore> mThis;
-
-		BS_STATIC_THREAD_SYNCHRONISER(mCoreGpuObjectLoadedCondition)
-		BS_STATIC_MUTEX(mCoreGpuObjectLoadedMutex)
-	};
-}
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsAsyncOp.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup CoreThread
+	 *  @{
+	 */
+
+	/**
+	 * Represents counterpart of a CoreObject that is meant to be used specifically on the core thread. 
+	 *
+	 * @note	Core thread only.
+	 * @note	Different CoreObject implementations should implement this class for their own needs.
+	 */
+	class BS_CORE_EXPORT CoreObjectCore
+	{
+	protected:
+		/** Values that represent current state of the object */
+		enum Flags
+		{
+			CGCO_INITIALIZED = 0x01, /**< Object has been initialized and can be used. */
+			CGCO_SCHEDULED_FOR_INIT = 0x02 /**< Object has been scheduled for initialization but core thread has not completed it yet. */
+		};
+
+	public:
+		CoreObjectCore();
+		virtual ~CoreObjectCore();
+
+		/**	Called on the core thread when the object is first created. */
+		virtual void initialize();
+
+		/** Returns a shared_ptr version of "this" pointer. */
+		SPtr<CoreObjectCore> getThisPtr() const { return mThis.lock(); }
+
+		/** @cond INTERNAL */
+
+		/**
+		 * Sets a shared this pointer to this object. This MUST be called immediately after construction.
+		 *
+		 * @note	Internal method.
+		 * @note	Called automatically by the factory creation methods so user should not call this manually.
+		 */
+		void _setThisPtr(std::shared_ptr<CoreObjectCore> ptrThis);
+
+		/** @endcond */
+
+	protected:
+		friend class CoreObjectManager;
+		friend class CoreObject;
+
+		/**
+		 * Update internal data from provided memory buffer that was populated with data from the sim thread.
+		 *
+		 * @note	
+		 * This generally happens at the start of a core thread frame. Data used was recorded on the previous sim thread 
+		 * frame.
+		 */
+		virtual void syncToCore(const CoreSyncData& data) { }
+
+		/**
+		 * Blocks the current thread until the resource is fully initialized.
+		 * 			
+		 * @note	
+		 * If you call this without calling initialize first a deadlock will occur. You should not call this from core thread.
+		 */
+		void synchronize();
+
+		/**
+		 * Returns true if the object has been properly initialized. Methods are not allowed to be called on the object
+		 * until it is initialized.
+		 */
+		bool isInitialized() const { return (mFlags & CGCO_INITIALIZED) != 0; }
+		bool isScheduledToBeInitialized() const { return (mFlags & CGCO_SCHEDULED_FOR_INIT) != 0; }
+
+		void setIsInitialized(bool initialized) { mFlags = initialized ? mFlags | CGCO_INITIALIZED : mFlags & ~CGCO_INITIALIZED; }
+		void setScheduledToBeInitialized(bool scheduled) { mFlags = scheduled ? mFlags | CGCO_SCHEDULED_FOR_INIT : mFlags & ~CGCO_SCHEDULED_FOR_INIT; }
+
+		volatile UINT8 mFlags;
+		std::weak_ptr<CoreObjectCore> mThis;
+
+		BS_STATIC_THREAD_SYNCHRONISER(mCoreGpuObjectLoadedCondition)
+		BS_STATIC_MUTEX(mCoreGpuObjectLoadedMutex)
+	};
+
+	/** @} */
+}
+

+ 142 - 151
BansheeCore/Include/BsCoreObjectManager.h

@@ -1,151 +1,142 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsCoreObjectCore.h"
-#include "BsModule.h"
-
-namespace BansheeEngine
-{
-	// TODO Low priority - Add debug option that would remember a call stack for each resource initialization,
-	// so when we fail to release one we know which one it is.
-	
-	/**
-	 * @brief	Manager that keeps track of all active CoreObjects.
-	 * 			
-	 * @note	Internal class. Thread safe unless specified otherwise.
-	 */
-	class BS_CORE_EXPORT CoreObjectManager : public Module<CoreObjectManager>
-	{
-		/**
-		 * @brief	Stores dirty data that is to be transferred from sim 
-		 *			thread to core thread part of a CoreObject, for a single object.
-		 */
-		struct CoreStoredSyncObjData
-		{
-			CoreStoredSyncObjData()
-				:internalId(0)
-			{ }
-
-			CoreStoredSyncObjData(const SPtr<CoreObjectCore> destObj, UINT64 internalId, const CoreSyncData& syncData)
-				:destinationObj(destObj), syncData(syncData), internalId(internalId)
-			{ }
-
-			std::weak_ptr<CoreObjectCore> destinationObj;
-			CoreSyncData syncData;
-			UINT64 internalId;
-		};
-
-		/**
-		 * @brief	Stores dirty data that is to be transferred from sim 
-		 *			thread to core thread part of a CoreObject, for all dirty
-		 *			objects in one frame.
-		 */
-		struct CoreStoredSyncData
-		{
-			FrameAlloc* alloc = nullptr;
-			Vector<CoreStoredSyncObjData> entries;
-		};
-
-		/**
-		 * @brief	Contains information about a dirty CoreObject that requires syncing to
-		 * 			the core thread.
-		 */	
-		struct DirtyObjectData
-		{
-			CoreObject* object;
-			INT32 syncDataId;
-		};
-
-	public:
-		CoreObjectManager();
-		~CoreObjectManager();
-
-		/**
-		 * @brief	Registers a new CoreObject notifying the manager the object
-		 * 			is created.
-		 */
-		UINT64 registerObject(CoreObject* object);
-
-		/**
-		 * @brief	Unregisters a CoreObject notifying the manager the object
-		 * 			is destroyed.
-		 */
-		void unregisterObject(CoreObject* object);
-
-		/**
-		 * @brief	Notifies the system that a CoreObject is dirty and needs to be synced with the
-		 * 			core thread.
-		 */
-		void notifyCoreDirty(CoreObject* object);
-
-		/**
-		 * @brief	Notifies the system that CoreObject dependencies are dirty and should be updated.
-		 */
-		void notifyDependenciesDirty(CoreObject* object);
-
-		/**
-		 * @brief	Synchronizes all dirty CoreObjects with the core thread. Their dirty data will be
-		 *			allocated using the global frame allocator and then queued for update using the provided
-		 *			core thread accessor.
-		 *
-		 * @note	Sim thread only.
-		 */
-		void syncToCore(CoreAccessor& accessor);
-
-		/**
-		 * @brief	Synchronizes an individual dirty CoreObject with the core thread. Its dirty data will be
-		 *			allocated using the global frame allocator and then queued for update using the provided
-		 *			core thread accessor.
-		 *
-		 * @note	Sim thread only.
-		 */
-		void syncToCore(CoreObject* object, CoreAccessor& accessor);
-
-		/**
-		 * @brief	Clears any objects that are dirty and queued for sync on the core thread. Normally you
-		 * 			only want to call this during shutdown when you no longer care about any of that data.
-		 */
-		void clearDirty();
-
-	private:
-		/**
-		 * @brief	Stores all syncable data from dirty core objects into memory allocated
-		 *			by the provided allocator. Additional meta-data is stored internally to be
-		 *			used by call to syncUpload.
-		 *
-		 * @param	allocator Allocator to use for allocating memory for stored data.
-		 *
-		 * @note	Sim thread only.
-		 *			Must be followed by a call to syncUpload with the same type.
-		 */
-		void syncDownload(FrameAlloc* allocator);
-
-		/**
-		 * @brief	Copies all the data stored by previous call to "syncDownload"
-		 *			into core thread versions of CoreObjects.
-		 *
-		 * @note	Core thread only.
-		 *			Must be preceded by a call to syncDownload.
-		 */
-		void syncUpload();
-
-		/**
-		 * @brief	Updates the cached list of dependencies and dependants for the specified object.
-		 * 			
-		 * @param	object			Update to update dependencies for.
-		 * @param	dependencies	New set of dependencies, or null to clear all dependencies.
-		 */
-		void updateDependencies(CoreObject* object, Vector<CoreObject*>* dependencies);
-
-		UINT64 mNextAvailableID;
-		Map<UINT64, CoreObject*> mObjects;
-		Map<UINT64, DirtyObjectData> mDirtyObjects;
-		Map<UINT64, Vector<CoreObject*>> mDependencies;
-		Map<UINT64, Vector<CoreObject*>> mDependants;
-
-		Vector<CoreStoredSyncObjData> mDestroyedSyncData;
-		List<CoreStoredSyncData> mCoreSyncData;
-
-		BS_MUTEX(mObjectsMutex);
-	};
-}
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsCoreObjectCore.h"
+#include "BsModule.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup CoreThread
+	 *  @{
+	 */
+
+	// TODO Low priority - Add debug option that would remember a call stack for each resource initialization,
+	// so when we fail to release one we know which one it is.
+	
+	/**
+	 * Manager that keeps track of all active CoreObject%s.
+	 * 			
+	 * @note	Internal class. 
+	 * @note	Thread safe unless specified otherwise.
+	 */
+	class BS_CORE_EXPORT CoreObjectManager : public Module<CoreObjectManager>
+	{
+		/**
+		 * Stores dirty data that is to be transferred from sim  thread to core thread part of a CoreObject, for a single 
+		 * object.
+		 */
+		struct CoreStoredSyncObjData
+		{
+			CoreStoredSyncObjData()
+				:internalId(0)
+			{ }
+
+			CoreStoredSyncObjData(const SPtr<CoreObjectCore> destObj, UINT64 internalId, const CoreSyncData& syncData)
+				:destinationObj(destObj), syncData(syncData), internalId(internalId)
+			{ }
+
+			std::weak_ptr<CoreObjectCore> destinationObj;
+			CoreSyncData syncData;
+			UINT64 internalId;
+		};
+
+		/**
+		 * Stores dirty data that is to be transferred from sim thread to core thread part of a CoreObject, for all dirty
+		 * objects in one frame.
+		 */
+		struct CoreStoredSyncData
+		{
+			FrameAlloc* alloc = nullptr;
+			Vector<CoreStoredSyncObjData> entries;
+		};
+
+		/** Contains information about a dirty CoreObject that requires syncing to the core thread. */	
+		struct DirtyObjectData
+		{
+			CoreObject* object;
+			INT32 syncDataId;
+		};
+
+	public:
+		CoreObjectManager();
+		~CoreObjectManager();
+
+		/** Registers a new CoreObject notifying the manager the object	is created. */
+		UINT64 registerObject(CoreObject* object);
+
+		/** Unregisters a CoreObject notifying the manager the object is destroyed. */
+		void unregisterObject(CoreObject* object);
+
+		/**	Notifies the system that a CoreObject is dirty and needs to be synced with the core thread. */
+		void notifyCoreDirty(CoreObject* object);
+
+		/**	Notifies the system that CoreObject dependencies are dirty and should be updated. */
+		void notifyDependenciesDirty(CoreObject* object);
+
+		/**
+		 * Synchronizes all dirty CoreObjects with the core thread. Their dirty data will be allocated using the global 
+		 * frame allocator and then queued for update using the provided core thread accessor.
+		 *
+		 * @note	Sim thread only.
+		 */
+		void syncToCore(CoreAccessor& accessor);
+
+		/**
+		 * Synchronizes an individual dirty CoreObject with the core thread. Its dirty data will be allocated using the 
+		 * global frame allocator and then queued for update using the provided core thread accessor.
+		 *
+		 * @note	Sim thread only.
+		 */
+		void syncToCore(CoreObject* object, CoreAccessor& accessor);
+
+		/**
+		 * Clears any objects that are dirty and queued for sync on the core thread. Normally you only want to call this 
+		 * during shutdown when you no longer care about any of that data.
+		 */
+		void clearDirty();
+
+	private:
+		/**
+		 * Stores all syncable data from dirty core objects into memory allocated by the provided allocator. Additional 
+		 * meta-data is stored internally to be used by call to syncUpload().
+		 *
+		 * @param[in]	allocator Allocator to use for allocating memory for stored data.
+		 *
+		 * @note	Sim thread only.
+		 * @note	Must be followed by a call to syncUpload() with the same type.
+		 */
+		void syncDownload(FrameAlloc* allocator);
+
+		/**
+		 * Copies all the data stored by previous call to syncDownload() into core thread versions of CoreObjects.
+		 *
+		 * @note	Core thread only.
+		 * @note	Must be preceded by a call to syncDownload().
+		 */
+		void syncUpload();
+
+		/**
+		 * Updates the cached list of dependencies and dependants for the specified object.
+		 * 			
+		 * @param[in]	object			Update to update dependencies for.
+		 * @param[in]	dependencies	New set of dependencies, or null to clear all dependencies.
+		 */
+		void updateDependencies(CoreObject* object, Vector<CoreObject*>* dependencies);
+
+		UINT64 mNextAvailableID;
+		Map<UINT64, CoreObject*> mObjects;
+		Map<UINT64, DirtyObjectData> mDirtyObjects;
+		Map<UINT64, Vector<CoreObject*>> mDependencies;
+		Map<UINT64, Vector<CoreObject*>> mDependants;
+
+		Vector<CoreStoredSyncObjData> mDestroyedSyncData;
+		List<CoreStoredSyncData> mCoreSyncData;
+
+		BS_MUTEX(mObjectsMutex);
+	};
+
+	/** @} */
+	/** @endcond */
+}
+

+ 453 - 433
BansheeCore/Include/BsCorePrerequisites.h

@@ -1,434 +1,454 @@
-#pragma once
-
-#include "BsPrerequisitesUtil.h"
-
-#define BS_MAX_MULTIPLE_RENDER_TARGETS 8
-#define BS_FORCE_SINGLETHREADED_RENDERING 0
-
-// Windows Settings
-#if BS_PLATFORM == BS_PLATFORM_WIN32
-
-// If we're not including this from a client build, specify that the stuff
-// should get exported. Otherwise, import it.
-#	if defined(BS_STATIC_LIB)
-// Linux compilers don't have symbol import/export directives.
-#   	define BS_CORE_EXPORT
-#   else
-#   	if defined(BS_CORE_EXPORTS)
-#       	define BS_CORE_EXPORT __declspec( dllexport )
-#   	else
-#           if defined( __MINGW32__ )
-#               define BS_CORE_EXPORT
-#           else
-#       	    define BS_CORE_EXPORT __declspec( dllimport )
-#           endif
-#   	endif
-#	endif
-// Win32 compilers use _DEBUG for specifying debug builds.
-// for MinGW, we set DEBUG
-#   if defined(_DEBUG) || defined(DEBUG)
-#       define BS_DEBUG_MODE 1
-#   else
-#       define BS_DEBUG_MODE 0
-#   endif
-
-#endif
-
-// Linux/Apple Settings
-#if BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_APPLE
-
-// Enable GCC symbol visibility
-#   if defined( BS_GCC_VISIBILITY )
-#       define BS_CORE_EXPORT  __attribute__ ((visibility("default")))
-#       define BS_HIDDEN __attribute__ ((visibility("hidden")))
-#   else
-#       define BS_CORE_EXPORT
-#       define BS_HIDDEN
-#   endif
-
-// A quick define to overcome different names for the same function
-#   define stricmp strcasecmp
-
-#   ifdef DEBUG
-#       define BS_DEBUG_MODE 1
-#   else
-#       define BS_DEBUG_MODE 0
-#   endif
-
-#endif
-
-#if BS_DEBUG_MODE
-#define BS_DEBUG_ONLY(x) x
-#define BS_ASSERT(x) assert(x)
-#else
-#define BS_DEBUG_ONLY(x)
-#define BS_ASSERT(x)
-#endif
-
-#include "BsHString.h"
-
-namespace BansheeEngine 
-{
-	static const StringID RenderAPIAny = "AnyRenderAPI";
-	static const StringID RendererAny = "AnyRenderer";
-
-    class Color;
-    class GpuProgram;
-    class GpuProgramManager;
-    class IndexBuffer;
-	class IndexBufferCore;
-    class OcclusionQuery;
-    class VertexBuffer;
-	class VertexBufferCore;
-	class PixelBuffer;
-	class GpuBuffer;
-	class HighLevelGpuProgram;
-	class GpuProgramManager;
-	class GpuProgramFactory;
-    class IndexData;
-    class Pass;
-	class Technique;
-	class Shader;
-	class Material;
-    class RenderAPICore;
-    class RenderAPICapabilities;
-    class RenderTarget;
-	class RenderTargetCore;
-    class RenderTexture;
-	class RenderTextureCore;
-	class MultiRenderTexture;
-	class MultiRenderTextureCore;
-    class RenderWindow;
-	class RenderWindowCore;
-	class RenderTargetProperties;
-    struct RenderOpMesh;
-    class StringInterface;
-    class SamplerState;
-	class SamplerStateCore;
-    class TextureManager;
-    class Viewport;
-    class VertexData;
-    class VertexDeclaration;
-	class Input;
-	struct PointerEvent;
-	class RawInputHandler;
-	class CoreRenderer;
-	class RendererFactory;
-	class AsyncOp;
-	class HardwareBufferManager;
-	class FontManager;
-	class DepthStencilState;
-	class DepthStencilStateCore;
-	class RenderStateManager;
-	class RasterizerState;
-	class RasterizerStateCore;
-	class BlendState;
-	class BlendStateCore;
-	class GpuParamBlock;
-	class GpuParamBlockBuffer;
-	class GpuParams;
-	struct GpuParamDesc;
-	struct GpuParamDataDesc;
-	struct GpuParamObjectDesc;
-	struct GpuParamBlockDesc;
-	class ShaderInclude;
-	class TextureView;
-	class CoreObject;
-	class CoreObjectCore;
-	class ImportOptions;
-	class TextureImportOptions;
-	class FontImportOptions;
-	class GpuProgramImportOptions;
-	class MeshImportOptions;
-	struct FontBitmap;
-	class GameObject;
-	class GpuResourceData;
-	struct RenderOperation;
-	class RenderQueue;
-	struct ProfilerReport;
-	class VertexDataDesc;
-	class EventQuery;
-	class TimerQuery;
-	class OcclusionQuery;
-	class FrameAlloc;
-	class FolderMonitor;
-	class VideoMode;
-	class VideoOutputInfo;
-	class VideoModeInfo;
-	class RenderableElement;
-	class CameraCore;
-	class MeshCoreBase;
-	class MeshCore;
-	struct SubMesh;
-	class TransientMeshCore;
-	class TextureCore;
-	class MeshHeapCore;
-	class VertexDeclarationCore;
-	class GpuBufferCore;
-	class GpuParamBlockBufferCore;
-	class GpuParamsCore;
-	class ShaderCore;
-	class ViewportCore;
-	class PassCore;
-	class PassParametersCore;
-	class TechniqueCore;
-	class MaterialCore;
-	class GpuProgramCore;
-	class IResourceListener;
-	class TextureProperties;
-	class IShaderIncludeHandler;
-	class Prefab;
-	class PrefabDiff;
-	class RendererMeshData;
-	class LightCore;
-	class Light;
-	class Win32Window;
-	// Asset import
-	class SpecificImporter;
-	class Importer;
-	// Resources
-	class Resource;
-	class Resources;
-	class ResourceManifest;
-	class Texture;
-	class Mesh;
-	class MeshBase;
-	class TransientMesh;
-	class MeshHeap;
-	class Font;
-	class ResourceMetaData;
-	class OSDropTarget;
-	class StringTable;
-	// Scene
-	class SceneObject;
-	class Component;
-	class SceneManager;
-	// RTTI
-	class MeshRTTI;
-	// Desc structs
-	struct SAMPLER_STATE_DESC;
-	struct DEPTH_STENCIL_STATE_DESC;
-	struct RASTERIZER_STATE_DESC;
-	struct BLEND_STATE_DESC;
-	struct RENDER_TARGET_BLEND_STATE_DESC;
-	struct RENDER_TEXTURE_DESC;
-	struct RENDER_WINDOW_DESC;
-	struct FONT_DESC;
-
-	template<class T>
-	class CoreThreadAccessor;
-	class CommandQueueNoSync;
-	class CommandQueueSync;
-}
-
-/************************************************************************/
-/* 						Shared pointer typedefs	                    	*/
-/************************************************************************/
-
-namespace BansheeEngine
-{
-	typedef std::shared_ptr<RenderAPICore> RenderAPIPtr;
-	typedef std::shared_ptr<GpuProgram> GpuProgramPtr;
-	typedef std::shared_ptr<PixelBuffer> PixelBufferPtr;
-	typedef std::shared_ptr<VertexBuffer> VertexBufferPtr;
-	typedef std::shared_ptr<IndexBuffer> IndexBufferPtr;
-	typedef std::shared_ptr<GpuBuffer> GpuBufferPtr;
-	typedef std::shared_ptr<VertexDeclaration> VertexDeclarationPtr;
-	typedef std::shared_ptr<Mesh> MeshPtr;
-	typedef std::shared_ptr<MeshBase> MeshBasePtr;
-	typedef std::shared_ptr<MeshHeap> MeshHeapPtr;
-	typedef std::shared_ptr<TransientMesh> TransientMeshPtr;
-	typedef std::shared_ptr<Texture> TexturePtr;
-	typedef std::shared_ptr<Resource> ResourcePtr;
-	typedef std::shared_ptr<Technique> TechniquePtr;
-	typedef std::shared_ptr<Pass> PassPtr;
-	typedef std::shared_ptr<Shader> ShaderPtr;
-	typedef std::shared_ptr<Material> MaterialPtr;
-	typedef std::shared_ptr<CoreRenderer> CoreRendererPtr;
-	typedef std::shared_ptr<RendererFactory> RendererFactoryPtr;
-	typedef std::shared_ptr<Component> ComponentPtr;
-	typedef std::shared_ptr<GameObject> GameObjectPtr;
-	typedef std::shared_ptr<SceneObject> SceneObjectPtr;
-	typedef std::shared_ptr<SamplerState> SamplerStatePtr;
-	typedef std::shared_ptr<DepthStencilState> DepthStencilStatePtr;
-	typedef std::shared_ptr<RasterizerState> RasterizerStatePtr;
-	typedef std::shared_ptr<BlendState> BlendStatePtr;
-	typedef std::shared_ptr<RenderWindow> RenderWindowPtr;
-	typedef std::shared_ptr<RenderTarget> RenderTargetPtr;
-	typedef std::shared_ptr<RenderTexture> RenderTexturePtr;
-	typedef std::shared_ptr<MultiRenderTexture> MultiRenderTexturePtr;
-	typedef std::shared_ptr<GpuParamBlockBuffer> GpuParamBlockBufferPtr;
-	typedef std::shared_ptr<GpuParams> GpuParamsPtr;
-	typedef std::shared_ptr<TextureView> TextureViewPtr;
-	typedef std::shared_ptr<Viewport> ViewportPtr;
-	typedef std::shared_ptr<ShaderInclude> ShaderIncludePtr;
-	typedef std::shared_ptr<ImportOptions> ImportOptionsPtr;
-	typedef std::shared_ptr<const ImportOptions> ConstImportOptionsPtr;
-	typedef std::shared_ptr<Font> FontPtr;
-	typedef std::shared_ptr<VertexDataDesc> VertexDataDescPtr;
-	typedef CoreThreadAccessor<CommandQueueNoSync> CoreAccessor;
-	typedef CoreThreadAccessor<CommandQueueSync> SyncedCoreAccessor;
-	typedef std::shared_ptr<CoreThreadAccessor<CommandQueueNoSync>> CoreAccessorPtr;
-	typedef std::shared_ptr<CoreThreadAccessor<CommandQueueSync>> SyncedCoreAccessorPtr;
-	typedef std::shared_ptr<EventQuery> EventQueryPtr;
-	typedef std::shared_ptr<TimerQuery> TimerQueryPtr;
-	typedef std::shared_ptr<OcclusionQuery> OcclusionQueryPtr;
-	typedef std::shared_ptr<ResourceManifest> ResourceManifestPtr;
-	typedef std::shared_ptr<VideoModeInfo> VideoModeInfoPtr;
-	typedef std::shared_ptr<RenderQueue> RenderQueuePtr;
-	typedef std::shared_ptr<GpuParamDesc> GpuParamDescPtr;
-	typedef std::shared_ptr<ResourceMetaData> ResourceMetaDataPtr;
-	typedef std::shared_ptr<IShaderIncludeHandler> ShaderIncludeHandlerPtr;
-	typedef std::shared_ptr<Prefab> PrefabPtr;
-	typedef std::shared_ptr<PrefabDiff> PrefabDiffPtr;
-	typedef std::shared_ptr<RendererMeshData> RendererMeshDataPtr;
-}
-
-/************************************************************************/
-/* 									RTTI                      			*/
-/************************************************************************/
-namespace BansheeEngine
-{
-	enum TypeID_Core
-	{
-		TID_Texture = 1001,
-		TID_Mesh = 1002,
-		TID_MeshData = 1003,
-		TID_VertexDeclaration = 1004,
-		TID_VertexElementData = 1005,
-		TID_Component = 1006,
-		TID_ResourceHandle = 1009,
-		TID_GpuProgram = 1010,
-		TID_ResourceHandleData = 1011,
-		TID_CgProgram = 1012,
-		TID_Pass = 1014,
-		TID_Technique = 1015,
-		TID_Shader = 1016,
-		TID_Material = 1017,
-		TID_MaterialParams = 1018,
-		TID_FloatParamKVP = 1019,
-		TID_MaterialTexParamKVP = 1020,
-		TID_SamplerState = 1021,
-		TID_SamplerStateParamKVP = 1022,
-		TID_BlendState = 1023,
-		TID_RasterizerState = 1024,
-		TID_DepthStencilState = 1025,
-		TID_MaterialParamFloat = 1026,
-		TID_MaterialParamVec2 = 1027,
-		TID_MaterialParamVec3 = 1028,
-		TID_MaterialParamVec4 = 1029,
-		TID_MaterialParamMat3 = 1030,
-		TID_MaterialParamMat4 = 1031,
-		TID_MaterialParamTexture = 1032,
-		TID_MaterialParamSamplerState = 1033,
-		TID_BLEND_STATE_DESC = 1034,
-		TID_SHADER_DATA_PARAM_DESC = 1035,
-		TID_SHADER_OBJECT_PARAM_DESC = 1036,
-		TID_SHADER_PARAM_BLOCK_DESC = 1047,
-		TID_ImportOptions = 1048,
-		TID_MaterialParamStruct = 1050,
-		TID_Font = 1051,
-		TID_FONT_DESC = 1052,
-		TID_CHAR_DESC = 1053,
-		TID_FontImportOptions = 1056,
-		TID_FontBitmap = 1057,
-		TID_SceneObject = 1059,
-		TID_GameObject = 1060,
-		TID_PixelData = 1062,
-		TID_GpuResourceData = 1063,
-		TID_VertexDataDesc = 1064,
-		TID_MeshBase = 1065,
-		TID_GameObjectHandleBase = 1066,
-		TID_ResourceManifest = 1067,
-		TID_ResourceManifestEntry = 1068,
-		TID_EmulatedParamBlock = 1069,
-		TID_TextureImportOptions = 1070,
-		TID_ResourceMetaData = 1071,
-		TID_ShaderInclude = 1072,
-		TID_Viewport = 1073,
-		TID_ResourceDependencies = 1074,
-		TID_ShaderMetaData = 1075,
-		TID_MeshImportOptions = 1076,
-		TID_Prefab = 1077,
-		TID_PrefabDiff = 1078,
-		TID_PrefabObjectDiff = 1079,
-		TID_PrefabComponentDiff = 1080,
-		TID_CGUIWidget = 1081,
-		TID_ProfilerOverlay = 1082,
-		TID_StringTable = 1083,
-		TID_LanguageData = 1084,
-		TID_LocalizedStringData = 1085,
-		TID_MaterialParamColor = 1086,
-		TID_WeakResourceHandle = 1087,
-	};
-}
-
-/************************************************************************/
-/* 							Resource references                   		*/
-/************************************************************************/
-
-#include "BsResourceHandle.h"
-
-namespace BansheeEngine
-{
-	// Resource handles
-	typedef ResourceHandle<Resource> HResource;
-	typedef ResourceHandle<Texture> HTexture;
-	typedef ResourceHandle<Mesh> HMesh;
-	typedef ResourceHandle<Material> HMaterial;
-	typedef ResourceHandle<ShaderInclude> HShaderInclude;
-	typedef ResourceHandle<Font> HFont;
-	typedef ResourceHandle<Shader> HShader;
-	typedef ResourceHandle<Prefab> HPrefab;
-	typedef ResourceHandle<StringTable> HStringTable;
-}
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Defers function execution until the next frame. If this function is called
-	 * 			within another deferred call, then it will be executed the same frame,
-	 * 			but only after all existing deferred calls are done.
-	 * 			
-	 * @note	This method can be used for breaking dependencies among other things. If a class
-	 * 			A depends on class B having something done, but class B also depends in some way on class A,
-	 * 			you can break up the initialization into two separate steps, queuing the second step
-	 * 			using this method.
-	 * 			
-	 *			Similar situation can happen if you have multiple classes being initialized in an undefined order
-	 *			but some of them depend on others. Using this method you can defer the dependent step until next frame,
-	 *			which will ensure everything was initialized.
-	 *
-	 * @param	callback	The callback.
-	 */
-	void BS_CORE_EXPORT deferredCall(std::function<void()> callback);
-
-	// Special types for use by profilers
-	typedef std::basic_string<char, std::char_traits<char>, StdAlloc<char, ProfilerAlloc>> ProfilerString;
-
-	template <typename T, typename A = StdAlloc<T, ProfilerAlloc>>
-	using ProfilerVector = std::vector<T, A>;
-
-	template <typename T, typename A = StdAlloc<T, ProfilerAlloc>>
-	using ProfilerStack = std::stack<T, std::deque<T, A>>;
-
-	/**
-	* @brief	Banshee thread policy that performs special startup/shutdown on threads
-	*			managed by thread pool.
-	*/
-	class BS_CORE_EXPORT ThreadBansheePolicy
-	{
-	public:
-		static void onThreadStarted(const String& name)
-		{
-			MemStack::beginThread();
-		}
-
-		static void onThreadEnded(const String& name)
-		{
-			MemStack::endThread();
-		}
-	};
-}
-
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+
+/** @defgroup Core Core
+ *	Second lowest layer that provides some very game-specific modules tied into a coherent whole, but it tries to be very 
+ *  generic and offer something that every engine might need instead of focusing on very specialized techniques.
+ *  @{
+ */
+
+/** @defgroup CoreThread Core thread
+ *	Functionality for dealing with core objects and interaction with the core thread.
+ */
+
+/** @defgroup Importer Importer
+ *	Functionality for dealing with import of resources into engine friendly format.
+ */
+
+/** @defgroup Input Input
+ *	Functionality for dealing with input (mouse, keyboard, gamepad, etc.).
+ */
+
+/** @} */
+
+#define BS_MAX_MULTIPLE_RENDER_TARGETS 8
+#define BS_FORCE_SINGLETHREADED_RENDERING 0
+
+// Windows Settings
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+
+// If we're not including this from a client build, specify that the stuff
+// should get exported. Otherwise, import it.
+#	if defined(BS_STATIC_LIB)
+// Linux compilers don't have symbol import/export directives.
+#   	define BS_CORE_EXPORT
+#   else
+#   	if defined(BS_CORE_EXPORTS)
+#       	define BS_CORE_EXPORT __declspec( dllexport )
+#   	else
+#           if defined( __MINGW32__ )
+#               define BS_CORE_EXPORT
+#           else
+#       	    define BS_CORE_EXPORT __declspec( dllimport )
+#           endif
+#   	endif
+#	endif
+// Win32 compilers use _DEBUG for specifying debug builds.
+// for MinGW, we set DEBUG
+#   if defined(_DEBUG) || defined(DEBUG)
+#       define BS_DEBUG_MODE 1
+#   else
+#       define BS_DEBUG_MODE 0
+#   endif
+
+#endif
+
+// Linux/Apple Settings
+#if BS_PLATFORM == BS_PLATFORM_LINUX || BS_PLATFORM == BS_PLATFORM_APPLE
+
+// Enable GCC symbol visibility
+#   if defined( BS_GCC_VISIBILITY )
+#       define BS_CORE_EXPORT  __attribute__ ((visibility("default")))
+#       define BS_HIDDEN __attribute__ ((visibility("hidden")))
+#   else
+#       define BS_CORE_EXPORT
+#       define BS_HIDDEN
+#   endif
+
+// A quick define to overcome different names for the same function
+#   define stricmp strcasecmp
+
+#   ifdef DEBUG
+#       define BS_DEBUG_MODE 1
+#   else
+#       define BS_DEBUG_MODE 0
+#   endif
+
+#endif
+
+#if BS_DEBUG_MODE
+#define BS_DEBUG_ONLY(x) x
+#define BS_ASSERT(x) assert(x)
+#else
+#define BS_DEBUG_ONLY(x)
+#define BS_ASSERT(x)
+#endif
+
+#include "BsHString.h"
+
+namespace BansheeEngine 
+{
+	static const StringID RenderAPIAny = "AnyRenderAPI";
+	static const StringID RendererAny = "AnyRenderer";
+
+    class Color;
+    class GpuProgram;
+    class GpuProgramManager;
+    class IndexBuffer;
+	class IndexBufferCore;
+    class OcclusionQuery;
+    class VertexBuffer;
+	class VertexBufferCore;
+	class PixelBuffer;
+	class GpuBuffer;
+	class HighLevelGpuProgram;
+	class GpuProgramManager;
+	class GpuProgramFactory;
+    class IndexData;
+    class Pass;
+	class Technique;
+	class Shader;
+	class Material;
+    class RenderAPICore;
+    class RenderAPICapabilities;
+    class RenderTarget;
+	class RenderTargetCore;
+    class RenderTexture;
+	class RenderTextureCore;
+	class MultiRenderTexture;
+	class MultiRenderTextureCore;
+    class RenderWindow;
+	class RenderWindowCore;
+	class RenderTargetProperties;
+    struct RenderOpMesh;
+    class StringInterface;
+    class SamplerState;
+	class SamplerStateCore;
+    class TextureManager;
+    class Viewport;
+    class VertexData;
+    class VertexDeclaration;
+	class Input;
+	struct PointerEvent;
+	class RawInputHandler;
+	class CoreRenderer;
+	class RendererFactory;
+	class AsyncOp;
+	class HardwareBufferManager;
+	class FontManager;
+	class DepthStencilState;
+	class DepthStencilStateCore;
+	class RenderStateManager;
+	class RasterizerState;
+	class RasterizerStateCore;
+	class BlendState;
+	class BlendStateCore;
+	class GpuParamBlock;
+	class GpuParamBlockBuffer;
+	class GpuParams;
+	struct GpuParamDesc;
+	struct GpuParamDataDesc;
+	struct GpuParamObjectDesc;
+	struct GpuParamBlockDesc;
+	class ShaderInclude;
+	class TextureView;
+	class CoreObject;
+	class CoreObjectCore;
+	class ImportOptions;
+	class TextureImportOptions;
+	class FontImportOptions;
+	class GpuProgramImportOptions;
+	class MeshImportOptions;
+	struct FontBitmap;
+	class GameObject;
+	class GpuResourceData;
+	struct RenderOperation;
+	class RenderQueue;
+	struct ProfilerReport;
+	class VertexDataDesc;
+	class EventQuery;
+	class TimerQuery;
+	class OcclusionQuery;
+	class FrameAlloc;
+	class FolderMonitor;
+	class VideoMode;
+	class VideoOutputInfo;
+	class VideoModeInfo;
+	class RenderableElement;
+	class CameraCore;
+	class MeshCoreBase;
+	class MeshCore;
+	struct SubMesh;
+	class TransientMeshCore;
+	class TextureCore;
+	class MeshHeapCore;
+	class VertexDeclarationCore;
+	class GpuBufferCore;
+	class GpuParamBlockBufferCore;
+	class GpuParamsCore;
+	class ShaderCore;
+	class ViewportCore;
+	class PassCore;
+	class PassParametersCore;
+	class TechniqueCore;
+	class MaterialCore;
+	class GpuProgramCore;
+	class IResourceListener;
+	class TextureProperties;
+	class IShaderIncludeHandler;
+	class Prefab;
+	class PrefabDiff;
+	class RendererMeshData;
+	class LightCore;
+	class Light;
+	class Win32Window;
+	// Asset import
+	class SpecificImporter;
+	class Importer;
+	// Resources
+	class Resource;
+	class Resources;
+	class ResourceManifest;
+	class Texture;
+	class Mesh;
+	class MeshBase;
+	class TransientMesh;
+	class MeshHeap;
+	class Font;
+	class ResourceMetaData;
+	class OSDropTarget;
+	class StringTable;
+	// Scene
+	class SceneObject;
+	class Component;
+	class SceneManager;
+	// RTTI
+	class MeshRTTI;
+	// Desc structs
+	struct SAMPLER_STATE_DESC;
+	struct DEPTH_STENCIL_STATE_DESC;
+	struct RASTERIZER_STATE_DESC;
+	struct BLEND_STATE_DESC;
+	struct RENDER_TARGET_BLEND_STATE_DESC;
+	struct RENDER_TEXTURE_DESC;
+	struct RENDER_WINDOW_DESC;
+	struct FONT_DESC;
+
+	template<class T>
+	class CoreThreadAccessor;
+	class CommandQueueNoSync;
+	class CommandQueueSync;
+}
+
+/************************************************************************/
+/* 						Shared pointer typedefs	                    	*/
+/************************************************************************/
+
+namespace BansheeEngine
+{
+	typedef std::shared_ptr<RenderAPICore> RenderAPIPtr;
+	typedef std::shared_ptr<GpuProgram> GpuProgramPtr;
+	typedef std::shared_ptr<PixelBuffer> PixelBufferPtr;
+	typedef std::shared_ptr<VertexBuffer> VertexBufferPtr;
+	typedef std::shared_ptr<IndexBuffer> IndexBufferPtr;
+	typedef std::shared_ptr<GpuBuffer> GpuBufferPtr;
+	typedef std::shared_ptr<VertexDeclaration> VertexDeclarationPtr;
+	typedef std::shared_ptr<Mesh> MeshPtr;
+	typedef std::shared_ptr<MeshBase> MeshBasePtr;
+	typedef std::shared_ptr<MeshHeap> MeshHeapPtr;
+	typedef std::shared_ptr<TransientMesh> TransientMeshPtr;
+	typedef std::shared_ptr<Texture> TexturePtr;
+	typedef std::shared_ptr<Resource> ResourcePtr;
+	typedef std::shared_ptr<Technique> TechniquePtr;
+	typedef std::shared_ptr<Pass> PassPtr;
+	typedef std::shared_ptr<Shader> ShaderPtr;
+	typedef std::shared_ptr<Material> MaterialPtr;
+	typedef std::shared_ptr<CoreRenderer> CoreRendererPtr;
+	typedef std::shared_ptr<RendererFactory> RendererFactoryPtr;
+	typedef std::shared_ptr<Component> ComponentPtr;
+	typedef std::shared_ptr<GameObject> GameObjectPtr;
+	typedef std::shared_ptr<SceneObject> SceneObjectPtr;
+	typedef std::shared_ptr<SamplerState> SamplerStatePtr;
+	typedef std::shared_ptr<DepthStencilState> DepthStencilStatePtr;
+	typedef std::shared_ptr<RasterizerState> RasterizerStatePtr;
+	typedef std::shared_ptr<BlendState> BlendStatePtr;
+	typedef std::shared_ptr<RenderWindow> RenderWindowPtr;
+	typedef std::shared_ptr<RenderTarget> RenderTargetPtr;
+	typedef std::shared_ptr<RenderTexture> RenderTexturePtr;
+	typedef std::shared_ptr<MultiRenderTexture> MultiRenderTexturePtr;
+	typedef std::shared_ptr<GpuParamBlockBuffer> GpuParamBlockBufferPtr;
+	typedef std::shared_ptr<GpuParams> GpuParamsPtr;
+	typedef std::shared_ptr<TextureView> TextureViewPtr;
+	typedef std::shared_ptr<Viewport> ViewportPtr;
+	typedef std::shared_ptr<ShaderInclude> ShaderIncludePtr;
+	typedef std::shared_ptr<ImportOptions> ImportOptionsPtr;
+	typedef std::shared_ptr<const ImportOptions> ConstImportOptionsPtr;
+	typedef std::shared_ptr<Font> FontPtr;
+	typedef std::shared_ptr<VertexDataDesc> VertexDataDescPtr;
+	typedef CoreThreadAccessor<CommandQueueNoSync> CoreAccessor;
+	typedef CoreThreadAccessor<CommandQueueSync> SyncedCoreAccessor;
+	typedef std::shared_ptr<CoreThreadAccessor<CommandQueueNoSync>> CoreAccessorPtr;
+	typedef std::shared_ptr<CoreThreadAccessor<CommandQueueSync>> SyncedCoreAccessorPtr;
+	typedef std::shared_ptr<EventQuery> EventQueryPtr;
+	typedef std::shared_ptr<TimerQuery> TimerQueryPtr;
+	typedef std::shared_ptr<OcclusionQuery> OcclusionQueryPtr;
+	typedef std::shared_ptr<ResourceManifest> ResourceManifestPtr;
+	typedef std::shared_ptr<VideoModeInfo> VideoModeInfoPtr;
+	typedef std::shared_ptr<RenderQueue> RenderQueuePtr;
+	typedef std::shared_ptr<GpuParamDesc> GpuParamDescPtr;
+	typedef std::shared_ptr<ResourceMetaData> ResourceMetaDataPtr;
+	typedef std::shared_ptr<IShaderIncludeHandler> ShaderIncludeHandlerPtr;
+	typedef std::shared_ptr<Prefab> PrefabPtr;
+	typedef std::shared_ptr<PrefabDiff> PrefabDiffPtr;
+	typedef std::shared_ptr<RendererMeshData> RendererMeshDataPtr;
+}
+
+/************************************************************************/
+/* 									RTTI                      			*/
+/************************************************************************/
+namespace BansheeEngine
+{
+	enum TypeID_Core
+	{
+		TID_Texture = 1001,
+		TID_Mesh = 1002,
+		TID_MeshData = 1003,
+		TID_VertexDeclaration = 1004,
+		TID_VertexElementData = 1005,
+		TID_Component = 1006,
+		TID_ResourceHandle = 1009,
+		TID_GpuProgram = 1010,
+		TID_ResourceHandleData = 1011,
+		TID_CgProgram = 1012,
+		TID_Pass = 1014,
+		TID_Technique = 1015,
+		TID_Shader = 1016,
+		TID_Material = 1017,
+		TID_MaterialParams = 1018,
+		TID_FloatParamKVP = 1019,
+		TID_MaterialTexParamKVP = 1020,
+		TID_SamplerState = 1021,
+		TID_SamplerStateParamKVP = 1022,
+		TID_BlendState = 1023,
+		TID_RasterizerState = 1024,
+		TID_DepthStencilState = 1025,
+		TID_MaterialParamFloat = 1026,
+		TID_MaterialParamVec2 = 1027,
+		TID_MaterialParamVec3 = 1028,
+		TID_MaterialParamVec4 = 1029,
+		TID_MaterialParamMat3 = 1030,
+		TID_MaterialParamMat4 = 1031,
+		TID_MaterialParamTexture = 1032,
+		TID_MaterialParamSamplerState = 1033,
+		TID_BLEND_STATE_DESC = 1034,
+		TID_SHADER_DATA_PARAM_DESC = 1035,
+		TID_SHADER_OBJECT_PARAM_DESC = 1036,
+		TID_SHADER_PARAM_BLOCK_DESC = 1047,
+		TID_ImportOptions = 1048,
+		TID_MaterialParamStruct = 1050,
+		TID_Font = 1051,
+		TID_FONT_DESC = 1052,
+		TID_CHAR_DESC = 1053,
+		TID_FontImportOptions = 1056,
+		TID_FontBitmap = 1057,
+		TID_SceneObject = 1059,
+		TID_GameObject = 1060,
+		TID_PixelData = 1062,
+		TID_GpuResourceData = 1063,
+		TID_VertexDataDesc = 1064,
+		TID_MeshBase = 1065,
+		TID_GameObjectHandleBase = 1066,
+		TID_ResourceManifest = 1067,
+		TID_ResourceManifestEntry = 1068,
+		TID_EmulatedParamBlock = 1069,
+		TID_TextureImportOptions = 1070,
+		TID_ResourceMetaData = 1071,
+		TID_ShaderInclude = 1072,
+		TID_Viewport = 1073,
+		TID_ResourceDependencies = 1074,
+		TID_ShaderMetaData = 1075,
+		TID_MeshImportOptions = 1076,
+		TID_Prefab = 1077,
+		TID_PrefabDiff = 1078,
+		TID_PrefabObjectDiff = 1079,
+		TID_PrefabComponentDiff = 1080,
+		TID_CGUIWidget = 1081,
+		TID_ProfilerOverlay = 1082,
+		TID_StringTable = 1083,
+		TID_LanguageData = 1084,
+		TID_LocalizedStringData = 1085,
+		TID_MaterialParamColor = 1086,
+		TID_WeakResourceHandle = 1087,
+	};
+}
+
+/************************************************************************/
+/* 							Resource references                   		*/
+/************************************************************************/
+
+#include "BsResourceHandle.h"
+
+namespace BansheeEngine
+{
+	// Resource handles
+	typedef ResourceHandle<Resource> HResource;
+	typedef ResourceHandle<Texture> HTexture;
+	typedef ResourceHandle<Mesh> HMesh;
+	typedef ResourceHandle<Material> HMaterial;
+	typedef ResourceHandle<ShaderInclude> HShaderInclude;
+	typedef ResourceHandle<Font> HFont;
+	typedef ResourceHandle<Shader> HShader;
+	typedef ResourceHandle<Prefab> HPrefab;
+	typedef ResourceHandle<StringTable> HStringTable;
+}
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Defers function execution until the next frame. If this function is called
+	 * 			within another deferred call, then it will be executed the same frame,
+	 * 			but only after all existing deferred calls are done.
+	 * 			
+	 * @note	This method can be used for breaking dependencies among other things. If a class
+	 * 			A depends on class B having something done, but class B also depends in some way on class A,
+	 * 			you can break up the initialization into two separate steps, queuing the second step
+	 * 			using this method.
+	 * 			
+	 *			Similar situation can happen if you have multiple classes being initialized in an undefined order
+	 *			but some of them depend on others. Using this method you can defer the dependent step until next frame,
+	 *			which will ensure everything was initialized.
+	 *
+	 * @param	callback	The callback.
+	 */
+	void BS_CORE_EXPORT deferredCall(std::function<void()> callback);
+
+	// Special types for use by profilers
+	typedef std::basic_string<char, std::char_traits<char>, StdAlloc<char, ProfilerAlloc>> ProfilerString;
+
+	template <typename T, typename A = StdAlloc<T, ProfilerAlloc>>
+	using ProfilerVector = std::vector<T, A>;
+
+	template <typename T, typename A = StdAlloc<T, ProfilerAlloc>>
+	using ProfilerStack = std::stack<T, std::deque<T, A>>;
+
+	/**
+	* @brief	Banshee thread policy that performs special startup/shutdown on threads
+	*			managed by thread pool.
+	*/
+	class BS_CORE_EXPORT ThreadBansheePolicy
+	{
+	public:
+		static void onThreadStarted(const String& name)
+		{
+			MemStack::beginThread();
+		}
+
+		static void onThreadEnded(const String& name)
+		{
+			MemStack::endThread();
+		}
+	};
+}
+
 #include "BsCommonTypes.h"
 #include "BsCommonTypes.h"

+ 218 - 221
BansheeCore/Include/BsCoreThread.h

@@ -1,221 +1,218 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsModule.h"
-#include "BsCommandQueue.h"
-#include "BsCoreThreadAccessor.h"
-#include "BsThreadPool.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Manager for the core thread. Takes care of starting, running, queuing commands
-	 * 			and shutting down the core thread.
-	 * 			
-	 * @note	How threading works:
-	 * 			 - This class contains a queue which is filled by commands from other threads via queueCommand and queueReturnCommand  
-	 * 			 - Commands are executed on the core thread as soon as they are queued (if core thread is not busy with previous commands)  
-	 * 			 - Core thread accessors are helpers for queuing commands. They perform better than queuing each command directly using 
-	 *			   queueCommand or queueReturnCommand.
-	 * 			 - Accessors contain a command queue of their own, and queuing commands in them will not automatically start executing the commands  
-	 * 			   like with queueCommand or queueReturnCommand. Instead you must manually call "submitAccessors" when you are ready to send their
-	 * 			   commands to the core thread. Sending commands "in bulk" like this is what makes them faster than directly queuing commands.
-	 * 			 - Synced accessor is a special type of accessor which may be accessed from any thread. Its commands are always executed after all other  
-	 * 			   non-synced accessors. It is primarily useful when multiple threads are managing the same resource and you must ensure proper order of operations.
-	 * 			   You should use normal accessors whenever possible as synced accessors involve potentially slow synchronization operations.
-	 */
-	class BS_CORE_EXPORT CoreThread : public Module<CoreThread>
-	{
-		/** Contains data about an accessor for a specific thread. */
-		struct AccessorContainer
-		{
-			CoreAccessorPtr accessor;
-			bool isMain;
-		};
-
-		/** Wrapper for the thread-local variable because MSVC can't deal with a thread-local variable marked with dllimport or dllexport,  
-		 *  and we cannot use per-member dllimport/dllexport specifiers because Module's members will then not be exported and its static
-		 *  members will not have external linkage. */
-		struct AccessorData
-		{
-			static BS_THREADLOCAL AccessorContainer* current;
-		};
-
-public:
-	CoreThread();
-	~CoreThread();
-
-	/**
-	 * @brief	Returns the id of the core thread. 
-	 */
-	BS_THREAD_ID_TYPE getCoreThreadId() { return mCoreThreadId; }
-
-	/**
-	 * @brief	Creates or retrieves an accessor that you can use for executing commands on the core thread from 
-	 * 			a non-core thread. The accessor will be bound to the thread you call this method on.
-	 * 			
-	 * @note		Accessors contain their own command queue and their commands will only start to get executed once that queue is submitted
-	 * 			to the core thread via "submitAccessors" method.
-	 */
-	CoreAccessorPtr getAccessor();
-
-	/**
-	 * @brief	Retrieves an accessor that you can use for executing commands on the core thread from
-	 * 			a non-core thread. There is only one synchronized accessor and you may access it from any thread you wish.
-	 * 			Note however that it is much more efficient to retrieve a separate non-synchronized accessor using
-	 * 			"getAccessor" for each thread you will be using it on.
-	 * 			
-	 * @note		Accessors contain their own command queue and their commands will only start to get executed once that queue is submitted
-	 * 			to the core thread via "submitAccessors" method.
-	 * 			
-	 *			Synced accessor commands are sent after all non-synced accessor commands are sent.
-	 */
-	SyncedCoreAccessor& getSyncedAccessor();
-
-	/**
-	 * @brief	Queues all the accessor commands and starts executing them on the core thread.
-	 */
-	void submitAccessors(bool blockUntilComplete = false);
-
-	/**
-	 * @brief	Queues a new command that will be added to the global command queue. You are allowed to call this from any thread,
-	 * 			however be aware that it involves possibly slow synchronization primitives, so limit your usage.
-	 * 			
-	 * @param	blockUntilComplete If true the thread will be blocked until the command executes. Be aware that there may be many commands queued before it
-	 * 							   and they all need to be executed in order before the current command is reached, which might take a long time.
-	 * 	
-	 * @see		CommandQueue::queueReturn
-	 */
-	AsyncOp queueReturnCommand(std::function<void(AsyncOp&)> commandCallback, bool blockUntilComplete = false);
-
-	/**
-	 * @brief	Queues a new command that will be added to the global command queue.You are allowed to call this from any thread,
-	 * 			however be aware that it involves possibly slow synchronization primitives, so limit your usage.
-	 * 	
-	 * @param	blockUntilComplete If true the thread will be blocked until the command executes. Be aware that there may be many commands queued before it
-	 * 							   and they all need to be executed in order before the current command is reached, which might take a long time.
-	 * @see		CommandQueue::queue
-	 */
-	void queueCommand(std::function<void()> commandCallback, bool blockUntilComplete = false);
-
-	/**
-	 * @brief	Called once every frame.
-	 * 			
-	 * @note	Must be called before sim thread schedules any core thread operations for the frame. 
-	 */
-	void update();
-
-	/**
-	 * @brief	Returns a frame allocator that should be used for allocating temporary data being passed to the
-	 * 			core thread. As the name implies the data only lasts one frame, so you need to be careful not
-	 * 			to use it for longer than that.
-	 * 			
-	 * @note	Sim thread only.
-	 */
-	FrameAlloc* getFrameAlloc() const;
-private:
-	static const int NUM_FRAME_ALLOCS = 2;
-
-	/**
-	 * @brief	Double buffered frame allocators. Means sim thread cannot be more than 1 frame ahead of core thread
-	 *			(If that changes you should be able to easily add more).
-	 */
-	FrameAlloc* mFrameAllocs[NUM_FRAME_ALLOCS];
-	UINT32 mActiveFrameAlloc;
-
-	static AccessorData mAccessor;
-	Vector<AccessorContainer*> mAccessors;
-
-	volatile bool mCoreThreadShutdown;
-
-	HThread mCoreThread;
-	bool mCoreThreadStarted;
-	BS_THREAD_ID_TYPE mSimThreadId;
-	BS_THREAD_ID_TYPE mCoreThreadId;
-	BS_MUTEX(mCommandQueueMutex)
-	BS_MUTEX(mAccessorMutex)
-	BS_THREAD_SYNCHRONISER(mCommandReadyCondition)
-	BS_MUTEX(mCommandNotifyMutex)
-	BS_THREAD_SYNCHRONISER(mCommandCompleteCondition)
-	BS_MUTEX(mThreadStartedMutex)
-	BS_THREAD_SYNCHRONISER(mCoreThreadStartedCondition)
-
-	CommandQueue<CommandQueueSync>* mCommandQueue;
-
-	UINT32 mMaxCommandNotifyId; /**< ID that will be assigned to the next command with a notifier callback. */
-	Vector<UINT32> mCommandsCompleted; /**< Completed commands that have notifier callbacks set up */
-
-	SyncedCoreAccessor* mSyncedCoreAccessor;
-
-	/**
-		* @brief	Starts the core thread worker method. Should only be called once.
-		*/
-	void initCoreThread();
-
-	/**
-		* @brief	Main worker method of the core thread. Called once thread is started.
-		*/
-	void runCoreThread();
-
-	/**
-		* @brief	Shutdowns the core thread. It will complete all ready commands
-		* 			before shutdown.
-		*/
-	void shutdownCoreThread();
-
-	/**
-		* @brief	Blocks the calling thread until the command with the specified ID completes.
-		* 			Make sure that the specified ID actually exists, otherwise this will block forever.
-		*/
-	void blockUntilCommandCompleted(UINT32 commandId);
-
-	/**
-		* @brief	Callback called by the command list when a specific command finishes executing.
-		* 			This is only called on commands that have a special notify on complete flag set.
-		*
-		* @param	commandId	Identifier for the command.
-		*/
-	void commandCompletedNotify(UINT32 commandId);
-	};
-
-	/**
-	 * @brief	Returns the core thread manager used for dealing with the core thread from external threads.
-	 * 			
-	 * @see		CoreThread
-	 */
-	BS_CORE_EXPORT CoreThread& gCoreThread();
-
-	/**
-	 * @brief	Returns a core thread accessor for the current thread. Accessor is retrieved or created depending
-	 * 			if it previously existed. Each thread has its own accessor.
-	 * 	
-	 * @see		CoreThread
-	 */
-	BS_CORE_EXPORT CoreThreadAccessor<CommandQueueNoSync>& gCoreAccessor();
-
-	/**
-	 * @brief	Returns a synchronized core accessor you may call from any thread for working with the core thread.
-	 * 			Only one of these exists.
-	 * 			
-	 * @see		CoreThread
-	 */
-	BS_CORE_EXPORT CoreThreadAccessor<CommandQueueSync>& gSyncedCoreAccessor();
-
-	/**
-	  * @brief	Throws an exception if current thread isn't the core thread;
-	  */
-	BS_CORE_EXPORT void throwIfNotCoreThread();
-
-	/**
-	  * @brief	Throws an exception if current thread is the core thread;
-	  */
-	BS_CORE_EXPORT void throwIfCoreThread();
-
-#if BS_DEBUG_MODE
-#define THROW_IF_NOT_CORE_THREAD throwIfNotCoreThread();
-#define THROW_IF_CORE_THREAD throwIfCoreThread();
-#else
-#define THROW_IF_NOT_CORE_THREAD 
-#define THROW_IF_CORE_THREAD
-#endif
-}
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsModule.h"
+#include "BsCommandQueue.h"
+#include "BsCoreThreadAccessor.h"
+#include "BsThreadPool.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup CoreThread
+	 *  @{
+	 */
+	/** @cond INTERNAL */
+
+	/**
+	 * Manager for the core thread. Takes care of starting, running, queuing commands and shutting down the core thread.
+	 * 			
+	 * @note	
+	 * How threading works:
+	 * 	- This class contains a queue which is filled by commands from other threads via queueCommand() and queueReturnCommand()  
+	 * 	- Commands are executed on the core thread as soon as they are queued (if core thread is not busy with previous commands)  
+	 * 	- Core thread accessors are helpers for queuing commands. They perform better than queuing each command directly 
+	 *    using queueCommand() or queueReturnCommand().
+	 * 	- Accessors contain a command queue of their own, and queuing commands in them will not automatically start 
+	 *    executing the commands like with queueCommand or queueReturnCommand. Instead you must manually call 
+	 *    submitAccessors() when you are ready to send their commands to the core thread. Sending commands "in bulk" like 
+	 *    this is what makes them faster than directly queuing commands.
+	 * 	- Synced accessor is a special type of accessor which may be accessed from any thread. Its commands are always 
+	 *    executed after all other non-synced accessors. It is primarily useful when multiple threads are managing the same
+	 *    resource and you must ensure proper order of operations. You should use normal accessors whenever possible as 
+	 *    synced accessors involve potentially slow synchronization operations.
+	 */
+	class BS_CORE_EXPORT CoreThread : public Module<CoreThread>
+	{
+		/** Contains data about an accessor for a specific thread. */
+		struct AccessorContainer
+		{
+			CoreAccessorPtr accessor;
+			bool isMain;
+		};
+
+		/** Wrapper for the thread-local variable because MSVC can't deal with a thread-local variable marked with dllimport or dllexport,  
+		 *  and we cannot use per-member dllimport/dllexport specifiers because Module's members will then not be exported and its static
+		 *  members will not have external linkage. */
+		struct AccessorData
+		{
+			static BS_THREADLOCAL AccessorContainer* current;
+		};
+
+public:
+	CoreThread();
+	~CoreThread();
+
+	/** Returns the id of the core thread.  */
+	BS_THREAD_ID_TYPE getCoreThreadId() { return mCoreThreadId; }
+
+	/**
+	 * Creates or retrieves an accessor that you can use for executing commands on the core thread from a non-core thread. 
+	 * The accessor will be bound to the thread you call this method on.
+	 * 			
+	 * @note		
+	 * Accessors contain their own command queue and their commands will only start to get executed once that queue is 
+	 * submitted to the core thread via submitAccessors() method.
+	 */
+	CoreAccessorPtr getAccessor();
+
+	/**
+	 * Retrieves an accessor that you can use for executing commands on the core thread from a non-core thread. There is 
+	 * only one synchronized accessor and you may access it from any thread you wish. Note however that it is much more 
+	 * efficient to retrieve a separate non-synchronized accessor for each thread you will be using it on.
+	 * 			
+	 * @note	
+	 * Accessors contain their own command queue and their commands will only start to get executed once that queue
+	 * is submitted to the core thread via submitAccessors() method.
+	 * @note			
+	 * Synced accessor commands are sent after all non-synced accessor commands are sent.
+	 */
+	SyncedCoreAccessor& getSyncedAccessor();
+
+	/** Queues all the accessor commands and starts executing them on the core thread. */
+	void submitAccessors(bool blockUntilComplete = false);
+
+	/**
+	 * Queues a new command that will be added to the global command queue. You are allowed to call this from any thread,
+	 * however be aware that it involves possibly slow synchronization primitives, so limit your usage.
+	 * 			
+	 * @param[in]	blockUntilComplete	If true the thread will be blocked until the command executes. Be aware that there 
+	 *									may be many commands queued before it and they all need to be executed in order 
+	 *									before the current command is reached, which might take a long time.
+	 * 	
+	 * @see		CommandQueue::queueReturn()
+	 */
+	AsyncOp queueReturnCommand(std::function<void(AsyncOp&)> commandCallback, bool blockUntilComplete = false);
+
+	/**
+	 * Queues a new command that will be added to the global command queue.You are allowed to call this from any thread,
+	 * however be aware that it involves possibly slow synchronization primitives, so limit your usage.
+	 * 	
+	 * @param[in]	blockUntilComplete	If true the thread will be blocked until the command executes. Be aware that there 
+	 *									may be many commands queued before it and they all need to be executed in order 
+	 *									before the current command is reached, which might take a long time.
+	 *
+	 * @see		CommandQueue::queue()
+	 */
+	void queueCommand(std::function<void()> commandCallback, bool blockUntilComplete = false);
+
+	/**
+	 * Called once every frame.
+	 * 			
+	 * @note	Must be called before sim thread schedules any core thread operations for the frame. 
+	 */
+	void update();
+
+	/**
+	 * Returns a frame allocator that should be used for allocating temporary data being passed to the core thread. As the 
+	 * name implies the data only lasts one frame, so you need to be careful not to use it for longer than that.
+	 * 			
+	 * @note	Sim thread only.
+	 */
+	FrameAlloc* getFrameAlloc() const;
+private:
+	static const int NUM_FRAME_ALLOCS = 2;
+
+	/**
+	 * Double buffered frame allocators. Means sim thread cannot be more than 1 frame ahead of core thread (If that changes
+	 * you should be able to easily add more).
+	 */
+	FrameAlloc* mFrameAllocs[NUM_FRAME_ALLOCS];
+	UINT32 mActiveFrameAlloc;
+
+	static AccessorData mAccessor;
+	Vector<AccessorContainer*> mAccessors;
+
+	volatile bool mCoreThreadShutdown;
+
+	HThread mCoreThread;
+	bool mCoreThreadStarted;
+	BS_THREAD_ID_TYPE mSimThreadId;
+	BS_THREAD_ID_TYPE mCoreThreadId;
+	BS_MUTEX(mCommandQueueMutex)
+	BS_MUTEX(mAccessorMutex)
+	BS_THREAD_SYNCHRONISER(mCommandReadyCondition)
+	BS_MUTEX(mCommandNotifyMutex)
+	BS_THREAD_SYNCHRONISER(mCommandCompleteCondition)
+	BS_MUTEX(mThreadStartedMutex)
+	BS_THREAD_SYNCHRONISER(mCoreThreadStartedCondition)
+
+	CommandQueue<CommandQueueSync>* mCommandQueue;
+
+	UINT32 mMaxCommandNotifyId; /**< ID that will be assigned to the next command with a notifier callback. */
+	Vector<UINT32> mCommandsCompleted; /**< Completed commands that have notifier callbacks set up */
+
+	SyncedCoreAccessor* mSyncedCoreAccessor;
+
+	/** Starts the core thread worker method. Should only be called once. */
+	void initCoreThread();
+
+	/**	Main worker method of the core thread. Called once thread is started. */
+	void runCoreThread();
+
+	/** Shutdowns the core thread. It will complete all ready commands before shutdown. */
+	void shutdownCoreThread();
+
+	/**
+	 * Blocks the calling thread until the command with the specified ID completes. Make sure that the specified ID 
+	 * actually exists, otherwise this will block forever.
+	 */
+	void blockUntilCommandCompleted(UINT32 commandId);
+
+	/**
+	 * Callback called by the command list when a specific command finishes executing. This is only called on commands that
+	 * have a special notify on complete flag set.
+	 *
+	 * @param[in]	commandId	Identifier for the command.
+	 */
+	void commandCompletedNotify(UINT32 commandId);
+	};
+
+	/**
+	 * Returns the core thread manager used for dealing with the core thread from external threads.
+	 * 			
+	 * @see		CoreThread
+	 */
+	BS_CORE_EXPORT CoreThread& gCoreThread();
+
+	/**	Throws an exception if current thread isn't the core thread. */
+	BS_CORE_EXPORT void throwIfNotCoreThread();
+
+	/** Throws an exception if current thread is the core thread. */
+	BS_CORE_EXPORT void throwIfCoreThread();
+
+#if BS_DEBUG_MODE
+#define THROW_IF_NOT_CORE_THREAD throwIfNotCoreThread();
+#define THROW_IF_CORE_THREAD throwIfCoreThread();
+#else
+#define THROW_IF_NOT_CORE_THREAD 
+#define THROW_IF_CORE_THREAD
+#endif
+
+	/** @endcond */
+
+	/** 
+	 * Creates or retrieves an accessor that you can use for executing commands on the core thread from a non-core thread. 
+	 * The accessor will be bound to the thread you call this method on. 
+	 */
+	BS_CORE_EXPORT CoreThreadAccessor<CommandQueueNoSync>& gCoreAccessor();
+
+	/**
+	 * Retrieves an accessor that you can use for executing commands on the core thread from a non-core thread. There is 
+	 * only one synchronized accessor and you may access it from any thread you wish. Note however that it is much more 
+	 * efficient to retrieve a separate non-synchronized accessor for each thread you will be using it on.
+	 */
+	BS_CORE_EXPORT CoreThreadAccessor<CommandQueueSync>& gSyncedCoreAccessor();
+
+	/** @} */
+}
+

+ 72 - 73
BansheeCore/Include/BsCoreThreadAccessor.h

@@ -1,74 +1,73 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsRenderAPI.h"
-#include "BsCommandQueue.h"
-#include "BsAsyncOp.h"
-#include "BsViewport.h"
-#include "BsColor.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Contains some base functionality used for CoreThreadAccessor.
-	 * 			
-	 * @see		CoreThreadAccesor
-	 */
-	class BS_CORE_EXPORT CoreThreadAccessorBase
-	{
-	public:
-		CoreThreadAccessorBase(CommandQueueBase* commandQueue);
-		virtual ~CoreThreadAccessorBase();
-
-		/**
-		* @brief	Queues a new generic command that will be added to the command queue. Returns an async operation object
-		*			that you may use to check if the operation has finished, and to retrieve the return value once finished.
-		*/
-		AsyncOp queueReturnCommand(std::function<void(AsyncOp&)> commandCallback);
-
-		/**
-		* @brief	Queues a new generic command that will be added to the command queue.
-		*/
-		void queueCommand(std::function<void()> commandCallback);
-
-		/**
-		 * @brief	Makes all the currently queued commands available to the core thread. They will be executed
-		 * 			as soon as the core thread is ready. All queued commands are removed from the accessor.
-		 *
-		 * @param	blockUntilComplete	If true, the calling thread will block until the core thread finished executing
-		 *								all currently queued commands. This is usually very expensive and should only be
-		 *								used in performance non-critical code.
-		 */
-		void submitToCoreThread(bool blockUntilComplete = false);
-
-		/**
-		 * @brief	Cancels all commands in the queue.
-		 */
-		void cancelAll();
-
-	private:
-		CommandQueueBase* mCommandQueue;
-	};
-
-	/**
-	 * @brief	Core thread accessor allows you to schedule core commands outside of the core thread. Provides a set of common
-	 * 			methods you may want to execute on the core thread, as well as a general command queuing methods.
-	 * 			
-	 * @note	Queued commands are only executed after the call to submitToCoreThread, in the order they were submitted.
-	 */
-	template <class CommandQueueSyncPolicy = CommandQueueNoSync>
-	class BS_CORE_EXPORT CoreThreadAccessor : public CoreThreadAccessorBase
-	{
-	public:
-		/**
-		 * @brief	Constructor.
-		 *
-		 * @param	threadId		Identifier for the thread that created the accessor.
-		 */
-		CoreThreadAccessor(BS_THREAD_ID_TYPE threadId)
-			:CoreThreadAccessorBase(bs_new<CommandQueue<CommandQueueSyncPolicy>>(threadId))
-		{
-
-		}
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsCommandQueue.h"
+#include "BsAsyncOp.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup CoreThread
+	 *  @{
+	 */
+
+	/**
+	 * Contains base functionality used for CoreThreadAccessor.
+	 * 			
+	 * @see		CoreThreadAccesor
+	 */
+	class BS_CORE_EXPORT CoreThreadAccessorBase
+	{
+	public:
+		CoreThreadAccessorBase(CommandQueueBase* commandQueue);
+		virtual ~CoreThreadAccessorBase();
+
+		/**
+		 * Queues a new generic command that will be added to the command queue. Returns an async operation object that you 
+		 * may use to check if the operation has finished, and to retrieve the return value once finished.
+		 */
+		AsyncOp queueReturnCommand(std::function<void(AsyncOp&)> commandCallback);
+
+		/** Queues a new generic command that will be added to the command queue. */
+		void queueCommand(std::function<void()> commandCallback);
+
+		/**
+		 * Makes all the currently queued commands available to the core thread. They will be executed as soon as the core 
+		 * thread is ready. All queued commands are removed from the accessor.
+		 *
+		 * @param[in]	blockUntilComplete	If true, the calling thread will block until the core thread finished executing
+		 *									all currently queued commands. This is usually very expensive and should only be
+		 *									used in performance non-critical code.
+		 */
+		void submitToCoreThread(bool blockUntilComplete = false);
+
+		/** Cancels all commands in the queue. */
+		void cancelAll();
+
+	private:
+		CommandQueueBase* mCommandQueue;
+	};
+
+	/**
+	 * Core thread accessor allows you to schedule core commands outside of the core thread. Provides a set of common 
+	 * methods you may want to execute on the core thread, as well as a general command queuing methods.
+	 * 			
+	 * @note	Queued commands are only executed after the call to submitToCoreThread(), in the order they were submitted.
+	 */
+	template <class CommandQueueSyncPolicy = CommandQueueNoSync>
+	class BS_CORE_EXPORT CoreThreadAccessor : public CoreThreadAccessorBase
+	{
+	public:
+		/**
+		 * Constructor.
+		 *
+		 * @param[in]	threadId		Identifier for the thread that created the accessor.
+		 */
+		CoreThreadAccessor(BS_THREAD_ID_TYPE threadId)
+			:CoreThreadAccessorBase(bs_new<CommandQueue<CommandQueueSyncPolicy>>(threadId))
+		{
+
+		}
+	};
+
+	/** @} */
 }
 }

+ 30 - 24
BansheeCore/Include/BsImportOptions.h

@@ -1,25 +1,31 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsIReflectable.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Base class for creating import options from. Import options
-	 *			are specific for each importer and control how is data imported.
-	 */
-	class BS_CORE_EXPORT ImportOptions : public IReflectable
-	{
-	public:
-		virtual ~ImportOptions() {}
-
-		/************************************************************************/
-		/* 								SERIALIZATION                      		*/
-		/************************************************************************/
-	public:
-		friend class ImportOptionsRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsIReflectable.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Importer
+	 *  @{
+	 */
+
+	/** 
+	 * Base class for creating import options from. Import options are specific for each importer and control how is data 
+	 * imported.
+	 */
+	class BS_CORE_EXPORT ImportOptions : public IReflectable
+	{
+	public:
+		virtual ~ImportOptions() {}
+
+		/************************************************************************/
+		/* 								SERIALIZATION                      		*/
+		/************************************************************************/
+	public:
+		friend class ImportOptionsRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
+	};
+
+	/** @} */
 }
 }

+ 108 - 112
BansheeCore/Include/BsImporter.h

@@ -1,113 +1,109 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsModule.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Module responsible for importing various asset types and converting
-	 * 			them to types usable by the engine.
-	 */
-	class BS_CORE_EXPORT Importer : public Module<Importer>
-	{
-	public:
-		Importer(); 
-		~Importer(); 
-
-		/**
-		 * @brief	Imports a resource at the specified location, and returns the loaded data.
-		 *
-		 * @param	inputFilePath	Pathname of the input file.
-		 * @param	importOptions	(optional) Options for controlling the import. Caller must
-		 *							ensure import options actually match the type of the importer used
-		 *							for the file type.
-		 *
-		 * @see		createImportOptions
-		 */
-		HResource import(const Path& inputFilePath, ConstImportOptionsPtr importOptions = nullptr);
-
-		/**
-		 * @copydoc import
-		 */
-		template <class T>
-		ResourceHandle<T> import(const Path& inputFilePath, ConstImportOptionsPtr importOptions = nullptr)
-		{
-			return static_resource_cast<T>(import(inputFilePath, importOptions));
-		}
-
-		/**
-		 * @brief	Imports a resource and replaces the contents of the provided existing resource with new imported data.
-		 *
-		 * @param	inputFilePath	Pathname of the input file.
-		 * @param	importOptions	(optional) Options for controlling the import. Caller must
-		 *							ensure import options actually match the type of the importer used
-		 *							for the file type. 
-		 *
-		 * @see		createImportOptions
-		 */
-		void reimport(HResource& existingResource, const Path& inputFilePath, ConstImportOptionsPtr importOptions = nullptr);
-
-		/**
-		 * @brief	Automatically detects the importer needed for the provided file and returns valid type of
-		 * 			import options for that importer.
-		 *
-		 * @param	inputFilePath	Pathname of the input file.
-		 *
-		 * @return	The new import options.
-		 * 			
-		 * @note	You will need to type cast the importer options to a valid type,
-		 * 			taking into consideration exact importer you expect to be used for this file type.
-		 * 			If you don't use a proper import options type, an exception will be thrown during import.
-		 * 			
-		 *			nullptr is returned if the file path is not valid, or if a valid importer cannot be found for
-		 *			the specified file.
-		 */
-		ImportOptionsPtr createImportOptions(const Path& inputFilePath);
-
-		/**
-		 * @copydoc createImportOptions
-		 */
-		template<class T>
-		SPtr<T> createImportOptions(const Path& inputFilePath)
-		{
-			return std::static_pointer_cast<T>(createImportOptions(inputFilePath));
-		}
-
-		/**
-		 * @brief	Checks if we can import a file with the specified extension.
-		 *
-		 * @param	extension	The extension without the leading dot.
-		 */
-		bool supportsFileType(const WString& extension) const;
-
-		/**
-		 * @brief	Checks if we can import a file with the specified magic number.
-		 *
-		 * @param	magicNumber 	The buffer containing the magic number.
-		 * @param	magicNumSize	Size of the magic number buffer.
-		 */
-		bool supportsFileType(const UINT8* magicNumber, UINT32 magicNumSize) const;
-
-		/**
-		 * @brief	Adds a new asset importer for the specified file extension. If an asset importer for that extension
-		 * 			already exists, it is removed and replaced with the current one.
-		 * 			
-		 * @note	Internal method. This method should only be called by asset importers themselves on startup. Importer takes ownership
-		 *			of the provided pointer and will release it. Assumes it is allocated using the general allocator.
-		 *
-		 * @param [in]	importer	The importer that is able to handle files with the specified extension. nullptr if you
-		 * 							want to remove an asset importer for the extension.
-		 */
-		void _registerAssetImporter(SpecificImporter* importer);
-	private:
-		Vector<SpecificImporter*> mAssetImporters;
-
-		SpecificImporter* getImporterForFile(const Path& inputFilePath) const;
-	};
-
-	/**
-	 * @brief	Provides global access to the importer.
-	 */
-	BS_CORE_EXPORT Importer& gImporter();
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsModule.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Importer
+	 *  @{
+	 */
+
+	/** Module responsible for importing various asset types and converting them to types usable by the engine. */
+	class BS_CORE_EXPORT Importer : public Module<Importer>
+	{
+	public:
+		Importer(); 
+		~Importer(); 
+
+		/**
+		 * Imports a resource at the specified location, and returns the loaded data.
+		 *
+		 * @param[in]	inputFilePath	Pathname of the input file.
+		 * @param[in]	importOptions	(optional) Options for controlling the import. Caller must ensure import options 
+		 *								actually match the type of the importer used for the file type.
+		 *
+		 * @see		createImportOptions
+		 */
+		HResource import(const Path& inputFilePath, ConstImportOptionsPtr importOptions = nullptr);
+
+		/** @copydoc import */
+		template <class T>
+		ResourceHandle<T> import(const Path& inputFilePath, ConstImportOptionsPtr importOptions = nullptr)
+		{
+			return static_resource_cast<T>(import(inputFilePath, importOptions));
+		}
+
+		/**
+		 * Imports a resource and replaces the contents of the provided existing resource with new imported data.
+		 *
+		 * @param[in]	inputFilePath	Pathname of the input file.
+		 * @param[in]	importOptions	(optional) Options for controlling the import. Caller must ensure import options 
+		 *								actually match the type of the importer used for the file type. 
+		 *
+		 * @see		createImportOptions
+		 */
+		void reimport(HResource& existingResource, const Path& inputFilePath, ConstImportOptionsPtr importOptions = nullptr);
+
+		/**
+		 * Automatically detects the importer needed for the provided file and returns valid type of import options for 
+		 * that importer.
+		 *
+		 * @param[in]	inputFilePath	Pathname of the input file.
+		 *
+		 * @return						The new import options. Null is returned if the file path is not valid, or if a 
+		 *								valid importer cannot be found for the specified file.
+		 * 			
+		 * @note	
+		 * You will need to type cast the importer options to a valid type, taking into consideration exact importer you 
+		 * expect to be used for this file type. If you don't use a proper import options type, an exception will be thrown 
+		 * during import.
+		 */
+		ImportOptionsPtr createImportOptions(const Path& inputFilePath);
+
+		/** @copydoc createImportOptions */
+		template<class T>
+		SPtr<T> createImportOptions(const Path& inputFilePath)
+		{
+			return std::static_pointer_cast<T>(createImportOptions(inputFilePath));
+		}
+
+		/**
+		 * Checks if we can import a file with the specified extension.
+		 *
+		 * @param[in]	extension	The extension without the leading dot.
+		 */
+		bool supportsFileType(const WString& extension) const;
+
+		/**
+		 * Checks if we can import a file with the specified magic number.
+		 *
+		 * @param[in]	magicNumber 	The buffer containing the magic number.
+		 * @param[in]	magicNumSize	Size of the magic number buffer.
+		 */
+		bool supportsFileType(const UINT8* magicNumber, UINT32 magicNumSize) const;
+
+		/**
+		 * Adds a new asset importer for the specified file extension. If an asset importer for that extension already 
+		 * exists, it is removed and replaced with the current one.
+		 *
+		 *
+		 * @param [in]	importer	The importer that is able to handle files with the specified extension. nullptr if you
+		 * 							want to remove an asset importer for the extension.
+		 *
+		 * @note	Internal method. 
+		 * @note	This method should only be called by asset importers themselves on startup. Importer takes ownership
+		 *			of the provided pointer and will release it. Assumes it is allocated using the general allocator.
+		 */
+		void _registerAssetImporter(SpecificImporter* importer);
+	private:
+		Vector<SpecificImporter*> mAssetImporters;
+
+		SpecificImporter* getImporterForFile(const Path& inputFilePath) const;
+	};
+
+	/** Provides easier access to Importer. */
+	BS_CORE_EXPORT Importer& gImporter();
+
+	/** @} */
 }
 }

+ 94 - 143
BansheeCore/Include/BsInput.h

@@ -2,25 +2,25 @@
 
 
 #include "BsCorePrerequisites.h"
 #include "BsCorePrerequisites.h"
 #include "BsModule.h"
 #include "BsModule.h"
-#include "BsRect2I.h"
 #include "BsOSInputHandler.h"
 #include "BsOSInputHandler.h"
 #include "BsRawInputHandler.h"
 #include "BsRawInputHandler.h"
 #include "BsInputFwd.h"
 #include "BsInputFwd.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	/** @addtogroup Input
+	 *  @{
+	 */
+
 	/**
 	/**
-	 * @brief	Primary module used for dealing with input. Allows you to receieve 
-	 *			and query raw or OS input for mouse/keyboard/gamepad.
+	 * Primary module used for dealing with input. Allows you to receieve and query raw or OS input for 
+	 * mouse/keyboard/gamepad.
 	 *
 	 *
-	 *			All inputs are received through an input handler, which can be overriden to 
-	 *			provide custom input functionality.
+	 * All inputs are received through an input handler, which can be overriden to provide custom input functionality.
 	 */
 	 */
 	class BS_CORE_EXPORT Input : public Module<Input>
 	class BS_CORE_EXPORT Input : public Module<Input>
 	{
 	{
-		/**
-		 * @brief	Possible button states
-		 */
+		/** Possible button states. */
 		enum class ButtonState
 		enum class ButtonState
 		{
 		{
 			Off, /**< Button is not being pressed. */
 			Off, /**< Button is not being pressed. */
@@ -30,9 +30,7 @@ namespace BansheeEngine
 			ToggledOnOff, /**< Button has been pressed and released this frame. */
 			ToggledOnOff, /**< Button has been pressed and released this frame. */
 		};
 		};
 
 
-		/**
-		 * @brief	Contains axis and device data per device
-		 */
+		/** Contains axis and device data per device. */
 		struct DeviceData
 		struct DeviceData
 		{
 		{
 			DeviceData();
 			DeviceData();
@@ -41,17 +39,13 @@ namespace BansheeEngine
 			ButtonState keyStates[BC_Count];
 			ButtonState keyStates[BC_Count];
 		};
 		};
 
 
-		/**
-		 * @brief	Different types of possible input event callbacks.
-		 */
+		/**	Different types of possible input event callbacks. */
 		enum class EventType
 		enum class EventType
 		{
 		{
 			ButtonUp, ButtonDown, PointerMoved, PointerUp, PointerDown, PointerDoubleClick, TextInput, Command
 			ButtonUp, ButtonDown, PointerMoved, PointerUp, PointerDown, PointerDoubleClick, TextInput, Command
 		};
 		};
 
 
-		/**
-		 * @brief	Stores information about a queued input event that is to be triggered later.
-		 */
+		/**	Stores information about a queued input event that is to be triggered later. */
 		struct QueuedEvent
 		struct QueuedEvent
 		{
 		{
 			QueuedEvent(EventType type, UINT32 idx)
 			QueuedEvent(EventType type, UINT32 idx)
@@ -67,194 +61,151 @@ namespace BansheeEngine
 		~Input();
 		~Input();
 
 
 		/**
 		/**
-		 * @brief	Triggered whenever a button is first pressed.
+		 * Returns value of the specified input axis. Normally in range [-1.0, 1.0] but can be outside the range for 
+		 * devices with unbound axes (e.g. mouse).
+		 *
+		 * @param[in]	type		Type of axis to query. Usually a type from InputAxis but can be a custom value.
+		 * @param[in]	deviceIdx	Index of the device in case more than one is hooked up (0 - primary).
 		 */
 		 */
-		Event<void(const ButtonEvent&)> onButtonDown;
+		float getAxisValue(UINT32 type, UINT32 deviceIdx = 0) const;
 
 
 		/**
 		/**
-		 * @brief	Triggered whenever a button is first released.
+		 * Query if the provided button is currently being held (this frame or previous frames).
+		 *
+		 * @param[in]	keyCode		Code of the button to query.
+		 * @param[in]	deviceIdx	Device to query the button on (0 - primary).
 		 */
 		 */
-		Event<void(const ButtonEvent&)> onButtonUp;
+		bool isButtonHeld(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
 
 
 		/**
 		/**
-		 * @brief	Triggered whenever user inputs a text character. 
+		 * Query if the provided button is currently being released (only true for one frame).
+		 *
+		 * @param[in]	keyCode		Code of the button to query.
+		 * @param[in]	deviceIdx	Device to query the button on (0 - primary).
 		 */
 		 */
-		Event<void(const TextInputEvent&)> onCharInput;
+		bool isButtonUp(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
 
 
 		/**
 		/**
-		 * @brief	Triggers when some pointing device (mouse cursor, touch) moves.
+		 * Query if the provided button is currently being pressed (only true for one frame).
+		 *
+		 * @param[in]	keyCode		Code of the button to query.
+		 * @param[in]	deviceIdx	Device to query the button on (0 - primary).
 		 */
 		 */
-		Event<void(const PointerEvent&)> onPointerMoved;
+		bool isButtonDown(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
 
 
-		/**
-		 * @brief	Triggers when some pointing device (mouse cursor, touch) button is pressed.
-		 */
-		Event<void(const PointerEvent&)> onPointerPressed;
+		/** Returns position of the pointer (e.g. mouse cursor) relative to the screen. */
+		Vector2I getPointerPosition() const;
+
+		/** Returns difference between last and current pointer position. */
+		Vector2I getPointerDelta() const { return mPointerDelta; }
 
 
 		/**
 		/**
-		 * @brief	Triggers when some pointing device (mouse cursor, touch) button is released.
+		 * Query if the provided pointer button is currently being held (this frame or previous frames).
+		 *
+		 * @param[in]	pointerButton		Code of the button to query.
 		 */
 		 */
-		Event<void(const PointerEvent&)> onPointerReleased;
+		bool isPointerButtonHeld(PointerEventButton pointerButton) const;
 
 
 		/**
 		/**
-		 * @brief	Triggers when some pointing device (mouse cursor, touch) button is double clicked.
+		 * Query if the provided pointer button is currently being released (only true for one frame).
+		 *
+		 * @param[in]	pointerButton		Code of the button to query.
 		 */
 		 */
-		Event<void(const PointerEvent&)> onPointerDoubleClick;
+		bool isPointerButtonUp(PointerEventButton pointerButton) const;
 
 
-		// TODO Low priority: Remove this, I can emulate it using virtual input
 		/**
 		/**
-		 * @brief	Triggers on special input commands.
+		 * Query if the provided pointer button is currently being pressed (only true for one frame).
+		 *
+		 * @param[in]	pointerButton		Code of the button to query.
 		 */
 		 */
-		Event<void(InputCommandType)> onInputCommand;
+		bool isPointerButtonDown(PointerEventButton pointerButton) const;
+
+		/** Query has the left pointer button has been double-clicked this frame. */
+		bool isPointerDoubleClicked() const;
+
+		/** Enables or disables mouse smoothing. Smoothing makes the changes to mouse axes more gradual. */
+		void setMouseSmoothing(bool enabled);
+
+		/** @cond INTERNAL */
 
 
 		/**
 		/**
-		 * @brief	Registers a new input handler. Replaces any previous input handler.
+		 * Registers a new input handler. Replaces any previous input handler.
 		 *
 		 *
 		 * @note	Internal method.
 		 * @note	Internal method.
 		 */
 		 */
 		void _registerRawInputHandler(std::shared_ptr<RawInputHandler> inputHandler);
 		void _registerRawInputHandler(std::shared_ptr<RawInputHandler> inputHandler);
 
 
 		/**
 		/**
-		 * @brief	Called every frame. Detects button state changes and prepares callback events to trigger
-		 *			via a call to _triggerCallbacks().
+		 * Called every frame. Detects button state changes and prepares callback events to trigger via a call to 
+		 * _triggerCallbacks().
 		 *
 		 *
 		 * @note	Internal method.
 		 * @note	Internal method.
 		 */
 		 */
 		void _update();
 		void _update();
 
 
 		/**
 		/**
-		 * @brief	Triggers any queued input event callbacks.
+		 * Triggers any queued input event callbacks.
+		 * 
+		 * @note	Internal method.
 		 */
 		 */
 		void _triggerCallbacks();
 		void _triggerCallbacks();
 
 
-		/**
-		 * @brief	Returns value of the specified input axis. Normally in range [-1.0, 1.0] but can be outside
-		 *			the range for devices with unbound axes (e.g. mouse).
-		 *
-		 * @param	type		Type of axis to query. Usually a type from InputAxis but can be a custom value.
-		 * @param	deviceIdx	Index of the device in case more than one is hooked up (0 - primary).
-		 */
-		float getAxisValue(UINT32 type, UINT32 deviceIdx = 0) const;
-
-		/**
-		 * @brief	Query if the provided button is currently being held (this frame or previous frames).
-		 *
-		 * @param	keyCode		Code of the button to query.
-		 * @param	deviceIdx	Device to query the button on (0 - primary).
-		 */
-		bool isButtonHeld(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
+		/** @endcond */
 
 
-		/**
-		 * @brief	Query if the provided button is currently being released (only true for one frame).
-		 *
-		 * @param	keyCode		Code of the button to query.
-		 * @param	deviceIdx	Device to query the button on (0 - primary).
-		 */
-		bool isButtonUp(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
-
-		/**
-		 * @brief	Query if the provided button is currently being pressed (only true for one frame).
-		 *
-		 * @param	keyCode		Code of the button to query.
-		 * @param	deviceIdx	Device to query the button on (0 - primary).
-		 */
-		bool isButtonDown(ButtonCode keyCode, UINT32 deviceIdx = 0) const;
+		/** Triggered whenever a button is first pressed. */
+		Event<void(const ButtonEvent&)> onButtonDown;
 
 
-		/**
-		 * @brief	Returns position of the pointer (e.g. mouse cursor) relative to the screen.
-		 */
-		Vector2I getPointerPosition() const;
+		/**	Triggered whenever a button is first released. */
+		Event<void(const ButtonEvent&)> onButtonUp;
 
 
-		/**
-		 * @brief	Returns difference between last and current pointer position.
-		 */
-		Vector2I getPointerDelta() const { return mPointerDelta; }
+		/**	Triggered whenever user inputs a text character. */
+		Event<void(const TextInputEvent&)> onCharInput;
 
 
-		/**
-		 * @brief	Query if the provided pointer button is currently 
-		 *			being held (this frame or previous frames).
-		 *
-		 * @param	pointerButton		Code of the button to query.
-		 */
-		bool isPointerButtonHeld(PointerEventButton pointerButton) const;
+		/**	Triggers when some pointing device (mouse cursor, touch) moves. */
+		Event<void(const PointerEvent&)> onPointerMoved;
 
 
-		/**
-		 * @brief	Query if the provided pointer button is currently 
-		 *			being released (only true for one frame).
-		 *
-		 * @param	pointerButton		Code of the button to query.
-		 */
-		bool isPointerButtonUp(PointerEventButton pointerButton) const;
+		/**	Triggers when some pointing device (mouse cursor, touch) button is pressed. */
+		Event<void(const PointerEvent&)> onPointerPressed;
 
 
-		/**
-		 * @brief	Query if the provided pointer button is currently 
-		 *			being pressed (only true for one frame).
-		 *
-		 * @param	pointerButton		Code of the button to query.
-		 */
-		bool isPointerButtonDown(PointerEventButton pointerButton) const;
+		/**	Triggers when some pointing device (mouse cursor, touch) button is released. */
+		Event<void(const PointerEvent&)> onPointerReleased;
 
 
-		/**
-		 * @brief	Query has the left pointer button has been 
-		 *			double-clicked this frame.
-		 */
-		bool isPointerDoubleClicked() const;
+		/**	Triggers when some pointing device (mouse cursor, touch) button is double clicked. */
+		Event<void(const PointerEvent&)> onPointerDoubleClick;
 
 
-		/**
-		 * @brief	Enables or disables mouse smoothing. Smoothing makes the changes to
-		 *			mouse axes more gradual.
-		 */
-		void setMouseSmoothing(bool enabled);
+		// TODO Low priority: Remove this, I can emulate it using virtual input
+		/**	Triggers on special input commands. */
+		Event<void(InputCommandType)> onInputCommand;
 
 
 	private:
 	private:
-		/**
-		 * @brief	Triggered by input handler when a button is pressed.
-		 */
+		/**	Triggered by input handler when a button is pressed. */
 		void buttonDown(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
 		void buttonDown(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
 
 
-		/**
-		 * @brief	Triggered by input handler when a button is released.
-		 */
+		/**	Triggered by input handler when a button is released. */
 		void buttonUp(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
 		void buttonUp(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp);
 
 
-		/**
-		 * @brief	Triggered by input handler when a single character is input.
-		 */
+		/**	Triggered by input handler when a single character is input. */
 		void charInput(UINT32 chr);
 		void charInput(UINT32 chr);
 
 
-		/**
-		 * @brief	Triggered by input handler when a mouse/joystick axis is moved.
-		 */
+		/**	Triggered by input handler when a mouse/joystick axis is moved. */
 		void axisMoved(UINT32 deviceIdx, const RawAxisState& state, UINT32 axis);
 		void axisMoved(UINT32 deviceIdx, const RawAxisState& state, UINT32 axis);
 
 
-		/**
-		 * @brief	Cursor movement as OS reports it. Used for screen cursor position.
-		 */
+		/**	Cursor movement as OS reports it. Used for screen cursor position. */
 		void cursorMoved(const PointerEvent& event);
 		void cursorMoved(const PointerEvent& event);
 
 
-		/**
-		 * @brief	Cursor button presses as OS reports it. 
-		 */
+		/**	Cursor button presses as OS reports it. */
 		void cursorPressed(const PointerEvent& event);
 		void cursorPressed(const PointerEvent& event);
 
 
-		/**
-		 * @brief	Cursor button releases as OS reports it.
-		 */
+		/**	Cursor button releases as OS reports it. */
 		void cursorReleased(const PointerEvent& event);
 		void cursorReleased(const PointerEvent& event);
 		
 		
-		/**
-		 * @brief	Cursor button releases as OS reports it.
-		 */
+		/**	Cursor button releases as OS reports it. */
 		void cursorDoubleClick(const PointerEvent& event);
 		void cursorDoubleClick(const PointerEvent& event);
 
 
-		/**
-		 * @brief	Input commands as OS reports them.
-		 */
+		/** Input commands as OS reports them. */
 		void inputCommandEntered(InputCommandType commandType);
 		void inputCommandEntered(InputCommandType commandType);
 
 
-		/**
-		 * @brief	Called when window in focus changes, as reported by the OS.
-		 */
+		/** Called when window in focus changes, as reported by the OS. */
 		void inputWindowChanged(RenderWindow& win);
 		void inputWindowChanged(RenderWindow& win);
 
 
 	private:
 	private:
@@ -287,8 +238,8 @@ namespace BansheeEngine
 		static const float WEIGHT_MODIFIER;
 		static const float WEIGHT_MODIFIER;
 	};
 	};
 
 
-	/**
-	 * @copydoc	Input
-	 */
+	/** Provides easier access to Input. */
 	BS_CORE_EXPORT Input& gInput();
 	BS_CORE_EXPORT Input& gInput();
+
+	/** @} */
 }
 }

+ 409 - 423
BansheeCore/Include/BsInputFwd.h

@@ -1,424 +1,410 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsVector2I.h"
-
-namespace BansheeEngine
-{
-	// Contains all possible keys, including keyboard scan codes, mouse buttons and gamepad buttons
-	// Note: These KeyCodes are only keyboard scan codes. This means that exact scan code identifier might 
-	// not correspond to that exact character on users keyboard, depending on users input locale. 
-	// Only for US locale will these scan code names will match the actual keyboard input. Think of the US key
-	// code names as only a convenience for more easily identifying which location on the keyboard a scan code represents.
-	//
-	// When storing these sequentially make sure to only reference the low order 2 bytes. Two high order bytes are used for various flags.
-	enum ButtonCode
-	{
-		BC_UNASSIGNED  = 0x00,
-		BC_ESCAPE      = 0x01,
-		BC_1           = 0x02,
-		BC_2           = 0x03,
-		BC_3           = 0x04,
-		BC_4           = 0x05,
-		BC_5           = 0x06,
-		BC_6           = 0x07,
-		BC_7           = 0x08,
-		BC_8           = 0x09,
-		BC_9           = 0x0A,
-		BC_0           = 0x0B,
-		BC_MINUS       = 0x0C,    // - on main keyboard
-		BC_EQUALS      = 0x0D,
-		BC_BACK        = 0x0E,    // backspace
-		BC_TAB         = 0x0F,
-		BC_Q           = 0x10,
-		BC_W           = 0x11,
-		BC_E           = 0x12,
-		BC_R           = 0x13,
-		BC_T           = 0x14,
-		BC_Y           = 0x15,
-		BC_U           = 0x16,
-		BC_I           = 0x17,
-		BC_O           = 0x18,
-		BC_P           = 0x19,
-		BC_LBRACKET    = 0x1A,
-		BC_RBRACKET    = 0x1B,
-		BC_RETURN      = 0x1C,    // Enter on main keyboard
-		BC_LCONTROL    = 0x1D,
-		BC_A           = 0x1E,
-		BC_S           = 0x1F,
-		BC_D           = 0x20,
-		BC_F           = 0x21,
-		BC_G           = 0x22,
-		BC_H           = 0x23,
-		BC_J           = 0x24,
-		BC_K           = 0x25,
-		BC_L           = 0x26,
-		BC_SEMICOLON   = 0x27,
-		BC_APOSTROPHE  = 0x28,
-		BC_GRAVE       = 0x29,    // accent
-		BC_LSHIFT      = 0x2A,
-		BC_BACKSLASH   = 0x2B,
-		BC_Z           = 0x2C,
-		BC_X           = 0x2D,
-		BC_C           = 0x2E,
-		BC_V           = 0x2F,
-		BC_B           = 0x30,
-		BC_N           = 0x31,
-		BC_M           = 0x32,
-		BC_COMMA       = 0x33,
-		BC_PERIOD      = 0x34,    // . on main keyboard
-		BC_SLASH       = 0x35,    // / on main keyboard
-		BC_RSHIFT      = 0x36,
-		BC_MULTIPLY    = 0x37,    // * on numeric keypad
-		BC_LMENU       = 0x38,    // left Alt
-		BC_SPACE       = 0x39,
-		BC_CAPITAL     = 0x3A,
-		BC_F1          = 0x3B,
-		BC_F2          = 0x3C,
-		BC_F3          = 0x3D,
-		BC_F4          = 0x3E,
-		BC_F5          = 0x3F,
-		BC_F6          = 0x40,
-		BC_F7          = 0x41,
-		BC_F8          = 0x42,
-		BC_F9          = 0x43,
-		BC_F10         = 0x44,
-		BC_NUMLOCK     = 0x45,
-		BC_SCROLL      = 0x46,    // Scroll Lock
-		BC_NUMPAD7     = 0x47,
-		BC_NUMPAD8     = 0x48,
-		BC_NUMPAD9     = 0x49,
-		BC_SUBTRACT    = 0x4A,    // - on numeric keypad
-		BC_NUMPAD4     = 0x4B,
-		BC_NUMPAD5     = 0x4C,
-		BC_NUMPAD6     = 0x4D,
-		BC_ADD         = 0x4E,    // + on numeric keypad
-		BC_NUMPAD1     = 0x4F,
-		BC_NUMPAD2     = 0x50,
-		BC_NUMPAD3     = 0x51,
-		BC_NUMPAD0     = 0x52,
-		BC_DECIMAL     = 0x53,    // . on numeric keypad
-		BC_OEM_102     = 0x56,    // < > | on UK/Germany keyboards
-		BC_F11         = 0x57,
-		BC_F12         = 0x58,
-		BC_F13         = 0x64,    //                     (NEC PC98)
-		BC_F14         = 0x65,    //                     (NEC PC98)
-		BC_F15         = 0x66,    //                     (NEC PC98)
-		BC_KANA        = 0x70,    // (Japanese keyboard)
-		BC_ABNT_C1     = 0x73,    // / ? on Portugese (Brazilian) keyboards
-		BC_CONVERT     = 0x79,    // (Japanese keyboard)
-		BC_NOCONVERT   = 0x7B,    // (Japanese keyboard)
-		BC_YEN         = 0x7D,    // (Japanese keyboard)
-		BC_ABNT_C2     = 0x7E,    // Numpad . on Portugese (Brazilian) keyboards
-		BC_NUMPADEQUALS= 0x8D,    // = on numeric keypad (NEC PC98)
-		BC_PREVTRACK   = 0x90,    // Previous Track (BC_CIRCUMFLEX on Japanese keyboard)
-		BC_AT          = 0x91,    //                     (NEC PC98)
-		BC_COLON       = 0x92,    //                     (NEC PC98)
-		BC_UNDERLINE   = 0x93,    //                     (NEC PC98)
-		BC_KANJI       = 0x94,    // (Japanese keyboard)
-		BC_STOP        = 0x95,    //                     (NEC PC98)
-		BC_AX          = 0x96,    //                     (Japan AX)
-		BC_UNLABELED   = 0x97,    //                        (J3100)
-		BC_NEXTTRACK   = 0x99,    // Next Track
-		BC_NUMPADENTER = 0x9C,    // Enter on numeric keypad
-		BC_RCONTROL    = 0x9D,
-		BC_MUTE        = 0xA0,    // Mute
-		BC_CALCULATOR  = 0xA1,    // Calculator
-		BC_PLAYPAUSE   = 0xA2,    // Play / Pause
-		BC_MEDIASTOP   = 0xA4,    // Media Stop
-		BC_VOLUMEDOWN  = 0xAE,    // Volume -
-		BC_VOLUMEUP    = 0xB0,    // Volume +
-		BC_WEBHOME     = 0xB2,    // Web home
-		BC_NUMPADCOMMA = 0xB3,    // , on numeric keypad (NEC PC98)
-		BC_DIVIDE      = 0xB5,    // / on numeric keypad
-		BC_SYSRQ       = 0xB7,
-		BC_RMENU       = 0xB8,    // right Alt
-		BC_PAUSE       = 0xC5,    // Pause
-		BC_HOME        = 0xC7,    // Home on arrow keypad
-		BC_UP          = 0xC8,    // UpArrow on arrow keypad
-		BC_PGUP        = 0xC9,    // PgUp on arrow keypad
-		BC_LEFT        = 0xCB,    // LeftArrow on arrow keypad
-		BC_RIGHT       = 0xCD,    // RightArrow on arrow keypad
-		BC_END         = 0xCF,    // End on arrow keypad
-		BC_DOWN        = 0xD0,    // DownArrow on arrow keypad
-		BC_PGDOWN      = 0xD1,    // PgDn on arrow keypad
-		BC_INSERT      = 0xD2,    // Insert on arrow keypad
-		BC_DELETE      = 0xD3,    // Delete on arrow keypad
-		BC_LWIN        = 0xDB,    // Left Windows key
-		BC_RWIN        = 0xDC,    // Right Windows key
-		BC_APPS        = 0xDD,    // AppMenu key
-		BC_POWER       = 0xDE,    // System Power
-		BC_SLEEP       = 0xDF,    // System Sleep
-		BC_WAKE        = 0xE3,    // System Wake
-		BC_WEBSEARCH   = 0xE5,    // Web Search
-		BC_WEBFAVORITES= 0xE6,    // Web Favorites
-		BC_WEBREFRESH  = 0xE7,    // Web Refresh
-		BC_WEBSTOP     = 0xE8,    // Web Stop
-		BC_WEBFORWARD  = 0xE9,    // Web Forward
-		BC_WEBBACK     = 0xEA,    // Web Back
-		BC_MYCOMPUTER  = 0xEB,    // My Computer
-		BC_MAIL        = 0xEC,    // Mail
-		BC_MEDIASELECT = 0xED,     // Media Select
-		BC_MOUSE_LEFT = 0x800000EE, // Mouse buttons - Most important bit signifies this key is a mouse button
-		BC_MOUSE_RIGHT = 0x800000EF,
-		BC_MOUSE_MIDDLE = 0x800000F0,
-		BC_MOUSE_BTN4 = 0x800000F1,
-		BC_MOUSE_BTN5 = 0x800000F2,
-		BC_MOUSE_BTN6 = 0x800000F3,
-		BC_MOUSE_BTN7 = 0x800000F4,
-		BC_MOUSE_BTN8 = 0x800000F5,
-		BC_MOUSE_BTN9 = 0x800000F6,
-		BC_MOUSE_BTN10 = 0x800000F7,
-		BC_MOUSE_BTN11 = 0x800000F8,
-		BC_MOUSE_BTN12 = 0x800000F9,
-		BC_MOUSE_BTN13 = 0x800000FA,
-		BC_MOUSE_BTN14 = 0x800000FB,
-		BC_MOUSE_BTN15 = 0x800000FC,
-		BC_MOUSE_BTN16 = 0x800000FD,
-		BC_MOUSE_BTN17 = 0x800000FE,
-		BC_MOUSE_BTN18 = 0x800000FF,
-		BC_MOUSE_BTN19 = 0x80000101,
-		BC_MOUSE_BTN20 = 0x80000102,
-		BC_MOUSE_BTN21 = 0x80000103,
-		BC_MOUSE_BTN22 = 0x80000104,
-		BC_MOUSE_BTN23 = 0x80000105,
-		BC_MOUSE_BTN24 = 0x80000106,
-		BC_MOUSE_BTN25 = 0x80000107,
-		BC_MOUSE_BTN26 = 0x80000108,
-		BC_MOUSE_BTN27 = 0x80000109,
-		BC_MOUSE_BTN28 = 0x8000010A,
-		BC_MOUSE_BTN29 = 0x8000010B,
-		BC_MOUSE_BTN30 = 0x8000010C,
-		BC_MOUSE_BTN31 = 0x8000010D,
-		BC_MOUSE_BTN32 = 0x8000010E,
-		BC_GAMEPAD_A = 0x4000010F, // Joystick/Gamepad buttons- Second most important bit signifies key is a gamepad button
-		BC_GAMEPAD_B = 0x40000110, // Similar to keyboard names, these are for convenience named after Xbox controller buttons
-		BC_GAMEPAD_X = 0x40000111, // but if some other controller is connected you will need to learn yourself which of these
-		BC_GAMEPAD_Y = 0x40000112, // corresponds to which actual button on the controller.
-		BC_GAMEPAD_LB = 0x40000113,
-		BC_GAMEPAD_RB = 0x40000114,
-		BC_GAMEPAD_LS = 0x40000115,
-		BC_GAMEPAD_RS = 0x40000116,
-		BC_GAMEPAD_BACK = 0x40000117,
-		BC_GAMEPAD_START = 0x40000118,
-		BC_GAMEPAD_DPAD_LEFT = 0x40000119,
-		BC_GAMEPAD_DPAD_RIGHT = 0x4000011A,
-		BC_GAMEPAD_DPAD_UP = 0x4000011B,
-		BC_GAMEPAD_DPAD_DOWN = 0x4000011C,
-		BC_GAMEPAD_BTN1 = 0x4000011D,
-		BC_GAMEPAD_BTN2 = 0x4000011E,
-		BC_GAMEPAD_BTN3 = 0x4000011F,
-		BC_GAMEPAD_BTN4 = 0x40000120,
-		BC_GAMEPAD_BTN5 = 0x40000121,
-		BC_GAMEPAD_BTN6 = 0x40000122,
-		BC_GAMEPAD_BTN7 = 0x40000123,
-		BC_GAMEPAD_BTN8 = 0x40000124,
-		BC_GAMEPAD_BTN9 = 0x40000125,
-		BC_GAMEPAD_BTN10 = 0x40000126,
-		BC_GAMEPAD_BTN11 = 0x40000127,
-		BC_GAMEPAD_BTN12 = 0x40000128,
-		BC_GAMEPAD_BTN13 = 0x40000129,
-		BC_GAMEPAD_BTN14 = 0x4000012A,
-		BC_GAMEPAD_BTN15 = 0x4000012B,
-		BC_GAMEPAD_BTN16 = 0x4000012C,
-		BC_GAMEPAD_BTN17 = 0x4000012D,
-		BC_GAMEPAD_BTN18 = 0x4000012E,
-		BC_GAMEPAD_BTN19 = 0x4000012F,
-		BC_GAMEPAD_BTN20 = 0x40000130,
-		BC_Count = 304,
-		BC_NumKeys = 238, // IMPORTANT: Make sure to update these if you modify the values above
-		BC_NumMouse = 32,
-		BC_NumGamepad = 34,
-	};
-
-	/**
-	 * @brief	Contains data about a button input event.
-	 */
-	struct ButtonEvent
-	{
-	public:
-		ButtonEvent()
-			:mIsUsed(false)
-		{ }
-
-		ButtonCode buttonCode; /**< Button code this event is referring to. */
-		UINT64 timestamp; /**< Timestamp in ticks when the event happened. */
-		UINT32 deviceIdx; /**< Index of the device that the event originated from. */
-
-		/**
-		 * @brief	Query is the pressed button a keyboard button.
-		 */
-		bool isKeyboard() const { return (buttonCode & 0xC0000000) == 0; }
-
-		/**
-		 * @brief	Query is the pressed button a mouse button.
-		 */
-		bool isMouse() const { return (buttonCode & 0x80000000) != 0; }
-
-		/**
-		 * @brief	Query is the pressed button a gamepad button.
-		 */
-		bool isGamepad() const { return (buttonCode & 0x40000000) != 0; }
-
-		/**
-		 * @brief	Check if the event has been marked as used. Internally this means nothing
-		 *			but caller might choose to ignore an used event.
-		 */
-		bool isUsed() const { return mIsUsed; }
-
-		/**
-		 * @brief	Mark the event as used. Internally this means nothing
-		 *			but caller might choose to ignore an used event.
-		 */
-		void markAsUsed() const { mIsUsed = true; }
-	private:
-		mutable bool mIsUsed;
-	};
-
-	/**
-	 * @brief	Pointer buttons. Generally these correspond to mouse
-	 * 			buttons, but may be used in some form for touch input as well.
-	 */
-	enum class PointerEventButton
-	{
-		Left, Middle, Right, Count
-	};
-
-	/**
-	 * @brief	Type of pointer event.
-	 */
-	enum class PointerEventType
-	{
-		CursorMoved,
-		ButtonPressed,
-		ButtonReleased,
-		DoubleClick
-	};
-
-	/**
-	 * @brief	Event that gets sent out when user interacts with the screen in some way,
-	 * 			usually by moving the mouse cursor or using touch input.
-	 */
-	struct PointerEvent
-	{
-	public:
-		PointerEvent()
-			:mIsUsed(false), mouseWheelScrollAmount(0.0f), type(PointerEventType::CursorMoved),
-			shift(false), control(false), alt(false), button(PointerEventButton::Left)
-		{
-			buttonStates[0] = false;
-			buttonStates[1] = false;
-			buttonStates[2] = false;
-		}
-
-		Vector2I screenPos; /**< Screen position where the input event occurred. */
-		Vector2I delta; /**< Change in movement since last sent event. */
-		bool buttonStates[(UINT32)PointerEventButton::Count]; /**< States of the pointer buttons (e.g. mouse buttons). */
-		PointerEventButton button; /**< Button that triggered the pointer event. Might be irrelevant 
-										depending on event type. (e.g. move events don't correspond to a button. */
-		PointerEventType type; /**< Type of the pointer event. */
-
-		bool shift; /**< Is shift button on the keyboard being held down. */
-		bool control; /**< Is control button on the keyboard being held down. */
-		bool alt; /**< Is alt button on the keyboard being held down. */
-
-		float mouseWheelScrollAmount; /**< If mouse wheel is being scrolled, what is the amount. Only relevant for move events. */
-
-		/**
-		 * @brief	Check if the event has been marked as used. Internally this means nothing
-		 *			but caller might choose to ignore an used event.
-		 */
-		bool isUsed() const { return mIsUsed; }
-
-		/**
-		 * @brief	Mark the event as used. Internally this means nothing
-		 *			but caller might choose to ignore an used event.
-		 */
-		void markAsUsed() const { mIsUsed = true; }
-
-	private:
-		mutable bool mIsUsed;
-	};
-
-	/**
-	 * @brief	Types of special input commands.
-	 */
-	enum class InputCommandType
-	{
-		CursorMoveLeft, CursorMoveRight, CursorMoveUp, CursorMoveDown, 
-		SelectLeft, SelectRight, SelectUp, SelectDown,
-		Escape, Delete, Backspace, Return, Confirm
-	};
-
-	/**
-	 * @brief	Event that gets sent out when user inputs some text. These events may be preceeded by
-	 *			normal button events if user is typing on a keyboard. 
-	 */
-	struct TextInputEvent
-	{
-	public:
-		TextInputEvent()
-			:mIsUsed(false)
-		{ }
-
-		UINT32 textChar; /**< Character the that was input. */
-
-		/**
-		 * @brief	Check if the event has been marked as used. Internally this means nothing
-		 *			but caller might choose to ignore an used event.
-		 */
-		bool isUsed() const { return mIsUsed; }
-
-		/**
-		 * @brief	Mark the event as used. Internally this means nothing
-		 *			but caller might choose to ignore an used event.
-		 */
-		void markAsUsed() const { mIsUsed = true; }
-
-	private:
-		mutable bool mIsUsed;
-	};
-
-	/**
-	 * @brief	Types of input devices.
-	 */
-	enum class InputDevice
-	{
-		Keyboard,
-		Mouse,
-		Gamepad,
-		Count // Keep at end
-	};
-
-	/**
-	 * @brief	Common input axis types.
-	 */
-	enum class InputAxis
-	{
-		MouseX, /**< Mouse axis X. */
-		MouseY, /**< Mouse axis Y. */
-		MouseZ, /**< Mouse wheel/scroll axis. */
-		LeftStickX, /**< Gamepad left stick X */
-		LeftStickY, /**<  Gamepad left stick Y */
-		RightStickX, /**< Gamepad right stick X */
-		RightStickY, /**< Gamepad right stick Y */
-		LeftTrigger, /**< Gamepad left trigger */
-		RightTrigger, /**< Gamepad right trigger */
-		Count // Keep at end
-	};
-
-	/**
-	 * @brief	Modifiers used with along with keyboard buttons.
-	 */
-	enum class ButtonModifier
-	{
-		None = 0x00,
-		Shift = 0x01,
-		Ctrl = 0x02,
-		Alt = 0x04,
-		ShiftCtrl = 0x03,
-		CtrlAlt = 0x06,
-		ShiftAlt = 0x05,
-		ShiftCtrlAlt = 0x07
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsVector2I.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Input
+	 *  @{
+	 */
+
+	/**
+	 * Contains all possible input buttons, including keyboard scan codes, mouse buttons and gamepad buttons.
+	 *
+	 * @note
+	 * These codes are only keyboard scan codes. This means that exact scan code identifier might not correspond to that 
+	 * exact character on users keyboard, depending on users input locale. Only for US locale will these scan code names 
+	 * will match the actual keyboard input. Think of the US key code names as only a convenience for more easily 
+	 * identifying which location on the keyboard a scan code represents.
+	 * @note
+	 * When storing these sequentially make sure to only reference the low order 2 bytes. Two high order bytes are used for 
+	 * various flags.
+	 */
+	enum ButtonCode
+	{
+		BC_UNASSIGNED  = 0x00,
+		BC_ESCAPE      = 0x01,
+		BC_1           = 0x02,
+		BC_2           = 0x03,
+		BC_3           = 0x04,
+		BC_4           = 0x05,
+		BC_5           = 0x06,
+		BC_6           = 0x07,
+		BC_7           = 0x08,
+		BC_8           = 0x09,
+		BC_9           = 0x0A,
+		BC_0           = 0x0B,
+		BC_MINUS       = 0x0C,    // - on main keyboard
+		BC_EQUALS      = 0x0D,
+		BC_BACK        = 0x0E,    // backspace
+		BC_TAB         = 0x0F,
+		BC_Q           = 0x10,
+		BC_W           = 0x11,
+		BC_E           = 0x12,
+		BC_R           = 0x13,
+		BC_T           = 0x14,
+		BC_Y           = 0x15,
+		BC_U           = 0x16,
+		BC_I           = 0x17,
+		BC_O           = 0x18,
+		BC_P           = 0x19,
+		BC_LBRACKET    = 0x1A,
+		BC_RBRACKET    = 0x1B,
+		BC_RETURN      = 0x1C,    // Enter on main keyboard
+		BC_LCONTROL    = 0x1D,
+		BC_A           = 0x1E,
+		BC_S           = 0x1F,
+		BC_D           = 0x20,
+		BC_F           = 0x21,
+		BC_G           = 0x22,
+		BC_H           = 0x23,
+		BC_J           = 0x24,
+		BC_K           = 0x25,
+		BC_L           = 0x26,
+		BC_SEMICOLON   = 0x27,
+		BC_APOSTROPHE  = 0x28,
+		BC_GRAVE       = 0x29,    // accent
+		BC_LSHIFT      = 0x2A,
+		BC_BACKSLASH   = 0x2B,
+		BC_Z           = 0x2C,
+		BC_X           = 0x2D,
+		BC_C           = 0x2E,
+		BC_V           = 0x2F,
+		BC_B           = 0x30,
+		BC_N           = 0x31,
+		BC_M           = 0x32,
+		BC_COMMA       = 0x33,
+		BC_PERIOD      = 0x34,    // . on main keyboard
+		BC_SLASH       = 0x35,    // / on main keyboard
+		BC_RSHIFT      = 0x36,
+		BC_MULTIPLY    = 0x37,    // * on numeric keypad
+		BC_LMENU       = 0x38,    // left Alt
+		BC_SPACE       = 0x39,
+		BC_CAPITAL     = 0x3A,
+		BC_F1          = 0x3B,
+		BC_F2          = 0x3C,
+		BC_F3          = 0x3D,
+		BC_F4          = 0x3E,
+		BC_F5          = 0x3F,
+		BC_F6          = 0x40,
+		BC_F7          = 0x41,
+		BC_F8          = 0x42,
+		BC_F9          = 0x43,
+		BC_F10         = 0x44,
+		BC_NUMLOCK     = 0x45,
+		BC_SCROLL      = 0x46,    // Scroll Lock
+		BC_NUMPAD7     = 0x47,
+		BC_NUMPAD8     = 0x48,
+		BC_NUMPAD9     = 0x49,
+		BC_SUBTRACT    = 0x4A,    // - on numeric keypad
+		BC_NUMPAD4     = 0x4B,
+		BC_NUMPAD5     = 0x4C,
+		BC_NUMPAD6     = 0x4D,
+		BC_ADD         = 0x4E,    // + on numeric keypad
+		BC_NUMPAD1     = 0x4F,
+		BC_NUMPAD2     = 0x50,
+		BC_NUMPAD3     = 0x51,
+		BC_NUMPAD0     = 0x52,
+		BC_DECIMAL     = 0x53,    // . on numeric keypad
+		BC_OEM_102     = 0x56,    // < > | on UK/Germany keyboards
+		BC_F11         = 0x57,
+		BC_F12         = 0x58,
+		BC_F13         = 0x64,    //                     (NEC PC98)
+		BC_F14         = 0x65,    //                     (NEC PC98)
+		BC_F15         = 0x66,    //                     (NEC PC98)
+		BC_KANA        = 0x70,    // (Japanese keyboard)
+		BC_ABNT_C1     = 0x73,    // / ? on Portugese (Brazilian) keyboards
+		BC_CONVERT     = 0x79,    // (Japanese keyboard)
+		BC_NOCONVERT   = 0x7B,    // (Japanese keyboard)
+		BC_YEN         = 0x7D,    // (Japanese keyboard)
+		BC_ABNT_C2     = 0x7E,    // Numpad . on Portugese (Brazilian) keyboards
+		BC_NUMPADEQUALS= 0x8D,    // = on numeric keypad (NEC PC98)
+		BC_PREVTRACK   = 0x90,    // Previous Track (BC_CIRCUMFLEX on Japanese keyboard)
+		BC_AT          = 0x91,    //                     (NEC PC98)
+		BC_COLON       = 0x92,    //                     (NEC PC98)
+		BC_UNDERLINE   = 0x93,    //                     (NEC PC98)
+		BC_KANJI       = 0x94,    // (Japanese keyboard)
+		BC_STOP        = 0x95,    //                     (NEC PC98)
+		BC_AX          = 0x96,    //                     (Japan AX)
+		BC_UNLABELED   = 0x97,    //                        (J3100)
+		BC_NEXTTRACK   = 0x99,    // Next Track
+		BC_NUMPADENTER = 0x9C,    // Enter on numeric keypad
+		BC_RCONTROL    = 0x9D,
+		BC_MUTE        = 0xA0,    // Mute
+		BC_CALCULATOR  = 0xA1,    // Calculator
+		BC_PLAYPAUSE   = 0xA2,    // Play / Pause
+		BC_MEDIASTOP   = 0xA4,    // Media Stop
+		BC_VOLUMEDOWN  = 0xAE,    // Volume -
+		BC_VOLUMEUP    = 0xB0,    // Volume +
+		BC_WEBHOME     = 0xB2,    // Web home
+		BC_NUMPADCOMMA = 0xB3,    // , on numeric keypad (NEC PC98)
+		BC_DIVIDE      = 0xB5,    // / on numeric keypad
+		BC_SYSRQ       = 0xB7,
+		BC_RMENU       = 0xB8,    // right Alt
+		BC_PAUSE       = 0xC5,    // Pause
+		BC_HOME        = 0xC7,    // Home on arrow keypad
+		BC_UP          = 0xC8,    // UpArrow on arrow keypad
+		BC_PGUP        = 0xC9,    // PgUp on arrow keypad
+		BC_LEFT        = 0xCB,    // LeftArrow on arrow keypad
+		BC_RIGHT       = 0xCD,    // RightArrow on arrow keypad
+		BC_END         = 0xCF,    // End on arrow keypad
+		BC_DOWN        = 0xD0,    // DownArrow on arrow keypad
+		BC_PGDOWN      = 0xD1,    // PgDn on arrow keypad
+		BC_INSERT      = 0xD2,    // Insert on arrow keypad
+		BC_DELETE      = 0xD3,    // Delete on arrow keypad
+		BC_LWIN        = 0xDB,    // Left Windows key
+		BC_RWIN        = 0xDC,    // Right Windows key
+		BC_APPS        = 0xDD,    // AppMenu key
+		BC_POWER       = 0xDE,    // System Power
+		BC_SLEEP       = 0xDF,    // System Sleep
+		BC_WAKE        = 0xE3,    // System Wake
+		BC_WEBSEARCH   = 0xE5,    // Web Search
+		BC_WEBFAVORITES= 0xE6,    // Web Favorites
+		BC_WEBREFRESH  = 0xE7,    // Web Refresh
+		BC_WEBSTOP     = 0xE8,    // Web Stop
+		BC_WEBFORWARD  = 0xE9,    // Web Forward
+		BC_WEBBACK     = 0xEA,    // Web Back
+		BC_MYCOMPUTER  = 0xEB,    // My Computer
+		BC_MAIL        = 0xEC,    // Mail
+		BC_MEDIASELECT = 0xED,     // Media Select
+		BC_MOUSE_LEFT = 0x800000EE, // Mouse buttons - Most important bit signifies this key is a mouse button
+		BC_MOUSE_RIGHT = 0x800000EF,
+		BC_MOUSE_MIDDLE = 0x800000F0,
+		BC_MOUSE_BTN4 = 0x800000F1,
+		BC_MOUSE_BTN5 = 0x800000F2,
+		BC_MOUSE_BTN6 = 0x800000F3,
+		BC_MOUSE_BTN7 = 0x800000F4,
+		BC_MOUSE_BTN8 = 0x800000F5,
+		BC_MOUSE_BTN9 = 0x800000F6,
+		BC_MOUSE_BTN10 = 0x800000F7,
+		BC_MOUSE_BTN11 = 0x800000F8,
+		BC_MOUSE_BTN12 = 0x800000F9,
+		BC_MOUSE_BTN13 = 0x800000FA,
+		BC_MOUSE_BTN14 = 0x800000FB,
+		BC_MOUSE_BTN15 = 0x800000FC,
+		BC_MOUSE_BTN16 = 0x800000FD,
+		BC_MOUSE_BTN17 = 0x800000FE,
+		BC_MOUSE_BTN18 = 0x800000FF,
+		BC_MOUSE_BTN19 = 0x80000101,
+		BC_MOUSE_BTN20 = 0x80000102,
+		BC_MOUSE_BTN21 = 0x80000103,
+		BC_MOUSE_BTN22 = 0x80000104,
+		BC_MOUSE_BTN23 = 0x80000105,
+		BC_MOUSE_BTN24 = 0x80000106,
+		BC_MOUSE_BTN25 = 0x80000107,
+		BC_MOUSE_BTN26 = 0x80000108,
+		BC_MOUSE_BTN27 = 0x80000109,
+		BC_MOUSE_BTN28 = 0x8000010A,
+		BC_MOUSE_BTN29 = 0x8000010B,
+		BC_MOUSE_BTN30 = 0x8000010C,
+		BC_MOUSE_BTN31 = 0x8000010D,
+		BC_MOUSE_BTN32 = 0x8000010E,
+		BC_GAMEPAD_A = 0x4000010F, // Joystick/Gamepad buttons- Second most important bit signifies key is a gamepad button
+		BC_GAMEPAD_B = 0x40000110, // Similar to keyboard names, these are for convenience named after Xbox controller buttons
+		BC_GAMEPAD_X = 0x40000111, // but if some other controller is connected you will need to learn yourself which of these
+		BC_GAMEPAD_Y = 0x40000112, // corresponds to which actual button on the controller.
+		BC_GAMEPAD_LB = 0x40000113,
+		BC_GAMEPAD_RB = 0x40000114,
+		BC_GAMEPAD_LS = 0x40000115,
+		BC_GAMEPAD_RS = 0x40000116,
+		BC_GAMEPAD_BACK = 0x40000117,
+		BC_GAMEPAD_START = 0x40000118,
+		BC_GAMEPAD_DPAD_LEFT = 0x40000119,
+		BC_GAMEPAD_DPAD_RIGHT = 0x4000011A,
+		BC_GAMEPAD_DPAD_UP = 0x4000011B,
+		BC_GAMEPAD_DPAD_DOWN = 0x4000011C,
+		BC_GAMEPAD_BTN1 = 0x4000011D,
+		BC_GAMEPAD_BTN2 = 0x4000011E,
+		BC_GAMEPAD_BTN3 = 0x4000011F,
+		BC_GAMEPAD_BTN4 = 0x40000120,
+		BC_GAMEPAD_BTN5 = 0x40000121,
+		BC_GAMEPAD_BTN6 = 0x40000122,
+		BC_GAMEPAD_BTN7 = 0x40000123,
+		BC_GAMEPAD_BTN8 = 0x40000124,
+		BC_GAMEPAD_BTN9 = 0x40000125,
+		BC_GAMEPAD_BTN10 = 0x40000126,
+		BC_GAMEPAD_BTN11 = 0x40000127,
+		BC_GAMEPAD_BTN12 = 0x40000128,
+		BC_GAMEPAD_BTN13 = 0x40000129,
+		BC_GAMEPAD_BTN14 = 0x4000012A,
+		BC_GAMEPAD_BTN15 = 0x4000012B,
+		BC_GAMEPAD_BTN16 = 0x4000012C,
+		BC_GAMEPAD_BTN17 = 0x4000012D,
+		BC_GAMEPAD_BTN18 = 0x4000012E,
+		BC_GAMEPAD_BTN19 = 0x4000012F,
+		BC_GAMEPAD_BTN20 = 0x40000130,
+		BC_Count = 304,
+		BC_NumKeys = 238, // IMPORTANT: Make sure to update these if you modify the values above
+		BC_NumMouse = 32,
+		BC_NumGamepad = 34,
+	};
+
+	/**	Contains data about a button input event. */
+	struct ButtonEvent
+	{
+	public:
+		ButtonEvent()
+			:mIsUsed(false)
+		{ }
+
+		ButtonCode buttonCode; /**< Button code this event is referring to. */
+		UINT64 timestamp; /**< Timestamp in ticks when the event happened. */
+		UINT32 deviceIdx; /**< Index of the device that the event originated from. */
+
+		/**	Query is the pressed button a keyboard button. */
+		bool isKeyboard() const { return (buttonCode & 0xC0000000) == 0; }
+
+		/** Query is the pressed button a mouse button. */
+		bool isMouse() const { return (buttonCode & 0x80000000) != 0; }
+
+		/** Query is the pressed button a gamepad button. */
+		bool isGamepad() const { return (buttonCode & 0x40000000) != 0; }
+
+		/**
+		 * Check if the event has been marked as used. Internally this means nothing but caller might choose to ignore an 
+		 * used event.
+		 */
+		bool isUsed() const { return mIsUsed; }
+
+		/** Mark the event as used. Internally this means nothing but caller might choose to ignore an used event. */
+		void markAsUsed() const { mIsUsed = true; }
+	private:
+		mutable bool mIsUsed;
+	};
+
+	/**
+	 * Pointer buttons. Generally these correspond to mouse buttons, but may be used in some form for touch input as well.
+	 */
+	enum class PointerEventButton
+	{
+		Left, Middle, Right, Count
+	};
+
+	/**	Type of pointer event.*/
+	enum class PointerEventType
+	{
+		CursorMoved,
+		ButtonPressed,
+		ButtonReleased,
+		DoubleClick
+	};
+
+	/**
+	 * Event that gets sent out when user interacts with the screen in some way, usually by moving the mouse cursor or
+	 * using touch input.
+	 */
+	struct PointerEvent
+	{
+	public:
+		PointerEvent()
+			:mIsUsed(false), mouseWheelScrollAmount(0.0f), type(PointerEventType::CursorMoved),
+			shift(false), control(false), alt(false), button(PointerEventButton::Left)
+		{
+			buttonStates[0] = false;
+			buttonStates[1] = false;
+			buttonStates[2] = false;
+		}
+
+		Vector2I screenPos; /**< Screen position where the input event occurred. */
+		Vector2I delta; /**< Change in movement since last sent event. */
+		bool buttonStates[(UINT32)PointerEventButton::Count]; /**< States of the pointer buttons (e.g. mouse buttons). */
+		PointerEventButton button; /**< Button that triggered the pointer event. Might be irrelevant 
+										depending on event type. (e.g. move events don't correspond to a button. */
+		PointerEventType type; /**< Type of the pointer event. */
+
+		bool shift; /**< Is shift button on the keyboard being held down. */
+		bool control; /**< Is control button on the keyboard being held down. */
+		bool alt; /**< Is alt button on the keyboard being held down. */
+
+		float mouseWheelScrollAmount; /**< If mouse wheel is being scrolled, what is the amount. Only relevant for move events. */
+
+		/**
+		 * Check if the event has been marked as used. Internally this means nothing but caller might choose to ignore an 
+		 * used event.
+		 */
+		bool isUsed() const { return mIsUsed; }
+
+		/** Mark the event as used. Internally this means nothing but caller might choose to ignore an used event. */
+		void markAsUsed() const { mIsUsed = true; }
+
+	private:
+		mutable bool mIsUsed;
+	};
+
+	/**	Types of special input commands. */
+	enum class InputCommandType
+	{
+		CursorMoveLeft, CursorMoveRight, CursorMoveUp, CursorMoveDown, 
+		SelectLeft, SelectRight, SelectUp, SelectDown,
+		Escape, Delete, Backspace, Return, Confirm
+	};
+
+	/**
+	 * Event that gets sent out when user inputs some text. These events may be preceeded by normal button events if user 
+	 * is typing on a keyboard. 
+	 */
+	struct TextInputEvent
+	{
+	public:
+		TextInputEvent()
+			:mIsUsed(false)
+		{ }
+
+		UINT32 textChar; /**< Character the that was input. */
+
+		/**
+		 * @brief	Check if the event has been marked as used. Internally this means nothing
+		 *			but caller might choose to ignore an used event.
+		 */
+		bool isUsed() const { return mIsUsed; }
+
+		/**
+		 * @brief	Mark the event as used. Internally this means nothing
+		 *			but caller might choose to ignore an used event.
+		 */
+		void markAsUsed() const { mIsUsed = true; }
+
+	private:
+		mutable bool mIsUsed;
+	};
+
+	/**	Types of input devices. */
+	enum class InputDevice
+	{
+		Keyboard,
+		Mouse,
+		Gamepad,
+		Count // Keep at end
+	};
+
+	/**	Common input axis types. */
+	enum class InputAxis
+	{
+		MouseX, /**< Mouse axis X. */
+		MouseY, /**< Mouse axis Y. */
+		MouseZ, /**< Mouse wheel/scroll axis. */
+		LeftStickX, /**< Gamepad left stick X */
+		LeftStickY, /**<  Gamepad left stick Y */
+		RightStickX, /**< Gamepad right stick X */
+		RightStickY, /**< Gamepad right stick Y */
+		LeftTrigger, /**< Gamepad left trigger */
+		RightTrigger, /**< Gamepad right trigger */
+		Count // Keep at end
+	};
+
+	/**	Modifiers used with along with keyboard buttons. */
+	enum class ButtonModifier
+	{
+		None = 0x00,
+		Shift = 0x01,
+		Ctrl = 0x02,
+		Alt = 0x04,
+		ShiftCtrl = 0x03,
+		CtrlAlt = 0x06,
+		ShiftAlt = 0x05,
+		ShiftCtrlAlt = 0x07
+	};
+
+	/** @} */
 }
 }

+ 86 - 111
BansheeCore/Include/BsMeshImportOptions.h

@@ -1,112 +1,87 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsImportOptions.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Contains import options you may use to control how is a mesh imported
-	 *			from some external format into engine format.
-	 */
-	class BS_CORE_EXPORT MeshImportOptions : public ImportOptions
-	{
-	public:
-		MeshImportOptions();
-
-		/**
-		 * @brief	Sets whether the texture data is also stored in CPU memory.
-		 */
-		void setCPUReadable(bool readable) { mCPUReadable = readable; }
-		
-		/**
-		 * @brief	Retrieves whether the texture data is also stored in CPU memory.
-		 */
-		bool getCPUReadable() const { return mCPUReadable; }
-
-		/**
-		 * @brief	Sets a value that controls should mesh normals be imported
-		 *			if available.
-		 */
-		void setImportNormals(bool import) { mImportNormals = import; }
-
-		/**
-		 * @brief	Retrieves a value that controls should mesh normals be imported
-		 *			if available.
-		 */
-		bool getImportNormals() const { return mImportNormals; }
-
-		/**
-		 * @brief	Sets a value that controls should mesh tangents/bitangents be imported
-		 *			if available.
-		 */
-		void setImportTangents(bool import) { mImportTangents = import; }
-
-		/**
-		 * @brief	Retrieves a value that controls should mesh tangent/bitangent be imported
-		 *			if available.
-		 */
-		bool getImportTangents() const { return mImportTangents; }
-
-		/**
-		 * @brief	Sets a value that controls should mesh blend shapes be imported
-		 *			if available.
-		 */
-		void setImportBlendShapes(bool import) { mImportBlendShapes = import; }
-
-		/**
-		 * @brief	Retrieves a value that controls should mesh blend shapes be imported
-		 *			if available.
-		 */
-		bool getImportBlendShapes() const { return mImportBlendShapes; }
-
-		/**
-		 * @brief	Sets a value that controls should mesh skin data like bone weights, 
-		 *			indices and bind poses be imported if available.
-		 */
-		void setImportSkin(bool import) { mImportSkin = import; }
-
-		/**
-		 * @brief	Retrieves a value that controls should mesh skin data like bone weights, 
-		 *			indices and bind poses be imported if available.
-		 */
-		bool getImportSkin() const { return mImportSkin; }
-
-		/**
-		 * @brief	Sets a value that controls should animation clips be imported if available.
-		 */
-		void setImportAnimation(bool import) { mImportAnimation = import; }
-
-		/**
-		 * @brief	Retrieves a value that controls should animation clips be imported if available.
-		 */
-		bool getImportAnimation() const { return mImportAnimation; }
-
-		/**
-		 * @brief	Sets a value that will uniformly scale the imported mesh by the specified value.
-		 */
-		void setImportScale(float import) { mImportScale = import; }
-
-		/**
-		 * @brief	Retrieves a value that will uniformly scale the imported mesh by the specified value.
-		 */
-		float getImportScale() const { return mImportScale; }
-
-		/************************************************************************/
-		/* 								SERIALIZATION                      		*/
-		/************************************************************************/
-	public:
-		friend class MeshImportOptionsRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-
-	private:
-		bool mCPUReadable;
-		bool mImportNormals;
-		bool mImportTangents;
-		bool mImportBlendShapes;
-		bool mImportSkin;
-		bool mImportAnimation;
-		float mImportScale;
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsImportOptions.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Importer
+	 *  @{
+	 */
+
+	/**
+	 * Contains import options you may use to control how is a mesh imported from some external format into engine format.
+	 */
+	class BS_CORE_EXPORT MeshImportOptions : public ImportOptions
+	{
+	public:
+		MeshImportOptions();
+
+		/**	Sets whether the texture data is also stored in CPU memory. */
+		void setCPUReadable(bool readable) { mCPUReadable = readable; }
+		
+		/**	Retrieves whether the texture data is also stored in CPU memory. */
+		bool getCPUReadable() const { return mCPUReadable; }
+
+		/**	Sets a value that controls should mesh normals be imported if available. */
+		void setImportNormals(bool import) { mImportNormals = import; }
+
+		/**	Retrieves a value that controls should mesh normals be imported if available. */
+		bool getImportNormals() const { return mImportNormals; }
+
+		/**	Sets a value that controls should mesh tangents/bitangents be imported if available. */
+		void setImportTangents(bool import) { mImportTangents = import; }
+
+		/**	Retrieves a value that controls should mesh tangent/bitangent be imported if available. */
+		bool getImportTangents() const { return mImportTangents; }
+
+		/**	Sets a value that controls should mesh blend shapes be imported	if available. */
+		void setImportBlendShapes(bool import) { mImportBlendShapes = import; }
+
+		/**	Retrieves a value that controls should mesh blend shapes be imported if available. */
+		bool getImportBlendShapes() const { return mImportBlendShapes; }
+
+		/**	
+		 * Sets a value that controls should mesh skin data like bone weights, indices and bind poses be imported if 
+		 * available.
+		 */
+		void setImportSkin(bool import) { mImportSkin = import; }
+
+		/**
+		 * Retrieves a value that controls should mesh skin data like bone weights, indices and bind poses be imported if 
+		 * available.
+		 */
+		bool getImportSkin() const { return mImportSkin; }
+
+		/** Sets a value that controls should animation clips be imported if available. */
+		void setImportAnimation(bool import) { mImportAnimation = import; }
+
+		/**	Retrieves a value that controls should animation clips be imported if available. */
+		bool getImportAnimation() const { return mImportAnimation; }
+
+		/**	Sets a value that will uniformly scale the imported mesh by the specified value. */
+		void setImportScale(float import) { mImportScale = import; }
+
+		/**	Retrieves a value that will uniformly scale the imported mesh by the specified value. */
+		float getImportScale() const { return mImportScale; }
+
+		/************************************************************************/
+		/* 								SERIALIZATION                      		*/
+		/************************************************************************/
+	public:
+		friend class MeshImportOptionsRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
+
+	private:
+		bool mCPUReadable;
+		bool mImportNormals;
+		bool mImportTangents;
+		bool mImportBlendShapes;
+		bool mImportSkin;
+		bool mImportAnimation;
+		float mImportScale;
+	};
+
+	/** @} */
 }
 }

+ 160 - 167
BansheeCore/Include/BsOSInputHandler.h

@@ -1,168 +1,161 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsPlatform.h"
-#include "BsEvent.h"
-#include "BsVector2I.h"
-
-namespace BansheeEngine
-{
-	/**
-		* @brief	Represents a specific way of acquiring OS input. InputManager (which provides a higher level input)
-		* 			must have at least one OSInputHandler attached. Attach events handler to the provided signals to handle input.
-		* 			
-		* @note		Unlike RawInputHandler this class receives input from the operating system, and is used for receiving
-		* 			text input, cursor position and similar.
-		*/
-	class BS_CORE_EXPORT OSInputHandler
-	{
-		/**
-		 * @brief	Contains information regarding a button state change event.
-		 */
-		struct ButtonStateChange
-		{
-			Vector2I cursorPos;
-			OSPointerButtonStates btnStates;
-			OSMouseButton button;
-			bool pressed;
-		};
-
-		/**
-		 * @brief	Contains information regarding a double click event.
-		 */
-		struct DoubleClick
-		{
-			Vector2I cursorPos;
-			OSPointerButtonStates btnStates;
-		};
-
-	public:
-		OSInputHandler();
-		virtual ~OSInputHandler();
-
-		/**
-		 * @brief	Triggers when user inputs a character. The character might be a result of pressing
-		 * 			multiple keys, so character input will not necessarily correspond with button presses.
-		 * 			Provide character code of the input character.
-		 */
-		Event<void(UINT32)> onCharInput;
-
-		/**
-		 * @brief	Triggers whenever user scrolls the mouse wheel. Returns the screen
-		 * 			position of the mouse cursor and delta amount of mouse scroll (can be negative or positive).
-		 */
-		Event<void(const Vector2I&, float)> onMouseWheelScrolled;
-
-		/**
-		 * @brief	Triggers whenever user moves the mouse cursor.
-		 */
-		Event<void(const PointerEvent&)> onCursorMoved;
-
-		/**
-		 * @brief	Triggers whenever user presses one of the mouse buttons.
-		 */
-		Event<void(const PointerEvent&)> onCursorPressed;
-
-		/**
-		 * @brief	Triggers whenever user releases one of the mouse buttons.
-		 */
-		Event<void(const PointerEvent&)> onCursorReleased;
-
-		/**
-		 * @brief	Triggers when user clicks a mouse button quickly twice in a row.
-		 */
-		Event<void(const PointerEvent&)> onDoubleClick;
-
-		/**
-		 * @brief	Triggers when user inputa a special input command, like commands user
-		 * 			for manipulating text input.
-		 */
-		Event<void(InputCommandType)> onInputCommand;
-
-		/**
-		 * @brief	Called once per frame. Capture input here if needed.
-		 * 			
-		 * @note	Internal method.
-		 */
-		virtual void _update();
-
-		/**
-		 * @brief	Called whenever the active window changes.
-		 *
-		 * @param	win	Newly active window.
-		 * 				
-		 * @note	Internal method.
-		 */
-		virtual void _inputWindowChanged(const RenderWindow& win) { }
-
-	private:
-		BS_MUTEX(mOSInputMutex);
-		Vector2I mLastCursorPos;
-		Vector2I mCursorPosition;
-		Vector2I mDelta;
-		bool mLastCursorPosSet;
-		float mMouseScroll;
-		WString mInputString;
-		Queue<ButtonStateChange> mButtonStates;
-		Queue<DoubleClick> mDoubleClicks;
-		Queue<InputCommandType> mInputCommands;
-		OSPointerButtonStates mMouseMoveBtnState;
-
-		HEvent mCharInputConn;
-		HEvent mCursorMovedConn;
-		HEvent mCursorPressedConn;
-		HEvent mCursorReleasedConn;
-		HEvent mCursorDoubleClickConn;
-		HEvent mInputCommandConn;
-		HEvent mMouseWheelScrolledConn;
-
-		/**
-		 * @brief	Called from the message loop to notify user has entered a character.
-		 * 			
-		 * @see		onCharInput
-		 */
-		void charInput(UINT32 character);
-
-		/**
-		 * @brief	Called from the message loop to notify user has moved the cursor.
-		 * 			
-		 * @see		onCursorMoved
-		 */
-		void cursorMoved(const Vector2I& cursorPos, OSPointerButtonStates& btnStates);
-
-		/**
-		 * @brief	Called from the message loop to notify user has pressed a mouse button.
-		 * 			
-		 * @see		onCursorPressed
-		 */
-		void cursorPressed(const Vector2I& cursorPos, OSMouseButton button, OSPointerButtonStates& btnStates);
-
-		/**
-		 * @brief	Called from the message loop to notify user has released a mouse button.
-		 * 			
-		 * @see		onCursorReleased
-		 */
-		void cursorReleased(const Vector2I& cursorPos, OSMouseButton button, OSPointerButtonStates& btnStates);
-
-		/**
-		 * @brief	Called from the message loop to notify user has double-clicked a mouse button.
-		 * 
-		 * @see		onDoubleClick
-		 */
-		void cursorDoubleClick(const Vector2I& cursorPos, OSPointerButtonStates& btnStates);
-
-		/**
-		 * @brief	Called from the message loop to notify user has entered an input command.
-		 * 			
-		 * @see		onInputCommand
-		 */
-		void inputCommandEntered(InputCommandType commandType);
-
-		/**
-		 * @brief	Called from the message loop to notify user has scrolled the mouse wheel.
-		 * 			
-		 * @see		onMouseWheelScrolled
-		 */
-		void mouseWheelScrolled(float scrollPos);
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsPlatform.h"
+#include "BsEvent.h"
+#include "BsVector2I.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Input
+	 *  @{
+	 */
+
+	/**
+	 * Represents a specific way of acquiring OS input. Input class (which provides a higher level input) must have at 
+	 * least one OSInputHandler attached. Attach events handler to the provided signals to handle input.
+	 * 			
+	 * @note		
+	 * Unlike RawInputHandler this class receives input from the operating system, and is used for receiving text input, 
+	 * cursor position and similar.
+	 */
+	class BS_CORE_EXPORT OSInputHandler
+	{
+		/**	Contains information regarding a button state change event. */
+		struct ButtonStateChange
+		{
+			Vector2I cursorPos;
+			OSPointerButtonStates btnStates;
+			OSMouseButton button;
+			bool pressed;
+		};
+
+		/**	Contains information regarding a double click event. */
+		struct DoubleClick
+		{
+			Vector2I cursorPos;
+			OSPointerButtonStates btnStates;
+		};
+
+	public:
+		OSInputHandler();
+		virtual ~OSInputHandler();
+
+		/**
+		 * Called once per frame. Capture input here if needed.
+		 * 			
+		 * @note	Internal method.
+		 */
+		virtual void _update();
+
+		/**
+		 * Called whenever the active window changes.
+		 *
+		 * @param[in]	win	Newly active window.
+		 * 				
+		 * @note	Internal method.
+		 */
+		virtual void _inputWindowChanged(const RenderWindow& win) { }
+
+		/**
+		 * Triggers when user inputs a character. The character might be a result of pressing multiple keys, so character 
+		 * input will not necessarily correspond with button presses. Provide character code of the input character.
+		 */
+		Event<void(UINT32)> onCharInput;
+
+		/**
+		 * Triggers whenever user scrolls the mouse wheel. Returns the screen position of the mouse cursor and delta amount 
+		 * of mouse scroll (can be negative or positive).
+		 */
+		Event<void(const Vector2I&, float)> onMouseWheelScrolled;
+
+		/** Triggers whenever user moves the mouse cursor. */
+		Event<void(const PointerEvent&)> onCursorMoved;
+
+		/**	Triggers whenever user presses one of the mouse buttons. */
+		Event<void(const PointerEvent&)> onCursorPressed;
+
+		/**	Triggers whenever user releases one of the mouse buttons. */
+		Event<void(const PointerEvent&)> onCursorReleased;
+
+		/**	Triggers when user clicks a mouse button quickly twice in a row. */
+		Event<void(const PointerEvent&)> onDoubleClick;
+
+		/**	Triggers when user inputa a special input command, like commands user for manipulating text input. */
+		Event<void(InputCommandType)> onInputCommand;
+
+	private:
+		BS_MUTEX(mOSInputMutex);
+		Vector2I mLastCursorPos;
+		Vector2I mCursorPosition;
+		Vector2I mDelta;
+		bool mLastCursorPosSet;
+		float mMouseScroll;
+		WString mInputString;
+		Queue<ButtonStateChange> mButtonStates;
+		Queue<DoubleClick> mDoubleClicks;
+		Queue<InputCommandType> mInputCommands;
+		OSPointerButtonStates mMouseMoveBtnState;
+
+		HEvent mCharInputConn;
+		HEvent mCursorMovedConn;
+		HEvent mCursorPressedConn;
+		HEvent mCursorReleasedConn;
+		HEvent mCursorDoubleClickConn;
+		HEvent mInputCommandConn;
+		HEvent mMouseWheelScrolledConn;
+
+		/**
+		 * Called from the message loop to notify user has entered a character.
+		 * 			
+		 * @see		onCharInput
+		 */
+		void charInput(UINT32 character);
+
+		/**
+		 * Called from the message loop to notify user has moved the cursor.
+		 * 			
+		 * @see		onCursorMoved
+		 */
+		void cursorMoved(const Vector2I& cursorPos, OSPointerButtonStates& btnStates);
+
+		/**
+		 * Called from the message loop to notify user has pressed a mouse button.
+		 * 			
+		 * @see		onCursorPressed
+		 */
+		void cursorPressed(const Vector2I& cursorPos, OSMouseButton button, OSPointerButtonStates& btnStates);
+
+		/**
+		 * Called from the message loop to notify user has released a mouse button.
+		 * 			
+		 * @see		onCursorReleased
+		 */
+		void cursorReleased(const Vector2I& cursorPos, OSMouseButton button, OSPointerButtonStates& btnStates);
+
+		/**
+		 * Called from the message loop to notify user has double-clicked a mouse button.
+		 * 
+		 * @see		onDoubleClick
+		 */
+		void cursorDoubleClick(const Vector2I& cursorPos, OSPointerButtonStates& btnStates);
+
+		/**
+		 * Called from the message loop to notify user has entered an input command.
+		 * 			
+		 * @see		onInputCommand
+		 */
+		void inputCommandEntered(InputCommandType commandType);
+
+		/**
+		 * Called from the message loop to notify user has scrolled the mouse wheel.
+		 * 			
+		 * @see		onMouseWheelScrolled
+		 */
+		void mouseWheelScrolled(float scrollPos);
+	};
+
+	/** @} */
+	/** @endcond */
 }
 }

+ 84 - 85
BansheeCore/Include/BsRawInputHandler.h

@@ -1,86 +1,85 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsInputFwd.h"
-#include "BsEvent.h"
-#include "BsVector2I.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Contains relative and absolute position
-	 * 			of an input axis. Relative state represents
-	 * 			the difference between current and last state.
-	 */
-	struct RawAxisState
-	{
-		RawAxisState()
-		 :rel(0.0f), abs(0.0f)
-		{ }
-
-		float rel;
-		float abs;
-	};
-
-	/**
-	 * @brief	Represents a specific way of acquiring low-level input. InputManager (which provides a higher level input)
-	 * 			must have at least one RawInputHandler attached. Raw input handlers receive input as sent by the hardware
-	 * 			without OS modifications.
-	 * 			
-	 *			Attach events handler to the provided signals to handle input.
-	 */
-	class BS_CORE_EXPORT RawInputHandler
-	{
-	public:
-		RawInputHandler()
-			:mMouseSmoothingEnabled(false) 
-		{}
-
-		virtual ~RawInputHandler() {}
-
-		/**
-		 * @brief	Triggered when user presses a button. Parameters
-		 * 			include device index, button code of the pressed button, 
-		 *			and a timestamp of the button press event.
-		 */
-		Event<void(UINT32, ButtonCode, UINT64)> onButtonDown;
-
-		/**
-		 * @brief	Triggered when user releases a button. Parameters
-		 * 			include device index, button code of the released button, 
-		 *			and a timestamp of the button release event.
-		 */
-		Event<void(UINT32, ButtonCode, UINT64)> onButtonUp;
-
-		/**
-		 * @brief	Triggered whenever the specified axis state changes.
-		 *			Parameters include device index, axis state data, and axis type.
-		 */
-		Event<void(UINT32, const RawAxisState&, UINT32)> onAxisMoved;
-
-		/**
-		 * @brief	Called once per frame. Capture input here if needed.
-		 * 			
-		 * @note	Internal method.
-		 */
-		virtual void _update() {}
-
-		/**
-		 * @brief	Called whenever the active window changes.
-		 *
-		 * @param	win	Newly active window.
-		 * 				
-		 * @note	Internal method.
-		 */
-		virtual void _inputWindowChanged(const RenderWindow& win) {}
-
-		/**
-		 * @brief	Enables or disables mouse smoothing. Smoothing makes the changes to
-		 *			mouse axes more gradual.
-		 */
-		void setMouseSmoothing(bool enabled) { mMouseSmoothingEnabled = enabled; }
-
-	protected:
-		bool mMouseSmoothingEnabled;
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsInputFwd.h"
+#include "BsEvent.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Input
+	 *  @{
+	 */
+
+	/**
+	 * Contains relative and absolute position of an input axis. Relative state represents the difference between current 
+	 * and last state.
+	 */
+	struct RawAxisState
+	{
+		RawAxisState()
+		 :rel(0.0f), abs(0.0f)
+		{ }
+
+		float rel;
+		float abs;
+	};
+
+	/**
+	 * Represents a specific way of acquiring low-level input. Input class (which provides a higher level input) must have 
+	 * at least one RawInputHandler attached. Raw input handlers receive input as sent by the hardware without OS 
+	 * modifications.
+	 */
+	class BS_CORE_EXPORT RawInputHandler
+	{
+	public:
+		RawInputHandler()
+			:mMouseSmoothingEnabled(false) 
+		{}
+
+		virtual ~RawInputHandler() {}
+
+		/**
+		 * Triggered when user presses a button. Parameters include device index, button code of the pressed button, 
+		 * and a timestamp of the button press event.
+		 */
+		Event<void(UINT32, ButtonCode, UINT64)> onButtonDown;
+
+		/**
+		 * Triggered when user releases a button. Parameters include device index, button code of the released button, 
+		 * and a timestamp of the button release event.
+		 */
+		Event<void(UINT32, ButtonCode, UINT64)> onButtonUp;
+
+		/**
+		 * Triggered whenever the specified axis state changes. Parameters include device index, axis state data, and axis 
+		 * type.
+		 */
+		Event<void(UINT32, const RawAxisState&, UINT32)> onAxisMoved;
+
+		/**
+		 * Called once per frame. Capture input here if needed.
+		 * 			
+		 * @note	Internal method.
+		 */
+		virtual void _update() {}
+
+		/**
+		 * Called whenever the active window changes.
+		 *
+		 * @param[in]	win	Newly active window.
+		 * 				
+		 * @note	Internal method.
+		 */
+		virtual void _inputWindowChanged(const RenderWindow& win) {}
+
+		/** Enables or disables mouse smoothing. Smoothing makes the changes to mouse axes more gradual. */
+		void setMouseSmoothing(bool enabled) { mMouseSmoothingEnabled = enabled; }
+
+	protected:
+		bool mMouseSmoothingEnabled;
+	};
+
+	/** @} */
+	/** @endcond */
 }
 }

+ 32 - 26
BansheeCore/Include/BsShaderIncludeImporter.h

@@ -1,27 +1,33 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsSpecificImporter.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Importer using for importing GPU program (i.e. shader) include files.
-	 * 			Include files are just text files ending with ".bsi" extension.
-	 */
-	class BS_CORE_EXPORT ShaderIncludeImporter : public SpecificImporter
-	{
-	public:
-		ShaderIncludeImporter();
-		virtual ~ShaderIncludeImporter();
-
-		/** @copydoc SpecificImporter::isExtensionSupported */
-		virtual bool isExtensionSupported(const WString& ext) const override;
-
-		/** @copydoc SpecificImporter::isMagicNumberSupported */
-		virtual bool isMagicNumberSupported(const UINT8* magicNumPtr, UINT32 numBytes) const override;
-
-		/** @copydoc SpecificImporter::import */
-		virtual ResourcePtr import(const Path& filePath, ConstImportOptionsPtr importOptions) override;
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsSpecificImporter.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Importer
+	 *  @{
+	 */
+
+	/**
+	 * Importer using for importing GPU program (i.e. shader) include files. Include files are just text files ending with 
+	 * ".bslinc" extension.
+	 */
+	class BS_CORE_EXPORT ShaderIncludeImporter : public SpecificImporter
+	{
+	public:
+		ShaderIncludeImporter();
+		virtual ~ShaderIncludeImporter();
+
+		/** @copydoc SpecificImporter::isExtensionSupported */
+		virtual bool isExtensionSupported(const WString& ext) const override;
+
+		/** @copydoc SpecificImporter::isMagicNumberSupported */
+		virtual bool isMagicNumberSupported(const UINT8* magicNumPtr, UINT32 numBytes) const override;
+
+		/** @copydoc SpecificImporter::import */
+		virtual ResourcePtr import(const Path& filePath, ConstImportOptionsPtr importOptions) override;
+	};
+
+	/** @} */
 }
 }

+ 62 - 58
BansheeCore/Include/BsSpecificImporter.h

@@ -1,59 +1,63 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Abstract class that is to be specialized in converting
-	 * 			a certain asset type into an engine usable resource. 
-	 * 			(e.g. a .png file into an engine usable texture).
-	 * 			
-	 *			On initialization this class must register itself with the Importer module,
-	 *			which delegates asset import calls to a specific importer.
-	 */
-	class BS_CORE_EXPORT SpecificImporter
-	{
-	public:
-		SpecificImporter() {}
-		virtual ~SpecificImporter() {}
-
-		/**
-		 * @brief	Check is the provided extension supported by this importer.
-		 *
-		 * @note	Provided extension should be without the leading dot.
-		 */
-		virtual bool isExtensionSupported(const WString& ext) const = 0;
-
-		/**
-		 * @brief	Check if the provided magic number is supported by this importer.
-		 */
-		virtual bool isMagicNumberSupported(const UINT8* magicNumPtr, UINT32 numBytes) const = 0; 
-
-		/**
-		 * @brief	Imports the given file.
-		 *
-		 * @param	filePath	Pathname of the file, with file extension.
-		 *
-		 * @return	null if it fails, otherwise the loaded object.
-		 */
-		virtual ResourcePtr import(const Path& filePath, ConstImportOptionsPtr importOptions) = 0;
-
-		/**
-		 * @brief	Creates import options specific for this importer. Import
-		 * 			options are provided when calling import() in order to customize the
-		 * 			import, and provide additional information.
-		 */
-		virtual ImportOptionsPtr createImportOptions() const;
-
-		/**
-		 * @brief	Gets the default import options.
-		 *
-		 * @return	The default import options.
-		 */
-		ConstImportOptionsPtr getDefaultImportOptions() const;
-
-	private:
-		mutable ConstImportOptionsPtr mDefaultImportOptions;
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+
+namespace BansheeEngine
+{
+	/** @cond INTERNAL */
+	/** @addtogroup Importer
+	 *  @{
+	 */
+
+	/**
+	 * Abstract class that is to be specialized in convertinga certain asset type into an engine usable resource. 
+	 * (e.g. a .png file into an engine usable texture).
+	 * 			
+	 * On initialization this class must register itself with the Importer module, which delegates asset import calls to a 
+	 * specific importer.
+	 */
+	class BS_CORE_EXPORT SpecificImporter
+	{
+	public:
+		SpecificImporter() {}
+		virtual ~SpecificImporter() {}
+
+		/**
+		 * Check is the provided extension supported by this importer.
+		 *
+		 * @note	Provided extension should be without the leading dot.
+		 */
+		virtual bool isExtensionSupported(const WString& ext) const = 0;
+
+		/** Check if the provided magic number is supported by this importer. */
+		virtual bool isMagicNumberSupported(const UINT8* magicNumPtr, UINT32 numBytes) const = 0; 
+
+		/**
+		 * Imports the given file.
+		 *
+		 * @param[in]	filePath	Pathname of the file, with file extension.
+		 *
+		 * @return					null if it fails, otherwise the loaded object.
+		 */
+		virtual ResourcePtr import(const Path& filePath, ConstImportOptionsPtr importOptions) = 0;
+
+		/**
+		 * Creates import options specific for this importer. Import options are provided when calling import() in order 
+		 * to customize the import, and provide additional information.
+		 */
+		virtual ImportOptionsPtr createImportOptions() const;
+
+		/**
+		 * Gets the default import options.
+		 *
+		 * @return	The default import options.
+		 */
+		ConstImportOptionsPtr getDefaultImportOptions() const;
+
+	private:
+		mutable ConstImportOptionsPtr mDefaultImportOptions;
+	};
+
+	/** @} */
+	/** @endcond */
 }
 }

+ 77 - 86
BansheeCore/Include/BsTextureImportOptions.h

@@ -1,87 +1,78 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsImportOptions.h"
-#include "BsGpuProgram.h"
-#include "BsPixelUtil.h"
-
-namespace BansheeEngine
-{
-	/**
-	* @brief	Contains import options you may use to control how is a texture imported.
-	*/
-	class BS_CORE_EXPORT TextureImportOptions : public ImportOptions
-	{
-	public:
-		TextureImportOptions();
-
-		/**
-		 * @brief	Sets the pixel format to import as.
-		 */
-		void setFormat(PixelFormat format) { mFormat = format; }
-
-		/**
-		 * @brief	Enables or disables mipmap generation for the texture.	
-		 */
-		void setGenerateMipmaps(bool generate) { mGenerateMips = generate; }
-
-		/**
-		 * @brief	Sets the maximum mip level to generate when generating mipmaps. If 0
-		 *			then maximum amount of mip levels will be generated.
-		 */
-		void setMaxMip(UINT32 maxMip) { mMaxMip = maxMip; }
-
-		/**
-		 * @brief	Sets whether the texture data is also stored in main memory, available for fast CPU access.
-		 */
-		void setCPUReadable(bool readable) { mCPUReadable = readable; }
-
-		/**
-		 * @brief	Sets whether the texture data should be treated as if its in sRGB (gamma) space.
-		 *			Such texture will be converted by hardware to linear space before use on the GPU.
-		 */
-		void setSRGB(bool sRGB) { mSRGB = sRGB; }
-
-		/**
-		 * @brief	Gets the pixel format to import as.
-		 */
-		PixelFormat getFormat() const { return mFormat; }
-
-		/**
-		 * @brief	Checks will be imported texture have automatically generated mipmaps.
-		 */
-		bool getGenerateMipmaps() const { return mGenerateMips; }
-
-		/**
-		 * @brief	Gets the maximum mip level to generate when generating mipmaps. If 0
-		 *			then maximum amount of mip levels will be generated.
-		 */
-		UINT32 getMaxMip() const { return mMaxMip; }
-
-		/**
-		 * @brief	Retrieves whether the texture data is also stored in main memory, available for fast CPU access.
-		 */
-		bool getCPUReadable() const { return mCPUReadable; }
-
-		/**
-		 * @brief	Retrieves whether the texture data should be treated as if its in sRGB (gamma) space.
-		 *			Such texture will be converted by hardware to linear space before use on the GPU.
-		 */
-		bool getSRGB() const { return mSRGB; }
-
-		/************************************************************************/
-		/* 								SERIALIZATION                      		*/
-		/************************************************************************/
-	public:
-		friend class TextureImportOptionsRTTI;
-		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;
-
-	private:
-		PixelFormat mFormat;
-		bool mGenerateMips;
-		UINT32 mMaxMip;
-		bool mCPUReadable;
-		bool mSRGB;
-	};
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsImportOptions.h"
+#include "BsPixelUtil.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Importer
+	 *  @{
+	 */
+
+	/** Contains import options you may use to control how is a texture imported. */
+	class BS_CORE_EXPORT TextureImportOptions : public ImportOptions
+	{
+	public:
+		TextureImportOptions();
+
+		/** Sets the pixel format to import as. */
+		void setFormat(PixelFormat format) { mFormat = format; }
+
+		/** Enables or disables mipmap generation for the texture. */
+		void setGenerateMipmaps(bool generate) { mGenerateMips = generate; }
+
+		/**
+		 * Sets the maximum mip level to generate when generating mipmaps. If 0 then maximum amount of mip levels will be 
+		 * generated.
+		 */
+		void setMaxMip(UINT32 maxMip) { mMaxMip = maxMip; }
+
+		/** Sets whether the texture data is also stored in main memory, available for fast CPU access. */
+		void setCPUReadable(bool readable) { mCPUReadable = readable; }
+
+		/** 
+		 * Sets whether the texture data should be treated as if its in sRGB (gamma) space. Such texture will be converted 
+		 * by hardware to linear space before use on the GPU.
+		 */
+		void setSRGB(bool sRGB) { mSRGB = sRGB; }
+
+		/** Gets the pixel format to import as. */
+		PixelFormat getFormat() const { return mFormat; }
+
+		/** Checks will be imported texture have automatically generated mipmaps. */
+		bool getGenerateMipmaps() const { return mGenerateMips; }
+
+		/**
+		 * Gets the maximum mip level to generate when generating mipmaps. If 0 then maximum amount of mip levels will be 
+		 * generated.
+		 */
+		UINT32 getMaxMip() const { return mMaxMip; }
+
+		/** Retrieves whether the texture data is also stored in main memory, available for fast CPU access. */
+		bool getCPUReadable() const { return mCPUReadable; }
+
+		/**
+		 * Retrieves whether the texture data should be treated as if its in sRGB (gamma) space. Such texture will be 
+		 * converted by hardware to linear space before use on the GPU.
+		 */
+		bool getSRGB() const { return mSRGB; }
+
+		/************************************************************************/
+		/* 								SERIALIZATION                      		*/
+		/************************************************************************/
+	public:
+		friend class TextureImportOptionsRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const override;
+
+	private:
+		PixelFormat mFormat;
+		bool mGenerateMips;
+		UINT32 mMaxMip;
+		bool mCPUReadable;
+		bool mSRGB;
+	};
+
+	/** @} */
 }
 }

+ 153 - 155
BansheeCore/Source/BsCoreObject.cpp

@@ -1,156 +1,154 @@
-#include "BsCoreObject.h"
-#include "BsCoreObjectCore.h"
-#include "BsCoreThread.h"
-#include "BsCoreObjectManager.h"
-#include "BsCoreThreadAccessor.h"
-#include "BsFrameAlloc.h"
-#include "BsDebug.h"
-
-using namespace std::placeholders;
-
-namespace BansheeEngine
-{
-	CoreObject::CoreObject(bool initializeOnRenderThread)
-		: mFlags(0), mInternalID(0), mCoreDirtyFlags(0xFFFFFFFF)
-	{
-		mInternalID = CoreObjectManager::instance().registerObject(this);
-		mFlags = initializeOnRenderThread ? mFlags | CGO_INIT_ON_CORE_THREAD : mFlags;
-	}
-
-	CoreObject::~CoreObject() 
-	{
-		if(!isDestroyed())
-		{
-			// Object must be released with destroy() otherwise engine can still try to use it, even if it was destructed
-			// (e.g. if an object has one of its methods queued in a command queue, and is destructed, you will be accessing invalid memory)
-			BS_EXCEPT(InternalErrorException, "Destructor called but object is not destroyed. This will result in nasty issues.");
-		}
-
-#if BS_DEBUG_MODE
-		if(!mThis.expired())
-		{
-			BS_EXCEPT(InternalErrorException, "Shared pointer to this object still has active references but " \
-				"the object is being deleted? You shouldn't delete CoreObjects manually.");
-		}
-#endif
-	}
-
-	void CoreObject::destroy()
-	{
-		CoreObjectManager::instance().unregisterObject(this);
-		setIsDestroyed(true);
-
-		if(requiresInitOnCoreThread())
-		{
-			assert(BS_THREAD_CURRENT_ID != CoreThread::instance().getCoreThreadId() && "Cannot destroy sim thead object from core thread.");
-
-			// This will only destroy the CoreObjectCore if this was the last reference
-			queueDestroyGpuCommand(mCoreSpecific);
-		}
-
-		mCoreSpecific = nullptr;
-	}
-
-	void CoreObject::initialize()
-	{
-		mCoreSpecific = createCore();
-
-		if (mCoreSpecific != nullptr)
-		{
-			if (requiresInitOnCoreThread())
-			{
-				mCoreSpecific->setScheduledToBeInitialized(true);
-
-				assert(BS_THREAD_CURRENT_ID != CoreThread::instance().getCoreThreadId() && "Cannot initialize sim thread object from core thread.");
-
-				queueInitializeGpuCommand(mCoreSpecific);
-			}
-			else
-			{
-				mCoreSpecific->initialize();
-
-				// Even though this object might not require initialization on the core thread, it will be used on it, therefore
-				// do a memory barrier to ensure any stores are finished before continuing (When it requires init on core thread
-				// we use the core accessor which uses a mutex, and therefore executes all stores as well, so we dont need to 
-				// do this explicitly)
-				std::atomic_thread_fence(std::memory_order_release);
-			}
-		}
-
-		markDependenciesDirty();
-	}
-
-	void CoreObject::blockUntilCoreInitialized()
-	{
-		if (mCoreSpecific != nullptr)
-			mCoreSpecific->synchronize();
-	}
-
-	void CoreObject::syncToCore(CoreAccessor& accessor)
-	{
-		CoreObjectManager::instance().syncToCore(this, accessor);
-	}
-
-	void CoreObject::markCoreDirty(UINT32 flags)
-	{
-		bool wasDirty = isCoreDirty();
-
-		mCoreDirtyFlags |= flags;
-
-		if (!wasDirty && isCoreDirty())
-			CoreObjectManager::instance().notifyCoreDirty(this);
-	}
-
-	void CoreObject::markDependenciesDirty()
-	{
-		CoreObjectManager::instance().notifyDependenciesDirty(this);
-	}
-
-	void CoreObject::_setThisPtr(std::shared_ptr<CoreObject> ptrThis)
-	{
-		mThis = ptrThis;
-	}
-
-	void CoreObject::queueGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void()> func)
-	{
-		// We call another internal method and go through an additional layer of abstraction in order to keep an active
-		// reference to the obj (saved in the bound function).
-		// We could have called the function directly using "this" pointer but then we couldn't have used a shared_ptr for the object,
-		// in which case there is a possibility that the object would be released and deleted while still being in the command queue.
-		gCoreAccessor().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
-	}
-
-	AsyncOp CoreObject::queueReturnGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void(AsyncOp&)> func)
-	{
-		// See queueGpuCommand
-		return gCoreAccessor().queueReturnCommand(std::bind(&CoreObject::executeReturnGpuCommand, obj, func, _1));
-	}
-
-	void CoreObject::queueInitializeGpuCommand(const SPtr<CoreObjectCore>& obj)
-	{
-		std::function<void()> func = std::bind(&CoreObjectCore::initialize, obj.get());
-
-		CoreThread::instance().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
-	}
-
-	void CoreObject::queueDestroyGpuCommand(const SPtr<CoreObjectCore>& obj)
-	{
-		std::function<void()> func = [&](){}; // Do nothing function. We just need the shared pointer to stay alive until it reaches the core thread
-
-		gCoreAccessor().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
-	}
-
-	void CoreObject::executeGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void()> func)
-	{
-		volatile std::shared_ptr<CoreObjectCore> objParam = obj; // Makes sure obj isn't optimized out?
-
-		func();
-	}
-
-	void CoreObject::executeReturnGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void(AsyncOp&)> func, AsyncOp& op)
-	{
-		volatile std::shared_ptr<CoreObjectCore> objParam = obj; // Makes sure obj isn't optimized out?
-
-		func(op);
-	}
+#include "BsCoreObject.h"
+#include "BsCoreObjectCore.h"
+#include "BsCoreThread.h"
+#include "BsCoreObjectManager.h"
+#include "BsCoreThreadAccessor.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	CoreObject::CoreObject(bool initializeOnCoreThread)
+		: mFlags(0), mInternalID(0), mCoreDirtyFlags(0xFFFFFFFF)
+	{
+		mInternalID = CoreObjectManager::instance().registerObject(this);
+		mFlags = initializeOnCoreThread ? mFlags | CGO_INIT_ON_CORE_THREAD : mFlags;
+	}
+
+	CoreObject::~CoreObject() 
+	{
+		if(!isDestroyed())
+		{
+			// Object must be released with destroy() otherwise engine can still try to use it, even if it was destructed
+			// (e.g. if an object has one of its methods queued in a command queue, and is destructed, you will be accessing invalid memory)
+			BS_EXCEPT(InternalErrorException, "Destructor called but object is not destroyed. This will result in nasty issues.");
+		}
+
+#if BS_DEBUG_MODE
+		if(!mThis.expired())
+		{
+			BS_EXCEPT(InternalErrorException, "Shared pointer to this object still has active references but " \
+				"the object is being deleted? You shouldn't delete CoreObjects manually.");
+		}
+#endif
+	}
+
+	void CoreObject::destroy()
+	{
+		CoreObjectManager::instance().unregisterObject(this);
+		setIsDestroyed(true);
+
+		if(requiresInitOnCoreThread())
+		{
+			assert(BS_THREAD_CURRENT_ID != CoreThread::instance().getCoreThreadId() && "Cannot destroy sim thead object from core thread.");
+
+			// This will only destroy the CoreObjectCore if this was the last reference
+			queueDestroyGpuCommand(mCoreSpecific);
+		}
+
+		mCoreSpecific = nullptr;
+	}
+
+	void CoreObject::initialize()
+	{
+		mCoreSpecific = createCore();
+
+		if (mCoreSpecific != nullptr)
+		{
+			if (requiresInitOnCoreThread())
+			{
+				mCoreSpecific->setScheduledToBeInitialized(true);
+
+				assert(BS_THREAD_CURRENT_ID != CoreThread::instance().getCoreThreadId() && "Cannot initialize sim thread object from core thread.");
+
+				queueInitializeGpuCommand(mCoreSpecific);
+			}
+			else
+			{
+				mCoreSpecific->initialize();
+
+				// Even though this object might not require initialization on the core thread, it will be used on it, therefore
+				// do a memory barrier to ensure any stores are finished before continuing (When it requires init on core thread
+				// we use the core accessor which uses a mutex, and therefore executes all stores as well, so we dont need to 
+				// do this explicitly)
+				std::atomic_thread_fence(std::memory_order_release);
+			}
+		}
+
+		markDependenciesDirty();
+	}
+
+	void CoreObject::blockUntilCoreInitialized()
+	{
+		if (mCoreSpecific != nullptr)
+			mCoreSpecific->synchronize();
+	}
+
+	void CoreObject::syncToCore(CoreAccessor& accessor)
+	{
+		CoreObjectManager::instance().syncToCore(this, accessor);
+	}
+
+	void CoreObject::markCoreDirty(UINT32 flags)
+	{
+		bool wasDirty = isCoreDirty();
+
+		mCoreDirtyFlags |= flags;
+
+		if (!wasDirty && isCoreDirty())
+			CoreObjectManager::instance().notifyCoreDirty(this);
+	}
+
+	void CoreObject::markDependenciesDirty()
+	{
+		CoreObjectManager::instance().notifyDependenciesDirty(this);
+	}
+
+	void CoreObject::_setThisPtr(std::shared_ptr<CoreObject> ptrThis)
+	{
+		mThis = ptrThis;
+	}
+
+	void CoreObject::queueGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void()> func)
+	{
+		// We call another internal method and go through an additional layer of abstraction in order to keep an active
+		// reference to the obj (saved in the bound function).
+		// We could have called the function directly using "this" pointer but then we couldn't have used a shared_ptr for the object,
+		// in which case there is a possibility that the object would be released and deleted while still being in the command queue.
+		gCoreAccessor().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
+	}
+
+	AsyncOp CoreObject::queueReturnGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void(AsyncOp&)> func)
+	{
+		// See queueGpuCommand
+		return gCoreAccessor().queueReturnCommand(std::bind(&CoreObject::executeReturnGpuCommand, obj, func, _1));
+	}
+
+	void CoreObject::queueInitializeGpuCommand(const SPtr<CoreObjectCore>& obj)
+	{
+		std::function<void()> func = std::bind(&CoreObjectCore::initialize, obj.get());
+
+		CoreThread::instance().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
+	}
+
+	void CoreObject::queueDestroyGpuCommand(const SPtr<CoreObjectCore>& obj)
+	{
+		std::function<void()> func = [&](){}; // Do nothing function. We just need the shared pointer to stay alive until it reaches the core thread
+
+		gCoreAccessor().queueCommand(std::bind(&CoreObject::executeGpuCommand, obj, func));
+	}
+
+	void CoreObject::executeGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void()> func)
+	{
+		volatile std::shared_ptr<CoreObjectCore> objParam = obj; // Makes sure obj isn't optimized out?
+
+		func();
+	}
+
+	void CoreObject::executeReturnGpuCommand(const SPtr<CoreObjectCore>& obj, std::function<void(AsyncOp&)> func, AsyncOp& op)
+	{
+		volatile std::shared_ptr<CoreObjectCore> objParam = obj; // Makes sure obj isn't optimized out?
+
+		func(op);
+	}
 }
 }

+ 593 - 596
BansheeCore/Source/BsMesh.cpp

@@ -1,597 +1,594 @@
-#include "BsMesh.h"
-#include "BsMeshRTTI.h"
-#include "BsMeshData.h"
-#include "BsVector2.h"
-#include "BsVector3.h"
-#include "BsDebug.h"
-#include "BsHardwareBufferManager.h"
-#include "BsMeshManager.h"
-#include "BsCoreThread.h"
-#include "BsAsyncOp.h"
-#include "BsAABox.h"
-#include "BsVertexDataDesc.h"
-#include "BsResources.h"
-#include "BsFrameAlloc.h"
-
-namespace BansheeEngine
-{
-	MeshCore::MeshCore(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType, MeshDataPtr initialMeshData)
-		:MeshCoreBase(numVertices, numIndices, subMeshes), mVertexData(nullptr), mIndexBuffer(nullptr), 
-		mVertexDesc(vertexDesc), mUsage(usage), mIndexType(indexType), mTempInitialMeshData(initialMeshData)
-	{ }
-
-	MeshCore::~MeshCore()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		mVertexData = nullptr;
-		mIndexBuffer = nullptr;
-		mVertexDesc = nullptr;
-		mTempInitialMeshData = nullptr;
-	}
-
-	void MeshCore::initialize()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		bool isDynamic = (mUsage & MU_DYNAMIC) != 0;
-
-		mIndexBuffer = HardwareBufferCoreManager::instance().createIndexBuffer(mIndexType,
-			mProperties.mNumIndices, isDynamic ? GBU_DYNAMIC : GBU_STATIC);
-
-		mVertexData = std::shared_ptr<VertexData>(bs_new<VertexData>());
-
-		mVertexData->vertexCount = mProperties.mNumVertices;
-
-		List<VertexElement> elements = mVertexDesc->createElements();
-		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(elements);
-
-		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
-		{
-			if (!mVertexDesc->hasStream(i))
-				continue;
-
-			SPtr<VertexBufferCore> vertexBuffer = HardwareBufferCoreManager::instance().createVertexBuffer(
-				mVertexData->vertexDeclaration->getProperties().getVertexSize(i),
-				mVertexData->vertexCount,
-				isDynamic ? GBU_DYNAMIC : GBU_STATIC);
-
-			mVertexData->setBuffer(i, vertexBuffer);
-		}
-
-		// TODO Low priority - DX11 (and maybe OpenGL)? allow an optimization that allows you to set
-		// buffer data upon buffer construction, instead of setting it in a second step like I do here
-		if (mTempInitialMeshData != nullptr)
-		{
-			writeSubresource(0, *mTempInitialMeshData, isDynamic);
-			mTempInitialMeshData = nullptr;
-		}
-
-		MeshCoreBase::initialize();
-	}
-
-	std::shared_ptr<VertexData> MeshCore::getVertexData() const
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		return mVertexData;
-	}
-
-	SPtr<IndexBufferCore> MeshCore::getIndexBuffer() const
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		return mIndexBuffer;
-	}
-
-	SPtr<VertexDataDesc> MeshCore::getVertexDesc() const
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		return mVertexDesc;
-	}
-
-	void MeshCore::writeSubresource(UINT32 subresourceIdx, const MeshData& meshData, bool discardEntireBuffer, bool performUpdateBounds)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		if (discardEntireBuffer)
-		{
-			if ((mUsage & MU_STATIC) != 0)
-			{
-				LOGWRN("Buffer discard is enabled but buffer was not created as dynamic. Disabling discard.");
-				discardEntireBuffer = false;
-			}
-		}
-		else
-		{
-			if ((mUsage & MU_DYNAMIC) != 0)
-			{
-				LOGWRN("Buffer discard is not enabled but buffer was created as dynamic. Enabling discard.");
-				discardEntireBuffer = true;
-			}
-		}
-
-		// Indices
-		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
-
-		UINT32 indicesSize = meshData.getIndexBufferSize();
-		UINT8* srcIdxData = meshData.getIndexData();
-
-		if (meshData.getIndexElementSize() != ibProps.getIndexSize())
-		{
-			BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
-				toString(ibProps.getIndexSize()) + ". Got: " + toString(meshData.getIndexElementSize()));
-		}
-
-		if (indicesSize > mIndexBuffer->getSizeInBytes())
-			BS_EXCEPT(InvalidParametersException, "Index buffer values are being written out of valid range.");
-
-		mIndexBuffer->writeData(0, indicesSize, srcIdxData, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
-
-		// Vertices
-		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
-		{
-			if (!mVertexDesc->hasStream(i))
-				continue;
-
-			if (!meshData.getVertexDesc()->hasStream(i))
-				continue;
-
-			// Ensure both have the same sized vertices
-			UINT32 myVertSize = mVertexDesc->getVertexStride(i);
-			UINT32 otherVertSize = meshData.getVertexDesc()->getVertexStride(i);
-			if (myVertSize != otherVertSize)
-			{
-				BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(i) + " doesn't match meshes vertex size. Needed: " +
-					toString(myVertSize) + ". Got: " + toString(otherVertSize));
-			}
-
-			SPtr<VertexBufferCore> vertexBuffer = mVertexData->getBuffer(i);
-			const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
-
-			UINT32 bufferSize = meshData.getStreamSize(i);
-			UINT8* srcVertBufferData = meshData.getStreamData(i);
-
-			if (bufferSize > vertexBuffer->getSizeInBytes())
-				BS_EXCEPT(InvalidParametersException, "Vertex buffer values for stream \"" + toString(i) + "\" are being written out of valid range.");
-
-			if (RenderAPICore::instance().getVertexColorFlipRequired())
-			{
-				UINT8* bufferCopy = (UINT8*)bs_alloc(bufferSize);
-				memcpy(bufferCopy, srcVertBufferData, bufferSize); // TODO Low priority - Attempt to avoid this copy
-
-				UINT32 vertexStride = meshData.getVertexDesc()->getVertexStride(i);
-				for (INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
-				{
-					if (!meshData.getVertexDesc()->hasElement(VES_COLOR, semanticIdx, i))
-						continue;
-
-					UINT8* colorData = bufferCopy + mVertexDesc->getElementOffsetFromStream(VES_COLOR, semanticIdx, i);
-					for (UINT32 j = 0; j < mVertexData->vertexCount; j++)
-					{
-						UINT32* curColor = (UINT32*)colorData;
-
-						(*curColor) = ((*curColor) & 0xFF00FF00) | ((*curColor >> 16) & 0x000000FF) | ((*curColor << 16) & 0x00FF0000);
-
-						colorData += vertexStride;
-					}
-				}
-
-				vertexBuffer->writeData(0, bufferSize, bufferCopy, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
-
-				bs_free(bufferCopy);
-			}
-			else
-			{
-				vertexBuffer->writeData(0, bufferSize, srcVertBufferData, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
-			}
-		}
-
-		if (performUpdateBounds)
-			updateBounds(meshData);
-	}
-
-	void MeshCore::readSubresource(UINT32 subresourceIdx, MeshData& meshData)
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		IndexType indexType = IT_32BIT;
-		if (mIndexBuffer)
-			indexType = mIndexBuffer->getProperties().getType();
-
-		if (mIndexBuffer)
-		{
-			const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
-
-			if (meshData.getIndexElementSize() != ibProps.getIndexSize())
-			{
-				BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
-					toString(ibProps.getIndexSize()) + ". Got: " + toString(meshData.getIndexElementSize()));
-			}
-
-			UINT8* idxData = static_cast<UINT8*>(mIndexBuffer->lock(GBL_READ_ONLY));
-			UINT32 idxElemSize = ibProps.getIndexSize();
-
-			UINT8* indices = nullptr;
-
-			if (indexType == IT_16BIT)
-				indices = (UINT8*)meshData.getIndices16();
-			else
-				indices = (UINT8*)meshData.getIndices32();
-
-			UINT32 numIndicesToCopy = std::min(mProperties.mNumIndices, meshData.getNumIndices());
-
-			UINT32 indicesSize = numIndicesToCopy * idxElemSize;
-			if (indicesSize > meshData.getIndexBufferSize())
-				BS_EXCEPT(InvalidParametersException, "Provided buffer doesn't have enough space to store mesh indices.");
-
-			memcpy(indices, idxData, numIndicesToCopy * idxElemSize);
-
-			mIndexBuffer->unlock();
-		}
-
-		if (mVertexData)
-		{
-			auto vertexBuffers = mVertexData->getBuffers();
-
-			UINT32 streamIdx = 0;
-			for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
-			{
-				if (!meshData.getVertexDesc()->hasStream(streamIdx))
-					continue;
-
-				SPtr<VertexBufferCore> vertexBuffer = iter->second;
-				const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
-
-				// Ensure both have the same sized vertices
-				UINT32 myVertSize = mVertexDesc->getVertexStride(streamIdx);
-				UINT32 otherVertSize = meshData.getVertexDesc()->getVertexStride(streamIdx);
-				if (myVertSize != otherVertSize)
-				{
-					BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(streamIdx) + " doesn't match meshes vertex size. Needed: " +
-						toString(myVertSize) + ". Got: " + toString(otherVertSize));
-				}
-
-				UINT32 numVerticesToCopy = meshData.getNumVertices();
-				UINT32 bufferSize = vbProps.getVertexSize() * numVerticesToCopy;
-
-				if (bufferSize > vertexBuffer->getSizeInBytes())
-					BS_EXCEPT(InvalidParametersException, "Vertex buffer values for stream \"" + toString(streamIdx) + "\" are being read out of valid range.");
-
-				UINT8* vertDataPtr = static_cast<UINT8*>(vertexBuffer->lock(GBL_READ_ONLY));
-
-				UINT8* dest = meshData.getStreamData(streamIdx);
-				memcpy(dest, vertDataPtr, bufferSize);
-
-				vertexBuffer->unlock();
-
-				streamIdx++;
-			}
-		}
-	}
-
-	void MeshCore::updateBounds(const MeshData& meshData)
-	{
-		mProperties.mBounds = meshData.calculateBounds();
-		
-		// TODO - Sync this to sim-thread possibly?
-	}
-
-	SPtr<MeshCore> MeshCore::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		int usage, DrawOperationType drawOp, IndexType indexType)
-	{
-		SubMesh subMesh(0, numIndices, drawOp);
-
-		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices, 
-			vertexDesc, { subMesh }, usage, indexType, nullptr));
-		mesh->_setThisPtr(mesh);
-		mesh->initialize();
-
-		return mesh;
-	}
-
-	SPtr<MeshCore> MeshCore::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
-	{
-		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
-			vertexDesc, subMeshes, usage, indexType, nullptr));
-
-		mesh->_setThisPtr(mesh);
-		mesh->initialize();
-
-		return mesh;
-	}
-
-	SPtr<MeshCore> MeshCore::create(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
-	{
-		UINT32 numVertices = initialMeshData->getNumVertices();
-		UINT32 numIndices = initialMeshData->getNumIndices();
-		VertexDataDescPtr vertexDesc = initialMeshData->getVertexDesc();
-		SubMesh subMesh(0, numIndices, drawOp);
-		IndexType indexType = initialMeshData->getIndexType();
-		
-		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
-			vertexDesc, { subMesh }, usage, indexType, initialMeshData));
-
-		mesh->_setThisPtr(mesh);
-		mesh->initialize();
-
-		return mesh;
-	}
-
-	SPtr<MeshCore> MeshCore::create(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
-	{
-		UINT32 numVertices = initialMeshData->getNumVertices();
-		UINT32 numIndices = initialMeshData->getNumIndices();
-		VertexDataDescPtr vertexDesc = initialMeshData->getVertexDesc();
-		IndexType indexType = initialMeshData->getIndexType();
-
-		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
-			vertexDesc, subMeshes, usage, indexType, initialMeshData));
-
-		mesh->_setThisPtr(mesh);
-		mesh->initialize();
-
-		return mesh;
-	}
-
-	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
-		int usage, DrawOperationType drawOp, IndexType indexType)
-		:MeshBase(numVertices, numIndices, drawOp), mVertexDesc(vertexDesc), mUsage(usage),
-		mIndexType(indexType)
-	{
-
-	}
-
-	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
-		:MeshBase(numVertices, numIndices, subMeshes), mVertexDesc(vertexDesc), mUsage(usage), 
-		mIndexType(indexType)
-	{
-
-	}
-
-	Mesh::Mesh(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
-		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), drawOp), 
-		mIndexType(initialMeshData->getIndexType()), mVertexDesc(initialMeshData->getVertexDesc()), 
-		mCPUData(initialMeshData), mUsage(usage)
-	{
-
-	}
-
-	Mesh::Mesh(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
-		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), subMeshes),
-		mIndexType(initialMeshData->getIndexType()), mVertexDesc(initialMeshData->getVertexDesc()), 
-		mCPUData(initialMeshData), mUsage(usage)
-	{
-
-	}
-
-	Mesh::Mesh()
-		:MeshBase(0, 0, DOT_TRIANGLE_LIST), mUsage(MU_STATIC), mIndexType(IT_32BIT)
-	{
-
-	}
-
-	Mesh::~Mesh()
-	{
-		
-	}
-
-	AsyncOp Mesh::writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data, bool discardEntireBuffer)
-	{
-		updateBounds(*data);
-		updateCPUBuffer(subresourceIdx, *data);
-
-		data->_lock();
-
-		std::function<void(const SPtr<MeshCore>&, UINT32, const MeshDataPtr&, bool, AsyncOp&)> func =
-			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const MeshDataPtr& _meshData, bool _discardEntireBuffer, AsyncOp& asyncOp)
-		{
-			mesh->writeSubresource(_subresourceIdx, *_meshData, _discardEntireBuffer, false);
-			_meshData->_unlock();
-			asyncOp._completeOperation();
-
-		};
-
-		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
-			 data, discardEntireBuffer, std::placeholders::_1));
-	}
-
-	AsyncOp Mesh::readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data)
-	{
-		data->_lock();
-
-		std::function<void(const SPtr<MeshCore>&, UINT32, const MeshDataPtr&, AsyncOp&)> func =
-			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const MeshDataPtr& _meshData, AsyncOp& asyncOp)
-		{
-			mesh->readSubresource(_subresourceIdx, *_meshData);
-			_meshData->_unlock();
-			asyncOp._completeOperation();
-
-		};
-
-		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
-			data, std::placeholders::_1));
-	}
-
-	MeshDataPtr Mesh::allocateSubresourceBuffer(UINT32 subresourceIdx) const
-	{
-		MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(mProperties.mNumVertices, mProperties.mNumIndices, mVertexDesc, mIndexType);
-
-		return meshData;
-	}
-
-	void Mesh::initialize()
-	{
-		if (mCPUData != nullptr)
-			updateBounds(*mCPUData);
-
-		MeshBase::initialize();
-
-		if ((mUsage & MU_CPUCACHED) != 0 && mCPUData == nullptr)
-			createCPUBuffer();
-	}
-
-	void Mesh::updateBounds(const MeshData& meshData)
-	{
-		mProperties.mBounds = meshData.calculateBounds();
-		markCoreDirty();
-	}
-
-	SPtr<MeshCore> Mesh::getCore() const
-	{
-		return std::static_pointer_cast<MeshCore>(mCoreSpecific);
-	}
-
-	SPtr<CoreObjectCore> Mesh::createCore() const
-	{
-		MeshCore* obj = new (bs_alloc<MeshCore>()) MeshCore(mProperties.mNumVertices, mProperties.mNumIndices, 
-			mVertexDesc, mProperties.mSubMeshes, mUsage, mIndexType, mCPUData);
-
-		SPtr<CoreObjectCore> meshCore = bs_shared_ptr<MeshCore>(obj);
-		meshCore->_setThisPtr(meshCore);
-
-		if ((mUsage & MU_CPUCACHED) == 0)
-			mCPUData = nullptr;
-
-		return meshCore;
-	}
-
-	void Mesh::updateCPUBuffer(UINT32 subresourceIdx, const MeshData& pixelData)
-	{
-		if ((mUsage & MU_CPUCACHED) == 0)
-			return;
-
-		if (subresourceIdx > 0)
-		{
-			LOGERR("Invalid subresource index: " + toString(subresourceIdx) + ". Supported range: 0 .. 1.");
-			return;
-		}
-
-		if (pixelData.getNumIndices() != mProperties.getNumIndices() ||
-			pixelData.getNumVertices() != mProperties.getNumVertices() ||
-			pixelData.getIndexType() != mIndexType ||
-			pixelData.getVertexDesc()->getVertexStride() != mVertexDesc->getVertexStride())
-		{
-			LOGERR("Provided buffer is not of valid dimensions or format in order to update this mesh.");
-			return;
-		}
-
-		if (mCPUData->getSize() != pixelData.getSize())
-			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
-
-		UINT8* dest = mCPUData->getData();
-		UINT8* src = pixelData.getData();
-
-		memcpy(dest, src, pixelData.getSize());
-	}
-
-	void Mesh::readData(MeshData& dest)
-	{
-		if ((mUsage & MU_CPUCACHED) == 0)
-		{
-			LOGERR("Attempting to read CPU data from a mesh that is created without CPU caching.");
-			return;
-		}
-
-		if (dest.getNumIndices() != mProperties.getNumIndices() ||
-			dest.getNumVertices() != mProperties.getNumVertices() ||
-			dest.getIndexType() != mIndexType ||
-			dest.getVertexDesc()->getVertexStride() != mVertexDesc->getVertexStride())
-		{
-			LOGERR("Provided buffer is not of valid dimensions or format in order to read from this mesh.");
-			return;
-		}
-		
-		if (mCPUData->getSize() != dest.getSize())
-			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
-
-		UINT8* srcPtr = mCPUData->getData();
-		UINT8* destPtr = dest.getData();
-
-		memcpy(destPtr, srcPtr, dest.getSize());
-	}
-
-	void Mesh::createCPUBuffer()
-	{
-		mCPUData = allocateSubresourceBuffer(0);
-	}
-
-	HMesh Mesh::dummy()
-	{
-		return MeshManager::instance().getDummyMesh();
-	}
-
-	/************************************************************************/
-	/* 								SERIALIZATION                      		*/
-	/************************************************************************/
-
-	RTTITypeBase* Mesh::getRTTIStatic()
-	{
-		return MeshRTTI::instance();
-	}
-
-	RTTITypeBase* Mesh::getRTTI() const
-	{
-		return Mesh::getRTTIStatic();
-	}
-
-	/************************************************************************/
-	/* 								STATICS		                     		*/
-	/************************************************************************/
-
-	HMesh Mesh::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
-		int usage, DrawOperationType drawOp, IndexType indexType)
-	{
-		MeshPtr meshPtr = _createPtr(numVertices, numIndices, vertexDesc, usage, drawOp, indexType);
-
-		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
-	}
-
-	HMesh Mesh::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
-	{
-		MeshPtr meshPtr = _createPtr(numVertices, numIndices, vertexDesc, subMeshes, usage, indexType);
-
-		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
-	}
-
-	HMesh Mesh::create(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
-	{
-		MeshPtr meshPtr = _createPtr(initialMeshData, usage, drawOp);
-
-		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
-	}
-
-	HMesh Mesh::create(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
-	{
-		MeshPtr meshPtr = _createPtr(initialMeshData, subMeshes, usage);
-
-		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
-	}
-
-	MeshPtr Mesh::_createPtr(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
-		int usage, DrawOperationType drawOp, IndexType indexType)
-	{
-		return MeshManager::instance().create(numVertices, numIndices, vertexDesc, usage, drawOp, indexType);
-	}
-
-	MeshPtr Mesh::_createPtr(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
-		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
-	{
-		return MeshManager::instance().create(numVertices, numIndices, vertexDesc, subMeshes, usage, indexType);
-	}
-
-	MeshPtr Mesh::_createPtr(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
-	{
-		return MeshManager::instance().create(initialMeshData, usage, drawOp);
-	}
-
-	MeshPtr Mesh::_createPtr(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
-	{
-		return MeshManager::instance().create(initialMeshData, subMeshes, usage);
-	}
+#include "BsMesh.h"
+#include "BsMeshRTTI.h"
+#include "BsMeshData.h"
+#include "BsDebug.h"
+#include "BsHardwareBufferManager.h"
+#include "BsMeshManager.h"
+#include "BsCoreThread.h"
+#include "BsAsyncOp.h"
+#include "BsVertexDataDesc.h"
+#include "BsResources.h"
+#include "BsRenderAPI.h"
+
+namespace BansheeEngine
+{
+	MeshCore::MeshCore(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType, MeshDataPtr initialMeshData)
+		:MeshCoreBase(numVertices, numIndices, subMeshes), mVertexData(nullptr), mIndexBuffer(nullptr), 
+		mVertexDesc(vertexDesc), mUsage(usage), mIndexType(indexType), mTempInitialMeshData(initialMeshData)
+	{ }
+
+	MeshCore::~MeshCore()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		mVertexData = nullptr;
+		mIndexBuffer = nullptr;
+		mVertexDesc = nullptr;
+		mTempInitialMeshData = nullptr;
+	}
+
+	void MeshCore::initialize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		bool isDynamic = (mUsage & MU_DYNAMIC) != 0;
+
+		mIndexBuffer = HardwareBufferCoreManager::instance().createIndexBuffer(mIndexType,
+			mProperties.mNumIndices, isDynamic ? GBU_DYNAMIC : GBU_STATIC);
+
+		mVertexData = std::shared_ptr<VertexData>(bs_new<VertexData>());
+
+		mVertexData->vertexCount = mProperties.mNumVertices;
+
+		List<VertexElement> elements = mVertexDesc->createElements();
+		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(elements);
+
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			if (!mVertexDesc->hasStream(i))
+				continue;
+
+			SPtr<VertexBufferCore> vertexBuffer = HardwareBufferCoreManager::instance().createVertexBuffer(
+				mVertexData->vertexDeclaration->getProperties().getVertexSize(i),
+				mVertexData->vertexCount,
+				isDynamic ? GBU_DYNAMIC : GBU_STATIC);
+
+			mVertexData->setBuffer(i, vertexBuffer);
+		}
+
+		// TODO Low priority - DX11 (and maybe OpenGL)? allow an optimization that allows you to set
+		// buffer data upon buffer construction, instead of setting it in a second step like I do here
+		if (mTempInitialMeshData != nullptr)
+		{
+			writeSubresource(0, *mTempInitialMeshData, isDynamic);
+			mTempInitialMeshData = nullptr;
+		}
+
+		MeshCoreBase::initialize();
+	}
+
+	std::shared_ptr<VertexData> MeshCore::getVertexData() const
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		return mVertexData;
+	}
+
+	SPtr<IndexBufferCore> MeshCore::getIndexBuffer() const
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		return mIndexBuffer;
+	}
+
+	SPtr<VertexDataDesc> MeshCore::getVertexDesc() const
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		return mVertexDesc;
+	}
+
+	void MeshCore::writeSubresource(UINT32 subresourceIdx, const MeshData& meshData, bool discardEntireBuffer, bool performUpdateBounds)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		if (discardEntireBuffer)
+		{
+			if ((mUsage & MU_STATIC) != 0)
+			{
+				LOGWRN("Buffer discard is enabled but buffer was not created as dynamic. Disabling discard.");
+				discardEntireBuffer = false;
+			}
+		}
+		else
+		{
+			if ((mUsage & MU_DYNAMIC) != 0)
+			{
+				LOGWRN("Buffer discard is not enabled but buffer was created as dynamic. Enabling discard.");
+				discardEntireBuffer = true;
+			}
+		}
+
+		// Indices
+		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
+
+		UINT32 indicesSize = meshData.getIndexBufferSize();
+		UINT8* srcIdxData = meshData.getIndexData();
+
+		if (meshData.getIndexElementSize() != ibProps.getIndexSize())
+		{
+			BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
+				toString(ibProps.getIndexSize()) + ". Got: " + toString(meshData.getIndexElementSize()));
+		}
+
+		if (indicesSize > mIndexBuffer->getSizeInBytes())
+			BS_EXCEPT(InvalidParametersException, "Index buffer values are being written out of valid range.");
+
+		mIndexBuffer->writeData(0, indicesSize, srcIdxData, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
+
+		// Vertices
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			if (!mVertexDesc->hasStream(i))
+				continue;
+
+			if (!meshData.getVertexDesc()->hasStream(i))
+				continue;
+
+			// Ensure both have the same sized vertices
+			UINT32 myVertSize = mVertexDesc->getVertexStride(i);
+			UINT32 otherVertSize = meshData.getVertexDesc()->getVertexStride(i);
+			if (myVertSize != otherVertSize)
+			{
+				BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(i) + " doesn't match meshes vertex size. Needed: " +
+					toString(myVertSize) + ". Got: " + toString(otherVertSize));
+			}
+
+			SPtr<VertexBufferCore> vertexBuffer = mVertexData->getBuffer(i);
+			const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
+
+			UINT32 bufferSize = meshData.getStreamSize(i);
+			UINT8* srcVertBufferData = meshData.getStreamData(i);
+
+			if (bufferSize > vertexBuffer->getSizeInBytes())
+				BS_EXCEPT(InvalidParametersException, "Vertex buffer values for stream \"" + toString(i) + "\" are being written out of valid range.");
+
+			if (RenderAPICore::instance().getVertexColorFlipRequired())
+			{
+				UINT8* bufferCopy = (UINT8*)bs_alloc(bufferSize);
+				memcpy(bufferCopy, srcVertBufferData, bufferSize); // TODO Low priority - Attempt to avoid this copy
+
+				UINT32 vertexStride = meshData.getVertexDesc()->getVertexStride(i);
+				for (INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
+				{
+					if (!meshData.getVertexDesc()->hasElement(VES_COLOR, semanticIdx, i))
+						continue;
+
+					UINT8* colorData = bufferCopy + mVertexDesc->getElementOffsetFromStream(VES_COLOR, semanticIdx, i);
+					for (UINT32 j = 0; j < mVertexData->vertexCount; j++)
+					{
+						UINT32* curColor = (UINT32*)colorData;
+
+						(*curColor) = ((*curColor) & 0xFF00FF00) | ((*curColor >> 16) & 0x000000FF) | ((*curColor << 16) & 0x00FF0000);
+
+						colorData += vertexStride;
+					}
+				}
+
+				vertexBuffer->writeData(0, bufferSize, bufferCopy, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
+
+				bs_free(bufferCopy);
+			}
+			else
+			{
+				vertexBuffer->writeData(0, bufferSize, srcVertBufferData, discardEntireBuffer ? BufferWriteType::Discard : BufferWriteType::Normal);
+			}
+		}
+
+		if (performUpdateBounds)
+			updateBounds(meshData);
+	}
+
+	void MeshCore::readSubresource(UINT32 subresourceIdx, MeshData& meshData)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		IndexType indexType = IT_32BIT;
+		if (mIndexBuffer)
+			indexType = mIndexBuffer->getProperties().getType();
+
+		if (mIndexBuffer)
+		{
+			const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
+
+			if (meshData.getIndexElementSize() != ibProps.getIndexSize())
+			{
+				BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
+					toString(ibProps.getIndexSize()) + ". Got: " + toString(meshData.getIndexElementSize()));
+			}
+
+			UINT8* idxData = static_cast<UINT8*>(mIndexBuffer->lock(GBL_READ_ONLY));
+			UINT32 idxElemSize = ibProps.getIndexSize();
+
+			UINT8* indices = nullptr;
+
+			if (indexType == IT_16BIT)
+				indices = (UINT8*)meshData.getIndices16();
+			else
+				indices = (UINT8*)meshData.getIndices32();
+
+			UINT32 numIndicesToCopy = std::min(mProperties.mNumIndices, meshData.getNumIndices());
+
+			UINT32 indicesSize = numIndicesToCopy * idxElemSize;
+			if (indicesSize > meshData.getIndexBufferSize())
+				BS_EXCEPT(InvalidParametersException, "Provided buffer doesn't have enough space to store mesh indices.");
+
+			memcpy(indices, idxData, numIndicesToCopy * idxElemSize);
+
+			mIndexBuffer->unlock();
+		}
+
+		if (mVertexData)
+		{
+			auto vertexBuffers = mVertexData->getBuffers();
+
+			UINT32 streamIdx = 0;
+			for (auto iter = vertexBuffers.begin(); iter != vertexBuffers.end(); ++iter)
+			{
+				if (!meshData.getVertexDesc()->hasStream(streamIdx))
+					continue;
+
+				SPtr<VertexBufferCore> vertexBuffer = iter->second;
+				const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
+
+				// Ensure both have the same sized vertices
+				UINT32 myVertSize = mVertexDesc->getVertexStride(streamIdx);
+				UINT32 otherVertSize = meshData.getVertexDesc()->getVertexStride(streamIdx);
+				if (myVertSize != otherVertSize)
+				{
+					BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(streamIdx) + " doesn't match meshes vertex size. Needed: " +
+						toString(myVertSize) + ". Got: " + toString(otherVertSize));
+				}
+
+				UINT32 numVerticesToCopy = meshData.getNumVertices();
+				UINT32 bufferSize = vbProps.getVertexSize() * numVerticesToCopy;
+
+				if (bufferSize > vertexBuffer->getSizeInBytes())
+					BS_EXCEPT(InvalidParametersException, "Vertex buffer values for stream \"" + toString(streamIdx) + "\" are being read out of valid range.");
+
+				UINT8* vertDataPtr = static_cast<UINT8*>(vertexBuffer->lock(GBL_READ_ONLY));
+
+				UINT8* dest = meshData.getStreamData(streamIdx);
+				memcpy(dest, vertDataPtr, bufferSize);
+
+				vertexBuffer->unlock();
+
+				streamIdx++;
+			}
+		}
+	}
+
+	void MeshCore::updateBounds(const MeshData& meshData)
+	{
+		mProperties.mBounds = meshData.calculateBounds();
+		
+		// TODO - Sync this to sim-thread possibly?
+	}
+
+	SPtr<MeshCore> MeshCore::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		int usage, DrawOperationType drawOp, IndexType indexType)
+	{
+		SubMesh subMesh(0, numIndices, drawOp);
+
+		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices, 
+			vertexDesc, { subMesh }, usage, indexType, nullptr));
+		mesh->_setThisPtr(mesh);
+		mesh->initialize();
+
+		return mesh;
+	}
+
+	SPtr<MeshCore> MeshCore::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
+	{
+		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
+			vertexDesc, subMeshes, usage, indexType, nullptr));
+
+		mesh->_setThisPtr(mesh);
+		mesh->initialize();
+
+		return mesh;
+	}
+
+	SPtr<MeshCore> MeshCore::create(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
+	{
+		UINT32 numVertices = initialMeshData->getNumVertices();
+		UINT32 numIndices = initialMeshData->getNumIndices();
+		VertexDataDescPtr vertexDesc = initialMeshData->getVertexDesc();
+		SubMesh subMesh(0, numIndices, drawOp);
+		IndexType indexType = initialMeshData->getIndexType();
+		
+		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
+			vertexDesc, { subMesh }, usage, indexType, initialMeshData));
+
+		mesh->_setThisPtr(mesh);
+		mesh->initialize();
+
+		return mesh;
+	}
+
+	SPtr<MeshCore> MeshCore::create(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
+	{
+		UINT32 numVertices = initialMeshData->getNumVertices();
+		UINT32 numIndices = initialMeshData->getNumIndices();
+		VertexDataDescPtr vertexDesc = initialMeshData->getVertexDesc();
+		IndexType indexType = initialMeshData->getIndexType();
+
+		SPtr<MeshCore> mesh = bs_shared_ptr<MeshCore>(new (bs_alloc<MeshCore>()) MeshCore(numVertices, numIndices,
+			vertexDesc, subMeshes, usage, indexType, initialMeshData));
+
+		mesh->_setThisPtr(mesh);
+		mesh->initialize();
+
+		return mesh;
+	}
+
+	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
+		int usage, DrawOperationType drawOp, IndexType indexType)
+		:MeshBase(numVertices, numIndices, drawOp), mVertexDesc(vertexDesc), mUsage(usage),
+		mIndexType(indexType)
+	{
+
+	}
+
+	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
+		:MeshBase(numVertices, numIndices, subMeshes), mVertexDesc(vertexDesc), mUsage(usage), 
+		mIndexType(indexType)
+	{
+
+	}
+
+	Mesh::Mesh(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
+		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), drawOp), 
+		mIndexType(initialMeshData->getIndexType()), mVertexDesc(initialMeshData->getVertexDesc()), 
+		mCPUData(initialMeshData), mUsage(usage)
+	{
+
+	}
+
+	Mesh::Mesh(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
+		:MeshBase(initialMeshData->getNumVertices(), initialMeshData->getNumIndices(), subMeshes),
+		mIndexType(initialMeshData->getIndexType()), mVertexDesc(initialMeshData->getVertexDesc()), 
+		mCPUData(initialMeshData), mUsage(usage)
+	{
+
+	}
+
+	Mesh::Mesh()
+		:MeshBase(0, 0, DOT_TRIANGLE_LIST), mUsage(MU_STATIC), mIndexType(IT_32BIT)
+	{
+
+	}
+
+	Mesh::~Mesh()
+	{
+		
+	}
+
+	AsyncOp Mesh::writeSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data, bool discardEntireBuffer)
+	{
+		updateBounds(*data);
+		updateCPUBuffer(subresourceIdx, *data);
+
+		data->_lock();
+
+		std::function<void(const SPtr<MeshCore>&, UINT32, const MeshDataPtr&, bool, AsyncOp&)> func =
+			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const MeshDataPtr& _meshData, bool _discardEntireBuffer, AsyncOp& asyncOp)
+		{
+			mesh->writeSubresource(_subresourceIdx, *_meshData, _discardEntireBuffer, false);
+			_meshData->_unlock();
+			asyncOp._completeOperation();
+
+		};
+
+		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+			 data, discardEntireBuffer, std::placeholders::_1));
+	}
+
+	AsyncOp Mesh::readSubresource(CoreAccessor& accessor, UINT32 subresourceIdx, const MeshDataPtr& data)
+	{
+		data->_lock();
+
+		std::function<void(const SPtr<MeshCore>&, UINT32, const MeshDataPtr&, AsyncOp&)> func =
+			[&](const SPtr<MeshCore>& mesh, UINT32 _subresourceIdx, const MeshDataPtr& _meshData, AsyncOp& asyncOp)
+		{
+			mesh->readSubresource(_subresourceIdx, *_meshData);
+			_meshData->_unlock();
+			asyncOp._completeOperation();
+
+		};
+
+		return accessor.queueReturnCommand(std::bind(func, getCore(), subresourceIdx,
+			data, std::placeholders::_1));
+	}
+
+	MeshDataPtr Mesh::allocateSubresourceBuffer(UINT32 subresourceIdx) const
+	{
+		MeshDataPtr meshData = bs_shared_ptr_new<MeshData>(mProperties.mNumVertices, mProperties.mNumIndices, mVertexDesc, mIndexType);
+
+		return meshData;
+	}
+
+	void Mesh::initialize()
+	{
+		if (mCPUData != nullptr)
+			updateBounds(*mCPUData);
+
+		MeshBase::initialize();
+
+		if ((mUsage & MU_CPUCACHED) != 0 && mCPUData == nullptr)
+			createCPUBuffer();
+	}
+
+	void Mesh::updateBounds(const MeshData& meshData)
+	{
+		mProperties.mBounds = meshData.calculateBounds();
+		markCoreDirty();
+	}
+
+	SPtr<MeshCore> Mesh::getCore() const
+	{
+		return std::static_pointer_cast<MeshCore>(mCoreSpecific);
+	}
+
+	SPtr<CoreObjectCore> Mesh::createCore() const
+	{
+		MeshCore* obj = new (bs_alloc<MeshCore>()) MeshCore(mProperties.mNumVertices, mProperties.mNumIndices, 
+			mVertexDesc, mProperties.mSubMeshes, mUsage, mIndexType, mCPUData);
+
+		SPtr<CoreObjectCore> meshCore = bs_shared_ptr<MeshCore>(obj);
+		meshCore->_setThisPtr(meshCore);
+
+		if ((mUsage & MU_CPUCACHED) == 0)
+			mCPUData = nullptr;
+
+		return meshCore;
+	}
+
+	void Mesh::updateCPUBuffer(UINT32 subresourceIdx, const MeshData& pixelData)
+	{
+		if ((mUsage & MU_CPUCACHED) == 0)
+			return;
+
+		if (subresourceIdx > 0)
+		{
+			LOGERR("Invalid subresource index: " + toString(subresourceIdx) + ". Supported range: 0 .. 1.");
+			return;
+		}
+
+		if (pixelData.getNumIndices() != mProperties.getNumIndices() ||
+			pixelData.getNumVertices() != mProperties.getNumVertices() ||
+			pixelData.getIndexType() != mIndexType ||
+			pixelData.getVertexDesc()->getVertexStride() != mVertexDesc->getVertexStride())
+		{
+			LOGERR("Provided buffer is not of valid dimensions or format in order to update this mesh.");
+			return;
+		}
+
+		if (mCPUData->getSize() != pixelData.getSize())
+			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
+
+		UINT8* dest = mCPUData->getData();
+		UINT8* src = pixelData.getData();
+
+		memcpy(dest, src, pixelData.getSize());
+	}
+
+	void Mesh::readData(MeshData& dest)
+	{
+		if ((mUsage & MU_CPUCACHED) == 0)
+		{
+			LOGERR("Attempting to read CPU data from a mesh that is created without CPU caching.");
+			return;
+		}
+
+		if (dest.getNumIndices() != mProperties.getNumIndices() ||
+			dest.getNumVertices() != mProperties.getNumVertices() ||
+			dest.getIndexType() != mIndexType ||
+			dest.getVertexDesc()->getVertexStride() != mVertexDesc->getVertexStride())
+		{
+			LOGERR("Provided buffer is not of valid dimensions or format in order to read from this mesh.");
+			return;
+		}
+		
+		if (mCPUData->getSize() != dest.getSize())
+			BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
+
+		UINT8* srcPtr = mCPUData->getData();
+		UINT8* destPtr = dest.getData();
+
+		memcpy(destPtr, srcPtr, dest.getSize());
+	}
+
+	void Mesh::createCPUBuffer()
+	{
+		mCPUData = allocateSubresourceBuffer(0);
+	}
+
+	HMesh Mesh::dummy()
+	{
+		return MeshManager::instance().getDummyMesh();
+	}
+
+	/************************************************************************/
+	/* 								SERIALIZATION                      		*/
+	/************************************************************************/
+
+	RTTITypeBase* Mesh::getRTTIStatic()
+	{
+		return MeshRTTI::instance();
+	}
+
+	RTTITypeBase* Mesh::getRTTI() const
+	{
+		return Mesh::getRTTIStatic();
+	}
+
+	/************************************************************************/
+	/* 								STATICS		                     		*/
+	/************************************************************************/
+
+	HMesh Mesh::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
+		int usage, DrawOperationType drawOp, IndexType indexType)
+	{
+		MeshPtr meshPtr = _createPtr(numVertices, numIndices, vertexDesc, usage, drawOp, indexType);
+
+		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
+	}
+
+	HMesh Mesh::create(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
+	{
+		MeshPtr meshPtr = _createPtr(numVertices, numIndices, vertexDesc, subMeshes, usage, indexType);
+
+		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
+	}
+
+	HMesh Mesh::create(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
+	{
+		MeshPtr meshPtr = _createPtr(initialMeshData, usage, drawOp);
+
+		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
+	}
+
+	HMesh Mesh::create(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
+	{
+		MeshPtr meshPtr = _createPtr(initialMeshData, subMeshes, usage);
+
+		return static_resource_cast<Mesh>(gResources()._createResourceHandle(meshPtr));
+	}
+
+	MeshPtr Mesh::_createPtr(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
+		int usage, DrawOperationType drawOp, IndexType indexType)
+	{
+		return MeshManager::instance().create(numVertices, numIndices, vertexDesc, usage, drawOp, indexType);
+	}
+
+	MeshPtr Mesh::_createPtr(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc,
+		const Vector<SubMesh>& subMeshes, int usage, IndexType indexType)
+	{
+		return MeshManager::instance().create(numVertices, numIndices, vertexDesc, subMeshes, usage, indexType);
+	}
+
+	MeshPtr Mesh::_createPtr(const MeshDataPtr& initialMeshData, int usage, DrawOperationType drawOp)
+	{
+		return MeshManager::instance().create(initialMeshData, usage, drawOp);
+	}
+
+	MeshPtr Mesh::_createPtr(const MeshDataPtr& initialMeshData, const Vector<SubMesh>& subMeshes, int usage)
+	{
+		return MeshManager::instance().create(initialMeshData, subMeshes, usage);
+	}
 }
 }

+ 700 - 699
BansheeCore/Source/BsMeshHeap.cpp

@@ -1,700 +1,701 @@
-#include "BsMeshHeap.h"
-#include "BsCoreThread.h"
-#include "BsTransientMesh.h"
-#include "BsHardwareBufferManager.h"
-#include "BsVertexDataDesc.h"
-#include "BsVertexData.h"
-#include "BsMeshData.h"
-#include "BsMath.h"
-#include "BsEventQuery.h"
-
-namespace BansheeEngine
-{
-	const float MeshHeapCore::GrowPercent = 1.5f;
-
-	MeshHeapCore::MeshHeapCore(UINT32 numVertices, UINT32 numIndices,
-		const VertexDataDescPtr& vertexDesc, IndexType indexType)
-		:mNumVertices(numVertices), mNumIndices(numIndices), mIndexType(indexType), 
-		mVertexDesc(vertexDesc), mCPUIndexData(nullptr), mNextQueryId(0)
-	{
-		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
-		{
-			mCPUVertexData.push_back(nullptr);
-		}
-	}
-
-	MeshHeapCore::~MeshHeapCore()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		for (auto& cpuVertBuffer : mCPUVertexData)
-			bs_free(cpuVertBuffer);
-
-		if (mCPUIndexData != nullptr)
-			bs_free(mCPUIndexData);
-
-		mVertexData = nullptr;
-		mIndexBuffer = nullptr;
-		mVertexDesc = nullptr;
-	}
-
-	void MeshHeapCore::initialize()
-	{
-		THROW_IF_NOT_CORE_THREAD;
-
-		growVertexBuffer(mNumVertices);
-		growIndexBuffer(mNumIndices);
-
-		CoreObjectCore::initialize();
-	}
-
-	void MeshHeapCore::alloc(SPtr<TransientMeshCore> mesh, const MeshDataPtr& meshData)
-	{
-		// Find free vertex chunk and grow if needed
-		UINT32 smallestVertFit = 0;
-		UINT32 smallestVertFitIdx = 0;
-
-		while (smallestVertFit == 0)
-		{
-			UINT32 curIdx = 0;
-			for (auto& chunkIdx : mFreeVertChunks)
-			{
-				ChunkData& chunk = mVertChunks[chunkIdx];
-
-				if (chunk.size >= meshData->getNumVertices() && (chunk.size < smallestVertFit || smallestVertFit == 0))
-				{
-					smallestVertFit = chunk.size;
-					smallestVertFitIdx = curIdx;
-				}
-
-				curIdx++;
-			}
-
-			if (smallestVertFit > 0)
-				break;
-
-			UINT32 newNumVertices = mNumVertices;
-			while (newNumVertices < (mNumVertices + meshData->getNumVertices()))
-			{
-				newNumVertices = Math::roundToInt(newNumVertices * GrowPercent);
-			}
-
-			growVertexBuffer(newNumVertices);
-		}
-
-		// Find free index chunk and grow if needed
-		UINT32 smallestIdxFit = 0;
-		UINT32 smallestIdxFitIdx = 0;
-
-		while (smallestIdxFit == 0)
-		{
-			UINT32 curIdx = 0;
-			for (auto& chunkIdx : mFreeIdxChunks)
-			{
-				ChunkData& chunk = mIdxChunks[chunkIdx];
-
-				if (chunk.size >= meshData->getNumIndices() && (chunk.size < smallestIdxFit || smallestIdxFit == 0))
-				{
-					smallestIdxFit = chunk.size;
-					smallestIdxFitIdx = curIdx;
-				}
-
-				curIdx++;
-			}
-
-			if (smallestIdxFit > 0)
-				break;
-
-			UINT32 newNumIndices = mNumIndices;
-			while (newNumIndices < (mNumIndices + meshData->getNumIndices()))
-			{
-				newNumIndices = Math::roundToInt(newNumIndices * GrowPercent);
-			}
-
-			growIndexBuffer(newNumIndices);
-		}
-
-		UINT32 freeVertChunkIdx = 0;
-		UINT32 freeIdxChunkIdx = 0;
-
-		auto freeVertIter = mFreeVertChunks.begin();
-		freeVertChunkIdx = (*freeVertIter);
-		for (UINT32 i = 0; i < smallestVertFitIdx; i++)
-		{
-			freeVertIter++;
-			freeVertChunkIdx = (*freeVertIter);
-		}
-
-		mFreeVertChunks.erase(freeVertIter);
-
-		auto freeIdxIter = mFreeIdxChunks.begin();
-		freeIdxChunkIdx = (*freeIdxIter);
-		for (UINT32 i = 0; i < smallestIdxFitIdx; i++)
-		{
-			freeIdxIter++;
-			freeIdxChunkIdx = (*freeIdxIter);
-		}
-
-		mFreeIdxChunks.erase(freeIdxIter);
-
-		ChunkData& vertChunk = mVertChunks[freeVertChunkIdx];
-		ChunkData& idxChunk = mIdxChunks[freeIdxChunkIdx];
-
-		UINT32 vertChunkStart = vertChunk.start;
-		UINT32 idxChunkStart = idxChunk.start;
-
-		UINT32 remainingNumVerts = vertChunk.size - meshData->getNumVertices();
-		UINT32 remainingNumIdx = idxChunk.size - meshData->getNumIndices();
-
-		vertChunk.size = meshData->getNumVertices();
-		idxChunk.size = meshData->getNumIndices();
-
-		if (remainingNumVerts > 0)
-		{
-			if (!mEmptyVertChunks.empty())
-			{
-				UINT32 emptyChunkIdx = mEmptyVertChunks.top();
-				ChunkData& emptyChunk = mVertChunks[emptyChunkIdx];
-				mEmptyVertChunks.pop();
-
-				emptyChunk.start = vertChunkStart + meshData->getNumVertices();
-				emptyChunk.size = remainingNumVerts;
-			}
-			else
-			{
-				ChunkData newChunk;
-				newChunk.size = remainingNumVerts;
-				newChunk.start = vertChunkStart + meshData->getNumVertices();
-
-				mVertChunks.push_back(newChunk);
-				mFreeVertChunks.push_back((UINT32)(mVertChunks.size() - 1));
-			}
-		}
-
-		if (remainingNumIdx > 0)
-		{
-			if (!mEmptyIdxChunks.empty())
-			{
-				UINT32 emptyChunkIdx = mEmptyIdxChunks.top();
-				ChunkData& emptyChunk = mIdxChunks[emptyChunkIdx];
-				mEmptyIdxChunks.pop();
-
-				emptyChunk.start = idxChunkStart + meshData->getNumIndices();
-				emptyChunk.size = remainingNumIdx;
-			}
-			else
-			{
-				ChunkData newChunk;
-				newChunk.size = remainingNumIdx;
-				newChunk.start = idxChunkStart + meshData->getNumIndices();
-
-				mIdxChunks.push_back(newChunk);
-				mFreeIdxChunks.push_back((UINT32)(mIdxChunks.size() - 1));
-			}
-		}
-
-		AllocatedData newAllocData;
-		newAllocData.vertChunkIdx = freeVertChunkIdx;
-		newAllocData.idxChunkIdx = freeIdxChunkIdx;
-		newAllocData.useFlags = UseFlags::GPUFree;
-		newAllocData.eventQueryIdx = createEventQuery();
-		newAllocData.mesh = mesh;
-
-		mMeshAllocData[mesh->getMeshHeapId()] = newAllocData;
-
-		// Actually copy data
-		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
-		{
-			if (!mVertexDesc->hasStream(i))
-				continue;
-
-			if (!meshData->getVertexDesc()->hasStream(i))
-				continue;
-
-			// Ensure vertex sizes match
-			UINT32 vertSize = mVertexData->vertexDeclaration->getProperties().getVertexSize(i);
-			UINT32 otherVertSize = meshData->getVertexDesc()->getVertexStride(i);
-			if (otherVertSize != vertSize)
-			{
-				BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(i) + " doesn't match meshes vertex size. Needed: " +
-					toString(vertSize) + ". Got: " + toString(otherVertSize));
-			}
-
-			SPtr<VertexBufferCore> vertexBuffer = mVertexData->getBuffer(i);
-			const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
-
-			UINT8* vertDest = mCPUVertexData[i] + vertChunkStart * vertSize;
-			memcpy(vertDest, meshData->getStreamData(i), meshData->getNumVertices() * vertSize);
-
-			if (RenderAPICore::instance().getVertexColorFlipRequired())
-			{
-				UINT32 vertexStride = mVertexDesc->getVertexStride(i);
-				for (INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
-				{
-					if (!mVertexDesc->hasElement(VES_COLOR, semanticIdx, i))
-						continue;
-
-					UINT8* colorData = vertDest + mVertexDesc->getElementOffsetFromStream(VES_COLOR, semanticIdx, i);
-					for (UINT32 j = 0; j < meshData->getNumVertices(); j++)
-					{
-						UINT32* curColor = (UINT32*)colorData;
-
-						(*curColor) = ((*curColor) & 0xFF00FF00) | ((*curColor >> 16) & 0x000000FF) | ((*curColor << 16) & 0x00FF0000);
-
-						colorData += vertexStride;
-					}
-				}
-			}
-
-			vertexBuffer->writeData(vertChunkStart * vertSize, meshData->getNumVertices() * vertSize, vertDest, BufferWriteType::NoOverwrite);
-		}
-
-		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
-
-		UINT32 idxSize = ibProps.getIndexSize();
-
-		// Ensure index sizes match
-		if (meshData->getIndexElementSize() != idxSize)
-		{
-			BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
-				toString(idxSize) + ". Got: " + toString(meshData->getIndexElementSize()));
-		}
-
-		UINT8* idxDest = mCPUIndexData + idxChunkStart * idxSize;
-		memcpy(idxDest, meshData->getIndexData(), meshData->getNumIndices() * idxSize);
-		mIndexBuffer->writeData(idxChunkStart * idxSize, meshData->getNumIndices() * idxSize, idxDest, BufferWriteType::NoOverwrite);
-	}
-
-	void MeshHeapCore::dealloc(SPtr<TransientMeshCore> mesh)
-	{
-		auto findIter = mMeshAllocData.find(mesh->getMeshHeapId());
-		assert(findIter != mMeshAllocData.end());
-
-		AllocatedData& allocData = findIter->second;
-		if (allocData.useFlags == UseFlags::GPUFree)
-		{
-			allocData.useFlags = UseFlags::Free;
-			freeEventQuery(allocData.eventQueryIdx);
-
-			mFreeVertChunks.push_back(allocData.vertChunkIdx);
-			mFreeIdxChunks.push_back(allocData.idxChunkIdx);
-
-			mergeWithNearbyChunks(allocData.vertChunkIdx, allocData.idxChunkIdx);
-
-			mMeshAllocData.erase(findIter);
-		}
-		else if (allocData.useFlags == UseFlags::Used)
-			allocData.useFlags = UseFlags::CPUFree;
-	}
-
-	void MeshHeapCore::growVertexBuffer(UINT32 numVertices)
-	{
-		mNumVertices = numVertices;
-		mVertexData = std::shared_ptr<VertexData>(bs_new<VertexData>());
-
-		mVertexData->vertexCount = mNumVertices;
-		List<VertexElement> elements = mVertexDesc->createElements();
-
-		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(elements);
-
-		// Create buffers and copy data
-		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
-		{
-			if (!mVertexDesc->hasStream(i))
-				continue;
-
-			UINT32 vertSize = mVertexData->vertexDeclaration->getProperties().getVertexSize(i);
-			SPtr<VertexBufferCore> vertexBuffer = HardwareBufferCoreManager::instance().createVertexBuffer(
-				vertSize, mVertexData->vertexCount, GBU_DYNAMIC);
-
-			mVertexData->setBuffer(i, vertexBuffer);
-
-			// Copy all data to the new buffer
-			UINT8* oldBuffer = mCPUVertexData[i];
-			UINT8* buffer = (UINT8*)bs_alloc(vertSize * numVertices);
-
-			UINT32 destOffset = 0;
-			if (oldBuffer != nullptr)
-			{
-				for (auto& allocData : mMeshAllocData)
-				{
-					ChunkData& oldChunk = mVertChunks[allocData.second.vertChunkIdx];
-
-					UINT8* oldData = oldBuffer + oldChunk.start * vertSize;
-					memcpy(buffer + destOffset * vertSize, oldData, oldChunk.size * vertSize);
-
-					destOffset += oldChunk.size;
-				}
-
-				bs_free(oldBuffer);
-			}
-
-			if (destOffset > 0)
-				vertexBuffer->writeData(0, destOffset * vertSize, buffer, BufferWriteType::NoOverwrite);
-
-			mCPUVertexData[i] = buffer;
-		}
-
-		// Reorder chunks
-		UINT32 destOffset = 0;
-		Vector<ChunkData> newVertChunks;
-		List<UINT32> freeVertChunks;
-
-		for (auto& allocData : mMeshAllocData)
-		{
-			ChunkData& oldChunk = mVertChunks[allocData.second.vertChunkIdx];
-
-			ChunkData newChunk;
-			newChunk.start = destOffset;
-			newChunk.size = oldChunk.size;
-
-			allocData.second.vertChunkIdx = (UINT32)newVertChunks.size();
-			newVertChunks.push_back(newChunk);
-
-			destOffset += oldChunk.size;
-		}
-
-		// Add free chunk
-		if (destOffset != mNumVertices)
-		{
-			ChunkData newChunk;
-			newChunk.start = destOffset;
-			newChunk.size = mNumVertices - destOffset;
-
-			newVertChunks.push_back(newChunk);
-			freeVertChunks.push_back((UINT32)(newVertChunks.size() - 1));
-		}
-
-		mVertChunks = newVertChunks;
-		mFreeVertChunks = freeVertChunks;
-
-		while (!mEmptyVertChunks.empty())
-			mEmptyVertChunks.pop();
-	}
-
-	void MeshHeapCore::growIndexBuffer(UINT32 numIndices)
-	{
-		mNumIndices = numIndices;
-
-		mIndexBuffer = HardwareBufferCoreManager::instance().createIndexBuffer(mIndexType, mNumIndices, GBU_DYNAMIC);
-		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
-
-		// Copy all data to the new buffer
-		UINT32 idxSize = ibProps.getIndexSize();
-
-		UINT8* oldBuffer = mCPUIndexData;
-		UINT8* buffer = (UINT8*)bs_alloc(idxSize * numIndices);
-
-		UINT32 destOffset = 0;
-		if (oldBuffer != nullptr)
-		{
-			for (auto& allocData : mMeshAllocData)
-			{
-				ChunkData& oldChunk = mIdxChunks[allocData.second.idxChunkIdx];
-
-				UINT8* oldData = oldBuffer + oldChunk.start * idxSize;
-				memcpy(buffer + destOffset * idxSize, oldData, oldChunk.size * idxSize);
-
-				destOffset += oldChunk.size;
-			}
-
-			bs_free(oldBuffer);
-		}
-
-		if (destOffset > 0)
-			mIndexBuffer->writeData(0, destOffset * idxSize, buffer, BufferWriteType::NoOverwrite);
-
-		mCPUIndexData = buffer;
-
-		// Reorder chunks
-		destOffset = 0;
-		Vector<ChunkData> newIdxChunks;
-		List<UINT32> freeIdxChunks;
-
-		for (auto& allocData : mMeshAllocData)
-		{
-			ChunkData& oldChunk = mIdxChunks[allocData.second.idxChunkIdx];
-
-			ChunkData newChunk;
-			newChunk.start = destOffset;
-			newChunk.size = oldChunk.size;
-
-			allocData.second.idxChunkIdx = (UINT32)newIdxChunks.size();
-			newIdxChunks.push_back(newChunk);
-
-			destOffset += oldChunk.size;
-		}
-
-		// Add free chunk
-		if (destOffset != mNumIndices)
-		{
-			ChunkData newChunk;
-			newChunk.start = destOffset;
-			newChunk.size = mNumIndices - destOffset;
-
-			newIdxChunks.push_back(newChunk);
-			freeIdxChunks.push_back((UINT32)(newIdxChunks.size() - 1));
-		}
-
-		mIdxChunks = newIdxChunks;
-		mFreeIdxChunks = freeIdxChunks;
-
-		while (!mEmptyIdxChunks.empty())
-			mEmptyIdxChunks.pop();
-	}
-
-	UINT32 MeshHeapCore::createEventQuery()
-	{
-		UINT32 idx = 0;
-		if (mFreeEventQueries.size() > 0)
-		{
-			idx = mFreeEventQueries.top();
-			mFreeEventQueries.pop();
-		}
-		else
-		{
-			QueryData newQuery;
-			newQuery.query = EventQuery::create();
-			newQuery.queryId = 0;
-
-			mEventQueries.push_back(newQuery);
-			idx = (UINT32)(mEventQueries.size() - 1);
-		}
-
-		return idx;
-	}
-
-	void MeshHeapCore::freeEventQuery(UINT32 idx)
-	{
-		mEventQueries[idx].query->onTriggered.clear();
-		mEventQueries[idx].queryId = 0;
-		mFreeEventQueries.push(idx);
-	}
-
-	SPtr<VertexData> MeshHeapCore::getVertexData() const
-	{
-		return mVertexData;
-	}
-
-	SPtr<IndexBufferCore> MeshHeapCore::getIndexBuffer() const
-	{
-		return mIndexBuffer;
-	}
-
-	SPtr<VertexDataDesc> MeshHeapCore::getVertexDesc() const
-	{
-		return mVertexDesc;
-	}
-
-	UINT32 MeshHeapCore::getVertexOffset(UINT32 meshId) const
-	{
-		auto findIter = mMeshAllocData.find(meshId);
-		assert(findIter != mMeshAllocData.end());
-
-		UINT32 chunkIdx = findIter->second.vertChunkIdx;
-		return mVertChunks[chunkIdx].start;
-	}
-
-	UINT32 MeshHeapCore::getIndexOffset(UINT32 meshId) const
-	{
-		auto findIter = mMeshAllocData.find(meshId);
-		assert(findIter != mMeshAllocData.end());
-
-		UINT32 chunkIdx = findIter->second.idxChunkIdx;
-		return mIdxChunks[chunkIdx].start;
-	}
-
-	void MeshHeapCore::notifyUsedOnGPU(UINT32 meshId)
-	{
-		auto findIter = mMeshAllocData.find(meshId);
-		assert(findIter != mMeshAllocData.end());
-
-		AllocatedData& allocData = findIter->second;
-		assert(allocData.useFlags != UseFlags::Free);
-
-		if (allocData.useFlags == UseFlags::GPUFree)
-			allocData.useFlags = UseFlags::Used;
-
-		SPtr<MeshHeapCore> thisPtr = std::static_pointer_cast<MeshHeapCore>(getThisPtr());
-
-		QueryData& queryData = mEventQueries[allocData.eventQueryIdx];
-		queryData.queryId = mNextQueryId++;
-		queryData.query->onTriggered.clear();
-		queryData.query->onTriggered.connect(std::bind(&MeshHeapCore::queryTriggered, thisPtr, meshId, queryData.queryId));
-		queryData.query->begin();
-	}
-
-	// Note: Need to use a shared ptr here to ensure MeshHeap doesn't get deallocated sometime during this callback
-	void MeshHeapCore::queryTriggered(SPtr<MeshHeapCore> thisPtr, UINT32 meshId, UINT32 queryId)
-	{
-		auto findIter = thisPtr->mMeshAllocData.find(meshId);
-		assert(findIter != thisPtr->mMeshAllocData.end());
-
-		AllocatedData& allocData = findIter->second;
-
-		// If query ids don't match then it means there either a more recent query or
-		// the buffer was discarded and we are not interested in query result
-		QueryData& queryData = thisPtr->mEventQueries[allocData.eventQueryIdx];
-		if (queryId == queryData.queryId)
-		{
-			assert(allocData.useFlags != UseFlags::Free && allocData.useFlags != UseFlags::GPUFree);
-
-			if (allocData.useFlags == UseFlags::CPUFree)
-			{
-				allocData.useFlags = UseFlags::Free;
-				thisPtr->freeEventQuery(allocData.eventQueryIdx);
-
-				thisPtr->mFreeVertChunks.push_back(allocData.vertChunkIdx);
-				thisPtr->mFreeIdxChunks.push_back(allocData.idxChunkIdx);
-
-				thisPtr->mergeWithNearbyChunks(allocData.vertChunkIdx, allocData.idxChunkIdx);
-
-				thisPtr->mMeshAllocData.erase(findIter);
-			}
-			else
-				allocData.useFlags = UseFlags::GPUFree;
-		}
-
-		queryData.query->onTriggered.clear();
-	}
-
-	void MeshHeapCore::mergeWithNearbyChunks(UINT32 chunkVertIdx, UINT32 chunkIdxIdx)
-	{
-		// Merge vertex chunks
-		ChunkData& vertChunk = mVertChunks[chunkVertIdx];
-		for (auto& freeChunkIdx : mFreeVertChunks)
-		{
-			if (chunkVertIdx == freeChunkIdx)
-				continue;
-
-			ChunkData& curChunk = mVertChunks[freeChunkIdx];
-			if (curChunk.size == 0) // Already merged
-				continue;
-
-			bool merged = false;
-			if (curChunk.start == (vertChunk.start + vertChunk.size))
-			{
-				vertChunk.size += curChunk.size;
-
-				merged = true;
-			}
-			else if ((curChunk.start + curChunk.size) == vertChunk.start)
-			{
-				vertChunk.start = curChunk.start;
-				vertChunk.size += curChunk.size;
-
-				merged = true;
-			}
-
-			if (merged)
-			{
-				// We can't remove the chunk since that would break the indexing scheme, so 
-				// mark it as empty and set size to 0. It will be reused when needed.
-				curChunk.start = 0;
-				curChunk.size = 0;
-				mEmptyVertChunks.push(freeChunkIdx);
-			}
-		}
-
-		// Merge index chunks
-		ChunkData& idxChunk = mIdxChunks[chunkIdxIdx];
-		for (auto& freeChunkIdx : mFreeIdxChunks)
-		{
-			if (chunkIdxIdx == freeChunkIdx)
-				continue;
-
-			ChunkData& curChunk = mIdxChunks[freeChunkIdx];
-			if (curChunk.size == 0) // Already merged
-				continue;
-
-			bool merged = false;
-			if (curChunk.start == (idxChunk.start + idxChunk.size))
-			{
-				idxChunk.size += curChunk.size;
-
-				merged = true;
-			}
-			else if ((curChunk.start + curChunk.size) == idxChunk.start)
-			{
-				idxChunk.start = curChunk.start;
-				idxChunk.size += curChunk.size;
-
-				merged = true;
-			}
-
-			if (merged)
-			{
-				// We can't remove the chunk since that would break the indexing scheme, so 
-				// mark it as empty and set size to 0. It will be reused when needed.
-				curChunk.start = 0;
-				curChunk.size = 0;
-				mEmptyIdxChunks.push(freeChunkIdx);
-			}
-		}
-	}
-
-	MeshHeap::MeshHeap(UINT32 numVertices, UINT32 numIndices, 
-		const VertexDataDescPtr& vertexDesc, IndexType indexType)
-		:mNumVertices(numVertices), mNumIndices(numIndices), mNextFreeId(0), 
-		mIndexType(indexType), mVertexDesc(vertexDesc)
-	{
-	}
-
-	MeshHeapPtr MeshHeap::create(UINT32 numVertices, UINT32 numIndices, 
-		const VertexDataDescPtr& vertexDesc, IndexType indexType)
-	{
-		MeshHeap* meshHeap = new (bs_alloc<MeshHeap>()) MeshHeap(numVertices, numIndices, vertexDesc, indexType); 
-		MeshHeapPtr meshHeapPtr = bs_core_ptr<MeshHeap>(meshHeap);
-
-		meshHeapPtr->_setThisPtr(meshHeapPtr);
-		meshHeapPtr->initialize();
-
-		return meshHeapPtr;
-	}
-
-	TransientMeshPtr MeshHeap::alloc(const MeshDataPtr& meshData, DrawOperationType drawOp)
-	{
-		UINT32 meshIdx = mNextFreeId++;
-
-		MeshHeapPtr thisPtr = std::static_pointer_cast<MeshHeap>(getThisPtr());
-		TransientMesh* transientMesh = new (bs_alloc<TransientMesh>()) TransientMesh(thisPtr, meshIdx, meshData->getNumVertices(), meshData->getNumIndices(), drawOp); 
-		TransientMeshPtr transientMeshPtr = bs_core_ptr<TransientMesh>(transientMesh);
-
-		transientMeshPtr->_setThisPtr(transientMeshPtr);
-		transientMeshPtr->initialize();
-
-		mMeshes[meshIdx] = transientMeshPtr;
-
-		queueGpuCommand(getCore(), std::bind(&MeshHeapCore::alloc, getCore().get(), transientMeshPtr->getCore(), meshData));
-
-		return transientMeshPtr;
-	}
-
-	void MeshHeap::dealloc(const TransientMeshPtr& mesh)
-	{
-		auto iterFind = mMeshes.find(mesh->mId);
-		if(iterFind == mMeshes.end())
-			return;
-
-		mesh->markAsDestroyed();
-		mMeshes.erase(iterFind);
-
-		queueGpuCommand(getCore(), std::bind(&MeshHeapCore::dealloc, getCore().get(), mesh->getCore()));
-	}
-
-	SPtr<MeshHeapCore> MeshHeap::getCore() const
-	{
-		return std::static_pointer_cast<MeshHeapCore>(mCoreSpecific);
-	}
-
-	SPtr<CoreObjectCore> MeshHeap::createCore() const
-	{
-		MeshHeapCore* obj = new (bs_alloc<MeshHeapCore>()) MeshHeapCore(mNumVertices, mNumIndices,
-			mVertexDesc, mIndexType);
-
-		SPtr<MeshHeapCore> corePtr = bs_shared_ptr<MeshHeapCore>(obj);
-		obj->_setThisPtr(corePtr);
-
-		return corePtr;
-	}
+#include "BsMeshHeap.h"
+#include "BsCoreThread.h"
+#include "BsTransientMesh.h"
+#include "BsHardwareBufferManager.h"
+#include "BsVertexDataDesc.h"
+#include "BsVertexData.h"
+#include "BsMeshData.h"
+#include "BsMath.h"
+#include "BsEventQuery.h"
+#include "BsRenderAPI.h"
+
+namespace BansheeEngine
+{
+	const float MeshHeapCore::GrowPercent = 1.5f;
+
+	MeshHeapCore::MeshHeapCore(UINT32 numVertices, UINT32 numIndices,
+		const VertexDataDescPtr& vertexDesc, IndexType indexType)
+		:mNumVertices(numVertices), mNumIndices(numIndices), mIndexType(indexType), 
+		mVertexDesc(vertexDesc), mCPUIndexData(nullptr), mNextQueryId(0)
+	{
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			mCPUVertexData.push_back(nullptr);
+		}
+	}
+
+	MeshHeapCore::~MeshHeapCore()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		for (auto& cpuVertBuffer : mCPUVertexData)
+			bs_free(cpuVertBuffer);
+
+		if (mCPUIndexData != nullptr)
+			bs_free(mCPUIndexData);
+
+		mVertexData = nullptr;
+		mIndexBuffer = nullptr;
+		mVertexDesc = nullptr;
+	}
+
+	void MeshHeapCore::initialize()
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		growVertexBuffer(mNumVertices);
+		growIndexBuffer(mNumIndices);
+
+		CoreObjectCore::initialize();
+	}
+
+	void MeshHeapCore::alloc(SPtr<TransientMeshCore> mesh, const MeshDataPtr& meshData)
+	{
+		// Find free vertex chunk and grow if needed
+		UINT32 smallestVertFit = 0;
+		UINT32 smallestVertFitIdx = 0;
+
+		while (smallestVertFit == 0)
+		{
+			UINT32 curIdx = 0;
+			for (auto& chunkIdx : mFreeVertChunks)
+			{
+				ChunkData& chunk = mVertChunks[chunkIdx];
+
+				if (chunk.size >= meshData->getNumVertices() && (chunk.size < smallestVertFit || smallestVertFit == 0))
+				{
+					smallestVertFit = chunk.size;
+					smallestVertFitIdx = curIdx;
+				}
+
+				curIdx++;
+			}
+
+			if (smallestVertFit > 0)
+				break;
+
+			UINT32 newNumVertices = mNumVertices;
+			while (newNumVertices < (mNumVertices + meshData->getNumVertices()))
+			{
+				newNumVertices = Math::roundToInt(newNumVertices * GrowPercent);
+			}
+
+			growVertexBuffer(newNumVertices);
+		}
+
+		// Find free index chunk and grow if needed
+		UINT32 smallestIdxFit = 0;
+		UINT32 smallestIdxFitIdx = 0;
+
+		while (smallestIdxFit == 0)
+		{
+			UINT32 curIdx = 0;
+			for (auto& chunkIdx : mFreeIdxChunks)
+			{
+				ChunkData& chunk = mIdxChunks[chunkIdx];
+
+				if (chunk.size >= meshData->getNumIndices() && (chunk.size < smallestIdxFit || smallestIdxFit == 0))
+				{
+					smallestIdxFit = chunk.size;
+					smallestIdxFitIdx = curIdx;
+				}
+
+				curIdx++;
+			}
+
+			if (smallestIdxFit > 0)
+				break;
+
+			UINT32 newNumIndices = mNumIndices;
+			while (newNumIndices < (mNumIndices + meshData->getNumIndices()))
+			{
+				newNumIndices = Math::roundToInt(newNumIndices * GrowPercent);
+			}
+
+			growIndexBuffer(newNumIndices);
+		}
+
+		UINT32 freeVertChunkIdx = 0;
+		UINT32 freeIdxChunkIdx = 0;
+
+		auto freeVertIter = mFreeVertChunks.begin();
+		freeVertChunkIdx = (*freeVertIter);
+		for (UINT32 i = 0; i < smallestVertFitIdx; i++)
+		{
+			freeVertIter++;
+			freeVertChunkIdx = (*freeVertIter);
+		}
+
+		mFreeVertChunks.erase(freeVertIter);
+
+		auto freeIdxIter = mFreeIdxChunks.begin();
+		freeIdxChunkIdx = (*freeIdxIter);
+		for (UINT32 i = 0; i < smallestIdxFitIdx; i++)
+		{
+			freeIdxIter++;
+			freeIdxChunkIdx = (*freeIdxIter);
+		}
+
+		mFreeIdxChunks.erase(freeIdxIter);
+
+		ChunkData& vertChunk = mVertChunks[freeVertChunkIdx];
+		ChunkData& idxChunk = mIdxChunks[freeIdxChunkIdx];
+
+		UINT32 vertChunkStart = vertChunk.start;
+		UINT32 idxChunkStart = idxChunk.start;
+
+		UINT32 remainingNumVerts = vertChunk.size - meshData->getNumVertices();
+		UINT32 remainingNumIdx = idxChunk.size - meshData->getNumIndices();
+
+		vertChunk.size = meshData->getNumVertices();
+		idxChunk.size = meshData->getNumIndices();
+
+		if (remainingNumVerts > 0)
+		{
+			if (!mEmptyVertChunks.empty())
+			{
+				UINT32 emptyChunkIdx = mEmptyVertChunks.top();
+				ChunkData& emptyChunk = mVertChunks[emptyChunkIdx];
+				mEmptyVertChunks.pop();
+
+				emptyChunk.start = vertChunkStart + meshData->getNumVertices();
+				emptyChunk.size = remainingNumVerts;
+			}
+			else
+			{
+				ChunkData newChunk;
+				newChunk.size = remainingNumVerts;
+				newChunk.start = vertChunkStart + meshData->getNumVertices();
+
+				mVertChunks.push_back(newChunk);
+				mFreeVertChunks.push_back((UINT32)(mVertChunks.size() - 1));
+			}
+		}
+
+		if (remainingNumIdx > 0)
+		{
+			if (!mEmptyIdxChunks.empty())
+			{
+				UINT32 emptyChunkIdx = mEmptyIdxChunks.top();
+				ChunkData& emptyChunk = mIdxChunks[emptyChunkIdx];
+				mEmptyIdxChunks.pop();
+
+				emptyChunk.start = idxChunkStart + meshData->getNumIndices();
+				emptyChunk.size = remainingNumIdx;
+			}
+			else
+			{
+				ChunkData newChunk;
+				newChunk.size = remainingNumIdx;
+				newChunk.start = idxChunkStart + meshData->getNumIndices();
+
+				mIdxChunks.push_back(newChunk);
+				mFreeIdxChunks.push_back((UINT32)(mIdxChunks.size() - 1));
+			}
+		}
+
+		AllocatedData newAllocData;
+		newAllocData.vertChunkIdx = freeVertChunkIdx;
+		newAllocData.idxChunkIdx = freeIdxChunkIdx;
+		newAllocData.useFlags = UseFlags::GPUFree;
+		newAllocData.eventQueryIdx = createEventQuery();
+		newAllocData.mesh = mesh;
+
+		mMeshAllocData[mesh->getMeshHeapId()] = newAllocData;
+
+		// Actually copy data
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			if (!mVertexDesc->hasStream(i))
+				continue;
+
+			if (!meshData->getVertexDesc()->hasStream(i))
+				continue;
+
+			// Ensure vertex sizes match
+			UINT32 vertSize = mVertexData->vertexDeclaration->getProperties().getVertexSize(i);
+			UINT32 otherVertSize = meshData->getVertexDesc()->getVertexStride(i);
+			if (otherVertSize != vertSize)
+			{
+				BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(i) + " doesn't match meshes vertex size. Needed: " +
+					toString(vertSize) + ". Got: " + toString(otherVertSize));
+			}
+
+			SPtr<VertexBufferCore> vertexBuffer = mVertexData->getBuffer(i);
+			const VertexBufferProperties& vbProps = vertexBuffer->getProperties();
+
+			UINT8* vertDest = mCPUVertexData[i] + vertChunkStart * vertSize;
+			memcpy(vertDest, meshData->getStreamData(i), meshData->getNumVertices() * vertSize);
+
+			if (RenderAPICore::instance().getVertexColorFlipRequired())
+			{
+				UINT32 vertexStride = mVertexDesc->getVertexStride(i);
+				for (INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
+				{
+					if (!mVertexDesc->hasElement(VES_COLOR, semanticIdx, i))
+						continue;
+
+					UINT8* colorData = vertDest + mVertexDesc->getElementOffsetFromStream(VES_COLOR, semanticIdx, i);
+					for (UINT32 j = 0; j < meshData->getNumVertices(); j++)
+					{
+						UINT32* curColor = (UINT32*)colorData;
+
+						(*curColor) = ((*curColor) & 0xFF00FF00) | ((*curColor >> 16) & 0x000000FF) | ((*curColor << 16) & 0x00FF0000);
+
+						colorData += vertexStride;
+					}
+				}
+			}
+
+			vertexBuffer->writeData(vertChunkStart * vertSize, meshData->getNumVertices() * vertSize, vertDest, BufferWriteType::NoOverwrite);
+		}
+
+		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
+
+		UINT32 idxSize = ibProps.getIndexSize();
+
+		// Ensure index sizes match
+		if (meshData->getIndexElementSize() != idxSize)
+		{
+			BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
+				toString(idxSize) + ". Got: " + toString(meshData->getIndexElementSize()));
+		}
+
+		UINT8* idxDest = mCPUIndexData + idxChunkStart * idxSize;
+		memcpy(idxDest, meshData->getIndexData(), meshData->getNumIndices() * idxSize);
+		mIndexBuffer->writeData(idxChunkStart * idxSize, meshData->getNumIndices() * idxSize, idxDest, BufferWriteType::NoOverwrite);
+	}
+
+	void MeshHeapCore::dealloc(SPtr<TransientMeshCore> mesh)
+	{
+		auto findIter = mMeshAllocData.find(mesh->getMeshHeapId());
+		assert(findIter != mMeshAllocData.end());
+
+		AllocatedData& allocData = findIter->second;
+		if (allocData.useFlags == UseFlags::GPUFree)
+		{
+			allocData.useFlags = UseFlags::Free;
+			freeEventQuery(allocData.eventQueryIdx);
+
+			mFreeVertChunks.push_back(allocData.vertChunkIdx);
+			mFreeIdxChunks.push_back(allocData.idxChunkIdx);
+
+			mergeWithNearbyChunks(allocData.vertChunkIdx, allocData.idxChunkIdx);
+
+			mMeshAllocData.erase(findIter);
+		}
+		else if (allocData.useFlags == UseFlags::Used)
+			allocData.useFlags = UseFlags::CPUFree;
+	}
+
+	void MeshHeapCore::growVertexBuffer(UINT32 numVertices)
+	{
+		mNumVertices = numVertices;
+		mVertexData = std::shared_ptr<VertexData>(bs_new<VertexData>());
+
+		mVertexData->vertexCount = mNumVertices;
+		List<VertexElement> elements = mVertexDesc->createElements();
+
+		mVertexData->vertexDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(elements);
+
+		// Create buffers and copy data
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		{
+			if (!mVertexDesc->hasStream(i))
+				continue;
+
+			UINT32 vertSize = mVertexData->vertexDeclaration->getProperties().getVertexSize(i);
+			SPtr<VertexBufferCore> vertexBuffer = HardwareBufferCoreManager::instance().createVertexBuffer(
+				vertSize, mVertexData->vertexCount, GBU_DYNAMIC);
+
+			mVertexData->setBuffer(i, vertexBuffer);
+
+			// Copy all data to the new buffer
+			UINT8* oldBuffer = mCPUVertexData[i];
+			UINT8* buffer = (UINT8*)bs_alloc(vertSize * numVertices);
+
+			UINT32 destOffset = 0;
+			if (oldBuffer != nullptr)
+			{
+				for (auto& allocData : mMeshAllocData)
+				{
+					ChunkData& oldChunk = mVertChunks[allocData.second.vertChunkIdx];
+
+					UINT8* oldData = oldBuffer + oldChunk.start * vertSize;
+					memcpy(buffer + destOffset * vertSize, oldData, oldChunk.size * vertSize);
+
+					destOffset += oldChunk.size;
+				}
+
+				bs_free(oldBuffer);
+			}
+
+			if (destOffset > 0)
+				vertexBuffer->writeData(0, destOffset * vertSize, buffer, BufferWriteType::NoOverwrite);
+
+			mCPUVertexData[i] = buffer;
+		}
+
+		// Reorder chunks
+		UINT32 destOffset = 0;
+		Vector<ChunkData> newVertChunks;
+		List<UINT32> freeVertChunks;
+
+		for (auto& allocData : mMeshAllocData)
+		{
+			ChunkData& oldChunk = mVertChunks[allocData.second.vertChunkIdx];
+
+			ChunkData newChunk;
+			newChunk.start = destOffset;
+			newChunk.size = oldChunk.size;
+
+			allocData.second.vertChunkIdx = (UINT32)newVertChunks.size();
+			newVertChunks.push_back(newChunk);
+
+			destOffset += oldChunk.size;
+		}
+
+		// Add free chunk
+		if (destOffset != mNumVertices)
+		{
+			ChunkData newChunk;
+			newChunk.start = destOffset;
+			newChunk.size = mNumVertices - destOffset;
+
+			newVertChunks.push_back(newChunk);
+			freeVertChunks.push_back((UINT32)(newVertChunks.size() - 1));
+		}
+
+		mVertChunks = newVertChunks;
+		mFreeVertChunks = freeVertChunks;
+
+		while (!mEmptyVertChunks.empty())
+			mEmptyVertChunks.pop();
+	}
+
+	void MeshHeapCore::growIndexBuffer(UINT32 numIndices)
+	{
+		mNumIndices = numIndices;
+
+		mIndexBuffer = HardwareBufferCoreManager::instance().createIndexBuffer(mIndexType, mNumIndices, GBU_DYNAMIC);
+		const IndexBufferProperties& ibProps = mIndexBuffer->getProperties();
+
+		// Copy all data to the new buffer
+		UINT32 idxSize = ibProps.getIndexSize();
+
+		UINT8* oldBuffer = mCPUIndexData;
+		UINT8* buffer = (UINT8*)bs_alloc(idxSize * numIndices);
+
+		UINT32 destOffset = 0;
+		if (oldBuffer != nullptr)
+		{
+			for (auto& allocData : mMeshAllocData)
+			{
+				ChunkData& oldChunk = mIdxChunks[allocData.second.idxChunkIdx];
+
+				UINT8* oldData = oldBuffer + oldChunk.start * idxSize;
+				memcpy(buffer + destOffset * idxSize, oldData, oldChunk.size * idxSize);
+
+				destOffset += oldChunk.size;
+			}
+
+			bs_free(oldBuffer);
+		}
+
+		if (destOffset > 0)
+			mIndexBuffer->writeData(0, destOffset * idxSize, buffer, BufferWriteType::NoOverwrite);
+
+		mCPUIndexData = buffer;
+
+		// Reorder chunks
+		destOffset = 0;
+		Vector<ChunkData> newIdxChunks;
+		List<UINT32> freeIdxChunks;
+
+		for (auto& allocData : mMeshAllocData)
+		{
+			ChunkData& oldChunk = mIdxChunks[allocData.second.idxChunkIdx];
+
+			ChunkData newChunk;
+			newChunk.start = destOffset;
+			newChunk.size = oldChunk.size;
+
+			allocData.second.idxChunkIdx = (UINT32)newIdxChunks.size();
+			newIdxChunks.push_back(newChunk);
+
+			destOffset += oldChunk.size;
+		}
+
+		// Add free chunk
+		if (destOffset != mNumIndices)
+		{
+			ChunkData newChunk;
+			newChunk.start = destOffset;
+			newChunk.size = mNumIndices - destOffset;
+
+			newIdxChunks.push_back(newChunk);
+			freeIdxChunks.push_back((UINT32)(newIdxChunks.size() - 1));
+		}
+
+		mIdxChunks = newIdxChunks;
+		mFreeIdxChunks = freeIdxChunks;
+
+		while (!mEmptyIdxChunks.empty())
+			mEmptyIdxChunks.pop();
+	}
+
+	UINT32 MeshHeapCore::createEventQuery()
+	{
+		UINT32 idx = 0;
+		if (mFreeEventQueries.size() > 0)
+		{
+			idx = mFreeEventQueries.top();
+			mFreeEventQueries.pop();
+		}
+		else
+		{
+			QueryData newQuery;
+			newQuery.query = EventQuery::create();
+			newQuery.queryId = 0;
+
+			mEventQueries.push_back(newQuery);
+			idx = (UINT32)(mEventQueries.size() - 1);
+		}
+
+		return idx;
+	}
+
+	void MeshHeapCore::freeEventQuery(UINT32 idx)
+	{
+		mEventQueries[idx].query->onTriggered.clear();
+		mEventQueries[idx].queryId = 0;
+		mFreeEventQueries.push(idx);
+	}
+
+	SPtr<VertexData> MeshHeapCore::getVertexData() const
+	{
+		return mVertexData;
+	}
+
+	SPtr<IndexBufferCore> MeshHeapCore::getIndexBuffer() const
+	{
+		return mIndexBuffer;
+	}
+
+	SPtr<VertexDataDesc> MeshHeapCore::getVertexDesc() const
+	{
+		return mVertexDesc;
+	}
+
+	UINT32 MeshHeapCore::getVertexOffset(UINT32 meshId) const
+	{
+		auto findIter = mMeshAllocData.find(meshId);
+		assert(findIter != mMeshAllocData.end());
+
+		UINT32 chunkIdx = findIter->second.vertChunkIdx;
+		return mVertChunks[chunkIdx].start;
+	}
+
+	UINT32 MeshHeapCore::getIndexOffset(UINT32 meshId) const
+	{
+		auto findIter = mMeshAllocData.find(meshId);
+		assert(findIter != mMeshAllocData.end());
+
+		UINT32 chunkIdx = findIter->second.idxChunkIdx;
+		return mIdxChunks[chunkIdx].start;
+	}
+
+	void MeshHeapCore::notifyUsedOnGPU(UINT32 meshId)
+	{
+		auto findIter = mMeshAllocData.find(meshId);
+		assert(findIter != mMeshAllocData.end());
+
+		AllocatedData& allocData = findIter->second;
+		assert(allocData.useFlags != UseFlags::Free);
+
+		if (allocData.useFlags == UseFlags::GPUFree)
+			allocData.useFlags = UseFlags::Used;
+
+		SPtr<MeshHeapCore> thisPtr = std::static_pointer_cast<MeshHeapCore>(getThisPtr());
+
+		QueryData& queryData = mEventQueries[allocData.eventQueryIdx];
+		queryData.queryId = mNextQueryId++;
+		queryData.query->onTriggered.clear();
+		queryData.query->onTriggered.connect(std::bind(&MeshHeapCore::queryTriggered, thisPtr, meshId, queryData.queryId));
+		queryData.query->begin();
+	}
+
+	// Note: Need to use a shared ptr here to ensure MeshHeap doesn't get deallocated sometime during this callback
+	void MeshHeapCore::queryTriggered(SPtr<MeshHeapCore> thisPtr, UINT32 meshId, UINT32 queryId)
+	{
+		auto findIter = thisPtr->mMeshAllocData.find(meshId);
+		assert(findIter != thisPtr->mMeshAllocData.end());
+
+		AllocatedData& allocData = findIter->second;
+
+		// If query ids don't match then it means there either a more recent query or
+		// the buffer was discarded and we are not interested in query result
+		QueryData& queryData = thisPtr->mEventQueries[allocData.eventQueryIdx];
+		if (queryId == queryData.queryId)
+		{
+			assert(allocData.useFlags != UseFlags::Free && allocData.useFlags != UseFlags::GPUFree);
+
+			if (allocData.useFlags == UseFlags::CPUFree)
+			{
+				allocData.useFlags = UseFlags::Free;
+				thisPtr->freeEventQuery(allocData.eventQueryIdx);
+
+				thisPtr->mFreeVertChunks.push_back(allocData.vertChunkIdx);
+				thisPtr->mFreeIdxChunks.push_back(allocData.idxChunkIdx);
+
+				thisPtr->mergeWithNearbyChunks(allocData.vertChunkIdx, allocData.idxChunkIdx);
+
+				thisPtr->mMeshAllocData.erase(findIter);
+			}
+			else
+				allocData.useFlags = UseFlags::GPUFree;
+		}
+
+		queryData.query->onTriggered.clear();
+	}
+
+	void MeshHeapCore::mergeWithNearbyChunks(UINT32 chunkVertIdx, UINT32 chunkIdxIdx)
+	{
+		// Merge vertex chunks
+		ChunkData& vertChunk = mVertChunks[chunkVertIdx];
+		for (auto& freeChunkIdx : mFreeVertChunks)
+		{
+			if (chunkVertIdx == freeChunkIdx)
+				continue;
+
+			ChunkData& curChunk = mVertChunks[freeChunkIdx];
+			if (curChunk.size == 0) // Already merged
+				continue;
+
+			bool merged = false;
+			if (curChunk.start == (vertChunk.start + vertChunk.size))
+			{
+				vertChunk.size += curChunk.size;
+
+				merged = true;
+			}
+			else if ((curChunk.start + curChunk.size) == vertChunk.start)
+			{
+				vertChunk.start = curChunk.start;
+				vertChunk.size += curChunk.size;
+
+				merged = true;
+			}
+
+			if (merged)
+			{
+				// We can't remove the chunk since that would break the indexing scheme, so 
+				// mark it as empty and set size to 0. It will be reused when needed.
+				curChunk.start = 0;
+				curChunk.size = 0;
+				mEmptyVertChunks.push(freeChunkIdx);
+			}
+		}
+
+		// Merge index chunks
+		ChunkData& idxChunk = mIdxChunks[chunkIdxIdx];
+		for (auto& freeChunkIdx : mFreeIdxChunks)
+		{
+			if (chunkIdxIdx == freeChunkIdx)
+				continue;
+
+			ChunkData& curChunk = mIdxChunks[freeChunkIdx];
+			if (curChunk.size == 0) // Already merged
+				continue;
+
+			bool merged = false;
+			if (curChunk.start == (idxChunk.start + idxChunk.size))
+			{
+				idxChunk.size += curChunk.size;
+
+				merged = true;
+			}
+			else if ((curChunk.start + curChunk.size) == idxChunk.start)
+			{
+				idxChunk.start = curChunk.start;
+				idxChunk.size += curChunk.size;
+
+				merged = true;
+			}
+
+			if (merged)
+			{
+				// We can't remove the chunk since that would break the indexing scheme, so 
+				// mark it as empty and set size to 0. It will be reused when needed.
+				curChunk.start = 0;
+				curChunk.size = 0;
+				mEmptyIdxChunks.push(freeChunkIdx);
+			}
+		}
+	}
+
+	MeshHeap::MeshHeap(UINT32 numVertices, UINT32 numIndices, 
+		const VertexDataDescPtr& vertexDesc, IndexType indexType)
+		:mNumVertices(numVertices), mNumIndices(numIndices), mNextFreeId(0), 
+		mIndexType(indexType), mVertexDesc(vertexDesc)
+	{
+	}
+
+	MeshHeapPtr MeshHeap::create(UINT32 numVertices, UINT32 numIndices, 
+		const VertexDataDescPtr& vertexDesc, IndexType indexType)
+	{
+		MeshHeap* meshHeap = new (bs_alloc<MeshHeap>()) MeshHeap(numVertices, numIndices, vertexDesc, indexType); 
+		MeshHeapPtr meshHeapPtr = bs_core_ptr<MeshHeap>(meshHeap);
+
+		meshHeapPtr->_setThisPtr(meshHeapPtr);
+		meshHeapPtr->initialize();
+
+		return meshHeapPtr;
+	}
+
+	TransientMeshPtr MeshHeap::alloc(const MeshDataPtr& meshData, DrawOperationType drawOp)
+	{
+		UINT32 meshIdx = mNextFreeId++;
+
+		MeshHeapPtr thisPtr = std::static_pointer_cast<MeshHeap>(getThisPtr());
+		TransientMesh* transientMesh = new (bs_alloc<TransientMesh>()) TransientMesh(thisPtr, meshIdx, meshData->getNumVertices(), meshData->getNumIndices(), drawOp); 
+		TransientMeshPtr transientMeshPtr = bs_core_ptr<TransientMesh>(transientMesh);
+
+		transientMeshPtr->_setThisPtr(transientMeshPtr);
+		transientMeshPtr->initialize();
+
+		mMeshes[meshIdx] = transientMeshPtr;
+
+		queueGpuCommand(getCore(), std::bind(&MeshHeapCore::alloc, getCore().get(), transientMeshPtr->getCore(), meshData));
+
+		return transientMeshPtr;
+	}
+
+	void MeshHeap::dealloc(const TransientMeshPtr& mesh)
+	{
+		auto iterFind = mMeshes.find(mesh->mId);
+		if(iterFind == mMeshes.end())
+			return;
+
+		mesh->markAsDestroyed();
+		mMeshes.erase(iterFind);
+
+		queueGpuCommand(getCore(), std::bind(&MeshHeapCore::dealloc, getCore().get(), mesh->getCore()));
+	}
+
+	SPtr<MeshHeapCore> MeshHeap::getCore() const
+	{
+		return std::static_pointer_cast<MeshHeapCore>(mCoreSpecific);
+	}
+
+	SPtr<CoreObjectCore> MeshHeap::createCore() const
+	{
+		MeshHeapCore* obj = new (bs_alloc<MeshHeapCore>()) MeshHeapCore(mNumVertices, mNumIndices,
+			mVertexDesc, mIndexType);
+
+		SPtr<MeshHeapCore> corePtr = bs_shared_ptr<MeshHeapCore>(obj);
+		obj->_setThisPtr(corePtr);
+
+		return corePtr;
+	}
 }
 }

+ 0 - 1
BansheeCore/Source/BsPixelVolume.cpp

@@ -1 +0,0 @@
-#include "BsPixelVolume.h"

+ 1 - 13
BansheeEditor/Source/BsBuiltinEditorResources.cpp

@@ -1,7 +1,6 @@
 #include "BsBuiltinEditorResources.h"
 #include "BsBuiltinEditorResources.h"
 #include "BsBuiltinResources.h"
 #include "BsBuiltinResources.h"
 #include "BsGUIElementStyle.h"
 #include "BsGUIElementStyle.h"
-
 #include "BsGUILabel.h"
 #include "BsGUILabel.h"
 #include "BsGUITexture.h"
 #include "BsGUITexture.h"
 #include "BsGUIButton.h"
 #include "BsGUIButton.h"
@@ -11,7 +10,6 @@
 #include "BsTextSprite.h"
 #include "BsTextSprite.h"
 #include "BsSpriteTexture.h"
 #include "BsSpriteTexture.h"
 #include "BsGUITreeViewEditBox.h"
 #include "BsGUITreeViewEditBox.h"
-
 #include "BsGUIIntField.h"
 #include "BsGUIIntField.h"
 #include "BsGUIFloatField.h"
 #include "BsGUIFloatField.h"
 #include "BsGUIColorField.h"
 #include "BsGUIColorField.h"
@@ -29,21 +27,11 @@
 #include "BsGUIMenuBar.h"
 #include "BsGUIMenuBar.h"
 #include "BsGUIListBox.h"
 #include "BsGUIListBox.h"
 #include "BsCoreThread.h"
 #include "BsCoreThread.h"
-
 #include "BsFont.h"
 #include "BsFont.h"
-#include "BsFontImportOptions.h"
-#include "BsImporter.h"
-#include "BsGpuProgram.h"
+#include "BsTexture.h"
 #include "BsShader.h"
 #include "BsShader.h"
-#include "BsShaderInclude.h"
-#include "BsTechnique.h"
-#include "BsPass.h"
 #include "BsMaterial.h"
 #include "BsMaterial.h"
-#include "BsBlendState.h"
-#include "BsDepthStencilState.h"
-#include "BsRasterizerState.h"
 #include "BsResources.h"
 #include "BsResources.h"
-#include "BsRTTIType.h"
 #include "BsFileSystem.h"
 #include "BsFileSystem.h"
 #include "BsResourceManifest.h"
 #include "BsResourceManifest.h"
 #include "BsDataStream.h"
 #include "BsDataStream.h"

+ 1 - 10
BansheeEngine/Source/BsBuiltinResources.cpp

@@ -1,6 +1,5 @@
 #include "BsBuiltinResources.h"
 #include "BsBuiltinResources.h"
 #include "BsGUIElementStyle.h"
 #include "BsGUIElementStyle.h"
-
 #include "BsGUILabel.h"
 #include "BsGUILabel.h"
 #include "BsGUIButton.h"
 #include "BsGUIButton.h"
 #include "BsGUIInputBox.h"
 #include "BsGUIInputBox.h"
@@ -8,26 +7,18 @@
 #include "BsGUIDropDownContent.h"
 #include "BsGUIDropDownContent.h"
 #include "BsTextSprite.h"
 #include "BsTextSprite.h"
 #include "BsSpriteTexture.h"
 #include "BsSpriteTexture.h"
-
 #include "BsFont.h"
 #include "BsFont.h"
 #include "BsFontImportOptions.h"
 #include "BsFontImportOptions.h"
+#include "BsTexture.h"
 #include "BsImporter.h"
 #include "BsImporter.h"
 #include "BsResources.h"
 #include "BsResources.h"
-#include "BsGpuProgram.h"
 #include "BsShader.h"
 #include "BsShader.h"
-#include "BsShaderInclude.h"
-#include "BsTechnique.h"
-#include "BsPass.h"
 #include "BsMaterial.h"
 #include "BsMaterial.h"
-#include "BsBlendState.h"
-#include "BsDepthStencilState.h"
 #include "BsRTTIType.h"
 #include "BsRTTIType.h"
 #include "BsFileSystem.h"
 #include "BsFileSystem.h"
 #include "BsCoreApplication.h"
 #include "BsCoreApplication.h"
 #include "BsCoreThread.h"
 #include "BsCoreThread.h"
-#include "BsApplication.h"
 #include "BsDataStream.h"
 #include "BsDataStream.h"
-#include "BsTime.h"
 #include "BsResourceManifest.h"
 #include "BsResourceManifest.h"
 #include "BsVertexDataDesc.h"
 #include "BsVertexDataDesc.h"
 #include "BsShapeMeshes3D.h"
 #include "BsShapeMeshes3D.h"

+ 2 - 0
BansheeEngine/Source/BsGUIManager.cpp

@@ -37,6 +37,8 @@
 #include "BsCamera.h"
 #include "BsCamera.h"
 #include "BsGUITooltipManager.h"
 #include "BsGUITooltipManager.h"
 #include "BsRendererUtility.h"
 #include "BsRendererUtility.h"
+#include "BsTexture.h"
+#include "BsRenderTexture.h"
 
 
 using namespace std::placeholders;
 using namespace std::placeholders;
 
 

+ 138 - 137
Game/Source/Main.cpp

@@ -1,138 +1,139 @@
-#include "BsApplication.h"
-#include "BsCrashHandler.h"
-#include "BsCoreThread.h"
-#include "BsFileSerializer.h"
-#include "BsGameSettings.h"
-#include "BsFileSystem.h"
-#include "BsResources.h"
-#include "BsResourceManifest.h"
-#include "BsPrefab.h"
-#include "BsSceneObject.h"
-#include "BsSceneManager.h"
-
-void runApplication();
-
-#if BS_PLATFORM == BS_PLATFORM_WIN32
-#include <windows.h>
-
-using namespace BansheeEngine;
-
-int CALLBACK WinMain(
-	_In_  HINSTANCE hInstance,
-	_In_  HINSTANCE hPrevInstance,
-	_In_  LPSTR lpCmdLine,
-	_In_  int nCmdShow
-	)
-{
-	CrashHandler::startUp();
-
-	__try
-	{
-		runApplication();
-	}
-	__except (gCrashHandler().reportCrash(GetExceptionInformation()))
-	{
-		PlatformUtility::terminate(true);
-	}
-
-	CrashHandler::shutDown();
-
-	return 0;
-}
-#endif // End BS_PLATFORM
-
-using namespace BansheeEngine;
-
-void runApplication()
-{
-	Path gameSettingsPath = Paths::getGameSettingsPath();
-
-	FileDecoder fd(gameSettingsPath);
-	SPtr<GameSettings> gameSettings = std::static_pointer_cast<GameSettings>(fd.decode());
-
-	if (gameSettings == nullptr)
-		gameSettings = bs_shared_ptr_new<GameSettings>();
-
-	unsigned int resolutionWidth = 200;
-	unsigned int resolutionHeight = 200;
-
-	if (!gameSettings->fullscreen)
-	{
-		resolutionWidth = gameSettings->resolutionWidth;
-		resolutionHeight = gameSettings->resolutionHeight;
-	}
-
-	RENDER_WINDOW_DESC renderWindowDesc;
-	renderWindowDesc.videoMode = VideoMode(resolutionWidth, resolutionHeight);
-	renderWindowDesc.title = toString(gameSettings->titleBarText);
-	renderWindowDesc.fullscreen = false;
-	renderWindowDesc.hidden = gameSettings->fullscreen;
-
-	Application::startUp(renderWindowDesc, RenderAPIPlugin::DX11);
-
-	if (gameSettings->fullscreen)
-	{
-		if (gameSettings->useDesktopResolution)
-		{
-			const VideoModeInfo& videoModeInfo = RenderAPI::getVideoModeInfo();
-			const VideoOutputInfo& primaryMonitorInfo = videoModeInfo.getOutputInfo(0);
-			const VideoMode& selectedVideoMode = primaryMonitorInfo.getDesktopVideoMode();
-
-			RenderWindowPtr window = gApplication().getPrimaryWindow();
-			window->setFullscreen(gCoreAccessor(), selectedVideoMode);
-
-			resolutionWidth = selectedVideoMode.getWidth();
-			resolutionHeight = selectedVideoMode.getHeight();
-		}
-		else
-		{
-			resolutionWidth = gameSettings->resolutionWidth;
-			resolutionHeight = gameSettings->resolutionHeight;
-
-			VideoMode videoMode(resolutionWidth, resolutionHeight);
-
-			RenderWindowPtr window = gApplication().getPrimaryWindow();
-			window->show(gCoreAccessor());
-			window->setFullscreen(gCoreAccessor(), videoMode);
-		}
-	}
-
-	gameSettings->useDesktopResolution = false; // Not relevant after first startup
-
-	// TODO - Save full video mode
-	gameSettings->resolutionWidth = resolutionWidth;
-	gameSettings->resolutionHeight = resolutionHeight;
-
-	FileEncoder fe(gameSettingsPath);
-	fe.encode(gameSettings.get());
-
-	Path resourcesPath = Paths::getGameResourcesPath();
-	Path resourceManifestPath = resourcesPath + GAME_RESOURCE_MANIFEST_NAME;
-
-	ResourceManifestPtr manifest;
-	if (FileSystem::exists(resourceManifestPath))
-	{
-		Path resourceRoot = FileSystem::getWorkingDirectoryPath();
-		resourceRoot.append(resourcesPath);
-		resourceRoot.makeParent(); // Remove /Resources entry, as we expect all resources to be relative to that path
-
-		manifest = ResourceManifest::load(resourceManifestPath, resourceRoot);
-
-		gResources().registerResourceManifest(manifest);
-	}
-
-	{
-		HPrefab mainScene = static_resource_cast<Prefab>(gResources().loadFromUUID(gameSettings->mainSceneUUID, false, true, false));
-		if (mainScene != nullptr)
-		{
-			HSceneObject root = mainScene->instantiate();
-			HSceneObject oldRoot = gSceneManager().getRootNode();
-
-			gSceneManager()._setRootNode(root);
-			oldRoot->destroy();
-		}
-	}
-
-	Application::instance().runMainLoop();
-	Application::shutDown();
+#include "BsApplication.h"
+#include "BsCrashHandler.h"
+#include "BsCoreThread.h"
+#include "BsFileSerializer.h"
+#include "BsGameSettings.h"
+#include "BsFileSystem.h"
+#include "BsResources.h"
+#include "BsResourceManifest.h"
+#include "BsPrefab.h"
+#include "BsSceneObject.h"
+#include "BsSceneManager.h"
+#include "BsRenderAPI.h"
+
+void runApplication();
+
+#if BS_PLATFORM == BS_PLATFORM_WIN32
+#include <windows.h>
+
+using namespace BansheeEngine;
+
+int CALLBACK WinMain(
+	_In_  HINSTANCE hInstance,
+	_In_  HINSTANCE hPrevInstance,
+	_In_  LPSTR lpCmdLine,
+	_In_  int nCmdShow
+	)
+{
+	CrashHandler::startUp();
+
+	__try
+	{
+		runApplication();
+	}
+	__except (gCrashHandler().reportCrash(GetExceptionInformation()))
+	{
+		PlatformUtility::terminate(true);
+	}
+
+	CrashHandler::shutDown();
+
+	return 0;
+}
+#endif // End BS_PLATFORM
+
+using namespace BansheeEngine;
+
+void runApplication()
+{
+	Path gameSettingsPath = Paths::getGameSettingsPath();
+
+	FileDecoder fd(gameSettingsPath);
+	SPtr<GameSettings> gameSettings = std::static_pointer_cast<GameSettings>(fd.decode());
+
+	if (gameSettings == nullptr)
+		gameSettings = bs_shared_ptr_new<GameSettings>();
+
+	unsigned int resolutionWidth = 200;
+	unsigned int resolutionHeight = 200;
+
+	if (!gameSettings->fullscreen)
+	{
+		resolutionWidth = gameSettings->resolutionWidth;
+		resolutionHeight = gameSettings->resolutionHeight;
+	}
+
+	RENDER_WINDOW_DESC renderWindowDesc;
+	renderWindowDesc.videoMode = VideoMode(resolutionWidth, resolutionHeight);
+	renderWindowDesc.title = toString(gameSettings->titleBarText);
+	renderWindowDesc.fullscreen = false;
+	renderWindowDesc.hidden = gameSettings->fullscreen;
+
+	Application::startUp(renderWindowDesc, RenderAPIPlugin::DX11);
+
+	if (gameSettings->fullscreen)
+	{
+		if (gameSettings->useDesktopResolution)
+		{
+			const VideoModeInfo& videoModeInfo = RenderAPI::getVideoModeInfo();
+			const VideoOutputInfo& primaryMonitorInfo = videoModeInfo.getOutputInfo(0);
+			const VideoMode& selectedVideoMode = primaryMonitorInfo.getDesktopVideoMode();
+
+			RenderWindowPtr window = gApplication().getPrimaryWindow();
+			window->setFullscreen(gCoreAccessor(), selectedVideoMode);
+
+			resolutionWidth = selectedVideoMode.getWidth();
+			resolutionHeight = selectedVideoMode.getHeight();
+		}
+		else
+		{
+			resolutionWidth = gameSettings->resolutionWidth;
+			resolutionHeight = gameSettings->resolutionHeight;
+
+			VideoMode videoMode(resolutionWidth, resolutionHeight);
+
+			RenderWindowPtr window = gApplication().getPrimaryWindow();
+			window->show(gCoreAccessor());
+			window->setFullscreen(gCoreAccessor(), videoMode);
+		}
+	}
+
+	gameSettings->useDesktopResolution = false; // Not relevant after first startup
+
+	// TODO - Save full video mode
+	gameSettings->resolutionWidth = resolutionWidth;
+	gameSettings->resolutionHeight = resolutionHeight;
+
+	FileEncoder fe(gameSettingsPath);
+	fe.encode(gameSettings.get());
+
+	Path resourcesPath = Paths::getGameResourcesPath();
+	Path resourceManifestPath = resourcesPath + GAME_RESOURCE_MANIFEST_NAME;
+
+	ResourceManifestPtr manifest;
+	if (FileSystem::exists(resourceManifestPath))
+	{
+		Path resourceRoot = FileSystem::getWorkingDirectoryPath();
+		resourceRoot.append(resourcesPath);
+		resourceRoot.makeParent(); // Remove /Resources entry, as we expect all resources to be relative to that path
+
+		manifest = ResourceManifest::load(resourceManifestPath, resourceRoot);
+
+		gResources().registerResourceManifest(manifest);
+	}
+
+	{
+		HPrefab mainScene = static_resource_cast<Prefab>(gResources().loadFromUUID(gameSettings->mainSceneUUID, false, true, false));
+		if (mainScene != nullptr)
+		{
+			HSceneObject root = mainScene->instantiate();
+			HSceneObject oldRoot = gSceneManager().getRootNode();
+
+			gSceneManager()._setRootNode(root);
+			oldRoot->destroy();
+		}
+	}
+
+	Application::instance().runMainLoop();
+	Application::shutDown();
 }
 }

+ 416 - 416
SBansheeEditor/Source/BsScriptBuildManager.cpp

@@ -1,416 +1,416 @@
-#include "BsScriptBuildManager.h"
-#include "BsMonoManager.h"
-#include "BsMonoClass.h"
-#include "BsMonoMethod.h"
-#include "BsMonoUtil.h"
-#include "BsScriptPlatformInfo.h"
-#include "BsFileSystem.h"
-#include "BsIconUtility.h"
-#include "BsCoreThread.h"
-#include "BsGameSettings.h"
-#include "BsFileSerializer.h"
-#include "BsProjectLibrary.h"
-#include "BsProjectResourceMeta.h"
-#include "BsResources.h"
-#include "BsPrefab.h"
-#include "BsEditorApplication.h"
-#include "BsResourceManifest.h"
-#include "BsBuiltinResources.h"
-#include "BsSceneObject.h"
-#include "BsDebug.h"
-
-namespace BansheeEngine
-{
-	ScriptBuildManager::ScriptBuildManager(MonoObject* instance)
-		:ScriptObject(instance)
-	{ }
-
-	void ScriptBuildManager::initRuntimeData()
-	{
-		metaData.scriptClass->addInternalCall("Internal_GetAvailablePlatforms", &ScriptBuildManager::internal_GetAvailablePlatforms);
-		metaData.scriptClass->addInternalCall("Internal_GetActivePlatform", &ScriptBuildManager::internal_GetActivePlatform);
-		metaData.scriptClass->addInternalCall("Internal_SetActivePlatform", &ScriptBuildManager::internal_SetActivePlatform);
-		metaData.scriptClass->addInternalCall("Internal_GetActivePlatformInfo", &ScriptBuildManager::internal_GetActivePlatformInfo);
-		metaData.scriptClass->addInternalCall("Internal_GetPlatformInfo", &ScriptBuildManager::internal_GetPlatformInfo);
-		metaData.scriptClass->addInternalCall("Internal_GetFrameworkAssemblies", &ScriptBuildManager::internal_GetFrameworkAssemblies);
-		metaData.scriptClass->addInternalCall("Internal_GetMainExecutable", &ScriptBuildManager::internal_GetMainExecutable);
-		metaData.scriptClass->addInternalCall("Internal_GetDefines", &ScriptBuildManager::internal_GetDefines);
-		metaData.scriptClass->addInternalCall("Internal_GetNativeBinaries", &ScriptBuildManager::internal_GetNativeBinaries);
-		metaData.scriptClass->addInternalCall("Internal_GetBuildFolder", &ScriptBuildManager::internal_GetBuildFolder);
-		metaData.scriptClass->addInternalCall("Internal_InjectIcons", &ScriptBuildManager::internal_InjectIcons);
-		metaData.scriptClass->addInternalCall("Internal_PackageResources", &ScriptBuildManager::internal_PackageResources);
-		metaData.scriptClass->addInternalCall("Internal_CreateStartupSettings", &ScriptBuildManager::internal_CreateStartupSettings);
-	}
-
-	MonoArray* ScriptBuildManager::internal_GetAvailablePlatforms()
-	{
-		const Vector<PlatformType>& availableType = BuildManager::instance().getAvailablePlatforms();
-
-		ScriptArray outArray = ScriptArray::create<UINT32>((UINT32)availableType.size());
-		UINT32 idx = 0;
-		for (auto& type : availableType)
-			outArray.set(idx++, type);
-
-		return outArray.getInternal();
-	}
-
-	PlatformType ScriptBuildManager::internal_GetActivePlatform()
-	{
-		return BuildManager::instance().getActivePlatform();
-	}
-
-	void ScriptBuildManager::internal_SetActivePlatform(PlatformType value)
-	{
-		BuildManager::instance().setActivePlatform(value);
-	}
-
-	MonoObject* ScriptBuildManager::internal_GetActivePlatformInfo()
-	{
-		return ScriptPlatformInfo::create(BuildManager::instance().getActivePlatformInfo());
-	}
-
-	MonoObject* ScriptBuildManager::internal_GetPlatformInfo(PlatformType type)
-	{
-		return ScriptPlatformInfo::create(BuildManager::instance().getPlatformInfo(type));
-	}
-
-	MonoArray* ScriptBuildManager::internal_GetFrameworkAssemblies(PlatformType type)
-	{
-		Vector<WString> frameworkAssemblies = BuildManager::instance().getFrameworkAssemblies(type);
-
-		ScriptArray outArray = ScriptArray::create<WString>((UINT32)frameworkAssemblies.size());
-		UINT32 idx = 0;
-		for (auto& assemblyName : frameworkAssemblies)
-			outArray.set(idx++, MonoUtil::wstringToMono(assemblyName));
-
-		return outArray.getInternal();
-	}
-
-	MonoString* ScriptBuildManager::internal_GetMainExecutable(PlatformType type)
-	{
-		return MonoUtil::wstringToMono(BuildManager::instance().getMainExecutable(type).toWString());
-	}
-
-	MonoString* ScriptBuildManager::internal_GetDefines(PlatformType type)
-	{
-		return MonoUtil::wstringToMono(BuildManager::instance().getDefines(type));
-	}
-
-	MonoArray* ScriptBuildManager::internal_GetNativeBinaries(PlatformType type)
-	{
-		Vector<Path> paths = BuildManager::instance().getNativeBinaries(type);
-
-		UINT32 numEntries = (UINT32)paths.size();
-		ScriptArray outArray = ScriptArray::create<WString>(numEntries);
-		for (UINT32 i = 0; i < numEntries; i++)
-		{
-			outArray.set(i, MonoUtil::wstringToMono(paths[i].toWString()));
-		}
-
-		return outArray.getInternal();
-	}
-
-	MonoString* ScriptBuildManager::internal_GetBuildFolder(ScriptBuildFolder folder, PlatformType platform)
-	{
-		Path path;
-
-		if (folder == ScriptBuildFolder::FrameworkAssemblies)
-		{
-			Path assemblyFolder = MonoManager::instance().getFrameworkAssembliesFolder();
-			assemblyFolder.makeAbsolute(FileSystem::getWorkingDirectoryPath());
-
-			Path sourceFolder = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platform);
-			path = assemblyFolder.makeRelative(sourceFolder);
-		}
-		else if (folder == ScriptBuildFolder::Mono)
-		{
-			Path monoEtcFolder = MonoManager::instance().getMonoEtcFolder();
-			monoEtcFolder.makeAbsolute(FileSystem::getWorkingDirectoryPath());
-
-			Path sourceFolder = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platform);
-			path = monoEtcFolder.makeRelative(sourceFolder);
-		}
-		else
-		{
-			BuildFolder nativeFolderType = BuildFolder::SourceRoot;
-			switch (folder)
-			{
-			case ScriptBuildFolder::SourceRoot:
-				nativeFolderType = BuildFolder::SourceRoot;
-				break;
-			case ScriptBuildFolder::DestinationRoot:
-				nativeFolderType = BuildFolder::DestinationRoot;
-				break;
-			case ScriptBuildFolder::NativeBinaries:
-				nativeFolderType = BuildFolder::NativeBinaries;
-				break;
-			case ScriptBuildFolder::BansheeDebugAssemblies:
-				nativeFolderType = BuildFolder::BansheeDebugAssemblies;
-				break;
-			case ScriptBuildFolder::BansheeReleaseAssemblies:
-				nativeFolderType = BuildFolder::BansheeReleaseAssemblies;
-				break;
-			case ScriptBuildFolder::Data:
-				nativeFolderType = BuildFolder::Data;
-				break;
-			}
-
-			path = BuildManager::instance().getBuildFolder(nativeFolderType, platform);
-		}
-
-		return MonoUtil::wstringToMono(path.toWString());
-	}
-
-	void ScriptBuildManager::internal_InjectIcons(MonoString* filePath, ScriptPlatformInfo* info)
-	{
-		if (info == nullptr)
-			return;
-
-		Path executablePath = MonoUtil::monoToWString(filePath);
-
-		Map<UINT32, PixelDataPtr> icons;
-		SPtr<PlatformInfo> platformInfo = info->getPlatformInfo();
-		switch (platformInfo->type)
-		{
-		case PlatformType::Windows:
-		{
-			SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
-
-			struct IconData
-			{
-				UINT32 size;
-				PixelDataPtr pixels;
-			};
-
-			IconData textures[] =
-			{ 
-				{ 16 },
-				{ 32 },
-				{ 48 },
-				{ 64 },
-				{ 96 },
-				{ 128 },
-				{ 192 }, 
-				{ 256 } 
-			};
-
-			HTexture icon = gResources().load(winPlatformInfo->icon);
-			if (icon.isLoaded())
-			{
-				auto& texProps = icon->getProperties();
-
-				PixelDataPtr pixels = texProps.allocateSubresourceBuffer(0);
-				icon->readSubresource(gCoreAccessor(), 0, pixels);
-				gCoreAccessor().submitToCoreThread(true);
-
-				for (auto& entry : textures)
-				{
-					entry.pixels = PixelData::create(entry.size, entry.size, 1, PF_R8G8B8A8);
-					PixelUtil::scale(*pixels, *entry.pixels);
-
-					icons[entry.size] = entry.pixels;
-				}
-			}
-		}
-			break;
-		}
-
-		IconUtility::updateIconExe(executablePath, icons);
-	}
-
-	void ScriptBuildManager::internal_PackageResources(MonoString* buildFolder, ScriptPlatformInfo* info)
-	{
-		UnorderedSet<Path> usedResources;
-
-		// Get all resources manually included in build
-		Vector<ProjectLibrary::ResourceEntry*> buildResources = gProjectLibrary().getResourcesForBuild();
-		for (auto& entry : buildResources)
-		{
-			if (entry->meta == nullptr)
-			{
-				LOGWRN("Cannot include resource in build, missing meta file for: " + entry->path.toString());
-				continue;
-			}
-
-			Path resourcePath;
-			if (gResources().getFilePathFromUUID(entry->meta->getUUID(), resourcePath))
-				usedResources.insert(resourcePath);
-			else
-				LOGWRN("Cannot include resource in build, missing imported asset for: " + entry->path.toString());
-		}
-
-		// Include main scene
-		SPtr<PlatformInfo> platformInfo;
-
-		if (info != nullptr)
-			platformInfo = info->getPlatformInfo();
-
-		if (platformInfo != nullptr)
-		{
-			Path resourcePath;
-			if (gResources().getFilePathFromUUID(platformInfo->mainScene.getUUID(), resourcePath))
-				usedResources.insert(resourcePath);
-			else
-				LOGWRN("Cannot include main scene in build, missing imported asset.");
-		}
-
-		// Find dependencies of all resources
-		Vector<Path> newResources;
-		for (auto& entry : usedResources)
-			newResources.push_back(entry);
-
-		while (!newResources.empty())
-		{
-			Vector<Path> allDependencies;
-			for (auto& entry : newResources)
-			{
-				Vector<String> curDependencies = gResources().getDependencies(entry);
-				for (auto& entry : curDependencies)
-				{
-					Path resourcePath;
-					if (gResources().getFilePathFromUUID(entry, resourcePath))
-					{
-						if (usedResources.find(resourcePath) == usedResources.end())
-						{
-							allDependencies.push_back(resourcePath);
-							usedResources.insert(resourcePath);
-						}
-					}
-				}
-			}
-
-			newResources = allDependencies;
-		} 
-
-		// Copy resources
-		Path outputPath = MonoUtil::monoToWString(buildFolder);
-		outputPath.append(GAME_RESOURCES_FOLDER_NAME);
-
-		FileSystem::createDir(outputPath);
-
-		for (auto& entry : usedResources)
-		{
-			String uuid;
-			BS_ASSERT(gResources().getUUIDFromFilePath(entry, uuid));
-
-			Path sourcePath = gProjectLibrary().uuidToPath(uuid);
-			if (sourcePath.isEmpty()) // Resource not part of library, meaning its built-in and we don't need to copy those here
-				continue;
-
-			ProjectLibrary::LibraryEntry* libEntry = gProjectLibrary().findEntry(sourcePath);
-			assert(libEntry != nullptr && libEntry->type == ProjectLibrary::LibraryEntryType::File);
-
-			ProjectLibrary::ResourceEntry* resEntry = static_cast<ProjectLibrary::ResourceEntry*>(libEntry);
-
-			Path destPath = outputPath;
-			destPath.setFilename(entry.getFilename());
-
-			// If resource is prefab make sure to update it in case any of the prefabs it is referencing changed
-			if (resEntry->meta->getTypeID() == TID_Prefab)
-			{
-				bool reload = gResources().isLoaded(uuid);
-
-				HPrefab prefab = static_resource_cast<Prefab>(gProjectLibrary().load(sourcePath));
-				prefab->_updateChildInstances();
-
-				// Clear prefab diffs as they're not used in standalone
-				Stack<HSceneObject> todo;
-				todo.push(prefab->_getRoot());
-
-				while (!todo.empty())
-				{
-					HSceneObject current = todo.top();
-					todo.pop();
-
-					current->_clearPrefabDiff();
-
-					UINT32 numChildren = current->getNumChildren();
-					for (UINT32 i = 0; i < numChildren; i++)
-					{
-						HSceneObject child = current->getChild(i);
-						todo.push(child);
-					}
-				}
-
-				gResources().save(prefab, destPath, false);
-
-				// Need to unload this one as we modified it in memory, and we don't want to persist those changes past
-				// this point
-				gResources().release(prefab);
-
-				if (reload)
-					gProjectLibrary().load(sourcePath);
-			}
-			else
-				FileSystem::copy(entry, destPath);
-		}
-
-		// Save icon
-		Path iconFolder = FileSystem::getWorkingDirectoryPath();
-		iconFolder.append(BuiltinResources::getIconFolder());
-
-		Path sourceRoot = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platformInfo->type);
-		iconFolder.makeRelative(sourceRoot);
-
-		Path destRoot = BuildManager::instance().getBuildFolder(BuildFolder::DestinationRoot, platformInfo->type);
-		Path destIconFile = destRoot;
-		destIconFile.append(iconFolder);
-		destIconFile.setFilename(BuiltinResources::IconTextureName + L".asset");
-
-		switch (platformInfo->type)
-		{
-		case PlatformType::Windows:
-		{
-			SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
-			
-			HTexture icon = gResources().load(winPlatformInfo->icon);
-			if (icon != nullptr)
-				gResources().save(icon, destIconFile, true);
-		}
-		};
-
-		// Save manifest
-		Path manifestPath = outputPath;
-		manifestPath.append(GAME_RESOURCE_MANIFEST_NAME);
-
-		Path internalResourcesFolder = gEditorApplication().getProjectPath();
-		internalResourcesFolder.append(PROJECT_INTERNAL_DIR);
-
-		ResourceManifestPtr manifest = gProjectLibrary()._getManifest();
-		ResourceManifest::save(manifest, manifestPath, internalResourcesFolder);
-	}
-
-	void ScriptBuildManager::internal_CreateStartupSettings(MonoString* buildFolder, ScriptPlatformInfo* info)
-	{
-		SPtr<PlatformInfo> platformInfo;
-
-		if (info != nullptr)
-			platformInfo = info->getPlatformInfo();
-
-		SPtr<GameSettings> gameSettings;
-		if (platformInfo != nullptr)
-		{
-			gameSettings = bs_shared_ptr_new<GameSettings>();
-			gameSettings->mainSceneUUID = platformInfo->mainScene.getUUID();
-			gameSettings->fullscreen = platformInfo->fullscreen;
-			gameSettings->resolutionWidth = platformInfo->windowedWidth;
-			gameSettings->resolutionWidth = platformInfo->windowedHeight;
-
-			switch (platformInfo->type)
-			{
-			case(PlatformType::Windows) :
-			{
-				SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
-				gameSettings->titleBarText = winPlatformInfo->titlebarText;
-			}
-				break;
-			}
-		}
-
-		Path outputPath = MonoUtil::monoToWString(buildFolder);
-		outputPath.append(GAME_SETTINGS_NAME);
-
-		FileEncoder fe(outputPath);
-		fe.encode(gameSettings.get());
-	}
-}
+#include "BsScriptBuildManager.h"
+#include "BsMonoManager.h"
+#include "BsMonoClass.h"
+#include "BsTexture.h"
+#include "BsMonoUtil.h"
+#include "BsScriptPlatformInfo.h"
+#include "BsFileSystem.h"
+#include "BsIconUtility.h"
+#include "BsCoreThread.h"
+#include "BsGameSettings.h"
+#include "BsFileSerializer.h"
+#include "BsProjectLibrary.h"
+#include "BsProjectResourceMeta.h"
+#include "BsResources.h"
+#include "BsPrefab.h"
+#include "BsEditorApplication.h"
+#include "BsResourceManifest.h"
+#include "BsBuiltinResources.h"
+#include "BsSceneObject.h"
+#include "BsDebug.h"
+
+namespace BansheeEngine
+{
+	ScriptBuildManager::ScriptBuildManager(MonoObject* instance)
+		:ScriptObject(instance)
+	{ }
+
+	void ScriptBuildManager::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_GetAvailablePlatforms", &ScriptBuildManager::internal_GetAvailablePlatforms);
+		metaData.scriptClass->addInternalCall("Internal_GetActivePlatform", &ScriptBuildManager::internal_GetActivePlatform);
+		metaData.scriptClass->addInternalCall("Internal_SetActivePlatform", &ScriptBuildManager::internal_SetActivePlatform);
+		metaData.scriptClass->addInternalCall("Internal_GetActivePlatformInfo", &ScriptBuildManager::internal_GetActivePlatformInfo);
+		metaData.scriptClass->addInternalCall("Internal_GetPlatformInfo", &ScriptBuildManager::internal_GetPlatformInfo);
+		metaData.scriptClass->addInternalCall("Internal_GetFrameworkAssemblies", &ScriptBuildManager::internal_GetFrameworkAssemblies);
+		metaData.scriptClass->addInternalCall("Internal_GetMainExecutable", &ScriptBuildManager::internal_GetMainExecutable);
+		metaData.scriptClass->addInternalCall("Internal_GetDefines", &ScriptBuildManager::internal_GetDefines);
+		metaData.scriptClass->addInternalCall("Internal_GetNativeBinaries", &ScriptBuildManager::internal_GetNativeBinaries);
+		metaData.scriptClass->addInternalCall("Internal_GetBuildFolder", &ScriptBuildManager::internal_GetBuildFolder);
+		metaData.scriptClass->addInternalCall("Internal_InjectIcons", &ScriptBuildManager::internal_InjectIcons);
+		metaData.scriptClass->addInternalCall("Internal_PackageResources", &ScriptBuildManager::internal_PackageResources);
+		metaData.scriptClass->addInternalCall("Internal_CreateStartupSettings", &ScriptBuildManager::internal_CreateStartupSettings);
+	}
+
+	MonoArray* ScriptBuildManager::internal_GetAvailablePlatforms()
+	{
+		const Vector<PlatformType>& availableType = BuildManager::instance().getAvailablePlatforms();
+
+		ScriptArray outArray = ScriptArray::create<UINT32>((UINT32)availableType.size());
+		UINT32 idx = 0;
+		for (auto& type : availableType)
+			outArray.set(idx++, type);
+
+		return outArray.getInternal();
+	}
+
+	PlatformType ScriptBuildManager::internal_GetActivePlatform()
+	{
+		return BuildManager::instance().getActivePlatform();
+	}
+
+	void ScriptBuildManager::internal_SetActivePlatform(PlatformType value)
+	{
+		BuildManager::instance().setActivePlatform(value);
+	}
+
+	MonoObject* ScriptBuildManager::internal_GetActivePlatformInfo()
+	{
+		return ScriptPlatformInfo::create(BuildManager::instance().getActivePlatformInfo());
+	}
+
+	MonoObject* ScriptBuildManager::internal_GetPlatformInfo(PlatformType type)
+	{
+		return ScriptPlatformInfo::create(BuildManager::instance().getPlatformInfo(type));
+	}
+
+	MonoArray* ScriptBuildManager::internal_GetFrameworkAssemblies(PlatformType type)
+	{
+		Vector<WString> frameworkAssemblies = BuildManager::instance().getFrameworkAssemblies(type);
+
+		ScriptArray outArray = ScriptArray::create<WString>((UINT32)frameworkAssemblies.size());
+		UINT32 idx = 0;
+		for (auto& assemblyName : frameworkAssemblies)
+			outArray.set(idx++, MonoUtil::wstringToMono(assemblyName));
+
+		return outArray.getInternal();
+	}
+
+	MonoString* ScriptBuildManager::internal_GetMainExecutable(PlatformType type)
+	{
+		return MonoUtil::wstringToMono(BuildManager::instance().getMainExecutable(type).toWString());
+	}
+
+	MonoString* ScriptBuildManager::internal_GetDefines(PlatformType type)
+	{
+		return MonoUtil::wstringToMono(BuildManager::instance().getDefines(type));
+	}
+
+	MonoArray* ScriptBuildManager::internal_GetNativeBinaries(PlatformType type)
+	{
+		Vector<Path> paths = BuildManager::instance().getNativeBinaries(type);
+
+		UINT32 numEntries = (UINT32)paths.size();
+		ScriptArray outArray = ScriptArray::create<WString>(numEntries);
+		for (UINT32 i = 0; i < numEntries; i++)
+		{
+			outArray.set(i, MonoUtil::wstringToMono(paths[i].toWString()));
+		}
+
+		return outArray.getInternal();
+	}
+
+	MonoString* ScriptBuildManager::internal_GetBuildFolder(ScriptBuildFolder folder, PlatformType platform)
+	{
+		Path path;
+
+		if (folder == ScriptBuildFolder::FrameworkAssemblies)
+		{
+			Path assemblyFolder = MonoManager::instance().getFrameworkAssembliesFolder();
+			assemblyFolder.makeAbsolute(FileSystem::getWorkingDirectoryPath());
+
+			Path sourceFolder = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platform);
+			path = assemblyFolder.makeRelative(sourceFolder);
+		}
+		else if (folder == ScriptBuildFolder::Mono)
+		{
+			Path monoEtcFolder = MonoManager::instance().getMonoEtcFolder();
+			monoEtcFolder.makeAbsolute(FileSystem::getWorkingDirectoryPath());
+
+			Path sourceFolder = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platform);
+			path = monoEtcFolder.makeRelative(sourceFolder);
+		}
+		else
+		{
+			BuildFolder nativeFolderType = BuildFolder::SourceRoot;
+			switch (folder)
+			{
+			case ScriptBuildFolder::SourceRoot:
+				nativeFolderType = BuildFolder::SourceRoot;
+				break;
+			case ScriptBuildFolder::DestinationRoot:
+				nativeFolderType = BuildFolder::DestinationRoot;
+				break;
+			case ScriptBuildFolder::NativeBinaries:
+				nativeFolderType = BuildFolder::NativeBinaries;
+				break;
+			case ScriptBuildFolder::BansheeDebugAssemblies:
+				nativeFolderType = BuildFolder::BansheeDebugAssemblies;
+				break;
+			case ScriptBuildFolder::BansheeReleaseAssemblies:
+				nativeFolderType = BuildFolder::BansheeReleaseAssemblies;
+				break;
+			case ScriptBuildFolder::Data:
+				nativeFolderType = BuildFolder::Data;
+				break;
+			}
+
+			path = BuildManager::instance().getBuildFolder(nativeFolderType, platform);
+		}
+
+		return MonoUtil::wstringToMono(path.toWString());
+	}
+
+	void ScriptBuildManager::internal_InjectIcons(MonoString* filePath, ScriptPlatformInfo* info)
+	{
+		if (info == nullptr)
+			return;
+
+		Path executablePath = MonoUtil::monoToWString(filePath);
+
+		Map<UINT32, PixelDataPtr> icons;
+		SPtr<PlatformInfo> platformInfo = info->getPlatformInfo();
+		switch (platformInfo->type)
+		{
+		case PlatformType::Windows:
+		{
+			SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
+
+			struct IconData
+			{
+				UINT32 size;
+				PixelDataPtr pixels;
+			};
+
+			IconData textures[] =
+			{ 
+				{ 16 },
+				{ 32 },
+				{ 48 },
+				{ 64 },
+				{ 96 },
+				{ 128 },
+				{ 192 }, 
+				{ 256 } 
+			};
+
+			HTexture icon = gResources().load(winPlatformInfo->icon);
+			if (icon.isLoaded())
+			{
+				auto& texProps = icon->getProperties();
+
+				PixelDataPtr pixels = texProps.allocateSubresourceBuffer(0);
+				icon->readSubresource(gCoreAccessor(), 0, pixels);
+				gCoreAccessor().submitToCoreThread(true);
+
+				for (auto& entry : textures)
+				{
+					entry.pixels = PixelData::create(entry.size, entry.size, 1, PF_R8G8B8A8);
+					PixelUtil::scale(*pixels, *entry.pixels);
+
+					icons[entry.size] = entry.pixels;
+				}
+			}
+		}
+			break;
+		}
+
+		IconUtility::updateIconExe(executablePath, icons);
+	}
+
+	void ScriptBuildManager::internal_PackageResources(MonoString* buildFolder, ScriptPlatformInfo* info)
+	{
+		UnorderedSet<Path> usedResources;
+
+		// Get all resources manually included in build
+		Vector<ProjectLibrary::ResourceEntry*> buildResources = gProjectLibrary().getResourcesForBuild();
+		for (auto& entry : buildResources)
+		{
+			if (entry->meta == nullptr)
+			{
+				LOGWRN("Cannot include resource in build, missing meta file for: " + entry->path.toString());
+				continue;
+			}
+
+			Path resourcePath;
+			if (gResources().getFilePathFromUUID(entry->meta->getUUID(), resourcePath))
+				usedResources.insert(resourcePath);
+			else
+				LOGWRN("Cannot include resource in build, missing imported asset for: " + entry->path.toString());
+		}
+
+		// Include main scene
+		SPtr<PlatformInfo> platformInfo;
+
+		if (info != nullptr)
+			platformInfo = info->getPlatformInfo();
+
+		if (platformInfo != nullptr)
+		{
+			Path resourcePath;
+			if (gResources().getFilePathFromUUID(platformInfo->mainScene.getUUID(), resourcePath))
+				usedResources.insert(resourcePath);
+			else
+				LOGWRN("Cannot include main scene in build, missing imported asset.");
+		}
+
+		// Find dependencies of all resources
+		Vector<Path> newResources;
+		for (auto& entry : usedResources)
+			newResources.push_back(entry);
+
+		while (!newResources.empty())
+		{
+			Vector<Path> allDependencies;
+			for (auto& entry : newResources)
+			{
+				Vector<String> curDependencies = gResources().getDependencies(entry);
+				for (auto& entry : curDependencies)
+				{
+					Path resourcePath;
+					if (gResources().getFilePathFromUUID(entry, resourcePath))
+					{
+						if (usedResources.find(resourcePath) == usedResources.end())
+						{
+							allDependencies.push_back(resourcePath);
+							usedResources.insert(resourcePath);
+						}
+					}
+				}
+			}
+
+			newResources = allDependencies;
+		} 
+
+		// Copy resources
+		Path outputPath = MonoUtil::monoToWString(buildFolder);
+		outputPath.append(GAME_RESOURCES_FOLDER_NAME);
+
+		FileSystem::createDir(outputPath);
+
+		for (auto& entry : usedResources)
+		{
+			String uuid;
+			BS_ASSERT(gResources().getUUIDFromFilePath(entry, uuid));
+
+			Path sourcePath = gProjectLibrary().uuidToPath(uuid);
+			if (sourcePath.isEmpty()) // Resource not part of library, meaning its built-in and we don't need to copy those here
+				continue;
+
+			ProjectLibrary::LibraryEntry* libEntry = gProjectLibrary().findEntry(sourcePath);
+			assert(libEntry != nullptr && libEntry->type == ProjectLibrary::LibraryEntryType::File);
+
+			ProjectLibrary::ResourceEntry* resEntry = static_cast<ProjectLibrary::ResourceEntry*>(libEntry);
+
+			Path destPath = outputPath;
+			destPath.setFilename(entry.getFilename());
+
+			// If resource is prefab make sure to update it in case any of the prefabs it is referencing changed
+			if (resEntry->meta->getTypeID() == TID_Prefab)
+			{
+				bool reload = gResources().isLoaded(uuid);
+
+				HPrefab prefab = static_resource_cast<Prefab>(gProjectLibrary().load(sourcePath));
+				prefab->_updateChildInstances();
+
+				// Clear prefab diffs as they're not used in standalone
+				Stack<HSceneObject> todo;
+				todo.push(prefab->_getRoot());
+
+				while (!todo.empty())
+				{
+					HSceneObject current = todo.top();
+					todo.pop();
+
+					current->_clearPrefabDiff();
+
+					UINT32 numChildren = current->getNumChildren();
+					for (UINT32 i = 0; i < numChildren; i++)
+					{
+						HSceneObject child = current->getChild(i);
+						todo.push(child);
+					}
+				}
+
+				gResources().save(prefab, destPath, false);
+
+				// Need to unload this one as we modified it in memory, and we don't want to persist those changes past
+				// this point
+				gResources().release(prefab);
+
+				if (reload)
+					gProjectLibrary().load(sourcePath);
+			}
+			else
+				FileSystem::copy(entry, destPath);
+		}
+
+		// Save icon
+		Path iconFolder = FileSystem::getWorkingDirectoryPath();
+		iconFolder.append(BuiltinResources::getIconFolder());
+
+		Path sourceRoot = BuildManager::instance().getBuildFolder(BuildFolder::SourceRoot, platformInfo->type);
+		iconFolder.makeRelative(sourceRoot);
+
+		Path destRoot = BuildManager::instance().getBuildFolder(BuildFolder::DestinationRoot, platformInfo->type);
+		Path destIconFile = destRoot;
+		destIconFile.append(iconFolder);
+		destIconFile.setFilename(BuiltinResources::IconTextureName + L".asset");
+
+		switch (platformInfo->type)
+		{
+		case PlatformType::Windows:
+		{
+			SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
+			
+			HTexture icon = gResources().load(winPlatformInfo->icon);
+			if (icon != nullptr)
+				gResources().save(icon, destIconFile, true);
+		}
+		};
+
+		// Save manifest
+		Path manifestPath = outputPath;
+		manifestPath.append(GAME_RESOURCE_MANIFEST_NAME);
+
+		Path internalResourcesFolder = gEditorApplication().getProjectPath();
+		internalResourcesFolder.append(PROJECT_INTERNAL_DIR);
+
+		ResourceManifestPtr manifest = gProjectLibrary()._getManifest();
+		ResourceManifest::save(manifest, manifestPath, internalResourcesFolder);
+	}
+
+	void ScriptBuildManager::internal_CreateStartupSettings(MonoString* buildFolder, ScriptPlatformInfo* info)
+	{
+		SPtr<PlatformInfo> platformInfo;
+
+		if (info != nullptr)
+			platformInfo = info->getPlatformInfo();
+
+		SPtr<GameSettings> gameSettings;
+		if (platformInfo != nullptr)
+		{
+			gameSettings = bs_shared_ptr_new<GameSettings>();
+			gameSettings->mainSceneUUID = platformInfo->mainScene.getUUID();
+			gameSettings->fullscreen = platformInfo->fullscreen;
+			gameSettings->resolutionWidth = platformInfo->windowedWidth;
+			gameSettings->resolutionWidth = platformInfo->windowedHeight;
+
+			switch (platformInfo->type)
+			{
+			case(PlatformType::Windows) :
+			{
+				SPtr<WinPlatformInfo> winPlatformInfo = std::static_pointer_cast<WinPlatformInfo>(platformInfo);
+				gameSettings->titleBarText = winPlatformInfo->titlebarText;
+			}
+				break;
+			}
+		}
+
+		Path outputPath = MonoUtil::monoToWString(buildFolder);
+		outputPath.append(GAME_SETTINGS_NAME);
+
+		FileEncoder fe(outputPath);
+		fe.encode(gameSettings.get());
+	}
+}