void CComponentProxyManager::Export(const TCHAR* pSavePath, std::function<bool(uint32_t, CComponentProxy*)> exportCallback)
{
    m_bExportingPhase = true;
    BEATS_ASSERT(pSavePath != NULL);
    static CSerializer serializer;
    serializer.Reset();
    serializer << COMPONENT_SYSTEM_VERSION;
    serializer << GetComponentTemplateMap()->size();
    CComponentProjectDirectory* pRootProject = m_pProject->GetRootDirectory();
    pRootProject->Serialize(serializer);
    serializer << m_pProject->GetStartFile();

    m_uOperateProgress = 0;
    uint32_t uFileCount = (uint32_t)(m_pProject->GetFileList()->size());
    serializer << uFileCount;

    for (uint32_t i = 0; i < uFileCount; ++i)
    {
        const TString strFileName = CFilePathTool::GetInstance()->FileName(m_pProject->GetComponentFileName(i).c_str());
        m_strCurrOperateFile = strFileName;
        serializer << strFileName;
        uint32_t uComponentCount = 0;
        uint32_t uWritePos = serializer.GetWritePos();
        serializer << uWritePos;// File Start pos.
        serializer << 12;// File size placeholder.
        serializer << uComponentCount; // component count place holder
        const std::map<uint32_t, std::map<uint32_t, std::set<uint32_t> > >* pFileToComponent = m_pProject->GetFileToComponentMap();
        auto iter = pFileToComponent->find(i);
        BEATS_ASSERT(iter != pFileToComponent->end(), _T("File: %s\ndoes not have a component!"), strFileName.c_str());
        if (iter != pFileToComponent->end())
        {
            std::vector<uint32_t>::iterator iterFile = std::find(m_loadedFiles.begin(), m_loadedFiles.end(), i);
            if (iterFile != m_loadedFiles.end())
            {
                for (auto subIter = iter->second.begin(); subIter != iter->second.end(); ++subIter)
                {
                    for (auto idIter = subIter->second.begin(); idIter != subIter->second.end(); ++idIter)
                    {
                        uint32_t uComponentId = *idIter;
                        CComponentProxy* pProxy = static_cast<CComponentProxy*>(CComponentProxyManager::GetInstance()->GetComponentInstance(uComponentId));
                        if (pProxy)
                        {
                            if (ExportComponentProxy(i, pProxy, serializer, exportCallback))
                            {
                                m_refreshFileList.insert(*iterFile);
                            }
                            ++uComponentCount;
                        }
                        else
                        {
                            BEATS_ASSERT(false, _T("Can't find proxy with GUID 0x%x id %d, have you removed that class in code?"), m_pProject->QueryComponentGuid(uComponentId), uComponentId);
                        }
                    }
                }
            }
            else
            {
                std::vector<CComponentBase*> vecComponents;
                // Don't create instance in LoadFile when exporting.
                BEATS_ASSERT(m_bCreateInstanceWithProxy);
                m_bCreateInstanceWithProxy = false;
                m_pIdManager->Lock();
                LoadFile(i, &vecComponents);
                iterFile = std::find(m_loadedFiles.begin(), m_loadedFiles.end(), i);
                BEATS_ASSERT(iterFile != m_loadedFiles.end(), _T("Load file index %d failed!"), i);
                for (uint32_t j = 0; j < vecComponents.size(); ++j)
                {
                    CComponentProxy* pProxy = static_cast<CComponentProxy*>(vecComponents[j]);
                    if (ExportComponentProxy(i, pProxy, serializer, exportCallback))
                    {
                        m_refreshFileList.insert(*iterFile);
                    }
                    ++uComponentCount;
                }
                ReSaveFreshFile();
                // Don't call CloseFile, because we have nothing to do with proxy's host component.
                for (uint32_t j = 0; j < vecComponents.size(); ++j)
                {
                    if (vecComponents[j]->GetId() != 0xFFFFFFFF)
                    {
                        CComponentProxyManager::GetInstance()->UnregisterInstance(vecComponents[j]);
                        CComponentProxyManager::GetInstance()->GetIdManager()->RecycleId(vecComponents[j]->GetId());
                    }
                    BEATS_SAFE_DELETE(vecComponents[j]);
                }
                m_loadedFiles.erase(iterFile);
                m_pIdManager->UnLock();
                m_bCreateInstanceWithProxy = true;// Restore.
            }
            uint32_t uCurWritePos = serializer.GetWritePos();
            uint32_t uFileDataSize = uCurWritePos - uWritePos;
            serializer.SetWritePos(uWritePos + sizeof(uint32_t));// Skip file start pos.
            serializer << uFileDataSize;
            serializer << uComponentCount;
            serializer.SetWritePos(uCurWritePos);
        }
        m_uOperateProgress = uint32_t((i + 1) * 100.f / uFileCount);
    }
    BEATS_ASSERT(m_uOperateProgress == 100);
    m_strCurrOperateFile.clear();
    serializer.Deserialize(pSavePath);
    m_bExportingPhase = false;
}
void ExportLanguage()
{
    std::map<uint32_t, std::map<ELanguageType, TString> > languageServerErrCodeMap;
    ReadServerErrCodeFile(languageServerErrCodeMap);
    std::map<TString, std::map<ELanguageType, TString> >& languageMap = CLanguageManager::GetInstance()->GetLanguageMap();
    // 1. Export Bin File.
    CSerializer fileData;
    for (int i = 0; i < eLT_Count; ++i)
    {
        fileData << languageMap.size();
        for (auto iter = languageMap.begin(); iter != languageMap.end(); ++iter)
        {
            auto subIter = iter->second.find((ELanguageType)i);
            if (subIter != iter->second.end())
            {
                fileData << subIter->second;
            }
            else
            {
                fileData << iter->first;
            }
        }
        bool bRet = false;
        for (auto iter : languageServerErrCodeMap)
        {
            auto subIter = iter.second.find((ELanguageType)i);
            if (subIter != iter.second.end())
            {
                if (!bRet)
                {
                    fileData << languageServerErrCodeMap.size();
                    bRet = true;
                }
                fileData << iter.first;
                fileData << iter.second[(ELanguageType)i];
            }
        }
        TString strFilePath = CResourceManager::GetInstance()->GetResourcePath(eRT_Language);
        strFilePath.append(_T("/")).append(pszLanguageTypeString[i]).append(_T(".bin"));
        fileData.Deserialize(strFilePath.c_str(), _T("wb+"));
        fileData.Reset();
    }
    //2. Export enum file.
    std::string content;
    content.append("#ifndef BEYONDENGINEEDITOR_LANGUAGEENUM_H__INCLUDE\n#define BEYONDENGINEEDITOR_LANGUAGEENUM_H__INCLUDE\n").append("\nenum ELanguageTextType\n{\n");
    for (auto iter = languageMap.begin(); iter != languageMap.end(); iter++)
    {
        content.append("    ").append(iter->first.c_str()).append(",\n");
    }
    content.append("\n    eL_Count,\n").append("    eL_Force32Bit = 0xFFFFFFFF\n};\n");
    content.append("#define LUA_LANGUAGE_MAP(LM)\\\n");
    int32_t nCounter = 0;
    for (auto iter = languageMap.begin(); iter != languageMap.end(); ++iter)
    {
        TCHAR szValueBuffer[32];
        _stprintf(szValueBuffer, "%d", nCounter++);
        content.append("    ").append("LM(").append(iter->first.c_str()).append(",").append(szValueBuffer).append(")\\\n");
    }
    content.append("\n#endif");
    fileData.Reset();
    fileData << content;
    fileData.SetWritePos(fileData.GetWritePos() - 1);// back scape the 0 in the string end.
    bool bFileTheSame = false;
    const TString strHeaderFilePath = CResourceManager::GetInstance()->GetResourcePath(eRT_SourceCode) + _T("/Language/Language.h");
    if (CFilePathTool::GetInstance()->Exists(strHeaderFilePath.c_str()))
    {
        CSerializer tmpData(strHeaderFilePath.c_str(), "rb");
        if (tmpData.GetWritePos() == fileData.GetWritePos())
        {
            CMD5 tmpMD5(tmpData.GetBuffer(), tmpData.GetWritePos());
            CMD5 currentMD5(fileData.GetBuffer(), fileData.GetWritePos());
            bFileTheSame = tmpMD5 == currentMD5;
        }
    }
    if (!bFileTheSame)
    {
        fileData.Deserialize(strHeaderFilePath.c_str(), _T("wb+"));
    }

    //3. Export txt file.
    for (int i = 0; i < eLT_Count; ++i)
    {
        bool bHasData = false;
        fileData.Reset();
        for (auto iter = languageMap.begin(); iter != languageMap.end(); ++iter)
        {
            auto subIter = iter->second.find((ELanguageType)i);
            if (subIter != iter->second.end())
            {
                TString strData = (TString)(wxString::FromUTF8(subIter->second.c_str()));
                if (!bHasData && !strData.empty())
                {
                    bHasData = true;
                }
                fileData << strData;
                fileData.SetWritePos(fileData.GetWritePos() - 1);
            }
            fileData << "\n";
            fileData.SetWritePos(fileData.GetWritePos() - 1);
        }
        if (bHasData)
        {
            TString strFilePath = CResourceManager::GetInstance()->GetResourcePath(eRT_Resource);
            strFilePath.append(_T("/")).append(pszLanguageTypeString[i]).append(_T(".txt"));
            fileData.Deserialize(strFilePath.c_str(), _T("wt+"));
        }
    }
    fileData.Reset();
    const std::map<TString, TString>& languageTagMap = CLanguageManager::GetInstance()->GetLanguageTagMap();
    for (auto iter = languageTagMap.begin(); iter != languageTagMap.end(); ++iter)
    {
        TString strData = (TString)(wxString::FromUTF8(iter->second.c_str()));
        fileData << strData;
        fileData.SetWritePos(fileData.GetWritePos() - 1);
        fileData << "\n";
        fileData.SetWritePos(fileData.GetWritePos() - 1);
    }
    TString strFilePath = CResourceManager::GetInstance()->GetResourcePath(eRT_Resource);
    strFilePath.append(_T("/")).append("Tag").append(_T(".txt"));
    fileData.Deserialize(strFilePath.c_str(), _T("wt+"));

    fileData.Reset();
    for (auto iter = languageMap.begin(); iter != languageMap.end(); ++iter)
    {
        TString strData = (TString)(wxString::FromUTF8(iter->first.c_str()));
        fileData << strData;
        fileData.SetWritePos(fileData.GetWritePos() - 1);
        fileData << "\n";
        fileData.SetWritePos(fileData.GetWritePos() - 1);
    }
    strFilePath = CResourceManager::GetInstance()->GetResourcePath(eRT_Resource);
    strFilePath.append(_T("/")).append(_T("Enum.txt"));
    fileData.Deserialize(strFilePath.c_str(), _T("wt+"));
}