Finalize viewport host interface closure

This commit is contained in:
2026-04-04 18:15:04 +08:00
parent 0807b5a753
commit a9bf9ef35c
9 changed files with 66 additions and 47 deletions

View File

@@ -1,8 +1,7 @@
#pragma once
#include <XCEngine/Core/Math/Vector3.h>
#include <imgui.h>
#include <XCEngine/UI/Types.h>
#include <cstdint>
#include <string>
@@ -24,17 +23,17 @@ enum class EditorViewportKind {
};
struct EditorViewportFrame {
ImTextureID textureId = {};
ImVec2 requestedSize = ImVec2(0.0f, 0.0f);
ImVec2 renderSize = ImVec2(0.0f, 0.0f);
::XCEngine::UI::UITextureHandle texture = {};
::XCEngine::UI::UISize requestedSize = {};
::XCEngine::UI::UISize renderSize = {};
bool hasTexture = false;
bool wasRequested = false;
std::string statusText;
};
struct SceneViewportInput {
ImVec2 viewportSize = ImVec2(0.0f, 0.0f);
ImVec2 mouseDelta = ImVec2(0.0f, 0.0f);
::XCEngine::UI::UISize viewportSize = {};
::XCEngine::UI::UIPoint mouseDelta = {};
float mouseWheel = 0.0f;
float flySpeedDelta = 0.0f;
float deltaTime = 0.0f;
@@ -77,12 +76,14 @@ public:
virtual ~IViewportHostService() = default;
virtual void BeginFrame() = 0;
virtual EditorViewportFrame RequestViewport(EditorViewportKind kind, const ImVec2& requestedSize) = 0;
virtual EditorViewportFrame RequestViewport(
EditorViewportKind kind,
const ::XCEngine::UI::UISize& requestedSize) = 0;
virtual void UpdateSceneViewInput(IEditorContext& context, const SceneViewportInput& input) = 0;
virtual uint64_t PickSceneViewEntity(
IEditorContext& context,
const ImVec2& viewportSize,
const ImVec2& viewportMousePosition) = 0;
const ::XCEngine::UI::UISize& viewportSize,
const ::XCEngine::UI::UIPoint& viewportMousePosition) = 0;
virtual void AlignSceneViewToOrientationAxis(SceneViewportOrientationAxis axis) = 0;
virtual SceneViewportOverlayData GetSceneViewOverlayData() const = 0;
virtual const SceneViewportOverlayFrameData& GetSceneViewEditorOverlayFrameData(IEditorContext& context) = 0;

View File

