Advertisement
Zgragselus

Directory Tree

May 15th, 2023
613
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.67 KB | None | 0 0
  1. #include "DirectoryTree.h"
  2.  
  3. using namespace SkyeCuillin;
  4.  
  5. DirectoryTree::Record* DirectoryTree::CreateSubtree(const std::string& directory)
  6. {
  7.     std::vector<std::string> list;
  8.  
  9.     Engine::Files::DirectoryRead(directory, list);
  10.  
  11.     Record* r = new Record(Type::DIRECTORY, directory.substr(directory.find_last_of('/') + 1));
  12.  
  13.     for (size_t i = 0; i < list.size(); i++)
  14.     {
  15.         if (list[i][list[i].length() - 1] == '/')
  16.         {
  17.             r->mChildren.push_back(CreateSubtree(directory + "/" + list[i].substr(0, list[i].length() - 1)));
  18.         }
  19.         else
  20.         {
  21.             printf("%s\n", (directory + "/" + list[i]).c_str());
  22.             Record* rec = new Record(Type::FILE, list[i]);
  23.             ProcessFile(rec, directory + "/" + list[i], list);
  24.             r->mChildren.push_back(rec);
  25.         }
  26.     }
  27.  
  28.     return r;
  29. }
  30.  
  31. void DirectoryTree::ProcessFile(Record* r, const std::string& file, std::vector<std::string>& files)
  32. {
  33.     Engine::LoaderDevIL textureLoader(mLog);
  34.     Engine::LoaderAssimp modelLoader(mLog, mRenderer);
  35.     modelLoader.SetManagers(mMeshManager, mModelManager, mTextureManager);
  36.     modelLoader.SetTextureHeap(mRenderer->Heap(), nullptr);
  37.  
  38.     if ((file.find(".tga") != std::string::npos) || (file.find(".png") != std::string::npos))
  39.     {
  40.         Engine::Manager<Engine::Texture>::Node* node = mTextureManager->GetNode(file);
  41.  
  42.         Engine::LoaderDevIL::Image* image = textureLoader.Load(file);
  43.         if (image != nullptr)
  44.         {
  45.             image->mUseAlphaMipmap = false;
  46.             textureLoader.GenerateMipmaps(image);
  47.         }
  48.         Engine::Texture* t = new Engine::Texture(file);
  49.         t->InitMipmaps(mRenderer, image->mWidth, image->mHeight, 1, image->mMipLevels, Engine::Graphics::RGBA8, (const void**)image->mMipmaps);
  50.         t->SetName(file);
  51.         if (node == nullptr)
  52.         {
  53.             mTextureManager->Insert<Engine::Texture>(file, t);
  54.             node = mTextureManager->GetNode(file);
  55.         }
  56.         else
  57.         {
  58.             delete node->mItem;
  59.             node->mItem = t;
  60.         }
  61.         delete image;
  62.  
  63.         r->mResourceType = ResourceType::TEXTURE;
  64.         r->mResource = node;
  65.     }
  66.     else if (file.find(".obj") != std::string::npos)
  67.     {
  68.         Engine::Manager<Engine::Model>::Node* node = mModelManager->GetNode(file);
  69.  
  70.         Engine::Model* mdl = modelLoader.Load(file);
  71.         if (node == nullptr)
  72.         {
  73.             mModelManager->Insert<Engine::Model>(file, mdl);
  74.             node = mModelManager->GetNode(file);
  75.         }
  76.         else
  77.         {
  78.             delete node->mItem;
  79.             node->mItem = mdl;
  80.         }
  81.        
  82.         r->mResourceType = ResourceType::MODEL;
  83.         r->mResource = node;
  84.     }
  85.     else if (file.find(".cpp") != std::string::npos)
  86.     {
  87.         // Check if there isn't dll that corresponds to the cpp file
  88.         bool compile = true;
  89.         for (size_t i = 0; i < files.size(); i++)
  90.         {
  91.             std::string filesName = files[i].substr(0, files[i].length() - 4);
  92.             std::string cmpName = Engine::Files::GetFile(file.substr(0, file.length() - 4));
  93.  
  94.             if ((files[i].substr(0, files[i].length() - 4) == Engine::Files::GetFile(file.substr(0, file.length() - 4))) &&
  95.                 (files[i].find(".dll") != std::string::npos))
  96.             {
  97.                 // If such dll exists, check if its write time is greater than cpp write time
  98.                 if (Engine::Files::GetWriteTime(Engine::Files::GetFolder(file) + files[i]) > Engine::Files::GetWriteTime(file))
  99.                 {
  100.                     // In such case our dll is most-recent version of the script, we don't need to compile
  101.                     compile = false;
  102.                 }
  103.             }
  104.         }
  105.  
  106.         // If we need to compile, build the dll
  107.         if (compile)
  108.         {
  109.             std::string command = "";
  110.  
  111.             switch (mCompilerType)
  112.             {
  113.             // MSVC Compiler
  114.             case MSVC:
  115.                 // Here is the deal, MSVC always generates .obj, .exp, .lib and .dll file in the current folder
  116.                 // so, we will call the MSVC compiler with all settings, and let it build dll, writing output
  117.                 // to Build.log
  118.                 //
  119.                 // Once this is done, we will delete .obj, .exp and .lib file as we don't need those anymore.
  120.                 // Which is followed by copying .dll file into the folder where .cpp file originally was, this
  121.                 // is not all though - as we just generated a new .dll plugin, we also need to queue it for
  122.                 // loading!
  123.                 //
  124.                 // The loading only happens when .dll exists (otherwise the compilation has failed and the
  125.                 // Build.log has to be examined.
  126.                 //
  127.                 // Uses system calls!
  128.  
  129.                 // Compilation (differs for DEBUG vs RELEASE builds)
  130. #ifdef NDEBUG
  131.                 command = std::string("cmd /S /C \"\"") + mCompilerPaths[0] + std::string("/vcvarsall.bat\" amd64 && \
  132.                     \"") + mCompilerPaths[1] + std::string("/cl.exe\" /O2 /EHsc /GL /MD /I \
  133.                     \"../Source/\" \
  134.                     /LD \
  135.                     ") + file + std::string(" \
  136.                     \"Core.lib\" \
  137.                     > Build.log\"");
  138. #else
  139.                 command = std::string("cmd /S /C \"\"") + mCompilerPaths[0] + std::string("/vcvarsall.bat\" amd64 && \
  140.                     \"") + mCompilerPaths[1] + std::string("/cl.exe\" /O2 /EHsc /GL /MDd /I \
  141.                     \"../Source/\" \
  142.                     /LD \
  143.                     ") + file + std::string(" \
  144.                     \"Core.lib\" \
  145.                     > Build.log\"");
  146. #endif
  147.                 system(command.c_str());
  148.  
  149.                 // Delete .obj, .exp and .lib files
  150.                 command = std::string("cmd /S /C \"del ")
  151.                     + std::string("\"") + Engine::Files::GetFile(file.substr(0, file.length() - 4)) + std::string(".obj") + std::string("\" ")
  152.                     + std::string("\"") + Engine::Files::GetFile(file.substr(0, file.length() - 4)) + std::string(".exp") + std::string("\" ")
  153.                     + std::string("\"") + Engine::Files::GetFile(file.substr(0, file.length() - 4)) + std::string(".lib") + std::string("\"\"");
  154.                 system(command.c_str());
  155.  
  156.                 // Move .dll file
  157.                 command = std::string("cmd /S /C \"move ")
  158.                     + std::string("\"") + Engine::Files::GetFile(file.substr(0, file.length() - 4)) + std::string(".dll") + std::string("\" ")
  159.                     + Engine::Files::GetFolder(file) + std::string("\"");
  160.                 system(command.c_str());
  161.  
  162.                 // If the .dll file exists in correct location, enqueue it for loading as next file
  163.                 if (Engine::Files::Exists(file.substr(0, file.length() - 4) + std::string(".dll")))
  164.                 {
  165.                     files.push_back(file.substr(0, file.length() - 4) + std::string(".dll"));
  166.                 }
  167.                 break;
  168.  
  169.             default:
  170.                 mLog->Print("Compiler", "Error: Invalid Compiler - Can't Compiler Any File!");
  171.                 break;
  172.             }
  173.         }
  174.     }
  175.     else if (file.find(".dll") != std::string::npos)
  176.     {
  177.         Engine::Manager<Engine::Plugin>::Node* node = mPluginManager->GetNode(file);
  178.  
  179.         mLog->Print("Plugin", std::string("Loading plugin: ") + file);
  180.         Engine::Plugin* plugin = new Engine::Plugin(file);
  181.         void* create = plugin->GetProc<void*>("CreateBehavior");
  182.         void* name = plugin->GetProc<void*>("GetName");
  183.         const char* (*fn)() = (const char*(*)())name;
  184.         const char* pluginName = (*fn)();
  185.  
  186.         if (create == nullptr || name == nullptr)
  187.         {
  188.             mLog->Print("Plugin", std::string("CreateBehavior or GetName function not found!"));
  189.             delete plugin;
  190.         }
  191.         else
  192.         {
  193.             mLog->Print("Plugin", std::string("CreateBehavior and GetName function found!"));
  194.             mLog->Print("Plugin", std::string("Initializing plugin with name: ") + pluginName);
  195.  
  196.             if (node == nullptr)
  197.             {
  198.                 mPluginManager->Insert<Engine::Plugin>(file, plugin);
  199.                 node = mPluginManager->GetNode(file);
  200.  
  201.                 Engine::ComponentId componentID = Engine::ComponentTypeId::Get(pluginName);
  202.  
  203.                 Engine::ComponentInterface* componentInterface = new Engine::ComponentInterface();
  204.                 componentInterface->CreateComponent = (Engine::Component*(*)())create;
  205.  
  206.                 Engine::ComponentFactory::GetScriptComponentManager().insert(std::pair<Engine::ComponentId, Engine::ComponentInterface*>(componentID, componentInterface));
  207.             }
  208.             else
  209.             {
  210.                 delete node->mItem;
  211.                 node->mItem = plugin;
  212.             }
  213.  
  214.             r->mResourceType = ResourceType::SCRIPT;
  215.             r->mResource = node;
  216.         }
  217.     }
  218. }
  219.  
  220. DirectoryTree::Record* DirectoryTree::GetSubtreeRoot(std::string& directory)
  221. {
  222.     Record* r = mRoot;
  223.  
  224.     std::string::iterator itDir = directory.begin();
  225.     std::string::iterator itNode = r->mName.begin();
  226.     while (itDir != directory.end() && itNode != r->mName.end() && (*itDir) == (*itNode))
  227.     {
  228.         itDir++;
  229.         itNode++;
  230.     }
  231.  
  232.     std::vector<std::string> path = Engine::String::Split(directory.substr(itDir - directory.begin()), '/');
  233.     for (size_t i = 0; i < path.size(); i++)
  234.     {
  235.         if (path[i].length() > 0)
  236.         {
  237.             for (size_t j = 0; j < r->mChildren.size(); j++)
  238.             {
  239.                 if (r->mChildren[j]->mName == path[i])
  240.                 {
  241.                     r = r->mChildren[j];
  242.                     break;
  243.                 }
  244.             }
  245.         }
  246.     }
  247.  
  248.     return r;
  249. }
  250.  
  251. void DirectoryTree::UpdateSubtree(std::string& directory)
  252. {
  253.     std::vector<std::string> list;
  254.  
  255.     Engine::Files::DirectoryRead(directory, list);
  256.  
  257.     Record* r = GetSubtreeRoot(directory);
  258.  
  259.     std::set<std::string> nodes;
  260.     for (Record* t : r->mChildren)
  261.     {
  262.         nodes.insert(t->mName);
  263.     }
  264.  
  265.     for (size_t i = 0; i < list.size(); i++)
  266.     {
  267.         bool found = false;
  268.  
  269.         std::string name = list[i];
  270.  
  271.         if (list[i][list[i].length() - 1] == '/')
  272.         {
  273.             name = list[i].substr(0, list[i].length() - 1);
  274.         }
  275.  
  276.         for (size_t j = 0; j < r->mChildren.size(); j++)
  277.         {
  278.             if (r->mChildren[j]->mName == name)
  279.             {
  280.                 found = true;
  281.                 nodes.erase(name);
  282.                 break;
  283.             }
  284.         }
  285.  
  286.         if (!found)
  287.         {
  288.             if (list[i][list[i].length() - 1] == '/')
  289.             {
  290.                 r->mChildren.push_back(CreateSubtree(directory + "/" + list[i].substr(0, list[i].length() - 1)));
  291.             }
  292.             else
  293.             {
  294.                 r->mChildren.push_back(new Record(Type::FILE, list[i]));
  295.             }
  296.         }
  297.     }
  298.  
  299.     for (const std::string& s : nodes)
  300.     {
  301.         for (size_t j = 0; j < r->mChildren.size(); j++)
  302.         {
  303.             if (r->mChildren[j]->mName == s)
  304.             {
  305.                 r->mChildren.erase(r->mChildren.begin() + j);
  306.                 break;
  307.             }
  308.         }
  309.     }
  310. }
  311.  
  312. void DirectoryTree::_ImguiRenderRecord(Record* r)
  313. {
  314.     for (size_t i = 0; i < r->mChildren.size(); i++)
  315.     {
  316.         bool nodeOpen = false;
  317.  
  318.         if (ImGui::TreeNodeEx(r->mChildren[i]->mName.c_str(),
  319.             //((r->mChildren[i]->mType == Type::FILE && r->mChildren[i]->mResourceType != ResourceType::MODEL) ? ImGuiTreeNodeFlags_Leaf : 0) |
  320.             (r->mChildren[i]->mType == Type::FILE ? ImGuiTreeNodeFlags_Leaf : 0) |
  321.             ImGuiTreeNodeFlags_OpenOnArrow |
  322.             (r->mChildren[i]->mResourceType != ResourceType::MODEL ? ImGuiTreeNodeFlags_DefaultOpen : 0)))
  323.         {
  324.             nodeOpen = true;
  325.  
  326.             if (r->mChildren[i]->mType != Type::DIRECTORY)
  327.             {
  328.                 if (ImGui::BeginDragDropSource())
  329.                 {
  330.                     printf("%lx\n", r->mChildren[i]->mResource);
  331.                     switch (r->mChildren[i]->mResourceType)
  332.                     {
  333.                     case ResourceType::MODEL:
  334.                         ImGui::SetDragDropPayload("RESOURCE_MODEL", &(r->mChildren[i]->mResource), sizeof(Record*));
  335.                         ImGui::Text("%s", r->mChildren[i]->mName.c_str());
  336.                         break;
  337.  
  338.                     case ResourceType::TEXTURE:
  339.                         ImGui::SetDragDropPayload("RESOURCE_TEXTURE", &(r->mChildren[i]->mResource), sizeof(void*));
  340.                         ImGui::Image((ImTextureID)(((Engine::Manager<Engine::Texture>::Node*)r->mChildren[i]->mResource)->mItem->GetSRV().mGpuHandle.ptr), ImVec2(64, 64));
  341.                         break;
  342.  
  343.                     case ResourceType::SCRIPT:
  344.                         ImGui::SetDragDropPayload("RESOURCE_SCRIPT", &(r->mChildren[i]->mResource), sizeof(void*));
  345.                         ImGui::Text("%s", r->mChildren[i]->mName.c_str());
  346.                         break;
  347.  
  348.                     default:
  349.                         break;
  350.                     }
  351.                     ImGui::EndDragDropSource();
  352.                 }
  353.  
  354.                 if (ImGui::IsItemClicked())
  355.                 {
  356.                     printf("%s\n", r->mChildren[i]->mName.c_str());
  357.                 }
  358.  
  359.                 if (r->mChildren[i]->mResourceType == ResourceType::MODEL)
  360.                 {
  361.                     Engine::Manager<Engine::Model>::Node* node = (Engine::Manager<Engine::Model>::Node*)(r->mChildren[i]->mResource);
  362.  
  363.                     for (size_t j = 0; j < node->Get()->GetMeshesCount(); j++)
  364.                     {
  365.                         if (ImGui::TreeNodeEx(node->Get()->GetMesh(j)->GetName().c_str(), ImGuiTreeNodeFlags_Leaf))
  366.                         {
  367.                             if (ImGui::BeginDragDropSource())
  368.                             {
  369.                                 Engine::Mesh* mesh = node->Get()->GetMesh(j);
  370.                                 ImGui::SetDragDropPayload("RESOURCE_MESH", &mesh, sizeof(void*));
  371.                                 ImGui::Text("%s", node->Get()->GetMesh(j)->GetName().c_str());
  372.                                 ImGui::EndDragDropSource();
  373.                             }
  374.                         }
  375.                         ImGui::TreePop();
  376.                     }
  377.                 }
  378.             }
  379.         }
  380.  
  381.         if (r->mChildren[i]->mType == Type::DIRECTORY)
  382.         {
  383.             if (nodeOpen)
  384.             {
  385.                 _ImguiRenderRecord(r->mChildren[i]);
  386.             }
  387.         }
  388.  
  389.         if (nodeOpen)
  390.         {
  391.             ImGui::TreePop();
  392.         }
  393.     }
  394. }
  395.  
  396. DirectoryTree::DirectoryTree(const std::string& directory, Engine::Constants* options, Engine::Log* log, Engine::D3DRenderer* renderer)
  397. {
  398.     std::string path = directory;
  399.     std::replace(path.begin(), path.end(), '\\', '/');
  400.  
  401.     mPath = path;
  402.     mOptions = options;
  403.     mLog = log;
  404.     mRenderer = renderer;
  405.  
  406.     std::string compilerType = mOptions->Get<std::string>("Compiler.Type");
  407.     if (compilerType == "Visual Studio 2022")
  408.     {
  409.         mCompilerType = MSVC;
  410.         mCompilerPaths = new std::string[2];
  411.         mCompilerPaths[0] = mOptions->Get<std::string>("Compiler.VCVarsAllPath");
  412.         mCompilerPaths[1] = mOptions->Get<std::string>("Compiler.CLPath");
  413.     }
  414.     else
  415.     {
  416.         mLog->Print("Compiler", std::string("Error: Unknown Compiler or Compiler Not Set - Critical Error - Please Fix Config File!"));
  417.         mCompilerPaths = nullptr;
  418.     }
  419. }
  420.  
  421. DirectoryTree::~DirectoryTree()
  422. {
  423.     delete mRoot;
  424.  
  425.     if (mCompilerPaths)
  426.     {
  427.         delete[] mCompilerPaths;
  428.     }
  429. }
  430.  
  431. void DirectoryTree::Initialize()
  432. {
  433.     mRoot = CreateSubtree(mPath);
  434. }
  435.  
  436. void DirectoryTree::SetManagers(Engine::Manager<Engine::Mesh>* meshManager,
  437.     Engine::Manager<Engine::Model>* modelManager,
  438.     Engine::Manager<Engine::Texture>* textureManager,
  439.     Engine::Manager<Engine::Plugin>* pluginManager)
  440. {
  441.     mMeshManager = meshManager;
  442.     mModelManager = modelManager;
  443.     mTextureManager = textureManager;
  444.     mPluginManager = pluginManager;
  445. }
  446.  
  447. void DirectoryTree::Imgui()
  448. {
  449.     _ImguiRenderRecord(mRoot);
  450. }
  451.  
  452. void DirectoryTree::NotifyChange(std::string location)
  453. {
  454.     mChanges.push_back(location);
  455. }
  456.  
  457. void DirectoryTree::ProcessChanges()
  458. {
  459.     for (const std::string& s : mChanges)
  460.     {
  461.         printf("Processing: '%s'\n", s.c_str());
  462.         std::string path = mOptions->Get<std::string>("Editor.Resources") + "/" + s;
  463.         std::replace(path.begin(), path.end(), '\\', '/');
  464.         Engine::Files::Type type = Engine::Files::GetType(path);
  465.  
  466.         if (type == Engine::Files::Type::DIRECTORY)
  467.         {
  468.             UpdateSubtree(path);
  469.         }
  470.         else
  471.         {
  472.             std::string directory = path.substr(0, path.find_last_of('/'));
  473.             mFiles.push_back(path);
  474.             UpdateSubtree(directory);
  475.         }
  476.  
  477.         mTextureManager->Print();
  478.     }
  479.  
  480.     mChanges.clear();
  481.  
  482.     for (const std::string& s : mFiles)
  483.     {
  484.         Engine::LoaderDevIL loader(mLog);
  485.  
  486.         printf("%s\n", s.c_str());
  487.         if (s.find(".tga") != std::string::npos)
  488.         {
  489.             Engine::Manager<Engine::Texture>::Node* node = mTextureManager->GetNode(s);
  490.             if (node != nullptr)
  491.             {
  492.                 Engine::LoaderDevIL::Image* image = loader.Load(s);
  493.                 if (image != nullptr)
  494.                 {
  495.                     image->mUseAlphaMipmap = false;
  496.                     loader.GenerateMipmaps(image);
  497.                 }
  498.                 Engine::Texture* t = new Engine::Texture(s);
  499.                 t->InitMipmaps(mRenderer, image->mWidth, image->mHeight, 1, image->mMipLevels, Engine::Graphics::RGBA8, (const void**)image->mMipmaps);
  500.                 t->SetName(s);
  501.                 delete node->mItem;
  502.                 node->mItem = t;
  503.                 delete image;
  504.             }
  505.         }
  506.     }
  507.  
  508.     mFiles.clear();
  509. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement