checkpoint(new_editor): native d3d12 ui path

Key node 1: move main-window UI presentation onto the D3D12 render loop with native UI renderer, text system, and texture host.

Key node 2: wire frame timing/FPS display, window runtime, swapchain presentation, and native screenshot capture around the new path.

Key node 3: carry editor shell/workspace/viewport/panel interaction updates needed by the new renderer and detached window flow.

Key node 4: pump async resource loads and scene bridge follow-up needed for scene content visibility in new_editor.
This commit is contained in:
2026-04-21 20:49:18 +08:00
parent a779b04dba
commit 6e9265e92e
53 changed files with 5330 additions and 858 deletions

View File

@@ -1,5 +1,6 @@
#include "ProjectBrowserModel.h"
#include <filesystem>
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
#include <string>
#include <string_view>
#include <vector>
@@ -89,6 +90,10 @@ std::u8string BuildU8String(std::string_view value) {
return result;
}
void TraceProjectBrowser(std::string message) {
::XCEngine::UI::Editor::AppendUIEditorRuntimeTrace("startup", std::move(message));
}
} // namespace
std::string ToLowerCopy(std::string value) {
@@ -550,14 +555,31 @@ std::string RemapMovedItemId(
void ProjectBrowserModel::Initialize(const std::filesystem::path& repoRoot) {
m_assetsRootPath = (repoRoot / "project/Assets").lexically_normal();
TraceProjectBrowser("ProjectBrowserModel::Initialize assetsRoot=" + PathToUtf8String(m_assetsRootPath));
std::error_code errorCode = {};
if (!std::filesystem::exists(m_assetsRootPath, errorCode)) {
std::filesystem::create_directories(m_assetsRootPath / "Scenes", errorCode);
}
if (errorCode) {
TraceProjectBrowser("ProjectBrowserModel::Initialize filesystem error=" + errorCode.message());
}
Refresh();
TraceProjectBrowser(
"ProjectBrowserModel::Initialize complete folders=" +
std::to_string(m_folderEntries.size()) +
" assets=" +
std::to_string(m_assetEntries.size()));
}
void ProjectBrowserModel::SetFolderIcon(const ::XCEngine::UI::UITextureHandle& icon) {
if (m_folderIcon.nativeHandle == icon.nativeHandle &&
m_folderIcon.width == icon.width &&
m_folderIcon.height == icon.height &&
m_folderIcon.kind == icon.kind &&
m_folderIcon.resourceHandle == icon.resourceHandle) {
return;
}
m_folderIcon = icon;
if (!m_assetsRootPath.empty()) {
RefreshFolderTree();
@@ -565,9 +587,17 @@ void ProjectBrowserModel::SetFolderIcon(const ::XCEngine::UI::UITextureHandle& i
}
void ProjectBrowserModel::Refresh() {
TraceProjectBrowser("ProjectBrowserModel::Refresh begin");
RefreshFolderTree();
EnsureValidCurrentFolder();
RefreshAssetList();
TraceProjectBrowser(
"ProjectBrowserModel::Refresh end currentFolder=" +
m_currentFolderId +
" folders=" +
std::to_string(m_folderEntries.size()) +
" assets=" +
std::to_string(m_assetEntries.size()));
}
bool ProjectBrowserModel::Empty() const {
@@ -1186,6 +1216,7 @@ namespace XCEngine::UI::Editor::App {
void ProjectBrowserModel::RefreshAssetList() {
TraceProjectBrowser("ProjectBrowserModel::RefreshAssetList begin");
EnsureValidCurrentFolder();
m_assetEntries.clear();
@@ -1239,6 +1270,12 @@ void ProjectBrowserModel::RefreshAssetList() {
CanPreviewItem(entry.path(), assetEntry.kind, assetEntry.directory);
m_assetEntries.push_back(std::move(assetEntry));
}
TraceProjectBrowser(
"ProjectBrowserModel::RefreshAssetList end currentFolder=" +
m_currentFolderId +
" assets=" +
std::to_string(m_assetEntries.size()));
}
} // namespace XCEngine::UI::Editor::App
@@ -1247,6 +1284,7 @@ namespace XCEngine::UI::Editor::App {
void ProjectBrowserModel::RefreshFolderTree() {
TraceProjectBrowser("ProjectBrowserModel::RefreshFolderTree begin");
m_folderEntries.clear();
m_treeItems.clear();
@@ -1280,6 +1318,9 @@ void ProjectBrowserModel::RefreshFolderTree() {
};
appendFolderRecursive(appendFolderRecursive, m_assetsRootPath, 0u);
TraceProjectBrowser(
"ProjectBrowserModel::RefreshFolderTree end folders=" +
std::to_string(m_folderEntries.size()));
}
std::vector<std::string> ProjectBrowserModel::CollectCurrentFolderAncestorIds() const {