chore: sync editor worktree changes

This commit is contained in:
2026-04-05 01:25:09 +08:00
parent 061e74d98f
commit b2774f1745
27 changed files with 1014 additions and 281 deletions

View File

@@ -4,6 +4,7 @@
#include "ProjectPanel.h"
#include "Core/IEditorContext.h"
#include "Core/IProjectManager.h"
#include "Core/ISceneManager.h"
#include "Core/AssetItem.h"
#include "Platform/Win32Utf8.h"
#include "Utils/ProjectFileUtils.h"
@@ -60,6 +61,51 @@ ImVec4 ResolveImportStatusColor(const XCEngine::Resources::AssetImportService::I
: XCEngine::Editor::UI::ConsoleErrorColor();
}
std::uint64_t ResolveSceneLoadElapsedMs(const XCEngine::Editor::SceneLoadProgressSnapshot& status) {
if (!status.HasValue() || status.startedAtMs == 0) {
return 0;
}
if (status.inProgress) {
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 - status.startedAtMs : 0;
}
if (status.streamingCompletedAtMs >= status.startedAtMs && status.streamingCompletedAtMs != 0) {
return status.streamingCompletedAtMs - status.startedAtMs;
}
if (status.firstFrameAtMs >= status.startedAtMs && status.firstFrameAtMs != 0) {
return status.firstFrameAtMs - status.startedAtMs;
}
if (status.structureReadyAtMs >= status.startedAtMs && status.structureReadyAtMs != 0) {
return status.structureReadyAtMs - status.startedAtMs;
}
return 0;
}
std::uint64_t ResolveSceneLoadMarkerDeltaMs(std::uint64_t startMs, std::uint64_t endMs) {
return endMs >= startMs && startMs != 0 ? endMs - startMs : 0;
}
ImVec4 ResolveSceneLoadStatusColor(const XCEngine::Editor::SceneLoadProgressSnapshot& 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";
@@ -76,6 +122,32 @@ std::string BuildImportStatusText(const XCEngine::Resources::AssetImportService:
return text;
}
std::string BuildSceneLoadStatusText(const XCEngine::Editor::SceneLoadProgressSnapshot& status) {
if (!status.HasValue()) {
return "Scene: ready";
}
std::string text = "Scene: ";
if (!status.success) {
text += status.message.empty() ? "failed" : status.message;
return text;
}
if (status.inProgress) {
text += status.message.empty() ? "loading..." : status.message;
} else {
text += "ready";
}
const std::uint64_t elapsedMs = ResolveSceneLoadElapsedMs(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.";
@@ -107,6 +179,68 @@ std::string BuildImportStatusTooltipText(const XCEngine::Resources::AssetImportS
return tooltip;
}
std::string BuildSceneLoadStatusTooltipText(const XCEngine::Editor::SceneLoadProgressSnapshot& status) {
if (!status.HasValue()) {
return "No scene load operations have been recorded in this session.";
}
std::string tooltip;
tooltip += "Operation: ";
tooltip += status.operation.empty() ? "Scene Load" : status.operation;
if (!status.scenePath.empty()) {
tooltip += "\nScene: ";
tooltip += status.scenePath;
}
tooltip += "\nState: ";
tooltip += status.inProgress ? "Running" : (status.success ? "Succeeded" : "Failed");
const std::uint64_t structureMs =
ResolveSceneLoadMarkerDeltaMs(status.startedAtMs, status.structureReadyAtMs);
if (structureMs > 0) {
tooltip += "\nStructure restore: ";
tooltip += std::to_string(structureMs);
tooltip += " ms";
}
const std::uint64_t firstFrameMs =
ResolveSceneLoadMarkerDeltaMs(status.startedAtMs, status.firstFrameAtMs);
if (firstFrameMs > 0) {
tooltip += "\nFirst viewport frame: ";
tooltip += std::to_string(firstFrameMs);
tooltip += " ms";
}
const std::uint64_t interactiveMs =
ResolveSceneLoadMarkerDeltaMs(status.startedAtMs, status.interactiveAtMs);
if (interactiveMs > 0) {
tooltip += "\nFirst interactive frame: ";
tooltip += std::to_string(interactiveMs);
tooltip += " ms";
}
const std::uint64_t streamingMs =
ResolveSceneLoadMarkerDeltaMs(status.startedAtMs, status.streamingCompletedAtMs);
if (streamingMs > 0) {
tooltip += "\nRuntime streaming complete: ";
tooltip += std::to_string(streamingMs);
tooltip += " ms";
}
if (status.peakPendingAsyncLoads > 0) {
tooltip += "\nPeak async loads: ";
tooltip += std::to_string(status.peakPendingAsyncLoads);
}
if (status.inProgress && status.currentPendingAsyncLoads > 0) {
tooltip += "\nPending async loads: ";
tooltip += std::to_string(status.currentPendingAsyncLoads);
}
if (!status.message.empty()) {
tooltip += "\nStatus: ";
tooltip += status.message;
}
return tooltip;
}
template <typename Fn>
void QueueDeferredAction(std::function<void()>& pendingAction, Fn&& fn) {
if (!pendingAction) {
@@ -457,8 +591,12 @@ void ProjectPanel::Render() {
void ProjectPanel::RenderToolbar() {
const auto importStatus = ::XCEngine::Resources::ResourceManager::Get().GetProjectAssetImportStatus();
const SceneLoadProgressSnapshot sceneLoadStatus =
m_context != nullptr ? m_context->GetSceneManager().GetSceneLoadProgress() : SceneLoadProgressSnapshot{};
const std::string importStatusText = BuildImportStatusText(importStatus);
const std::string importStatusTooltip = BuildImportStatusTooltipText(importStatus);
const std::string sceneLoadStatusText = BuildSceneLoadStatusText(sceneLoadStatus);
const std::string sceneLoadStatusTooltip = BuildSceneLoadStatusTooltipText(sceneLoadStatus);
UI::PanelToolbarScope toolbar(
"ProjectToolbar",
@@ -473,8 +611,9 @@ void ProjectPanel::RenderToolbar() {
}
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.0f, 0.0f));
if (ImGui::BeginTable("##ProjectToolbarLayout", 2, ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_SizingStretchProp)) {
if (ImGui::BeginTable("##ProjectToolbarLayout", 3, ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_SizingStretchProp)) {
ImGui::TableSetupColumn("##ImportStatus", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("##SceneLoadStatus", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("##Search", ImGuiTableColumnFlags_WidthFixed, 220.0f);
ImGui::TableNextRow();
@@ -492,6 +631,19 @@ void ProjectPanel::RenderToolbar() {
ImGui::EndTooltip();
}
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::PushStyleColor(ImGuiCol_Text, ResolveSceneLoadStatusColor(sceneLoadStatus));
ImGui::TextUnformatted(sceneLoadStatusText.c_str());
ImGui::PopStyleColor();
if (ImGui::IsItemHovered() && !sceneLoadStatusTooltip.empty()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 36.0f);
ImGui::TextUnformatted(sceneLoadStatusTooltip.c_str());
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
ImGui::TableNextColumn();
UI::ToolbarSearchField("##Search", "Search assets", m_searchBuffer, sizeof(m_searchBuffer));