cocos2dx 资源合并.

时间:2023-03-09 18:48:24
cocos2dx 资源合并.

cocos2dx 资源合并.

文件合并之前

cocos2dx 资源合并.

文件合并之后

cocos2dx 资源合并.

吐槽

我们项目比较奇葩, ui用cocostudio做, 这项光荣的任务由美术接手.

这个美术是个新手, 经过我长时间的观察, 她似乎不用怎么画画. 至少在很长一段时间里, 她很悠闲, 只管拼UI即可.

这是我们客户端噩梦的源头.

她不懂需求, 任何ui, 只要截图下来符合策划草图就算完成任务.

因此, 什么层次结构, 什么命名规范, 统统没有.

程序接手过来的ui自己要从头到尾翻新一遍, 甚至比重做花的时间更长.

于是, 一个伟大的决定诞生了, 我把她的活一起做了, 摆脱了厄运, 让我事倍功半.

两周以后, 她说她太闲了, 又把活接了过去, 从此厄运continue..

她把每一个ui都新建一个工程, 可以看到合并前有多个目录, 容量达到500M.

而且, 同一个文件, 在不同的目录就可能是不同的名字, 总之错乱不堪, 一塌糊涂.

她的杰作, 导致apk远远过150m, 直逼200m.

就在策划, 美术大呼, 节省资源的同时, 他们依然没有意识到问题出在哪里.

随着他们的呼声越来越高, 资源也越来越大.

卧槽, 彻底服了.

实际行动

终于, 我忍无可忍了, 决定要彻底优化一次资源.

由于资源文件太乱, 根本无从下手, 于是我订好了目录结构, 统一了文件名, 把这个活交给了美术.

这个事情很容易完成, 因为他们只要整理文件就OK, 至于ui资源里指定的文件路径, 都是由程序各自去修改.

所以, 这个工作量是相当的小, 我以为美术一周内怎么也可以做完了...

2个月以后, 美术把文件整理好了.

然后我把文件合并了, 有效资源居然只有22m.

