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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,6 +11,14 @@
namespace XCEngine { namespace XCEngine {
namespace Editor { 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 { struct ViewportPanelContentResult {
EditorViewportFrame frame; EditorViewportFrame frame;
ImVec2 availableSize = ImVec2(0.0f, 0.0f); ImVec2 availableSize = ImVec2(0.0f, 0.0f);
@@ -95,12 +103,12 @@ inline ViewportPanelContentResult RenderViewportPanelContent(IEditorContext& con
return result; return result;
} }
result.frame = viewportHostService->RequestViewport(kind, result.availableSize); result.frame = viewportHostService->RequestViewport(kind, ToUISize(result.availableSize));
RenderViewportInteractionSurface(result, kind, result.availableSize); RenderViewportInteractionSurface(result, kind, result.availableSize);
if (result.frame.hasTexture) { if (result.frame.hasTexture) {
if (ImDrawList* drawList = ImGui::GetWindowDrawList()) { if (ImDrawList* drawList = ImGui::GetWindowDrawList()) {
drawList->AddImage(result.frame.textureId, result.itemMin, result.itemMax); drawList->AddImage(ToImGuiTextureId(result.frame.texture), result.itemMin, result.itemMax);
} }
} }