2026-04-12 11:12:27 +08:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <XCEditor/Collections/UIEditorTreeView.h>
|
|
|
|
|
|
|
|
|
|
#include <XCEngine/UI/Types.h>
|
|
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <filesystem>
|
2026-04-19 00:03:25 +08:00
|
|
|
#include <optional>
|
2026-04-12 11:12:27 +08:00
|
|
|
#include <string>
|
|
|
|
|
#include <string_view>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
namespace XCEngine::UI::Editor::App {
|
2026-04-12 11:12:27 +08:00
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
class ProjectBrowserModel {
|
2026-04-12 11:12:27 +08:00
|
|
|
public:
|
2026-04-19 00:03:25 +08:00
|
|
|
enum class ItemKind : std::uint8_t {
|
|
|
|
|
Folder = 0,
|
|
|
|
|
Scene,
|
|
|
|
|
Model,
|
|
|
|
|
Material,
|
|
|
|
|
Texture,
|
|
|
|
|
Script,
|
|
|
|
|
File
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-12 11:12:27 +08:00
|
|
|
struct BreadcrumbSegment {
|
|
|
|
|
std::string label = {};
|
|
|
|
|
std::string targetFolderId = {};
|
|
|
|
|
bool current = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct FolderEntry {
|
|
|
|
|
std::string itemId = {};
|
|
|
|
|
std::filesystem::path absolutePath = {};
|
|
|
|
|
std::string label = {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct AssetEntry {
|
|
|
|
|
std::string itemId = {};
|
|
|
|
|
std::filesystem::path absolutePath = {};
|
|
|
|
|
std::string displayName = {};
|
2026-04-19 00:03:25 +08:00
|
|
|
std::string nameWithExtension = {};
|
|
|
|
|
std::string extensionLower = {};
|
|
|
|
|
ItemKind kind = ItemKind::File;
|
2026-04-12 11:12:27 +08:00
|
|
|
bool directory = false;
|
2026-04-19 00:03:25 +08:00
|
|
|
bool canOpen = false;
|
|
|
|
|
bool canPreview = false;
|
2026-04-12 11:12:27 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void Initialize(const std::filesystem::path& repoRoot);
|
|
|
|
|
void SetFolderIcon(const ::XCEngine::UI::UITextureHandle& icon);
|
|
|
|
|
void Refresh();
|
|
|
|
|
|
|
|
|
|
bool Empty() const;
|
2026-04-19 00:03:25 +08:00
|
|
|
std::filesystem::path GetProjectRootPath() const;
|
2026-04-12 11:12:27 +08:00
|
|
|
const std::filesystem::path& GetAssetsRootPath() const;
|
|
|
|
|
const std::vector<FolderEntry>& GetFolderEntries() const;
|
|
|
|
|
const std::vector<Widgets::UIEditorTreeViewItem>& GetTreeItems() const;
|
|
|
|
|
const std::vector<AssetEntry>& GetAssetEntries() const;
|
|
|
|
|
const std::string& GetCurrentFolderId() const;
|
2026-04-19 00:03:25 +08:00
|
|
|
bool IsAssetsRoot(std::string_view itemId) const;
|
2026-04-12 11:12:27 +08:00
|
|
|
|
|
|
|
|
const FolderEntry* FindFolderEntry(std::string_view itemId) const;
|
|
|
|
|
const AssetEntry* FindAssetEntry(std::string_view itemId) const;
|
2026-04-19 00:03:25 +08:00
|
|
|
std::optional<std::filesystem::path> ResolveItemAbsolutePath(
|
|
|
|
|
std::string_view itemId) const;
|
|
|
|
|
std::string BuildProjectRelativePath(std::string_view itemId) const;
|
2026-04-12 11:12:27 +08:00
|
|
|
bool NavigateToFolder(std::string_view itemId);
|
2026-04-19 00:03:25 +08:00
|
|
|
bool CreateFolder(
|
|
|
|
|
std::string_view parentFolderId,
|
|
|
|
|
std::string_view requestedName,
|
|
|
|
|
std::string* createdFolderId = nullptr);
|
|
|
|
|
bool CreateMaterial(
|
|
|
|
|
std::string_view parentFolderId,
|
|
|
|
|
std::string_view requestedName,
|
|
|
|
|
std::string* createdItemId = nullptr);
|
|
|
|
|
bool RenameItem(
|
|
|
|
|
std::string_view itemId,
|
|
|
|
|
std::string_view newName,
|
|
|
|
|
std::string* renamedItemId = nullptr);
|
|
|
|
|
bool DeleteItem(std::string_view itemId);
|
|
|
|
|
bool CanMoveItemToFolder(
|
|
|
|
|
std::string_view itemId,
|
|
|
|
|
std::string_view targetFolderId) const;
|
|
|
|
|
bool MoveItemToFolder(
|
|
|
|
|
std::string_view itemId,
|
|
|
|
|
std::string_view targetFolderId,
|
|
|
|
|
std::string* movedItemId = nullptr);
|
|
|
|
|
std::optional<std::string> GetParentFolderId(std::string_view itemId) const;
|
|
|
|
|
bool CanReparentFolder(std::string_view sourceFolderId, std::string_view targetParentId) const;
|
|
|
|
|
bool ReparentFolder(
|
|
|
|
|
std::string_view sourceFolderId,
|
|
|
|
|
std::string_view targetParentId,
|
|
|
|
|
std::string* movedFolderId = nullptr);
|
|
|
|
|
bool MoveFolderToRoot(
|
|
|
|
|
std::string_view sourceFolderId,
|
|
|
|
|
std::string* movedFolderId = nullptr);
|
2026-04-12 11:12:27 +08:00
|
|
|
std::vector<BreadcrumbSegment> BuildBreadcrumbSegments() const;
|
|
|
|
|
std::vector<std::string> CollectCurrentFolderAncestorIds() const;
|
|
|
|
|
std::vector<std::string> BuildAncestorFolderIds(std::string_view itemId) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void RefreshFolderTree();
|
|
|
|
|
void RefreshAssetList();
|
|
|
|
|
void EnsureValidCurrentFolder();
|
|
|
|
|
|
|
|
|
|
std::filesystem::path m_assetsRootPath = {};
|
|
|
|
|
std::vector<FolderEntry> m_folderEntries = {};
|
|
|
|
|
std::vector<Widgets::UIEditorTreeViewItem> m_treeItems = {};
|
|
|
|
|
std::vector<AssetEntry> m_assetEntries = {};
|
|
|
|
|
::XCEngine::UI::UITextureHandle m_folderIcon = {};
|
|
|
|
|
std::string m_currentFolderId = {};
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
} // namespace XCEngine::UI::Editor::App
|
|
|
|
|
|
|
|
|
|
|