diff options
Diffstat (limited to 'libs/assimp/tools/assimp_view/MessageProc.cpp')
| -rw-r--r-- | libs/assimp/tools/assimp_view/MessageProc.cpp | 2434 | 
1 files changed, 2434 insertions, 0 deletions
diff --git a/libs/assimp/tools/assimp_view/MessageProc.cpp b/libs/assimp/tools/assimp_view/MessageProc.cpp new file mode 100644 index 0000000..e51c829 --- /dev/null +++ b/libs/assimp/tools/assimp_view/MessageProc.cpp @@ -0,0 +1,2434 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2022, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +  copyright notice, this list of conditions and the +  following disclaimer. + +* Redistributions in binary form must reproduce the above +  copyright notice, this list of conditions and the +  following disclaimer in the documentation and/or other +  materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +  contributors may be used to endorse or promote products +  derived from this software without specific prior +  written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "assimp_view.h" +#include <assimp/Exporter.hpp> +#include <algorithm> + +#include <windowsx.h> +#include <commdlg.h> + +#ifdef __MINGW32__ +#   include <mmsystem.h> +#else +#   include <timeapi.h> +#endif + +namespace AssimpView { + +using namespace Assimp; + +// Static array to keep custom color values +COLORREF g_aclCustomColors[16] = {0}; + +// Global registry key +HKEY g_hRegistry = nullptr; + +// list of previous files (always 5) +std::vector<std::string> g_aPreviousFiles; + +// history menu item +HMENU g_hHistoryMenu = nullptr; + +float g_fACMR = 3.0f; + +#define AI_VIEW_NUM_RECENT_FILES 0x8 +#define AI_VIEW_RECENT_FILE_ID(_n_) (5678 + _n_) + +#define AI_VIEW_EXPORT_FMT_BASE 7912 +#define AI_VIEW_EXPORT_FMT_ID(_n_)  (AI_VIEW_EXPORT_FMT_BASE + _n_) + +void UpdateHistory(); +void SaveHistory(); + +//------------------------------------------------------------------------------- +// Setup file associations for all formats supported by the library +// +// File associations are registered in HKCU\Software\Classes. They might +// be overwritten by global file associations. +//------------------------------------------------------------------------------- +void MakeFileAssociations() { +    char szTemp2[MAX_PATH]; +    char szTemp[MAX_PATH + 10]; + +    GetModuleFileName(nullptr,szTemp2,MAX_PATH); +    sprintf(szTemp,"%s %%1",szTemp2); + +    HKEY hRegistry = nullptr; + +    aiString list, tmp; +    aiGetExtensionList(&list); +    tmp = list; + +    const char* sz = strtok(list.data,";"); +    do { +        char buf[256]; +        ai_assert(sz[0] == '*'); +        sprintf(buf,"Software\\Classes\\%s",sz+1); + +        RegCreateKeyEx(HKEY_CURRENT_USER,buf,0,nullptr,0,KEY_ALL_ACCESS, nullptr, &hRegistry,nullptr); +        RegSetValueEx(hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); +        RegCloseKey(hRegistry); +    } while ((sz = strtok(nullptr,";")) != nullptr); + +    RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS",0,nullptr,0,KEY_ALL_ACCESS, nullptr, &hRegistry,nullptr); +    RegCloseKey(hRegistry); + +    RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS\\shell\\open\\command",0,nullptr,0,KEY_ALL_ACCESS, nullptr, &hRegistry,nullptr); +    RegSetValueEx(hRegistry,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); +    RegCloseKey(hRegistry); + +    CLogDisplay::Instance().AddEntry("[OK] File associations have been registered", +        D3DCOLOR_ARGB(0xFF,0,0xFF,0)); + +    CLogDisplay::Instance().AddEntry(tmp.data,D3DCOLOR_ARGB(0xFF,0,0xFF,0)); +} + +//------------------------------------------------------------------------------- +// Handle command line parameters +// +// The function loads an asset specified on the command line as first argument +// Other command line parameters are not handled +//------------------------------------------------------------------------------- +void HandleCommandLine(char* p_szCommand) { +    char* sz = p_szCommand; +    //bool bQuak = false; + +    if (strlen(sz) < 2) { +        return; +    } + +    if (*sz == '\"') { +        char* sz2 = strrchr(sz,'\"'); +        if (sz2)*sz2 = 0; +        sz++; // skip the starting quote +    } + +    strcpy( g_szFileName, sz ); +    LoadAsset(); + +    // update the history +    UpdateHistory(); + +    // Save the list of previous files to the registry +    SaveHistory(); +} + +//------------------------------------------------------------------------------- +// Load the light colors from the registry +//------------------------------------------------------------------------------- +void LoadLightColors() { +    DWORD dwTemp = 4; +    RegQueryValueEx(g_hRegistry,"LightColor0",nullptr,nullptr, (BYTE*)&g_avLightColors[0],&dwTemp); +    RegQueryValueEx(g_hRegistry,"LightColor1",nullptr,nullptr, (BYTE*)&g_avLightColors[1],&dwTemp); +    RegQueryValueEx(g_hRegistry,"LightColor2",nullptr,nullptr, (BYTE*)&g_avLightColors[2],&dwTemp); +} + +//------------------------------------------------------------------------------- +// Save the light colors to the registry +//------------------------------------------------------------------------------- +void SaveLightColors() { +    RegSetValueExA(g_hRegistry,"LightColor0",0,REG_DWORD,(const BYTE*)&g_avLightColors[0],4); +    RegSetValueExA(g_hRegistry,"LightColor1",0,REG_DWORD,(const BYTE*)&g_avLightColors[1],4); +    RegSetValueExA(g_hRegistry,"LightColor2",0,REG_DWORD,(const BYTE*)&g_avLightColors[2],4); +} + +//------------------------------------------------------------------------------- +// Save the checker pattern colors to the registry +//------------------------------------------------------------------------------- +void SaveCheckerPatternColors() { +    // we have it as float4. save it as binary value --. +    RegSetValueExA(g_hRegistry,"CheckerPattern0",0,REG_BINARY, +        (const BYTE*)CDisplay::Instance().GetFirstCheckerColor(), +        sizeof(D3DXVECTOR3)); + +    RegSetValueExA(g_hRegistry,"CheckerPattern1",0,REG_BINARY, +        (const BYTE*)CDisplay::Instance().GetSecondCheckerColor(), +        sizeof(D3DXVECTOR3)); +} + +//------------------------------------------------------------------------------- +// Load the checker pattern colors from the registry +//------------------------------------------------------------------------------- +void LoadCheckerPatternColors() { +    DWORD dwTemp = sizeof(D3DXVECTOR3); +    RegQueryValueEx(g_hRegistry,"CheckerPattern0",nullptr,nullptr, +        (BYTE*) /* jep, this is evil */ CDisplay::Instance().GetFirstCheckerColor(),&dwTemp); + +    RegQueryValueEx(g_hRegistry,"CheckerPattern1",nullptr,nullptr, +        (BYTE*) /* jep, this is evil */ CDisplay::Instance().GetSecondCheckerColor(),&dwTemp); +} + +//------------------------------------------------------------------------------- +// Changed pp setup +//------------------------------------------------------------------------------- +void UpdatePPSettings() { +    DWORD dwValue = ppsteps; +    RegSetValueExA(g_hRegistry,"PostProcessing",0,REG_DWORD,(const BYTE*)&dwValue,4); +    UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Toggle the "Display Normals" state +//------------------------------------------------------------------------------- +void ToggleNormals() { +    g_sOptions.bRenderNormals = !g_sOptions.bRenderNormals; + +    // store this in the registry, too +    DWORD dwValue = 0; +    if (g_sOptions.bRenderNormals)dwValue = 1; +    RegSetValueExA(g_hRegistry,"RenderNormals",0,REG_DWORD,(const BYTE*)&dwValue,4); +} + +static void storeRegKey(bool option, LPCSTR name) { +    // store this in the registry, too +    DWORD dwValue = 0; +    if (option) { +        dwValue = 1; +    } +    RegSetValueExA(g_hRegistry, name, 0, REG_DWORD, (const BYTE*)&dwValue, 4); + +} +//------------------------------------------------------------------------------- +// Toggle the "AutoRotate" state +//------------------------------------------------------------------------------- +void ToggleAutoRotate() { +    g_sOptions.bRotate = !g_sOptions.bRotate; +    storeRegKey(g_sOptions.bRotate, "AutoRotate"); +    UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Toggle the "FPS" state +//------------------------------------------------------------------------------- +void ToggleFPSView() { +    g_bFPSView = !g_bFPSView; +    SetupFPSView(); +    storeRegKey(g_bFPSView, "FPSView"); +} + +//------------------------------------------------------------------------------- +// Toggle the "2 Light sources" state +//------------------------------------------------------------------------------- +void ToggleMultipleLights() { +    g_sOptions.b3Lights = !g_sOptions.b3Lights; +    storeRegKey(g_sOptions.b3Lights, "MultipleLights"); +} + +//------------------------------------------------------------------------------- +// Toggle the "LightRotate" state +//------------------------------------------------------------------------------- +void ToggleLightRotate() { +    g_sOptions.bLightRotate = !g_sOptions.bLightRotate; +    storeRegKey(g_sOptions.bLightRotate, "LightRotate"); +} + +//------------------------------------------------------------------------------- +// Toggle the "NoTransparency" state +//------------------------------------------------------------------------------- +void ToggleTransparency() { +    g_sOptions.bNoAlphaBlending = !g_sOptions.bNoAlphaBlending; +    storeRegKey(g_sOptions.bNoAlphaBlending, "NoTransparency"); +} + +//------------------------------------------------------------------------------- +// Toggle the "LowQuality" state +//------------------------------------------------------------------------------- +void ToggleLowQuality() { +    g_sOptions.bLowQuality = !g_sOptions.bLowQuality; +    storeRegKey(g_sOptions.bLowQuality, "LowQuality"); +} + +//------------------------------------------------------------------------------- +// Toggle the "Specular" state +//------------------------------------------------------------------------------- +void ToggleSpecular() { +    g_sOptions.bNoSpecular = !g_sOptions.bNoSpecular; + +    storeRegKey(g_sOptions.bNoSpecular, "NoSpecular"); + +    // update all specular materials +    CMaterialManager::Instance().UpdateSpecularMaterials(); +} + +//------------------------------------------------------------------------------- +// Toggle the "RenderMats" state +//------------------------------------------------------------------------------- +void ToggleMats() { +    g_sOptions.bRenderMats = !g_sOptions.bRenderMats; + +    storeRegKey(g_sOptions.bRenderMats, "RenderMats"); + +    // update all specular materials +    CMaterialManager::Instance().UpdateSpecularMaterials(); +} + +//------------------------------------------------------------------------------- +// Toggle the "Culling" state +//------------------------------------------------------------------------------- +void ToggleCulling() { +    g_sOptions.bCulling = !g_sOptions.bCulling; +    storeRegKey(g_sOptions.bCulling, "Culling"); +} + +//------------------------------------------------------------------------------- +// Toggle the "Skeleton" state +//------------------------------------------------------------------------------- +void ToggleSkeleton() { +    g_sOptions.bSkeleton = !g_sOptions.bSkeleton; +    storeRegKey(g_sOptions.bSkeleton, "Skeleton"); +} + +//------------------------------------------------------------------------------- +// Toggle the "WireFrame" state +//------------------------------------------------------------------------------- +void ToggleWireFrame() { +    if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME) { +        g_sOptions.eDrawMode = RenderOptions::NORMAL; +    } else { +        g_sOptions.eDrawMode = RenderOptions::WIREFRAME; +    } + +    storeRegKey(RenderOptions::WIREFRAME == g_sOptions.eDrawMode, "Wireframe"); +} + +//------------------------------------------------------------------------------- +// Toggle the "MultiSample" state +//------------------------------------------------------------------------------- +void ToggleMS() { +    g_sOptions.bMultiSample = !g_sOptions.bMultiSample; +    DeleteAssetData(); +    ShutdownDevice(); +    if (0 == CreateDevice()) { +        CLogDisplay::Instance().AddEntry( +            "[ERROR] Failed to toggle MultiSampling mode"); +        g_sOptions.bMultiSample = !g_sOptions.bMultiSample; +        CreateDevice(); +    } +    CreateAssetData(); + +    if (g_sOptions.bMultiSample) { +        CLogDisplay::Instance().AddEntry( +            "[OK] Changed MultiSampling mode to the maximum value for this device"); +    } else { +        CLogDisplay::Instance().AddEntry( +            "[OK] MultiSampling has been disabled"); +    } + +    storeRegKey(g_sOptions.bMultiSample, "MultiSampling"); +} + +//------------------------------------------------------------------------------- +// Expand or collapse the UI +//------------------------------------------------------------------------------- +void ToggleUIState() { +    // adjust the size +    RECT sRect; +    GetWindowRect(g_hDlg,&sRect); +    sRect.right -= sRect.left; +    sRect.bottom -= sRect.top; + +    RECT sRect2; +    GetWindowRect(GetDlgItem ( g_hDlg, IDC_BLUBB ),&sRect2); +    sRect2.left -= sRect.left; +    sRect2.top -= sRect.top; + +    if (BST_UNCHECKED == IsDlgButtonChecked(g_hDlg,IDC_BLUBB)) { +        SetWindowPos(g_hDlg,nullptr,0,0,sRect.right-214,sRect.bottom, +            SWP_NOMOVE | SWP_NOZORDER); + +        SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),">>"); +        storeRegKey(false, "MultiSampling"); +    } else { +        SetWindowPos(g_hDlg,nullptr,0,0,sRect.right+214,sRect.bottom, +            SWP_NOMOVE | SWP_NOZORDER); + +        storeRegKey(true, "LastUIState"); +        SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),"<<"); +    } +    UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Load the background texture for the viewer +//------------------------------------------------------------------------------- +void LoadBGTexture() { +    char szFileName[MAX_PATH]; + +    DWORD dwTemp = MAX_PATH; +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"TextureSrc",nullptr,nullptr, (BYTE*)szFileName,&dwTemp)) { +        // Key was not found. Use C: +        strcpy(szFileName,""); +    } else { +        // need to remove the file name +        char* sz = strrchr(szFileName,'\\'); +        if (!sz) +            sz = strrchr(szFileName,'/'); +        if (sz) +            *sz = 0; +    } +    OPENFILENAME sFilename1 = { +        sizeof(OPENFILENAME), +        g_hDlg,GetModuleHandle(nullptr), +        "Textures\0*.png;*.dds;*.tga;*.bmp;*.tif;*.ppm;*.ppx;*.jpg;*.jpeg;*.exr\0*.*\0", +        nullptr, 0, 1, +        szFileName, MAX_PATH, nullptr, 0, nullptr, +        "Open texture as background", +        OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, +        0, 1, ".jpg", 0, nullptr, nullptr +    }; +    if(GetOpenFileName(&sFilename1) == 0) return; + +    // Now store the file in the registry +    RegSetValueExA(g_hRegistry,"TextureSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); +    RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); +    RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + +    CBackgroundPainter::Instance().SetTextureBG(szFileName); +} + +//------------------------------------------------------------------------------- +// Reset the background color to a smart and nice grey +//------------------------------------------------------------------------------- +void ClearBG() { +    D3DCOLOR clrColor = D3DCOLOR_ARGB(0xFF,100,100,100); +    CBackgroundPainter::Instance().SetColor(clrColor); + +    RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); +    RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + +    RegSetValueExA(g_hRegistry,"Color",0,REG_DWORD,(const BYTE*)&clrColor,4); +} + +//------------------------------------------------------------------------------- +// Let the user choose a color in a windows standard color dialog +//------------------------------------------------------------------------------- +void DisplayColorDialog(D3DCOLOR* pclrResult) { +    CHOOSECOLOR clr; +    clr.lStructSize = sizeof(CHOOSECOLOR); +    clr.hwndOwner = g_hDlg; +    clr.Flags = CC_RGBINIT | CC_FULLOPEN; +    clr.rgbResult = RGB((*pclrResult >> 16) & 0xff,(*pclrResult >> 8) & 0xff,*pclrResult & 0xff); +    clr.lpCustColors = g_aclCustomColors; +    clr.lpfnHook = nullptr; +    clr.lpTemplateName = nullptr; +    clr.lCustData = 0; + +    ChooseColor(&clr); + +    *pclrResult = D3DCOLOR_ARGB(0xFF, +        GetRValue(clr.rgbResult), +        GetGValue(clr.rgbResult), +        GetBValue(clr.rgbResult)); +} + +//------------------------------------------------------------------------------- +// Let the user choose a color in a windows standard color dialog +//------------------------------------------------------------------------------- +void DisplayColorDialog(D3DXVECTOR4* pclrResult) { +    CHOOSECOLOR clr; +    clr.lStructSize = sizeof(CHOOSECOLOR); +    clr.hwndOwner = g_hDlg; +    clr.Flags = CC_RGBINIT | CC_FULLOPEN; +    clr.rgbResult = RGB(clamp<unsigned char>(pclrResult->x * 255.0f), +        clamp<unsigned char>(pclrResult->y * 255.0f), +        clamp<unsigned char>(pclrResult->z * 255.0f)); +    clr.lpCustColors = g_aclCustomColors; +    clr.lpfnHook = nullptr; +    clr.lpTemplateName = nullptr; +    clr.lCustData = 0; + +    ChooseColor(&clr); + +    pclrResult->x = GetRValue(clr.rgbResult) / 255.0f; +    pclrResult->y = GetGValue(clr.rgbResult) / 255.0f; +    pclrResult->z = GetBValue(clr.rgbResult) / 255.0f; +} + +//------------------------------------------------------------------------------- +// Let the user choose the background color for the viewer +//------------------------------------------------------------------------------- +void ChooseBGColor() { +    RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); +    RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + +    D3DCOLOR clrColor; +    DisplayColorDialog(&clrColor); +    CBackgroundPainter::Instance().SetColor(clrColor); + +    RegSetValueExA(g_hRegistry,"Color",0,REG_DWORD,(const BYTE*)&clrColor,4); +} + +//------------------------------------------------------------------------------- +// Display the OpenFile dialog and let the user choose a new slybox as bg +//------------------------------------------------------------------------------- +void LoadSkybox() { +    char szFileName[MAX_PATH]; + +    DWORD dwTemp = MAX_PATH; +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"SkyBoxSrc",nullptr,nullptr, +        (BYTE*)szFileName,&dwTemp)) +    { +        // Key was not found. Use C: +        strcpy(szFileName,""); +    } +    else +    { +        // need to remove the file name +        char* sz = strrchr(szFileName,'\\'); +        if (!sz) +            sz = strrchr(szFileName,'/'); +        if (sz) +            *sz = 0; +    } +    OPENFILENAME sFilename1 = { +        sizeof(OPENFILENAME), +        g_hDlg,GetModuleHandle(nullptr), +        "Skyboxes\0*.dds\0*.*\0", nullptr, 0, 1, +        szFileName, MAX_PATH, nullptr, 0, nullptr, +        "Open skybox as background", +        OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, +        0, 1, ".dds", 0, nullptr, nullptr +    }; +    if(GetOpenFileName(&sFilename1) == 0) return; + +    // Now store the file in the registry +    RegSetValueExA(g_hRegistry,"SkyBoxSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); +    RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); +    RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + +    CBackgroundPainter::Instance().SetCubeMapBG(szFileName); +    return; +} + +template<class T> +inline +void SaveRelease(T **iface ) { +    if (nullptr != iface) { +        (*iface)->Release(); +        *iface = nullptr; +    } +} + +//------------------------------------------------------------------------------- +// Save a screenshot to an user-defined file +//------------------------------------------------------------------------------- +void SaveScreenshot() { +    char szFileName[MAX_PATH]; + +    DWORD dwTemp = MAX_PATH; +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"ScreenShot",nullptr,nullptr, (BYTE*)szFileName,&dwTemp)) { +        // Key was not found. Use C: +        strcpy(szFileName,""); +    } else { +        // need to remove the file name +        char* sz = strrchr(szFileName,'\\'); +        if (!sz) +            sz = strrchr(szFileName,'/'); +        if (sz) +            *sz = 0; +    } +    OPENFILENAME sFilename1 = { +        sizeof(OPENFILENAME), +        g_hDlg,GetModuleHandle(nullptr), +        "PNG Images\0*.png", nullptr, 0, 1, +        szFileName, MAX_PATH, nullptr, 0, nullptr, +        "Save Screenshot to file", +        OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, +        0, 1, ".png", 0, nullptr, nullptr +    }; +    if(GetSaveFileName(&sFilename1) == 0) return; + +    // Now store the file in the registry +    RegSetValueExA(g_hRegistry,"ScreenShot",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + +    IDirect3DSurface9* pi = nullptr; +    g_piDevice->GetRenderTarget(0,&pi); +    if(!pi || FAILED(D3DXSaveSurfaceToFile(szFileName,D3DXIFF_PNG,pi,nullptr,nullptr))) { +        CLogDisplay::Instance().AddEntry("[ERROR] Unable to save screenshot", +            D3DCOLOR_ARGB(0xFF,0xFF,0,0)); +    } else { +        CLogDisplay::Instance().AddEntry("[INFO] The screenshot has been saved", +            D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); +    } +    SaveRelease(&pi); +} + +//------------------------------------------------------------------------------- +// Get the amount of memory required for textures +//------------------------------------------------------------------------------- +void AddTextureMem(IDirect3DTexture9* pcTex, unsigned int& out) { +    if (!pcTex) { +        return; +    } + +    D3DSURFACE_DESC sDesc; +    pcTex->GetLevelDesc(0,&sDesc); + +    out += (sDesc.Width * sDesc.Height) << 2; +} + +//------------------------------------------------------------------------------- +// Display memory statistics +//------------------------------------------------------------------------------- +void DisplayMemoryConsumption() { +    // first get the memory consumption for the aiScene +    if (! g_pcAsset ||!g_pcAsset->pcScene) { +        MessageBox(g_hDlg,"No asset is loaded. Can you guess how much memory I need to store nothing?", +            "Memory consumption",MB_OK); +        return; +    } +    unsigned int iScene = sizeof(aiScene); +    for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { +        iScene += sizeof(aiMesh); +        if (g_pcAsset->pcScene->mMeshes[i]->HasPositions()) +            iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; + +        if (g_pcAsset->pcScene->mMeshes[i]->HasNormals()) +            iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; + +        if (g_pcAsset->pcScene->mMeshes[i]->HasTangentsAndBitangents()) +            iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices * 2; + +        for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) { +            if (g_pcAsset->pcScene->mMeshes[i]->HasVertexColors(a)) { +                iScene += sizeof(aiColor4D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; +            } else { +                break; +            } +        } +        for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) { +            if (g_pcAsset->pcScene->mMeshes[i]->HasTextureCoords(a)) +                iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; +            else break; +        } +        if (g_pcAsset->pcScene->mMeshes[i]->HasBones()) { +            for (unsigned int p = 0; p < g_pcAsset->pcScene->mMeshes[i]->mNumBones;++p) { +                iScene += sizeof(aiBone); +                iScene += g_pcAsset->pcScene->mMeshes[i]->mBones[p]->mNumWeights * sizeof(aiVertexWeight); +            } +        } +        iScene += (sizeof(aiFace) + 3 * sizeof(unsigned int))*g_pcAsset->pcScene->mMeshes[i]->mNumFaces; +    } +    // add all embedded textures +    for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumTextures;++i) { +        const aiTexture* pc = g_pcAsset->pcScene->mTextures[i]; +        if (0 != pc->mHeight) { +            iScene += 4 * pc->mHeight * pc->mWidth; +        } else { +            iScene += pc->mWidth; +        } +    } +    // add 30k for each material ... a string has 4k for example +    iScene += g_pcAsset->pcScene->mNumMaterials * 30 * 1024; + +    // now get the memory consumption required by D3D, first all textures +    unsigned int iTexture = 0; +    for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { +        AssetHelper::MeshHelper* pc = g_pcAsset->apcMeshes[i]; + +        AddTextureMem(pc->piDiffuseTexture,iTexture); +        AddTextureMem(pc->piSpecularTexture,iTexture); +        AddTextureMem(pc->piAmbientTexture,iTexture); +        AddTextureMem(pc->piEmissiveTexture,iTexture); +        AddTextureMem(pc->piOpacityTexture,iTexture); +        AddTextureMem(pc->piNormalTexture,iTexture); +        AddTextureMem(pc->piShininessTexture,iTexture); +    } +    unsigned int iVRAM = iTexture; + +    // now get the memory consumption of all vertex/index buffers +    unsigned int iVB( 0 ), iIB(0); +    for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { +        AssetHelper:: MeshHelper* pc = g_pcAsset->apcMeshes[i]; + +        union{ +            D3DVERTEXBUFFER_DESC sDesc; +            D3DINDEXBUFFER_DESC sDesc2; +        }; + +        if (pc->piVB) +        { +            pc->piVB->GetDesc(&sDesc); +            iVB += sDesc.Size; +        } +        if (pc->piVBNormals) +        { +            pc->piVBNormals->GetDesc(&sDesc); +            iVB += sDesc.Size; +        } +        if (pc->piIB) +        { +            pc->piIB->GetDesc(&sDesc2); +            iIB += sDesc2.Size; +        } +    } +    iVRAM += iVB + iIB; +    // add the memory for the back buffer and depth stencil buffer +    RECT sRect; +    GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); +    sRect.bottom -= sRect.top; +    sRect.right -= sRect.left; +    iVRAM += sRect.bottom * sRect.right * 8; + +    char szOut[2048]; +    sprintf(szOut, +        "(1 KiB = 1024 bytes)\n\n" +        "ASSIMP Import Data: \t%i KiB\n" +        "Texture data:\t\t%i KiB\n" +        "Vertex buffers:\t\t%i KiB\n" +        "Index buffers:\t\t%i KiB\n" +        "Video Memory:\t\t%i KiB\n\n" +        "Total: \t\t\t%i KiB", +        iScene / 1024,iTexture / 1024,iVB / 1024,iIB / 1024,iVRAM / 1024, +        (iScene + iTexture + iVB + iIB + iVRAM) / 1024); +    MessageBox(g_hDlg,szOut,"Memory consumption",MB_OK); +} + +//------------------------------------------------------------------------------- +// Save the list of recent files to the registry +//------------------------------------------------------------------------------- +void SaveHistory() { +    for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) { +        char szName[66]; +        sprintf(szName,"Recent%i",i+1); + +        RegSetValueEx(g_hRegistry,szName,0,REG_SZ, +            (const BYTE*)g_aPreviousFiles[i].c_str(),(DWORD)g_aPreviousFiles[i].length()); +    } +} + +//------------------------------------------------------------------------------- +// Recover the file history +//------------------------------------------------------------------------------- +void LoadHistory() { +    g_aPreviousFiles.resize(AI_VIEW_NUM_RECENT_FILES); + +    char szFileName[MAX_PATH]; + +    for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) { +        char szName[66]; +        sprintf(szName,"Recent%i",i+1); + +        DWORD dwTemp = MAX_PATH; + +        szFileName[0] ='\0'; +        if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,szName,nullptr,nullptr, +                (BYTE*)szFileName,&dwTemp)) { +            g_aPreviousFiles[i] = std::string(szFileName); +        } +    } + +    // add sub items for all recent files +    g_hHistoryMenu = CreateMenu(); +    for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) { +        const char* szText = g_aPreviousFiles[i].c_str(); +        UINT iFlags = 0; +        if ('\0' == *szText) { +            szText = "<empty>"; +            iFlags = MF_GRAYED | MF_DISABLED; +        } +        AppendMenu(g_hHistoryMenu,MF_STRING | iFlags,AI_VIEW_RECENT_FILE_ID(i),szText); +    } + +    ModifyMenu(GetMenu(g_hDlg),ID_VIEWER_RECENTFILES,MF_BYCOMMAND | MF_POPUP, +        (UINT_PTR)g_hHistoryMenu,"Recent files"); +} + +//------------------------------------------------------------------------------- +// Clear the file history +//------------------------------------------------------------------------------- +void ClearHistory() { +    for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES; ++i) { +        g_aPreviousFiles[i] = std::string(""); +    } + +    for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) { +        ModifyMenu(g_hHistoryMenu,AI_VIEW_RECENT_FILE_ID(i), +            MF_STRING | MF_BYCOMMAND | MF_GRAYED | MF_DISABLED,AI_VIEW_RECENT_FILE_ID(i),"<empty>"); +    } + +    SaveHistory(); +} + +//------------------------------------------------------------------------------- +// Update the file history +//------------------------------------------------------------------------------- +void UpdateHistory() { +    if (!g_hHistoryMenu) { +        return; +    } + +    std::string sz = std::string(g_szFileName); +    if (g_aPreviousFiles[AI_VIEW_NUM_RECENT_FILES - 1] == sz) { +        return; +    } + +    // add the new asset to the list of recent files +    for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES-1;++i) { +        g_aPreviousFiles[i] = g_aPreviousFiles[i+1]; +    } +    g_aPreviousFiles[AI_VIEW_NUM_RECENT_FILES-1] = sz; +    for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) { +        const char* szText = g_aPreviousFiles[i].c_str(); +        UINT iFlags = 0; +        if ('\0' == *szText) { +            szText = "<empty>"; +            iFlags = MF_GRAYED | MF_DISABLED; +        } +        ModifyMenu(g_hHistoryMenu,AI_VIEW_RECENT_FILE_ID(i), +            MF_STRING | MF_BYCOMMAND | iFlags,AI_VIEW_RECENT_FILE_ID(i),szText); +    } +} + +//------------------------------------------------------------------------------- +// Open a new asset +//------------------------------------------------------------------------------- +void OpenAsset() { +    char szFileName[MAX_PATH]; + +    DWORD dwTemp = MAX_PATH; +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"CurrentApp",nullptr,nullptr, (BYTE*)szFileName,&dwTemp)) { +        // Key was not found. Use C: +        strcpy(szFileName,""); +    } else { +        // need to remove the file name +        char* sz = strrchr(szFileName,'\\'); +        if (!sz) +            sz = strrchr(szFileName,'/'); +        if (sz) +            *sz = 0; +    } + +    // get a list of all file extensions supported by ASSIMP +    aiString sz; +    aiGetExtensionList(&sz); + +    char szList[MAXLEN + 100]; +    strcpy(szList,"ASSIMP assets"); +    char* szCur = szList + 14; +    strcpy(szCur,sz.data); +    szCur += sz.length+1; +    strcpy(szCur,"All files"); +    szCur += 10; +    strcpy(szCur,"*.*"); +    szCur[4] = 0; + +    OPENFILENAME sFilename1; +    ZeroMemory(&sFilename1, sizeof(sFilename1)); +    sFilename1.lStructSize = sizeof(sFilename1); +    sFilename1.hwndOwner = g_hDlg; +    sFilename1.hInstance = GetModuleHandle(nullptr); +    sFilename1.lpstrFile = szFileName; +    sFilename1.lpstrFile[0] = '\0'; +    sFilename1.nMaxFile = sizeof(szList); +    sFilename1.lpstrFilter = szList; +    sFilename1.nFilterIndex = 1; +    sFilename1.lpstrFileTitle = nullptr; +    sFilename1.nMaxFileTitle = 0; +    sFilename1.lpstrInitialDir = nullptr; +    sFilename1.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; +    if (GetOpenFileName(&sFilename1) == 0) { +        return; +    } + +    // Now store the file in the registry +    RegSetValueExA(g_hRegistry,"CurrentApp",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + +    if (0 != strcmp(g_szFileName,szFileName)) { +        strcpy(g_szFileName, szFileName); +        DeleteAssetData(); +        DeleteAsset(); +        LoadAsset(); + +        // update the history +        UpdateHistory(); + +        // Save the list of previous files to the registry +        SaveHistory(); +    } +} + +//------------------------------------------------------------------------------- +void SetupPPUIState() { +    // that's ugly. anyone willing to rewrite me from scratch? +    HMENU hMenu = GetMenu(g_hDlg); +    CheckMenuItem(hMenu,ID_VIEWER_PP_JIV,ppsteps & aiProcess_JoinIdenticalVertices ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_CTS,ppsteps & aiProcess_CalcTangentSpace ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_FD,ppsteps & aiProcess_FindDegenerates ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_FID,ppsteps & aiProcess_FindInvalidData ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_FIM,ppsteps & aiProcess_FindInstances ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_FIN,ppsteps & aiProcess_FixInfacingNormals ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_GUV,ppsteps & aiProcess_GenUVCoords ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_ICL,ppsteps & aiProcess_ImproveCacheLocality ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_OG,ppsteps & aiProcess_OptimizeGraph ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_OM,ppsteps & aiProcess_OptimizeMeshes ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_PTV,ppsteps & aiProcess_PreTransformVertices ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_RRM2,ppsteps & aiProcess_RemoveRedundantMaterials ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_TUV,ppsteps & aiProcess_TransformUVCoords ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_VDS,ppsteps & aiProcess_ValidateDataStructure ? MF_CHECKED : MF_UNCHECKED); +    CheckMenuItem(hMenu,ID_VIEWER_PP_DB,ppsteps & aiProcess_Debone ? MF_CHECKED : MF_UNCHECKED); +} + +#ifndef ASSIMP_BUILD_NO_EXPORT +//------------------------------------------------------------------------------- +// Fill the 'export' top level menu with a list of all supported export formats +//------------------------------------------------------------------------------- +void PopulateExportMenu() { +    // add sub items for all recent files +    Exporter exp; +    HMENU hm = ::CreateMenu(); +    for(size_t i = 0; i < exp.GetExportFormatCount(); ++i) { +        const aiExportFormatDesc* const e = exp.GetExportFormatDescription(i); +        char tmp[256]; +        sprintf(tmp,"%s (%s)",e->description,e->id); + +        AppendMenu(hm,MF_STRING,AI_VIEW_EXPORT_FMT_ID(i),tmp); +    } + +    ModifyMenu(GetMenu(g_hDlg),ID_EXPORT,MF_BYCOMMAND | MF_POPUP, +        (UINT_PTR)hm,"Export"); +} + +//------------------------------------------------------------------------------- +// Export function +//------------------------------------------------------------------------------- +void DoExport(size_t formatId) { +    if (!g_szFileName[0]) { +        MessageBox(g_hDlg, "No model loaded", "Export", MB_ICONERROR); +        return; +    } +    Exporter exp; +    const aiExportFormatDesc* const e = exp.GetExportFormatDescription(formatId); +    ai_assert(e); + +    char szFileName[MAX_PATH*2]; +    DWORD dwTemp = sizeof(szFileName); +    if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"ModelExportDest",nullptr,nullptr,(BYTE*)szFileName, &dwTemp)) { +        ai_assert(strlen(szFileName) <= MAX_PATH); + +        // invent a nice default file name +        char* sz = std::max(strrchr(szFileName,'\\'),strrchr(szFileName,'/')); +        if (sz) { +            strncpy(sz,std::max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/')),MAX_PATH); +        } +    } +    else { +        // Key was not found. Use the folder where the asset comes from +        strncpy(szFileName,g_szFileName,MAX_PATH); +    } + +    // fix file extension +    {   char * const sz = strrchr(szFileName,'.'); +        if(sz) { +            ai_assert((sz - &szFileName[0]) + strlen(e->fileExtension) + 1 <= MAX_PATH); +            strcpy(sz+1,e->fileExtension); +        } +    } + +    // build the stupid info string for GetSaveFileName() - can't use sprintf() because the string must contain binary zeros. +    char desc[256] = {0}; +    char* c = strcpy(desc,e->description) + strlen(e->description)+1; +    c += sprintf(c,"*.%s",e->fileExtension)+1; +    strcpy(c, "*.*\0"); c += 4; + +    ai_assert(c - &desc[0] <= 256); + +    const std::string ext = "."+std::string(e->fileExtension); +    OPENFILENAME sFilename1 = { +        sizeof(OPENFILENAME), +        g_hDlg,GetModuleHandle(nullptr), +        desc, nullptr, 0, 1, +        szFileName, MAX_PATH, nullptr, 0, nullptr, +        "Export asset", +        OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, +        0, 1, ext.c_str(), 0, nullptr, nullptr +    }; +    if(::GetSaveFileName(&sFilename1) == 0) { +        return; +    } + +    // Now store the file in the registry unless the user decided to stay in the model directory +    const std::string sFinal = szFileName, sub = sFinal.substr(0,sFinal.find_last_of("\\/")); +    if (strncmp(sub.c_str(),g_szFileName,sub.length())) { +        RegSetValueExA(g_hRegistry,"ModelExportDest",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); +    } + +    // export the file +    const aiReturn res = exp.Export(g_pcAsset->pcScene,e->id,sFinal.c_str(), +        ppsteps | /* configurable pp steps */ +        aiProcess_GenSmoothNormals         | // generate smooth normal vectors if not existing +        aiProcess_SplitLargeMeshes         | // split large, unrenderable meshes into submeshes +        aiProcess_Triangulate              | // triangulate polygons with more than 3 edges +        aiProcess_ConvertToLeftHanded      | // convert everything to D3D left handed space +        aiProcess_SortByPType              | // make 'clean' meshes which consist of a single typ of primitives +        0 +    ); +    if (res == aiReturn_SUCCESS) { +        CLogDisplay::Instance().AddEntry("[INFO] Exported file " + sFinal,D3DCOLOR_ARGB(0xFF,0x00,0xFF,0x00)); +        return; +    } +    CLogDisplay::Instance().AddEntry("[INFO] Failure exporting file " + +        sFinal,D3DCOLOR_ARGB(0xFF,0xFF,0x00,0x00)); +} +#endif + +//------------------------------------------------------------------------------- +// Initialize the user interface +//------------------------------------------------------------------------------- +void InitUI() { +    SetDlgItemText(g_hDlg,IDC_EVERT,"0"); +    SetDlgItemText(g_hDlg,IDC_EFACE,"0"); +    SetDlgItemText(g_hDlg,IDC_EMAT,"0"); +    SetDlgItemText(g_hDlg,IDC_ESHADER,"0"); +    SetDlgItemText(g_hDlg,IDC_ENODEWND,"0"); +    SetDlgItemText(g_hDlg,IDC_ETEX,"0"); +    SetDlgItemText(g_hDlg,IDC_EMESH,"0"); + +#ifndef ASSIMP_BUILD_NO_EXPORT +    PopulateExportMenu(); +#endif + +    // setup the default window title +    SetWindowText(g_hDlg,AI_VIEW_CAPTION_BASE); + +    // read some UI properties from the registry and apply them +    DWORD dwValue; +    DWORD dwTemp = sizeof( DWORD ); + +    // store the key in a global variable for later use +    RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ASSIMP\\Viewer", +        0,nullptr,0,KEY_ALL_ACCESS, nullptr, &g_hRegistry,nullptr); + +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LastUIState",nullptr,nullptr, (BYTE*)&dwValue,&dwTemp)) { +        dwValue = 1; +    } +    if (0 == dwValue) { +        // collapse the viewer +        // adjust the size +        RECT sRect; +        GetWindowRect(g_hDlg,&sRect); +        sRect.right -= sRect.left; +        sRect.bottom -= sRect.top; + +        RECT sRect2; +        GetWindowRect(GetDlgItem ( g_hDlg, IDC_BLUBB ),&sRect2); +        sRect2.left -= sRect.left; +        sRect2.top -= sRect.top; + +        SetWindowPos(g_hDlg,nullptr,0,0,sRect.right-214,sRect.bottom, +            SWP_NOMOVE | SWP_NOZORDER); +        SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),">>"); +    } else { +        CheckDlgButton(g_hDlg,IDC_BLUBB,BST_CHECKED); +    } + +    // AutoRotate +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"AutoRotate",nullptr,nullptr, +        (BYTE*)&dwValue,&dwTemp))dwValue = 0; +    if (0 == dwValue) { +        g_sOptions.bRotate = false; +        CheckDlgButton(g_hDlg,IDC_AUTOROTATE,BST_UNCHECKED); +    } else { +        g_sOptions.bRotate = true; +        CheckDlgButton(g_hDlg,IDC_AUTOROTATE,BST_CHECKED); +    } + +    // MultipleLights +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"MultipleLights",nullptr,nullptr, +        (BYTE*)&dwValue,&dwTemp))dwValue = 0; +    if (0 == dwValue) { +        g_sOptions.b3Lights = false; +        CheckDlgButton(g_hDlg,IDC_3LIGHTS,BST_UNCHECKED); +    } else { +        g_sOptions.b3Lights = true; +        CheckDlgButton(g_hDlg,IDC_3LIGHTS,BST_CHECKED); +    } + +    // Light rotate +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LightRotate",nullptr,nullptr, +        (BYTE*)&dwValue,&dwTemp))dwValue = 0; +    if (0 == dwValue) { +        g_sOptions.bLightRotate = false; +        CheckDlgButton(g_hDlg,IDC_LIGHTROTATE,BST_UNCHECKED); +    } else { +        g_sOptions.bLightRotate = true; +        CheckDlgButton(g_hDlg,IDC_LIGHTROTATE,BST_CHECKED); +    } + +    // NoSpecular +    if (ERROR_SUCCESS != RegQueryValueEx(g_hRegistry, "NoSpecular", nullptr, nullptr, (BYTE*)&dwValue, &dwTemp)) { +        dwValue = 0; +    } +    if (0 == dwValue) { +        g_sOptions.bNoSpecular = false; +        CheckDlgButton(g_hDlg,IDC_NOSPECULAR,BST_UNCHECKED); +    } else { +        g_sOptions.bNoSpecular = true; +        CheckDlgButton(g_hDlg,IDC_NOSPECULAR,BST_CHECKED); +    } + +    // LowQuality +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LowQuality",nullptr,nullptr, +        (BYTE*)&dwValue,&dwTemp))dwValue = 0; +    if (0 == dwValue) { +        g_sOptions.bLowQuality = false; +        CheckDlgButton(g_hDlg,IDC_LOWQUALITY,BST_UNCHECKED); +    } else { +        g_sOptions.bLowQuality = true; +        CheckDlgButton(g_hDlg,IDC_LOWQUALITY,BST_CHECKED); +    } + +    // LowQuality +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"NoTransparency",nullptr,nullptr, +        (BYTE*)&dwValue,&dwTemp))dwValue = 0; +    if (0 == dwValue) { +        g_sOptions.bNoAlphaBlending = false; +        CheckDlgButton(g_hDlg,IDC_NOAB,BST_UNCHECKED); +    } else { +        g_sOptions.bNoAlphaBlending = true; +        CheckDlgButton(g_hDlg,IDC_NOAB,BST_CHECKED); +    } + +    // DisplayNormals +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"RenderNormals",nullptr,nullptr, +        (BYTE*)&dwValue,&dwTemp))dwValue = 0; +    if (0 == dwValue) { +        g_sOptions.bRenderNormals = false; +        CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS,BST_UNCHECKED); +    } else { +        g_sOptions.bRenderNormals = true; +        CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS,BST_CHECKED); +    } + +    // NoMaterials +    if (ERROR_SUCCESS != RegQueryValueEx(g_hRegistry, "RenderMats", nullptr, nullptr, +        (BYTE*)&dwValue, &dwTemp)) { +        dwValue = 1; +    } +    if (0 == dwValue) { +        g_sOptions.bRenderMats = false; +        CheckDlgButton(g_hDlg,IDC_TOGGLEMAT,BST_CHECKED); +    } else { +        g_sOptions.bRenderMats = true; +        CheckDlgButton(g_hDlg,IDC_TOGGLEMAT,BST_UNCHECKED); +    } + +    // MultiSampling +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"MultiSampling",nullptr,nullptr, +        (BYTE*)&dwValue,&dwTemp))dwValue = 1; +    if (0 == dwValue) +    { +        g_sOptions.bMultiSample = false; +        CheckDlgButton(g_hDlg,IDC_TOGGLEMS,BST_UNCHECKED); +    } else { +        g_sOptions.bMultiSample = true; +        CheckDlgButton(g_hDlg,IDC_TOGGLEMS,BST_CHECKED); +    } + +    // FPS Mode +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"FPSView",nullptr,nullptr, +        (BYTE*)&dwValue,&dwTemp))dwValue = 0; +    if (0 == dwValue) { +        g_bFPSView = false; +        CheckDlgButton(g_hDlg,IDC_ZOOM,BST_CHECKED); +    } else { +        g_bFPSView = true; +        CheckDlgButton(g_hDlg,IDC_ZOOM,BST_UNCHECKED); +    } + +    // WireFrame +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"Wireframe",nullptr,nullptr, +        (BYTE*)&dwValue,&dwTemp))dwValue = 0; +    if (0 == dwValue) +    { +        g_sOptions.eDrawMode = RenderOptions::NORMAL; +        CheckDlgButton(g_hDlg,IDC_TOGGLEWIRE,BST_UNCHECKED); +    } +    else +    { +        g_sOptions.eDrawMode = RenderOptions::WIREFRAME; +        CheckDlgButton(g_hDlg,IDC_TOGGLEWIRE,BST_CHECKED); +    } + +    if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"PostProcessing",nullptr,nullptr,(BYTE*)&dwValue,&dwTemp)) +        ppsteps = ppstepsdefault; +    else ppsteps = dwValue; + +    SetupPPUIState(); +    LoadCheckerPatternColors(); + +    SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETRANGEMIN,TRUE,0); +    SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETRANGEMAX,TRUE,10000); +} + +//------------------------------------------------------------------------------- +// Message procedure for the smooth normals dialog +//------------------------------------------------------------------------------- +INT_PTR CALLBACK SMMessageProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM lParam) { +    UNREFERENCED_PARAMETER(lParam); +    switch (uMsg) { +    case WM_INITDIALOG: +        { +            char s[30]; +            ::sprintf(s, "%.2f", g_smoothAngle); +            SetDlgItemText(hwndDlg, IDC_EDITSM, s); +        } +        return TRUE; + +    case WM_CLOSE: +        EndDialog(hwndDlg,0); +        return TRUE; + +    case WM_COMMAND: +        { +            if (IDOK == LOWORD(wParam)) { +                char s[30]; +                GetDlgItemText(hwndDlg, IDC_EDITSM, s, 30); +                g_smoothAngle = (float)atof(s); + +                EndDialog(hwndDlg, 0); +            } else if (IDCANCEL == LOWORD(wParam)) { +                EndDialog(hwndDlg, 1); +            } +        } +        return TRUE; +    } +    return FALSE; +} + +//------------------------------------------------------------------------------- +// Main message procedure of the application +// +// The function handles all incoming messages for the main window. +// However, if does not directly process input commands. +// NOTE: Due to the impossibility to process WM_CHAR messages in dialogs +// properly the code for all hotkeys has been moved to the WndMain +//------------------------------------------------------------------------------- +INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM lParam) { +    UNREFERENCED_PARAMETER(lParam); +    UNREFERENCED_PARAMETER(wParam); + +    int xPos,yPos; +    int xPos2,yPos2; +    int fHalfX; +    int fHalfY; + +    TRACKMOUSEEVENT sEvent; +    switch (uMsg) +        { +        case WM_INITDIALOG: + +            g_hDlg = hwndDlg; + +            // load the state of the user interface +            InitUI(); + +            // load the file history +            LoadHistory(); + +            // load the current color of the lights +            LoadLightColors(); +            return TRUE; + +        case WM_HSCROLL: + +            // XXX quick and dirty fix for #3029892 +            if (GetDlgItem(g_hDlg, IDC_SLIDERANIM) == (HWND)lParam && g_pcAsset && g_pcAsset->pcScene->mAnimations) +            { +                double num = (double)SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_GETPOS,0,0); +                const aiAnimation* anim = g_pcAsset->pcScene->mAnimations[ g_pcAsset->mAnimator->CurrentAnimIndex() ]; + +                g_dCurrent = (anim->mDuration/anim->mTicksPerSecond) * num/10000; +                g_pcAsset->mAnimator->Calculate(g_dCurrent); +            } +            break; + +        case WM_MOUSEWHEEL: + +            if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) +            { +                CDisplay::Instance().SetTextureViewZoom ( GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f ); +            } +            else +            { +                if (!g_bFPSView) +                    { +                    g_sCamera.vPos.z += GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f; +                    } +                else +                    { +                    g_sCamera.vPos += (GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f) * +                        g_sCamera.vLookAt.Normalize(); +                    } +            } +            return TRUE; + +        case WM_MOUSELEAVE: + +            g_bMousePressed = false; +            g_bMousePressedR = false; +            g_bMousePressedM = false; +            g_bMousePressedBoth = false; +            return TRUE; + +        case WM_LBUTTONDBLCLK: + +            CheckDlgButton(hwndDlg,IDC_AUTOROTATE, +                IsDlgButtonChecked(hwndDlg,IDC_AUTOROTATE) == BST_CHECKED +                ? BST_UNCHECKED : BST_CHECKED); + +            ToggleAutoRotate(); +            return TRUE; + + +        case WM_CLOSE: +            PostQuitMessage(0); +            DestroyWindow(hwndDlg); +            return TRUE; + +        case WM_NOTIFY: + +            if (IDC_TREE1 == wParam) +            { +                NMTREEVIEW* pnmtv = (LPNMTREEVIEW) lParam; + +                if (TVN_SELCHANGED == pnmtv->hdr.code) +                    CDisplay::Instance().OnSetup( pnmtv->itemNew.hItem ); +                else if (NM_RCLICK == pnmtv->hdr.code) +                { +                    // determine in which item the click was ... +                    POINT sPoint; +                    GetCursorPos(&sPoint); +                    ScreenToClient(GetDlgItem(g_hDlg,IDC_TREE1),&sPoint); + +                    TVHITTESTINFO sHit; +                    sHit.pt = sPoint; +                    TreeView_HitTest(GetDlgItem(g_hDlg,IDC_TREE1),&sHit); +                    CDisplay::Instance().ShowTreeViewContextMenu(sHit.hItem); +                } +            } +            return TRUE; + +        case WM_DRAWITEM: +            { +                // draw the two light colors +                DRAWITEMSTRUCT* pcStruct = (DRAWITEMSTRUCT*)lParam; + +                RECT sRect; +                GetWindowRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),&sRect); +                sRect.right -= sRect.left; +                sRect.bottom -= sRect.top; +                sRect.left = sRect.top = 0; + +                bool bDraw = false; + +                if(IDC_LCOLOR1 == pcStruct->CtlID) +                { +                    unsigned char r,g,b; +                    const char* szText; +                    if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || +                        CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) +                    { +                        r = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->x * 255.0f); +                        g = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->y * 255.0f); +                        b = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->z * 255.0f); +                        szText = "Background #0"; +                    } +                    else if (!g_pcAsset) +                    { +                        r = g = b = 150;szText = ""; +                    } +                    else +                    { +                        r = (unsigned char)((g_avLightColors[0] >> 16) & 0xFF); +                        g = (unsigned char)((g_avLightColors[0] >> 8) & 0xFF); +                        b = (unsigned char)((g_avLightColors[0]) & 0xFF); +                        szText = "Light #0"; +                    } +                    HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); + +                    FillRect(pcStruct->hDC,&sRect,hbr); + + +                    SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); +                    SetBkMode(pcStruct->hDC,TRANSPARENT); +                    TextOut(pcStruct->hDC,4,1,szText, static_cast<int>(strlen(szText))); +                    bDraw = true; +                } +                else if(IDC_LCOLOR2 == pcStruct->CtlID) +                { +                    unsigned char r,g,b; +                    const char* szText; +                    if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || +                        CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) +                    { +                        r = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->x * 255.0f); +                        g = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->y * 255.0f); +                        b = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->z * 255.0f); +                        szText = "Background #1"; +                    } +                    else if (!g_pcAsset) +                    { +                        r = g = b = 150;szText = ""; +                    } +                    else +                    { +                        r = (unsigned char)((g_avLightColors[1] >> 16) & 0xFF); +                        g = (unsigned char)((g_avLightColors[1] >> 8) & 0xFF); +                        b = (unsigned char)((g_avLightColors[1]) & 0xFF); +                        szText = "Light #1"; +                    } +                    HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); +                    FillRect(pcStruct->hDC,&sRect,hbr); + +                    SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); +                    SetBkMode(pcStruct->hDC,TRANSPARENT); +                    TextOut(pcStruct->hDC,4,1,szText, static_cast<int>(strlen(szText))); +                    bDraw = true; +                } +                else if(IDC_LCOLOR3 == pcStruct->CtlID) +                { +                    unsigned char r,g,b; +                    const char* szText; +                    if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || +                        CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) +                    { +                        r = g = b = 0; +                        szText = ""; +                    } +                    else if (!g_pcAsset) +                    { +                        r = g = b = 150;szText = ""; +                    } +                    else +                    { +                        r = (unsigned char)((g_avLightColors[2] >> 16) & 0xFF); +                        g = (unsigned char)((g_avLightColors[2] >> 8) & 0xFF); +                        b = (unsigned char)((g_avLightColors[2]) & 0xFF); +                        szText = "Ambient"; +                    } +                    HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); +                    FillRect(pcStruct->hDC,&sRect,hbr); + +                    SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); +                    SetBkMode(pcStruct->hDC,TRANSPARENT); +                    TextOut(pcStruct->hDC,4,1,szText,static_cast<int>(strlen(szText))); +                    bDraw = true; +                } +                // draw the black border around the rects +                if (bDraw) +                { +                    SetBkColor(pcStruct->hDC,RGB(0,0,0)); +                    MoveToEx(pcStruct->hDC,0,0,nullptr); +                    LineTo(pcStruct->hDC,sRect.right-1,0); +                    LineTo(pcStruct->hDC,sRect.right-1,sRect.bottom-1); +                    LineTo(pcStruct->hDC,0,sRect.bottom-1); +                    LineTo(pcStruct->hDC,0,0); +                } +            } +            return TRUE; + +        case WM_DESTROY: + +            // close the open registry key +            RegCloseKey(g_hRegistry); +            return TRUE; + +        case WM_LBUTTONDOWN: +            g_bMousePressed = true; + +            // register a mouse track handler to be sure we'll know +            // when the mouse leaves the display view again +            sEvent.cbSize = sizeof(TRACKMOUSEEVENT); +            sEvent.dwFlags = TME_LEAVE; +            sEvent.hwndTrack = g_hDlg; +            sEvent.dwHoverTime = HOVER_DEFAULT; +            TrackMouseEvent(&sEvent); + +            if (g_bMousePressedR) +                { +                g_bMousePressed = false; +                g_bMousePressedR = false; +                g_bMousePressedBoth = true; +                return TRUE; +                } + +            // need to determine the position of the mouse and the +            // distance from the center +            //xPos = (int)(short)LOWORD(lParam); +            //yPos = (int)(short)HIWORD(lParam); + +            POINT sPoint; +            GetCursorPos(&sPoint); +            ScreenToClient(GetDlgItem(g_hDlg,IDC_RT),&sPoint); +            xPos = xPos2 = sPoint.x; +            yPos = yPos2 = sPoint.y; + +            RECT sRect; +            GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); +            sRect.right -= sRect.left; +            sRect.bottom -= sRect.top; + +            // if the mouse click was inside the viewer panel +            // give the focus to it +            if (xPos > 0 && xPos < sRect.right && yPos > 0 && yPos < sRect.bottom) +                { +                SetFocus(GetDlgItem(g_hDlg,IDC_RT)); +                } + +            // g_bInvert stores whether the mouse has started on the negative +            // x or on the positive x axis of the imaginary coordinate system +            // with origin p at the center of the HUD texture +            xPos -= sRect.right/2; +            yPos -= sRect.bottom/2; + +            if (xPos > 0)g_bInvert = true; +            else g_bInvert = false; + +            D3DSURFACE_DESC sDesc; +            g_pcTexture->GetLevelDesc(0,&sDesc); + +            fHalfX = (int)(((float)sRect.right-(float)sDesc.Width) / 2.0f); +            fHalfY = (int)(((float)sRect.bottom-(float)sDesc.Height) / 2.0f); + +            // Determine the input operation to perform for this position +            g_eClick = EClickPos_Outside; +            if (xPos2 >= fHalfX && xPos2 < fHalfX + (int)sDesc.Width && +                yPos2 >= fHalfY && yPos2 < fHalfY + (int)sDesc.Height && +                nullptr != g_szImageMask) +                { +                // inside the texture. Lookup the grayscale value from it +                xPos2 -= fHalfX; +                yPos2 -= fHalfY; + +                unsigned char chValue = g_szImageMask[xPos2 + yPos2 * sDesc.Width]; +                if (chValue > 0xFF-20) +                    { +                    g_eClick = EClickPos_Circle; +                    } +                else if (chValue < 0xFF-20 && chValue > 185) +                    { +                    g_eClick = EClickPos_CircleHor; +                    } +                else if (chValue > 0x10 && chValue < 185) +                    { +                    g_eClick = EClickPos_CircleVert; +                    } +                } +            return TRUE; + +        case WM_RBUTTONDOWN: +            g_bMousePressedR = true; + +            sEvent.cbSize = sizeof(TRACKMOUSEEVENT); +            sEvent.dwFlags = TME_LEAVE; +            sEvent.hwndTrack = g_hDlg; +            sEvent.dwHoverTime = HOVER_DEFAULT; +            TrackMouseEvent(&sEvent); + +            if (g_bMousePressed) +                { +                g_bMousePressedR = false; +                g_bMousePressed = false; +                g_bMousePressedBoth = true; +                } + +            return TRUE; + +        case WM_MBUTTONDOWN: + + +            g_bMousePressedM = true; + +            sEvent.cbSize = sizeof(TRACKMOUSEEVENT); +            sEvent.dwFlags = TME_LEAVE; +            sEvent.hwndTrack = g_hDlg; +            sEvent.dwHoverTime = HOVER_DEFAULT; +            TrackMouseEvent(&sEvent); +            return TRUE; + +        case WM_LBUTTONUP: +            g_bMousePressed = false; +            g_bMousePressedBoth = false; +            return TRUE; + +        case WM_RBUTTONUP: +            g_bMousePressedR = false; +            g_bMousePressedBoth = false; +            return TRUE; + +        case WM_MBUTTONUP: +            g_bMousePressedM = false; +            return TRUE; + +        case WM_DROPFILES: +            { +                HDROP hDrop = (HDROP)wParam; +                char szFile[MAX_PATH]; +                DragQueryFile(hDrop,0,szFile,sizeof(szFile)); +                const char* sz = strrchr(szFile,'.'); +                if (!sz) { +                    sz = szFile; +                } + +                if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) { +                    // replace the selected texture with the new one ... +                    CDisplay::Instance().ReplaceCurrentTexture(szFile); +                } else { +                    // check whether it is a typical texture file format ... +                    ++sz; +                    if (0 == ASSIMP_stricmp(sz,"png") || +                        0 == ASSIMP_stricmp(sz,"bmp") || +                        0 == ASSIMP_stricmp(sz,"jpg") || +                        0 == ASSIMP_stricmp(sz,"tga") || +                        0 == ASSIMP_stricmp(sz,"tif") || +                        0 == ASSIMP_stricmp(sz,"hdr") || +                        0 == ASSIMP_stricmp(sz,"ppm") || +                        0 == ASSIMP_stricmp(sz,"pfm")) +                    { +                        CBackgroundPainter::Instance().SetTextureBG(szFile); +                    } +                    else if (0 == Assimp::ASSIMP_stricmp(sz,"dds")) +                    { +                        // DDS files could contain skyboxes, but they could also +                        // contain normal 2D textures. The easiest way to find this +                        // out is to open the file and check the header ... +                        FILE* pFile = fopen(szFile,"rb"); +                        if (!pFile) +                            return TRUE; + +                        // header of a dds file (begin) +                        /* +                        DWORD dwMagic +                        DWORD dwSize +                        DWORD dwFlags +                        DWORD dwHeight +                        DWORD dwWidth +                        DWORD dwPitchOrLinearSize +                        DWORD dwDepth +                        DWORD dwMipMapCount           -> total with this: 32 +                        DWORD dwReserved1[11]         -> total with this: 76 +                        DDPIXELFORMAT ddpfPixelFormat -> total with this: 108 +                        DWORD dwCaps1;                -> total with this: 112 +                        DWORD dwCaps2; ---< here we are! +                        */ +                        DWORD dwCaps = 0; +                        fseek(pFile,112,SEEK_SET); +                        fread(&dwCaps,4,1,pFile); + +                        if (dwCaps & 0x00000400L /* DDSCAPS2_CUBEMAP_POSITIVEX */) { +                            CLogDisplay::Instance().AddEntry( +                                "[INFO] Assuming this dds file is a skybox ...", +                                D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); + +                            CBackgroundPainter::Instance().SetCubeMapBG(szFile); +                        } else { +                            CBackgroundPainter::Instance().SetTextureBG(szFile); +                        } +                        fclose(pFile); +                    } else { +                        strcpy(g_szFileName,szFile); + +                        DeleteAsset(); +                        LoadAsset(); +                        UpdateHistory(); +                        SaveHistory(); +                    } +                } +                DragFinish(hDrop); +            } +            return TRUE; + +        case WM_COMMAND: +            HMENU hMenu = GetMenu(g_hDlg); +            if (ID_VIEWER_QUIT == LOWORD(wParam)) { +                PostQuitMessage(0); +                DestroyWindow(hwndDlg); +            } else if (IDC_COMBO1 == LOWORD(wParam)) { +                if(HIWORD(wParam) == CBN_SELCHANGE) { +                    const size_t sel = static_cast<size_t>(ComboBox_GetCurSel(GetDlgItem(hwndDlg,IDC_COMBO1))); +                    if(g_pcAsset) { +                        g_pcAsset->mAnimator->SetAnimIndex(sel); +                        SendDlgItemMessage(hwndDlg,IDC_SLIDERANIM,TBM_SETPOS,TRUE,0); +                    } +                } +            } else if (ID_VIEWER_RESETVIEW == LOWORD(wParam)) { +                g_sCamera.vPos = aiVector3D(0.0f,0.0f,-10.0f); +                g_sCamera.vLookAt = aiVector3D(0.0f,0.0f,1.0f); +                g_sCamera.vUp = aiVector3D(0.0f,1.0f,0.0f); +                g_sCamera.vRight = aiVector3D(0.0f,1.0f,0.0f); +                g_mWorldRotate = aiMatrix4x4(); +                g_mWorld = aiMatrix4x4(); + +                // don't forget to reset the st +                CBackgroundPainter::Instance().ResetSB(); +            } else if (ID__HELP == LOWORD(wParam)) { +                DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_AVHELP), +                    hwndDlg,&HelpDialogProc); +            } else if (ID__ABOUT == LOWORD(wParam)) { +                DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_ABOUTBOX), +                    hwndDlg,&AboutMessageProc); +            } else if (ID_TOOLS_LOGWINDOW == LOWORD(wParam)) { +                CLogWindow::Instance().Show(); +            } else if (ID__WEBSITE == LOWORD(wParam)) { +                ShellExecute(nullptr,"open","http://assimp.sourceforge.net","","",SW_SHOW); +            } else if (ID__WEBSITESF == LOWORD(wParam)) { +                ShellExecute(nullptr,"open","https://sourceforge.net/projects/assimp","","",SW_SHOW); +            }  else if (ID_REPORTBUG == LOWORD(wParam)) { +                ShellExecute(nullptr,"open","https://sourceforge.net/tracker/?func=add&group_id=226462&atid=1067632","","",SW_SHOW); +            } else if (ID_FR == LOWORD(wParam)) { +                ShellExecute(nullptr,"open","https://sourceforge.net/forum/forum.php?forum_id=817653","","",SW_SHOW); +            } else if (ID_TOOLS_CLEARLOG == LOWORD(wParam)) { +                CLogWindow::Instance().Clear(); +            } else if (ID_TOOLS_SAVELOGTOFILE == LOWORD(wParam)) { +                CLogWindow::Instance().Save(); +            } else if (ID_VIEWER_MEMORYCONSUMATION == LOWORD(wParam)) { +                DisplayMemoryConsumption(); +            } else if (ID_VIEWER_H == LOWORD(wParam)) { +                MakeFileAssociations(); +            } else if (ID_BACKGROUND_CLEAR == LOWORD(wParam)) { +                ClearBG(); +            } else if (ID_BACKGROUND_SETCOLOR == LOWORD(wParam)) { +                ChooseBGColor(); +            } else if (ID_BACKGROUND_LOADTEXTURE == LOWORD(wParam)) { +                LoadBGTexture(); +            } else if (ID_BACKGROUND_LOADSKYBOX == LOWORD(wParam)) { +                LoadSkybox(); +            } else if (ID_VIEWER_SAVESCREENSHOTTOFILE == LOWORD(wParam)) { +                SaveScreenshot(); +            } else if (ID_VIEWER_OPEN == LOWORD(wParam)) { +                OpenAsset(); +            } else if (ID_TOOLS_FLIPNORMALS == LOWORD(wParam)) { +                if (g_pcAsset && g_pcAsset->pcScene) { +                    g_pcAsset->FlipNormals(); +                } +            } +            // this is ugly. anyone willing to rewrite it from scratch using wxwidgets or similar? +            else if (ID_VIEWER_PP_JIV == LOWORD(wParam))    { +                ppsteps ^= aiProcess_JoinIdenticalVertices; +                CheckMenuItem(hMenu,ID_VIEWER_PP_JIV,ppsteps & aiProcess_JoinIdenticalVertices ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } else if (ID_VIEWER_PP_CTS == LOWORD(wParam))    { +                ppsteps ^= aiProcess_CalcTangentSpace; +                CheckMenuItem(hMenu,ID_VIEWER_PP_CTS,ppsteps & aiProcess_CalcTangentSpace ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } else if (ID_VIEWER_PP_FD == LOWORD(wParam)) { +                ppsteps ^= aiProcess_FindDegenerates; +                CheckMenuItem(hMenu,ID_VIEWER_PP_FD,ppsteps & aiProcess_FindDegenerates ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } else if (ID_VIEWER_PP_FID == LOWORD(wParam))    { +                ppsteps ^= aiProcess_FindInvalidData; +                CheckMenuItem(hMenu,ID_VIEWER_PP_FID,ppsteps & aiProcess_FindInvalidData ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } +            else if (ID_VIEWER_PP_FIM == LOWORD(wParam))    { +                ppsteps ^= aiProcess_FindInstances; +                CheckMenuItem(hMenu,ID_VIEWER_PP_FIM,ppsteps & aiProcess_FindInstances ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } +            else if (ID_VIEWER_PP_FIN == LOWORD(wParam))    { +                ppsteps ^= aiProcess_FixInfacingNormals; +                CheckMenuItem(hMenu,ID_VIEWER_PP_FIN,ppsteps & aiProcess_FixInfacingNormals ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } +            else if (ID_VIEWER_PP_GUV == LOWORD(wParam))    { +                ppsteps ^= aiProcess_GenUVCoords; +                CheckMenuItem(hMenu,ID_VIEWER_PP_GUV,ppsteps & aiProcess_GenUVCoords ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } +            else if (ID_VIEWER_PP_ICL == LOWORD(wParam))    { +                ppsteps ^= aiProcess_ImproveCacheLocality; +                CheckMenuItem(hMenu,ID_VIEWER_PP_ICL,ppsteps & aiProcess_ImproveCacheLocality ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } +            else if (ID_VIEWER_PP_OG == LOWORD(wParam)) { +                if (ppsteps & aiProcess_PreTransformVertices) { +                    CLogDisplay::Instance().AddEntry("[ERROR] This setting is incompatible with \'Pretransform Vertices\'"); +                } +                else { +                    ppsteps ^= aiProcess_OptimizeGraph; +                    CheckMenuItem(hMenu,ID_VIEWER_PP_OG,ppsteps & aiProcess_OptimizeGraph ? MF_CHECKED : MF_UNCHECKED); +                    UpdatePPSettings(); +                } +            } +            else if (ID_VIEWER_PP_OM == LOWORD(wParam)) { +                ppsteps ^= aiProcess_OptimizeMeshes; +                CheckMenuItem(hMenu,ID_VIEWER_PP_OM,ppsteps & aiProcess_OptimizeMeshes ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } +            else if (ID_VIEWER_PP_PTV == LOWORD(wParam))    { +                if (ppsteps & aiProcess_OptimizeGraph) { +                    CLogDisplay::Instance().AddEntry("[ERROR] This setting is incompatible with \'Optimize Scenegraph\'"); +                } +                else { +                    ppsteps ^= aiProcess_PreTransformVertices; +                    CheckMenuItem(hMenu,ID_VIEWER_PP_PTV,ppsteps & aiProcess_PreTransformVertices ? MF_CHECKED : MF_UNCHECKED); +                    UpdatePPSettings(); +                } +            } +            else if (ID_VIEWER_PP_RRM2 == LOWORD(wParam))   { +                ppsteps ^= aiProcess_RemoveRedundantMaterials; +                CheckMenuItem(hMenu,ID_VIEWER_PP_RRM2,ppsteps & aiProcess_RemoveRedundantMaterials ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } +            else if (ID_VIEWER_PP_TUV == LOWORD(wParam))    { +                ppsteps ^= aiProcess_TransformUVCoords; +                CheckMenuItem(hMenu,ID_VIEWER_PP_TUV,ppsteps & aiProcess_TransformUVCoords ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } +            else if (ID_VIEWER_PP_DB == LOWORD(wParam)) { +                ppsteps ^= aiProcess_Debone; +                CheckMenuItem(hMenu,ID_VIEWER_PP_DB,ppsteps & aiProcess_Debone ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } +            else if (ID_VIEWER_PP_VDS == LOWORD(wParam))    { +                ppsteps ^= aiProcess_ValidateDataStructure; +                CheckMenuItem(hMenu,ID_VIEWER_PP_VDS,ppsteps & aiProcess_ValidateDataStructure ? MF_CHECKED : MF_UNCHECKED); +                UpdatePPSettings(); +            } +            else if (ID_VIEWER_RELOAD == LOWORD(wParam)) +            { +                DeleteAsset(); +                LoadAsset(); +            } +            else if (ID_IMPORTSETTINGS_RESETTODEFAULT == LOWORD(wParam)) +            { +                ppsteps = ppstepsdefault; +                UpdatePPSettings(); +                SetupPPUIState(); +            } +            else if (ID_IMPORTSETTINGS_OPENPOST == LOWORD(wParam)) +            { +                ShellExecute(nullptr,"open","http://assimp.sourceforge.net/lib_html/ai_post_process_8h.html","","",SW_SHOW); +            } +            else if (ID_TOOLS_ORIGINALNORMALS == LOWORD(wParam)) +            { +                if (g_pcAsset && g_pcAsset->pcScene) +                    { +                    g_pcAsset->SetNormalSet(AssimpView::AssetHelper::ORIGINAL); +                    CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_CHECKED); +                    CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_UNCHECKED); +                    CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_UNCHECKED); +                    } +                } + +            else if (ID_TOOLS_SMOOTHNORMALS == LOWORD(wParam)) +                { +                if (g_pcAsset && g_pcAsset->pcScene) +                    { +                    g_pcAsset->SetNormalSet(AssimpView::AssetHelper::SMOOTH); +                    CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_UNCHECKED); +                    CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_UNCHECKED); +                    CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_CHECKED); +                    } +                } +            else if (ID_TOOLS_HARDNORMALS == LOWORD(wParam)) +                { +                if (g_pcAsset && g_pcAsset->pcScene) +                    { +                    g_pcAsset->SetNormalSet(AssimpView::AssetHelper::HARD); +                    CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_UNCHECKED); +                    CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_CHECKED); +                    CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_UNCHECKED); +                    } +                } +            else if (ID_TOOLS_STEREOVIEW == LOWORD(wParam)) +                { +                    g_sOptions.bStereoView =! g_sOptions.bStereoView; + +                    HMENU menu = ::GetMenu(g_hDlg); +                    if (g_sOptions.bStereoView) { +                        ::ModifyMenu(menu,ID_TOOLS_STEREOVIEW, +                            MF_BYCOMMAND | MF_CHECKED | MF_STRING,ID_TOOLS_STEREOVIEW,"Stereo view"); + +                        CLogDisplay::Instance().AddEntry("[INFO] Switched to stereo mode", +                            D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); +                    } else { +                        ModifyMenu(menu,ID_TOOLS_STEREOVIEW, +                            MF_BYCOMMAND | MF_UNCHECKED | MF_STRING,ID_TOOLS_STEREOVIEW,"Stereo view"); + +                        CLogDisplay::Instance().AddEntry("[INFO] Switched to mono mode", +                            D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); +                    } +            } else if (ID_TOOLS_SETANGLELIMIT == LOWORD(wParam)) { +                DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_DIALOGSMOOTH),g_hDlg,&SMMessageProc); +            } else if (ID_VIEWER_CLEARHISTORY == LOWORD(wParam)) { +                ClearHistory(); +            } else if (ID_VIEWER_CLOSEASSET == LOWORD(wParam)) { +                DeleteAssetData(); +                DeleteAsset(); +                } +            else if (BN_CLICKED == HIWORD(wParam)) +                { +                if (IDC_TOGGLEMS == LOWORD(wParam)) +                    { +                    ToggleMS(); +                    } +                else if (IDC_TOGGLEMAT == LOWORD(wParam)) +                    { +                    ToggleMats(); +                    } +                else if (IDC_LCOLOR1 == LOWORD(wParam)) +                    { + +                    if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || +                        CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) +                    { +                        // hey, I'm tired and yes, I KNOW IT IS EVIL! +                        DisplayColorDialog(const_cast<D3DXVECTOR4*>(CDisplay::Instance().GetFirstCheckerColor())); +                        SaveCheckerPatternColors(); +                    } +                    else +                    { +                        DisplayColorDialog(&g_avLightColors[0]); +                        SaveLightColors(); +                    } +                    InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),nullptr,TRUE); +                    UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); +                    } +                else if (IDC_LCOLOR2 == LOWORD(wParam)) +                    { +                    if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || +                        CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) +                    { +                        // hey, I'm tired and yes, I KNOW IT IS EVIL! +                        DisplayColorDialog(const_cast<D3DXVECTOR4*>(CDisplay::Instance().GetSecondCheckerColor())); +                        SaveCheckerPatternColors(); +                    } +                    else +                    { +                        DisplayColorDialog(&g_avLightColors[1]); +                        SaveLightColors(); +                    } +                    InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),nullptr,TRUE); +                    UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); +                    } +                else if (IDC_LCOLOR3 == LOWORD(wParam)) +                    { +                    DisplayColorDialog(&g_avLightColors[2]); +                    InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),nullptr,TRUE); +                    UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3)); +                    SaveLightColors(); +                } +                else if (IDC_LRESET == LOWORD(wParam)) +                { +                    if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || +                        CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) +                    { +                        CDisplay::Instance().SetFirstCheckerColor(D3DXVECTOR4(0.4f,0.4f,0.4f,1.0f)); +                        CDisplay::Instance().SetSecondCheckerColor(D3DXVECTOR4(0.6f,0.6f,0.6f,1.0f)); +                        SaveCheckerPatternColors(); +                    } +                    else +                    { +                        g_avLightColors[0] = D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF); +                        g_avLightColors[1] = D3DCOLOR_ARGB(0xFF,0xFF,0x00,0x00); +                        g_avLightColors[2] = D3DCOLOR_ARGB(0xFF,0x05,0x05,0x05); +                        SaveLightColors(); +                    } + +                    InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),nullptr,TRUE); +                    UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); +                    InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),nullptr,TRUE); +                    UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); +                    InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),nullptr,TRUE); +                    UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3)); +                    } +                else if (IDC_NOSPECULAR == LOWORD(wParam)) +                    { +                    ToggleSpecular(); +                    } +                else if (IDC_NOAB == LOWORD(wParam)) +                    { +                    ToggleTransparency(); +                    } +                else if (IDC_ZOOM == LOWORD(wParam)) +                    { +                    ToggleFPSView(); +                    } +                else if (IDC_BLUBB == LOWORD(wParam)) +                    { +                    ToggleUIState(); +                    } +                else if (IDC_TOGGLENORMALS == LOWORD(wParam)) +                    { +                    ToggleNormals(); +                    } +                else if (IDC_LOWQUALITY == LOWORD(wParam)) +                    { +                    ToggleLowQuality(); +                    } +                else if (IDC_3LIGHTS == LOWORD(wParam)) +                    { +                    ToggleMultipleLights(); +                    } +                else if (IDC_LIGHTROTATE == LOWORD(wParam)) +                    { +                    ToggleLightRotate(); +                    } +                else if (IDC_AUTOROTATE == LOWORD(wParam)) +                    { +                    ToggleAutoRotate(); +                    } +                else if (IDC_TOGGLEWIRE == LOWORD(wParam)) +                    { +                    ToggleWireFrame(); +                    } +                else if (IDC_SHOWSKELETON == LOWORD(wParam)) +                    { +                    ToggleSkeleton(); +                    } +                else if (IDC_BFCULL == LOWORD(wParam)) +                    { +                    ToggleCulling(); +                    } +                else if (IDC_PLAY == LOWORD(wParam)) +                    { +                        g_bPlay = !g_bPlay; +                        SetDlgItemText(g_hDlg,IDC_PLAY,(g_bPlay ? "Stop" : "Play")); + +                        if (g_bPlay) +                            EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),FALSE); +                        else EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),TRUE); +                    } +                } +            // check the file history +            for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) +            { +                if (AI_VIEW_RECENT_FILE_ID(i) == LOWORD(wParam)) +                { +                    strcpy(g_szFileName,g_aPreviousFiles[i].c_str()); +                    DeleteAssetData(); +                    DeleteAsset(); +                    LoadAsset(); + +                    // update and safe the history +                    UpdateHistory(); +                    SaveHistory(); +                } +            } + +#ifndef ASSIMP_BUILD_NO_EXPORT +            if (LOWORD(wParam) >= AI_VIEW_EXPORT_FMT_BASE && LOWORD(wParam) < AI_VIEW_EXPORT_FMT_BASE+Assimp::Exporter().GetExportFormatCount()) { +                DoExport(LOWORD(wParam) - AI_VIEW_EXPORT_FMT_BASE); +            } +#endif + +            // handle popup menus for the tree window +            CDisplay::Instance().HandleTreeViewPopup(wParam,lParam); + +            return TRUE; +        }; +    return FALSE; +    } + + +//------------------------------------------------------------------------------- +// Message prcoedure for the progress dialog +//------------------------------------------------------------------------------- +INT_PTR CALLBACK ProgressMessageProc(HWND hwndDlg,UINT uMsg, +     WPARAM wParam,LPARAM lParam) +    { +    UNREFERENCED_PARAMETER(lParam); +    switch (uMsg) +        { +        case WM_INITDIALOG: + +            SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETRANGE,0, +                MAKELPARAM(0,500)); + +            SetTimer(hwndDlg,0,40,nullptr); +            return TRUE; + +        case WM_CLOSE: +            EndDialog(hwndDlg,0); +            return TRUE; + +        case WM_COMMAND: + +            if (IDOK == LOWORD(wParam)) +                { +#if 0 +                g_bLoadingCanceled = true; +                TerminateThread(g_hThreadHandle,5); +                g_pcAsset = nullptr; + +                EndDialog(hwndDlg,0); +#endif + +                // PROBLEM: If we terminate the loader thread, ASSIMP's state +                // is undefined. Any further attempts to load assets will +                // fail. +                exit(5); +//              return TRUE; +                } +        case WM_TIMER: + +            UINT iPos = (UINT)SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_GETPOS,0,0); +            iPos += 10; +            if (iPos > 490)iPos = 0; +            SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETPOS,iPos,0); + +            if (g_bLoadingFinished) +                { +                EndDialog(hwndDlg,0); +                return TRUE; +                } + +            return TRUE; +        } +    return FALSE; +    } + + +//------------------------------------------------------------------------------- +// Message procedure for the about dialog +//------------------------------------------------------------------------------- +INT_PTR CALLBACK AboutMessageProc(HWND hwndDlg,UINT uMsg, +    WPARAM wParam,LPARAM lParam) +    { +    UNREFERENCED_PARAMETER(lParam); +    switch (uMsg) +        { +        case WM_CLOSE: +            EndDialog(hwndDlg,0); +            return TRUE; + +        case WM_COMMAND: + +            if (IDOK == LOWORD(wParam)) +                { +                EndDialog(hwndDlg,0); +                return TRUE; +                } +        } +    return FALSE; +    } +} + +using namespace AssimpView; + +//------------------------------------------------------------------------------- +// Entry point to the application +//------------------------------------------------------------------------------- +int APIENTRY _tWinMain(HINSTANCE hInstance, +                       HINSTANCE hPrevInstance, +                       LPTSTR    lpCmdLine, +                       int       nCmdShow) +{ +    UNREFERENCED_PARAMETER(hPrevInstance); +    UNREFERENCED_PARAMETER(lpCmdLine); + +    // needed for the RichEdit control in the about/help dialog +    LoadLibrary( "riched20.dll" ); + +    // load windows common controls library to get XP style +    InitCommonControls(); + +    // initialize the IDirect3D9 interface +    g_hInstance = hInstance; +    if (0 == InitD3D()) { +        MessageBox(nullptr,"Failed to initialize Direct3D 9", +            "ASSIMP ModelViewer",MB_OK); +        return -6; +    } + +    // create the main dialog +    HWND hDlg = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOGMAIN), +        nullptr,&MessageProc); + +    // ensure we get high priority +    ::SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS); + +    // initialize the default logger if necessary +    Assimp::DefaultLogger::create("",Assimp::Logger::VERBOSE); + +    CLogWindow::Instance().pcStream = new CMyLogStream(); +    Assimp::DefaultLogger::get()->attachStream(CLogWindow::Instance().pcStream, +        Assimp::DefaultLogger::Debugging | Assimp::DefaultLogger::Info | +        Assimp::DefaultLogger::Err | Assimp::DefaultLogger::Warn); + +    if (nullptr == hDlg) { +        MessageBox(nullptr,"Failed to create dialog from resource", +            "ASSIMP ModelViewer",MB_OK); +        return -5; +    } + +    // display the window +    g_hDlg = hDlg; +    MSG uMsg; +    memset(&uMsg,0,sizeof( MSG)); +    ShowWindow( hDlg, nCmdShow ); +    UpdateWindow( hDlg ); + +    // create the D3D device object +    if (0 == CreateDevice(g_sOptions.bMultiSample,false,true)) { +        MessageBox(nullptr,"Failed to initialize Direct3D 9 (2)", +            "ASSIMP ModelViewer",MB_OK); +        return -4; +    } + +    CLogDisplay::Instance().AddEntry("[OK] Here we go!"); + +    // create the log window +    CLogWindow::Instance().Init(); +    // set the focus to the main window +    SetFocus(g_hDlg); + +    // recover background skyboxes/textures from the last session +    HKEY hRegistry; +    union { +        char szFileName[MAX_PATH]; +        D3DCOLOR clrColor; +    }; +    DWORD dwTemp = MAX_PATH; +    RegCreateKeyEx(HKEY_CURRENT_USER, +        "Software\\ASSIMP\\Viewer",0,nullptr,0,KEY_ALL_ACCESS, nullptr, &hRegistry,nullptr); +    if(ERROR_SUCCESS == RegQueryValueEx(hRegistry,"LastSkyBoxSrc",nullptr,nullptr, +        (BYTE*)szFileName,&dwTemp) && '\0' != szFileName[0]) +        { +        CBackgroundPainter::Instance().SetCubeMapBG(szFileName); +        } +    else if(ERROR_SUCCESS == RegQueryValueEx(hRegistry,"LastTextureSrc",nullptr,nullptr, +        (BYTE*)szFileName,&dwTemp) && '\0' != szFileName[0]) +        { +        CBackgroundPainter::Instance().SetTextureBG(szFileName); +        } +    else if(ERROR_SUCCESS == RegQueryValueEx(hRegistry,"Color",nullptr,nullptr, +        (BYTE*)&clrColor,&dwTemp)) +        { +        CBackgroundPainter::Instance().SetColor(clrColor); +        } +    RegCloseKey(hRegistry); + +    // now handle command line arguments +    HandleCommandLine(lpCmdLine); + +    double adLast[30]; +    for (int i = 0; i < 30;++i)adLast[i] = 0.0f; +    int iCurrent = 0; + +    double g_dCurTime = 0; +    double g_dLastTime = 0; +    while( uMsg.message != WM_QUIT ) +        { +        if( PeekMessage( &uMsg, nullptr, 0, 0, PM_REMOVE ) ) +            { +            TranslateMessage( &uMsg ); +            DispatchMessage( &uMsg ); + +            if (WM_CHAR == uMsg.message) +                { + +                switch ((char)uMsg.wParam) +                    { +                    case 'M': +                    case 'm': + +                        CheckDlgButton(g_hDlg,IDC_TOGGLEMS, +                            IsDlgButtonChecked(g_hDlg,IDC_TOGGLEMS) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleMS(); +                        break; + +                    case 'L': +                    case 'l': + +                        CheckDlgButton(g_hDlg,IDC_3LIGHTS, +                            IsDlgButtonChecked(g_hDlg,IDC_3LIGHTS) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleMultipleLights(); +                        break; + +                    case 'P': +                    case 'p': + +                        CheckDlgButton(g_hDlg,IDC_LOWQUALITY, +                            IsDlgButtonChecked(g_hDlg,IDC_LOWQUALITY) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleLowQuality(); +                        break; + +                    case 'D': +                    case 'd': + +                        CheckDlgButton(g_hDlg,IDC_TOGGLEMAT, +                            IsDlgButtonChecked(g_hDlg,IDC_TOGGLEMAT) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleMats(); +                        break; + + +                    case 'N': +                    case 'n': + +                        CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS, +                            IsDlgButtonChecked(g_hDlg,IDC_TOGGLENORMALS) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); +                        ToggleNormals(); +                        break; + + +                    case 'S': +                    case 's': + +                        CheckDlgButton(g_hDlg,IDC_NOSPECULAR, +                            IsDlgButtonChecked(g_hDlg,IDC_NOSPECULAR) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleSpecular(); +                        break; + +                    case 'A': +                    case 'a': + +                        CheckDlgButton(g_hDlg,IDC_AUTOROTATE, +                            IsDlgButtonChecked(g_hDlg,IDC_AUTOROTATE) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleAutoRotate(); +                        break; + + +                    case 'R': +                    case 'r': + +                        CheckDlgButton(g_hDlg,IDC_LIGHTROTATE, +                            IsDlgButtonChecked(g_hDlg,IDC_LIGHTROTATE) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleLightRotate(); +                        break; + +                    case 'Z': +                    case 'z': + +                        CheckDlgButton(g_hDlg,IDC_ZOOM, +                            IsDlgButtonChecked(g_hDlg,IDC_ZOOM) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleFPSView(); +                        break; + + +                    case 'W': +                    case 'w': + +                        CheckDlgButton(g_hDlg,IDC_TOGGLEWIRE, +                            IsDlgButtonChecked(g_hDlg,IDC_TOGGLEWIRE) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleWireFrame(); +                        break; + +                    case 'K': +                    case 'k': + +                        CheckDlgButton(g_hDlg,IDC_SHOWSKELETON, +                            IsDlgButtonChecked(g_hDlg,IDC_SHOWSKELETON) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleSkeleton(); +                        break; + +                    case 'C': +                    case 'c': + +                        CheckDlgButton(g_hDlg,IDC_BFCULL, +                            IsDlgButtonChecked(g_hDlg,IDC_BFCULL) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleCulling(); +                        break; + +                    case 'T': +                    case 't': + +                        CheckDlgButton(g_hDlg,IDC_NOAB, +                            IsDlgButtonChecked(g_hDlg,IDC_NOAB) == BST_CHECKED +                            ? BST_UNCHECKED : BST_CHECKED); + +                        ToggleTransparency(); +                        break; +                    } +                } +            } + + +        // render the scene +        CDisplay::Instance().OnRender(); + +        // measure FPS, average it out +        g_dCurTime     = timeGetTime(); +        g_fElpasedTime = (float)((g_dCurTime - g_dLastTime) * 0.001); +        g_dLastTime    = g_dCurTime; + +        adLast[iCurrent++] = 1.0f / g_fElpasedTime; + +        double dFPS = 0.0; +        for (int i = 0; i < 30; ++i) { +            dFPS += adLast[ i ]; +        } +        dFPS /= 30.0; + +        if (30 == iCurrent) { +            iCurrent = 0; +            if (dFPS != g_fFPS) { +                g_fFPS = dFPS; +                char szOut[256]; + +                sprintf(szOut,"%i",(int)floorf((float)dFPS+0.5f)); +                SetDlgItemText(g_hDlg,IDC_EFPS,szOut); +            } +        } +    } +    DeleteAsset(); +    Assimp::DefaultLogger::kill(); +    ShutdownDevice(); +    ShutdownD3D(); + +    return 0; +}  | 