@@ -98,7 +98,7 @@ void DispatchSceneViewportInteractionActions(
const SceneViewportInteractionActions& actions,
IEditorContext& context,
IViewportHostService& viewportHostService,
const ImVec2& viewportSize,
const ::XCEngine::UI::UISize& viewportSize,
const Math::Vector2& localMousePosition) {
if (actions.orientationGizmoClick) {
viewportHostService.AlignSceneViewToOrientationAxis(actions.orientationAxis);
@@ -116,7 +116,7 @@ void DispatchSceneViewportInteractionActions(
const uint64_t selectedEntity = viewportHostService.PickSceneViewEntity(
context,
viewportSize,
ImVec2(localMousePosition.x, localMousePosition.y));
::XCEngine::UI::UIPoint(localMousePosition.x, localMousePosition.y));
if (selectedEntity != 0) {
context.GetSelectionManager().SetSelectedEntity(selectedEntity);
} else {

View File

@@ -58,7 +58,7 @@ void DispatchSceneViewportInteractionActions(
const SceneViewportInteractionActions& actions,
IEditorContext& context,
IViewportHostService& viewportHostService,
const ImVec2& viewportSize,
const ::XCEngine::UI::UISize& viewportSize,
const Math::Vector2& localMousePosition);
} // namespace Editor

View File

@@ -213,8 +213,8 @@ inline bool CanResolveSceneViewportInteraction(
struct SceneViewportInputBuildRequest {
SceneViewportNavigationState state = {};
ImVec2 viewportSize = ImVec2(0.0f, 0.0f);
ImVec2 mouseDelta = ImVec2(0.0f, 0.0f);
::XCEngine::UI::UISize viewportSize = {};
::XCEngine::UI::UIPoint mouseDelta = {};
float mouseWheel = 0.0f;
float deltaTime = 0.0f;
bool viewportHovered = false;

View File

@@ -6,6 +6,7 @@
#include <XCEngine/RHI/RHIDevice.h>
#include <XCEngine/RHI/RHIResourceView.h>
#include <XCEngine/RHI/RHITexture.h>
#include <XCEngine/UI/Types.h>
namespace XCEngine {
namespace Editor {
@@ -22,7 +23,7 @@ struct ViewportRenderTargets {
RHI::RHIResourceView* objectIdShaderView = nullptr;
D3D12_CPU_DESCRIPTOR_HANDLE imguiCpuHandle = {};
D3D12_GPU_DESCRIPTOR_HANDLE imguiGpuHandle = {};
ImTextureID textureId = {};
::XCEngine::UI::UITextureHandle textureHandle = {};
RHI::ResourceStates colorState = RHI::ResourceStates::Common;
RHI::ResourceStates objectIdState = RHI::ResourceStates::Common;
bool hasValidObjectIdFrame = false;
@@ -46,7 +47,7 @@ inline ViewportHostResourceReuseQuery BuildViewportRenderTargetsReuseQuery(
query.resources.hasObjectIdTexture = targets.objectIdTexture != nullptr;
query.resources.hasObjectIdView = targets.objectIdView != nullptr;
query.resources.hasObjectIdShaderView = targets.objectIdShaderView != nullptr;
query.resources.hasTextureDescriptor = targets.textureId != ImTextureID{};
query.resources.hasTextureDescriptor = targets.textureHandle.IsValid();
return query;
}
@@ -142,12 +143,20 @@ inline bool CreateViewportTextureDescriptor(
UI::ImGuiBackendBridge* backend,
RHI::RHIDevice* device,
ViewportRenderTargets& targets) {
return backend->CreateTextureDescriptor(
ImTextureID imguiTextureId = {};
if (!backend->CreateTextureDescriptor(
device,
targets.colorTexture,
&targets.imguiCpuHandle,
&targets.imguiGpuHandle,
&targets.textureId);
&imguiTextureId)) {
return false;
}
targets.textureHandle.nativeHandle = static_cast<std::uintptr_t>(targets.imguiGpuHandle.ptr);
targets.textureHandle.width = targets.width;
targets.textureHandle.height = targets.height;
return true;
}
} // namespace Detail
@@ -171,7 +180,7 @@ inline void DestroyViewportRenderTargets(
targets.height = 0;
targets.imguiCpuHandle = {};
targets.imguiGpuHandle = {};
targets.textureId = {};
targets.textureHandle = {};
targets.colorState = RHI::ResourceStates::Common;
targets.objectIdState = RHI::ResourceStates::Common;
targets.hasValidObjectIdFrame = false;

View File

@@ -6,8 +6,8 @@
#include "IViewportHostService.h"
#include "SceneViewportCameraController.h"
#include "SceneViewportEditorOverlayData.h"
#include "SceneViewportOverlayFrameCache.h"
#include "SceneViewportOverlayHandleBuilder.h"
#include "SceneViewportOverlayFrameCache.h"
#include "SceneViewportOverlayBuilder.h"
#include "SceneViewportRenderPassBundle.h"
#include "SceneViewportRenderPlan.h"
@@ -97,14 +97,16 @@ public:
m_sceneViewTransformGizmoOverlayDirty = true;
}
EditorViewportFrame RequestViewport(EditorViewportKind kind, const ImVec2& requestedSize) override {
EditorViewportFrame RequestViewport(
EditorViewportKind kind,
const ::XCEngine::UI::UISize& requestedSize) override {
ViewportEntry& entry = GetEntry(kind);
entry.requestedThisFrame = requestedSize.x > 1.0f && requestedSize.y > 1.0f;
entry.requestedThisFrame = requestedSize.width > 1.0f && requestedSize.height > 1.0f;
entry.requestedWidth = entry.requestedThisFrame
? static_cast<uint32_t>(requestedSize.x)
? static_cast<uint32_t>(requestedSize.width)
: 0u;
entry.requestedHeight = entry.requestedThisFrame
? static_cast<uint32_t>(requestedSize.y)
? static_cast<uint32_t>(requestedSize.height)
: 0u;
if (entry.requestedThisFrame && m_backend != nullptr && m_device != nullptr) {
@@ -112,12 +114,12 @@ public:
}
EditorViewportFrame frame = {};
frame.textureId = entry.renderTargets.textureId;
frame.texture = entry.renderTargets.textureHandle;
frame.requestedSize = requestedSize;
frame.renderSize = ImVec2(
frame.renderSize = ::XCEngine::UI::UISize(
static_cast<float>(entry.renderTargets.width),
static_cast<float>(entry.renderTargets.height));
frame.hasTexture = entry.renderTargets.textureId != ImTextureID{};
frame.hasTexture = entry.renderTargets.textureHandle.IsValid();
frame.wasRequested = entry.requestedThisFrame;
frame.statusText = entry.statusText;
return frame;
@@ -133,7 +135,7 @@ public:
}
SceneViewportCameraInputState controllerInput = {};
controllerInput.viewportHeight = input.viewportSize.y;
controllerInput.viewportHeight = input.viewportSize.height;
controllerInput.zoomDelta = input.hovered ? input.mouseWheel : 0.0f;
controllerInput.flySpeedDelta = input.hovered ? input.flySpeedDelta : 0.0f;
controllerInput.deltaTime = input.deltaTime;
@@ -163,8 +165,8 @@ public:
uint64_t PickSceneViewEntity(
IEditorContext& context,
const ImVec2& viewportSize,
const ImVec2& viewportMousePosition) override {
const ::XCEngine::UI::UISize& viewportSize,
const ::XCEngine::UI::UIPoint& viewportMousePosition) override {
if (!EnsureSceneViewCamera()) {
return 0;
}
@@ -491,9 +493,7 @@ private:
void BuildSceneViewportRenderState(
ViewportEntry& entry,
IEditorContext& context,
const Components::Scene& scene,
SceneViewportRenderState& outState) {
(void)scene;
outState.overlay = GetSceneViewOverlayData();
if (!outState.overlay.valid) {
return;
@@ -542,7 +542,7 @@ private:
}
SceneViewportRenderState sceneState = {};
BuildSceneViewportRenderState(entry, context, *scene, sceneState);
BuildSceneViewportRenderState(entry, context, sceneState);
std::vector<Rendering::CameraRenderRequest> requests =
m_sceneRenderer->BuildRenderRequests(*scene, m_sceneViewCamera.camera, renderContext, surface);
@@ -668,8 +668,8 @@ private:
ViewportObjectIdPickResult PickSceneViewEntityWithObjectId(
ViewportEntry& entry,
const ImVec2& viewportSize,
const ImVec2& viewportMousePosition) {
const ::XCEngine::UI::UISize& viewportSize,
const ::XCEngine::UI::UIPoint& viewportMousePosition) {
if (m_device == nullptr) {
return {};
}

View File

@@ -6,6 +6,7 @@
#include <XCEngine/RHI/RHIEnums.h>
#include <XCEngine/RHI/RHITexture.h>
#include <XCEngine/Rendering/ObjectIdEncoding.h>
#include <XCEngine/UI/Types.h>
#include <array>
#include <cstdint>
@@ -21,8 +22,8 @@ struct ViewportObjectIdPickContext {
uint32_t textureWidth = 0;
uint32_t textureHeight = 0;
bool hasValidFrame = false;
ImVec2 viewportSize = ImVec2(0.0f, 0.0f);
ImVec2 viewportMousePosition = ImVec2(0.0f, 0.0f);
::XCEngine::UI::UISize viewportSize = {};
::XCEngine::UI::UIPoint viewportMousePosition = {};
};
struct ViewportObjectIdReadbackRequest {
@@ -54,12 +55,12 @@ inline bool CanPickViewportObjectId(const ViewportObjectIdPickContext& context)
context.textureWidth > 0 &&
context.textureHeight > 0 &&
context.hasValidFrame &&
context.viewportSize.x > 1.0f &&
context.viewportSize.y > 1.0f &&
context.viewportSize.width > 1.0f &&
context.viewportSize.height > 1.0f &&
context.viewportMousePosition.x >= 0.0f &&
context.viewportMousePosition.y >= 0.0f &&
context.viewportMousePosition.x <= context.viewportSize.x &&
context.viewportMousePosition.y <= context.viewportSize.y;
context.viewportMousePosition.x <= context.viewportSize.width &&
context.viewportMousePosition.y <= context.viewportSize.height;
}
inline bool BuildViewportObjectIdReadbackRequest(

View File

@@ -144,7 +144,7 @@ void SceneViewPanel::Render() {
interactionActions,
*m_context,
*viewportHostService,
content.availableSize,
::XCEngine::UI::UISize(content.availableSize.x, content.availableSize.y),
frameGeometry.localMousePosition);
ExecuteSceneViewportTransformGizmoLifecycleCommand(
@@ -172,8 +172,8 @@ void SceneViewPanel::Render() {
SceneViewportInputBuildRequest inputRequest = {};
inputRequest.state = m_navigationState;
inputRequest.viewportSize = content.availableSize;
inputRequest.mouseDelta = io.MouseDelta;
inputRequest.viewportSize = ::XCEngine::UI::UISize(content.availableSize.x, content.availableSize.y);
inputRequest.mouseDelta = ::XCEngine::UI::UIPoint(io.MouseDelta.x, io.MouseDelta.y);
inputRequest.mouseWheel = io.MouseWheel;
inputRequest.deltaTime = io.DeltaTime;
inputRequest.viewportHovered = viewportContentHovered;

View File

@@ -11,6 +11,14 @@
namespace XCEngine {
namespace Editor {
inline ::XCEngine::UI::UISize ToUISize(const ImVec2& value) {
return ::XCEngine::UI::UISize(value.x, value.y);
}
inline ImTextureID ToImGuiTextureId(const ::XCEngine::UI::UITextureHandle& texture) {
return static_cast<ImTextureID>(texture.nativeHandle);
}
struct ViewportPanelContentResult {
EditorViewportFrame frame;
ImVec2 availableSize = ImVec2(0.0f, 0.0f);
@@ -95,12 +103,12 @@ inline ViewportPanelContentResult RenderViewportPanelContent(IEditorContext& con
return result;
}
result.frame = viewportHostService->RequestViewport(kind, result.availableSize);
result.frame = viewportHostService->RequestViewport(kind, ToUISize(result.availableSize));
RenderViewportInteractionSurface(result, kind, result.availableSize);
if (result.frame.hasTexture) {
if (ImDrawList* drawList = ImGui::GetWindowDrawList()) {
drawList->AddImage(result.frame.textureId, result.itemMin, result.itemMax);
drawList->AddImage(ToImGuiTextureId(result.frame.texture), result.itemMin, result.itemMax);
}
}