源码

 #include <Windows.h>
 #include <windowsx.h>

 #include <string>
 #include <memory>
 #include <utility>
 #include <vector>
 #include <fstream>
 #include <list>
 #include <iterator>
 #include <functional>
 #include <iostream>
 #include <thread>
 #include <regex>

 #define LOG(param)    {std::wcout << param << std::endl;}

 size_t getFileSize(std::wifstream &ifile)
 {
     ifile.seekg(, std::ios::end);
     auto pos = (size_t)ifile.tellg();
     ifile.seekg(, std::ios::beg);
     return pos;
 }

 //    获得目录.
 inline std::wstring getDirectoryName(const std::wstring &fullName)
 {
     auto pos = fullName.find_last_of(L'\\');
     , pos) : L"";
 }
 //    获得文件名.
 inline std::wstring getFileName(const std::wstring &fullName)
 {
     auto pos = fullName.find_last_of(L'\\');
     ) : L"";
 }
 //    获取后缀.
 inline std::wstring getFileExtName(const std::wstring &fullName)
 {
     auto pos = fullName.find_last_of(L'.');
     ) : L"";
 }

 class Project {
 public:
     std::wstring directoryName;
     std::wstring directoryPath;
     std::wstring jsonPath;
     std::wstring projectName;
     std::vector<std::wstring> jsonList;
 };

 bool handleFileList(const std::wstring &rootDirectory, const std::wstring &outDirectory, const std::vector<std::wstring> &fileList)
 {
     auto result = false;
     LOG("handleFileList");
     std::vector<Project> projectList;

     {
         Project project;
         for (auto &fullName : fileList)
         {
             auto directoryPath = getDirectoryName(fullName);
             auto fileName = getFileName(fullName);
             auto extName = getFileExtName(fileName);

             if (extName == L"ui" && directoryPath != project.directoryPath)
             {
                 //    记录路径.
                 if (!project.directoryPath.empty())
                 {
                     projectList.push_back(project);
                 }
                 project = Project();
                 project.directoryPath = directoryPath;
                 project.directoryName = getFileName(directoryPath);
                 project.jsonPath = directoryPath + L"\\Json";
             }

             //    记录项目文件名.
             if (extName == L"ui")
             { project.projectName = fileName; }

             //    记录项目的json文件名.
             if ( getFileName(directoryPath) == L"Json" && extName == L"json")
             {
                 project.jsonList.push_back(fileName);
             }
         }
     }

     //    生产新的项目.
     {
         //    cat json file.
         std::wstring jsonList;

         CreateDirectory( (outDirectory + L"\\Json").c_str(), nullptr );
         CopyFile(L"null_project\\Json\\null_project_1.json", (outDirectory + L"\\Json\\null_project_1.json").c_str(), FALSE);

         for (auto &project : projectList)
         {
             for (auto &json : project.jsonList)
             {
                 auto name = project.directoryName + L"_" + json;
                 auto inName = project.jsonPath + L"\\" + json;
                 auto outName = outDirectory + L"\\Json\\" + name;
                 auto copy = CopyFile(inName.c_str(), outName.c_str(), FALSE);
                 jsonList.append(L"<string>" + name + L"</string>\n");
                 LOG(L"copy " << inName << L", " << outName << L" | " << copy);
             }
             LOG(L"copy resources.");
             wchar_t commandLine[] = {  };
             auto inName = project.directoryPath + L"\\Resources";
             auto outName = outDirectory + L"\\Resources";
             wsprintf(commandLine, L"/c xcopy %s\\*.* %s\\ /E /Y", inName.c_str(), outName.c_str());
             ShellExecute(nullptr, L"open", L"cmd", commandLine, nullptr, SW_SHOW);
         }

         do {
             //    写入 project.
             std::wifstream ifile(L"null_project\\null_project.xml.ui", std::ios::binary | std::ios::in);
             if (!ifile)
             {
                 break;
             }
             auto fileSize = getFileSize(ifile);
             auto templateBuffer = std::wstring(fileSize, L'\0');
             ifile.read(&templateBuffer[], fileSize);
             ifile.close();

             auto writeStr = std::regex_replace(
                 templateBuffer, std::wregex(L"JsonList_Replace"), jsonList);
             std::wfstream ofile(outDirectory + L"\\project.xml.ui", std::ios::binary | std::ios::out);
             ofile.write(writeStr.c_str(), writeStr.size());
             ofile.close();
         } );

         result = true;
     }
     return result;
 }

 bool run(const std::wstring &rootDirectory, const std::wstring &outDirectory)
 {
     auto result = false;

     do {
         {
             wchar_t commadBuffer[];
             wsprintf(commadBuffer,
                      L"/c "
                      L"%c:&"
                      L"cd %s&"
                      L"del config.txt&"
                      L"for /R %%i in (*) do (echo %%i>>%s\\config.txt)",
                      rootDirectory[], rootDirectory.c_str(), rootDirectory.c_str());
             ShellExecute(nullptr, L"open", L"cmd", commadBuffer, nullptr, SW_SHOW);
             LOG(L"Wait 10 Seconds...");
             std::this_thread::sleep_for(std::chrono::milliseconds());
         }

         //    打开文件
         std::wifstream ifile(rootDirectory + L"\\config.txt");

         //    读取文件列表.
         std::vector<std::wstring> fileList;
         if (ifile)
         {
             LOG(L"open config.txt.");
             do {
                 std::wstring fileName;
                 std::getline(ifile, fileName);
                 fileList.push_back(fileName);
             } while (!ifile.eof());
             ifile.close();
             LOG(L"init file list.");
         }

         if (!fileList.empty())
         {
             result = handleFileList(rootDirectory, outDirectory, fileList);
         }
     } );

     return result;
 }

 int main()
 {
     std::locale::global(std::locale("chs"));

     std::wifstream ifile(L"config.txt");
     if (ifile)
     {
         std::wstring rootDirectory = L"X:\\Output\\office\\UI\\11月新版UI";
         std::wstring outDirectory = L"X:\\Output\\test_out";
         std::getline(ifile, rootDirectory);
         std::getline(ifile, outDirectory);

         std::wcout
             << L"rootDirectory: " << rootDirectory << L"\n"
             << L"outDirectory: " << outDirectory << std::endl;
         std::wcout << (run(rootDirectory, outDirectory) ? L"done." : L"failed.");
     }
     std::wcout << L"\n===========================end.===========================\n";
     std::cin.get();
     ;
 }

思路比较简单, 效果看起来很高端有没有.

一堆的控制台弹窗.

好久没写博客了, 今天坐一会标题党.