#include "ProjectManager.h" #include #include #include #include namespace fs = std::filesystem; namespace XCEngine { namespace Editor { std::vector& ProjectManager::GetCurrentItems() { if (m_path.empty()) { static std::vector empty; return empty; } return m_path.back()->children; } void ProjectManager::NavigateToFolder(const AssetItemPtr& folder) { m_path.push_back(folder); m_selectedIndex = -1; } void ProjectManager::NavigateBack() { if (m_path.size() > 1) { m_path.pop_back(); m_selectedIndex = -1; } } void ProjectManager::NavigateToIndex(size_t index) { if (index >= m_path.size()) return; while (m_path.size() > index + 1) { m_path.pop_back(); } m_selectedIndex = -1; } std::string ProjectManager::GetCurrentPath() const { if (m_path.empty()) return "Assets"; std::string result = "Assets"; for (size_t i = 1; i < m_path.size(); i++) { result += "/"; result += m_path[i]->name; } return result; } std::string ProjectManager::GetPathName(size_t index) const { if (index >= m_path.size()) return ""; return m_path[index]->name; } static std::wstring Utf8ToWstring(const std::string& str) { if (str.empty()) return L""; int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0); if (len <= 0) return L""; std::wstring result(len - 1, 0); MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &result[0], len); return result; } static std::string WstringToUtf8(const std::wstring& wstr) { if (wstr.empty()) return ""; int len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr); if (len <= 0) return ""; std::string result(len - 1, 0); WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &result[0], len, nullptr, nullptr); return result; } void ProjectManager::Initialize(const std::string& projectPath) { m_projectPath = projectPath; std::wstring projectPathW = Utf8ToWstring(projectPath); fs::path assetsPath = fs::path(projectPathW) / L"Assets"; try { if (!fs::exists(assetsPath)) { fs::create_directories(assetsPath); fs::create_directories(assetsPath / L"Textures"); fs::create_directories(assetsPath / L"Models"); fs::create_directories(assetsPath / L"Scripts"); fs::create_directories(assetsPath / L"Materials"); fs::create_directories(assetsPath / L"Scenes"); std::ofstream((assetsPath / L"Textures" / L"Grass.png").wstring()); std::ofstream((assetsPath / L"Textures" / L"Stone.png").wstring()); std::ofstream((assetsPath / L"Models" / L"Character.fbx").wstring()); std::ofstream((assetsPath / L"Scripts" / L"PlayerController.cs").wstring()); std::ofstream((assetsPath / L"Scenes" / L"Main.unity").wstring()); } m_rootFolder = ScanDirectory(assetsPath.wstring()); m_rootFolder->name = "Assets"; m_rootFolder->fullPath = WstringToUtf8(assetsPath.wstring()); m_path.clear(); m_path.push_back(m_rootFolder); m_selectedIndex = -1; } catch (const std::exception& e) { m_rootFolder = std::make_shared(); m_rootFolder->name = "Assets"; m_rootFolder->isFolder = true; m_rootFolder->type = "Folder"; m_path.push_back(m_rootFolder); } } std::wstring ProjectManager::GetCurrentFullPathW() const { if (m_path.empty()) return Utf8ToWstring(m_projectPath); std::wstring fullPath = Utf8ToWstring(m_projectPath); for (size_t i = 0; i < m_path.size(); i++) { fullPath += L"/" + Utf8ToWstring(m_path[i]->name); } return fullPath; } void ProjectManager::RefreshCurrentFolder() { if (m_path.empty()) return; try { auto newFolder = ScanDirectory(GetCurrentFullPathW()); m_path.back()->children = newFolder->children; } catch (...) { } } void ProjectManager::CreateFolder(const std::string& name) { try { std::wstring fullPath = GetCurrentFullPathW(); fs::path newFolderPath = fs::path(fullPath) / Utf8ToWstring(name); fs::create_directory(newFolderPath); RefreshCurrentFolder(); } catch (...) { } } void ProjectManager::DeleteItem(int index) { if (m_path.empty()) return; auto& items = m_path.back()->children; if (index < 0 || index >= (int)items.size()) return; try { std::wstring fullPath = GetCurrentFullPathW(); fs::path itemPath = fs::path(fullPath) / Utf8ToWstring(items[index]->name); fs::remove_all(itemPath); m_selectedIndex = -1; RefreshCurrentFolder(); } catch (...) { } } bool ProjectManager::MoveItem(const std::string& sourceFullPath, const std::string& destFolderFullPath) { try { fs::path sourcePath = Utf8ToWstring(sourceFullPath); fs::path destPath = fs::path(Utf8ToWstring(destFolderFullPath)) / sourcePath.filename(); if (!fs::exists(sourcePath)) { return false; } if (fs::exists(destPath)) { return false; } fs::rename(sourcePath, destPath); RefreshCurrentFolder(); return true; } catch (...) { return false; } } AssetItemPtr ProjectManager::ScanDirectory(const std::wstring& path) { auto folder = std::make_shared(); folder->name = WstringToUtf8(fs::path(path).filename().wstring()); folder->isFolder = true; folder->type = "Folder"; if (!fs::exists(path)) return folder; std::vector items; try { for (const auto& entry : fs::directory_iterator(path)) { std::wstring nameW = entry.path().filename().wstring(); bool isFolder = entry.is_directory(); items.push_back(CreateAssetItem(entry.path().wstring(), nameW, isFolder)); } } catch (...) { } std::sort(items.begin(), items.end(), [](const AssetItemPtr& a, const AssetItemPtr& b) { if (a->isFolder != b->isFolder) return a->isFolder; return a->name < b->name; }); folder->children = items; return folder; } AssetItemPtr ProjectManager::CreateAssetItem(const std::wstring& path, const std::wstring& nameW, bool isFolder) { auto item = std::make_shared(); item->name = WstringToUtf8(nameW); item->isFolder = isFolder; item->fullPath = WstringToUtf8(path); if (isFolder) { item->type = "Folder"; try { auto subFolder = ScanDirectory(path); item->children = subFolder->children; } catch (...) { } } else { std::wstring ext = fs::path(path).extension().wstring(); std::transform(ext.begin(), ext.end(), ext.begin(), ::towlower); if (ext == L".png" || ext == L".jpg" || ext == L".tga" || ext == L".bmp") { item->type = "Texture"; } else if (ext == L".fbx" || ext == L".obj" || ext == L".gltf" || ext == L".glb") { item->type = "Model"; } else if (ext == L".cs" || ext == L".cpp" || ext == L".h") { item->type = "Script"; } else if (ext == L".mat") { item->type = "Material"; } else if (ext == L".unity" || ext == L".scene") { item->type = "Scene"; } else if (ext == L".prefab") { item->type = "Prefab"; } else { item->type = "File"; } } return item; } } }