2026-03-28 17:04:14 +08:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "Core/IEditorContext.h"
|
|
|
|
|
#include "Viewport/IViewportHostService.h"
|
|
|
|
|
|
|
|
|
|
#include <imgui.h>
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
namespace XCEngine {
|
|
|
|
|
namespace Editor {
|
|
|
|
|
|
2026-03-28 17:40:14 +08:00
|
|
|
struct ViewportPanelContentResult {
|
|
|
|
|
EditorViewportFrame frame;
|
|
|
|
|
ImVec2 availableSize = ImVec2(0.0f, 0.0f);
|
|
|
|
|
ImVec2 itemMin = ImVec2(0.0f, 0.0f);
|
|
|
|
|
ImVec2 itemMax = ImVec2(0.0f, 0.0f);
|
|
|
|
|
bool hasViewportArea = false;
|
|
|
|
|
bool hovered = false;
|
|
|
|
|
bool focused = false;
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-28 17:04:14 +08:00
|
|
|
inline void DrawViewportStatusMessage(const std::string& message) {
|
|
|
|
|
if (message.empty()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
|
|
|
|
if (drawList == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ImVec2 min = ImGui::GetItemRectMin();
|
|
|
|
|
const ImVec2 max = ImGui::GetItemRectMax();
|
|
|
|
|
const ImVec2 textSize = ImGui::CalcTextSize(message.c_str());
|
|
|
|
|
const ImVec2 textPos(
|
|
|
|
|
min.x + ((max.x - min.x) - textSize.x) * 0.5f,
|
|
|
|
|
min.y + ((max.y - min.y) - textSize.y) * 0.5f);
|
|
|
|
|
|
|
|
|
|
drawList->AddText(textPos, ImGui::GetColorU32(ImGuiCol_TextDisabled), message.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-28 17:40:14 +08:00
|
|
|
inline ViewportPanelContentResult RenderViewportPanelContent(IEditorContext& context, EditorViewportKind kind) {
|
|
|
|
|
ViewportPanelContentResult result = {};
|
|
|
|
|
result.availableSize = ImGui::GetContentRegionAvail();
|
|
|
|
|
result.focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows);
|
|
|
|
|
|
2026-03-28 17:04:14 +08:00
|
|
|
IViewportHostService* viewportHostService = context.GetViewportHostService();
|
2026-03-28 17:40:14 +08:00
|
|
|
if (result.availableSize.x <= 1.0f || result.availableSize.y <= 1.0f) {
|
2026-03-28 17:04:14 +08:00
|
|
|
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
2026-03-28 17:40:14 +08:00
|
|
|
return result;
|
2026-03-28 17:04:14 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-28 17:40:14 +08:00
|
|
|
result.hasViewportArea = true;
|
|
|
|
|
|
2026-03-28 17:04:14 +08:00
|
|
|
if (viewportHostService == nullptr) {
|
2026-03-28 17:40:14 +08:00
|
|
|
ImGui::Dummy(result.availableSize);
|
|
|
|
|
result.itemMin = ImGui::GetItemRectMin();
|
|
|
|
|
result.itemMax = ImGui::GetItemRectMax();
|
|
|
|
|
result.hovered = ImGui::IsMouseHoveringRect(result.itemMin, result.itemMax, true);
|
2026-03-28 17:04:14 +08:00
|
|
|
DrawViewportStatusMessage("Viewport host is unavailable");
|
2026-03-28 17:40:14 +08:00
|
|
|
return result;
|
2026-03-28 17:04:14 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-28 17:40:14 +08:00
|
|
|
result.frame = viewportHostService->RequestViewport(kind, result.availableSize);
|
|
|
|
|
if (result.frame.hasTexture) {
|
|
|
|
|
ImGui::Image(result.frame.textureId, result.availableSize);
|
|
|
|
|
} else {
|
|
|
|
|
ImGui::Dummy(result.availableSize);
|
2026-03-28 17:04:14 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-28 17:40:14 +08:00
|
|
|
result.itemMin = ImGui::GetItemRectMin();
|
|
|
|
|
result.itemMax = ImGui::GetItemRectMax();
|
|
|
|
|
result.hovered = ImGui::IsMouseHoveringRect(result.itemMin, result.itemMax, true);
|
|
|
|
|
|
2026-03-28 17:04:14 +08:00
|
|
|
DrawViewportStatusMessage(
|
2026-03-28 17:40:14 +08:00
|
|
|
result.frame.statusText.empty() && !result.frame.hasTexture
|
|
|
|
|
? "Viewport is initializing"
|
|
|
|
|
: result.frame.statusText);
|
|
|
|
|
return result;
|
2026-03-28 17:04:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Editor
|
|
|
|
|
} // namespace XCEngine
|