Finalize library bootstrap status and stabilize async asset regressions

This commit is contained in:
2026-04-04 19:44:59 +08:00
parent 013e5a73b9
commit bcef1f145b
25 changed files with 3415 additions and 81 deletions

View File

@@ -9,8 +9,12 @@
#include "Utils/ProjectFileUtils.h"
#include "UI/UI.h"
#include <XCEngine/Core/Asset/ResourceManager.h>
#include <algorithm>
#include <chrono>
#include <cctype>
#include <cstdint>
#include <filesystem>
#include <imgui.h>
#include <shellapi.h>
@@ -24,6 +28,85 @@ namespace {
constexpr float kProjectToolbarHeight = 26.0f;
constexpr float kProjectToolbarPaddingY = 3.0f;
std::uint64_t ResolveImportStatusElapsedMs(
const XCEngine::Resources::AssetImportService::ImportStatusSnapshot& status) {
if (!status.HasValue() || status.startedAtMs == 0) {
return 0;
}
if (!status.inProgress) {
return static_cast<std::uint64_t>(status.durationMs);
}
const auto nowMs = static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch()).count());
return nowMs >= status.startedAtMs
? nowMs - static_cast<std::uint64_t>(status.startedAtMs)
: 0;
}
ImVec4 ResolveImportStatusColor(const XCEngine::Resources::AssetImportService::ImportStatusSnapshot& status) {
if (!status.HasValue()) {
return XCEngine::Editor::UI::ConsoleSecondaryTextColor();
}
if (status.inProgress) {
return XCEngine::Editor::UI::ConsoleWarningColor();
}
return status.success
? XCEngine::Editor::UI::ConsoleSecondaryTextColor()
: XCEngine::Editor::UI::ConsoleErrorColor();
}
std::string BuildImportStatusText(const XCEngine::Resources::AssetImportService::ImportStatusSnapshot& status) {
if (!status.HasValue()) {
return "Library: ready";
}
std::string text = "Library: ";
text += status.message.CStr();
const std::uint64_t elapsedMs = ResolveImportStatusElapsedMs(status);
if (elapsedMs > 0) {
text += " (";
text += std::to_string(elapsedMs);
text += " ms)";
}
return text;
}
std::string BuildImportStatusTooltipText(const XCEngine::Resources::AssetImportService::ImportStatusSnapshot& status) {
if (!status.HasValue()) {
return "No import operations have been recorded in this session.";
}
std::string tooltip;
tooltip += "Operation: ";
tooltip += status.operation.CStr();
tooltip += "\nState: ";
tooltip += status.inProgress ? "Running" : (status.success ? "Succeeded" : "Failed");
const std::uint64_t elapsedMs = ResolveImportStatusElapsedMs(status);
if (elapsedMs > 0) {
tooltip += "\nDuration: ";
tooltip += std::to_string(elapsedMs);
tooltip += " ms";
}
if (!status.targetPath.Empty()) {
tooltip += "\nTarget: ";
tooltip += status.targetPath.CStr();
}
if (status.importedAssetCount > 0) {
tooltip += "\nImported: ";
tooltip += std::to_string(status.importedAssetCount);
}
if (status.removedArtifactCount > 0) {
tooltip += "\nRemoved orphans: ";
tooltip += std::to_string(status.removedArtifactCount);
}
return tooltip;
}
template <typename Fn>
void QueueDeferredAction(std::function<void()>& pendingAction, Fn&& fn) {
if (!pendingAction) {
@@ -373,6 +456,10 @@ void ProjectPanel::Render() {
}
void ProjectPanel::RenderToolbar() {
const auto importStatus = ::XCEngine::Resources::ResourceManager::Get().GetProjectAssetImportStatus();
const std::string importStatusText = BuildImportStatusText(importStatus);
const std::string importStatusTooltip = BuildImportStatusTooltipText(importStatus);
UI::PanelToolbarScope toolbar(
"ProjectToolbar",
kProjectToolbarHeight,
@@ -387,12 +474,23 @@ void ProjectPanel::RenderToolbar() {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.0f, 0.0f));
if (ImGui::BeginTable("##ProjectToolbarLayout", 2, ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_SizingStretchProp)) {
ImGui::TableSetupColumn("##Spacer", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("##ImportStatus", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("##Search", ImGuiTableColumnFlags_WidthFixed, 220.0f);
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::PushStyleColor(ImGuiCol_Text, ResolveImportStatusColor(importStatus));
ImGui::TextUnformatted(importStatusText.c_str());
ImGui::PopStyleColor();
if (ImGui::IsItemHovered() && !importStatusTooltip.empty()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 36.0f);
ImGui::TextUnformatted(importStatusTooltip.c_str());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
ImGui::TableNextColumn();
UI::ToolbarSearchField("##Search", "Search assets", m_searchBuffer, sizeof(m_searchBuffer));