127 lines
3.9 KiB
C++
127 lines
3.9 KiB
C++
#pragma once
|
|
|
|
#include "ViewportHostSurfaceUtils.h"
|
|
|
|
#include <XCEngine/RHI/RHICommandQueue.h>
|
|
#include <XCEngine/RHI/RHIEnums.h>
|
|
#include <XCEngine/RHI/RHITexture.h>
|
|
#include <XCEngine/Rendering/Picking/ObjectIdCodec.h>
|
|
#include <XCEngine/UI/Types.h>
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <utility>
|
|
|
|
namespace XCEngine {
|
|
namespace Editor {
|
|
|
|
struct ViewportObjectIdPickContext {
|
|
RHI::RHICommandQueue* commandQueue = nullptr;
|
|
RHI::RHITexture* texture = nullptr;
|
|
RHI::ResourceStates textureState = RHI::ResourceStates::Common;
|
|
uint32_t textureWidth = 0;
|
|
uint32_t textureHeight = 0;
|
|
bool hasValidFrame = false;
|
|
::XCEngine::UI::UISize viewportSize = {};
|
|
::XCEngine::UI::UIPoint viewportMousePosition = {};
|
|
};
|
|
|
|
struct ViewportObjectIdReadbackRequest {
|
|
RHI::RHICommandQueue* commandQueue = nullptr;
|
|
RHI::RHITexture* texture = nullptr;
|
|
RHI::ResourceStates textureState = RHI::ResourceStates::Common;
|
|
uint32_t pixelX = 0;
|
|
uint32_t pixelY = 0;
|
|
};
|
|
|
|
enum class ViewportObjectIdPickStatus : uint8_t {
|
|
Unavailable = 0,
|
|
Success,
|
|
ReadbackFailed
|
|
};
|
|
|
|
struct ViewportObjectIdPickResult {
|
|
ViewportObjectIdPickStatus status = ViewportObjectIdPickStatus::Unavailable;
|
|
Rendering::RenderObjectId renderObjectId = Rendering::kInvalidRenderObjectId;
|
|
uint64_t entityId = 0;
|
|
|
|
bool HasResolvedSample() const {
|
|
return status == ViewportObjectIdPickStatus::Success;
|
|
}
|
|
};
|
|
|
|
inline bool CanPickViewportObjectId(const ViewportObjectIdPickContext& context) {
|
|
return context.commandQueue != nullptr &&
|
|
context.texture != nullptr &&
|
|
context.textureWidth > 0 &&
|
|
context.textureHeight > 0 &&
|
|
context.hasValidFrame &&
|
|
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.width &&
|
|
context.viewportMousePosition.y <= context.viewportSize.height;
|
|
}
|
|
|
|
inline bool BuildViewportObjectIdReadbackRequest(
|
|
const ViewportObjectIdPickContext& context,
|
|
ViewportObjectIdReadbackRequest& outRequest) {
|
|
outRequest = {};
|
|
if (!CanPickViewportObjectId(context)) {
|
|
return false;
|
|
}
|
|
|
|
outRequest.commandQueue = context.commandQueue;
|
|
outRequest.texture = context.texture;
|
|
outRequest.textureState = context.textureState;
|
|
outRequest.pixelX = ClampViewportPixelCoordinate(
|
|
context.viewportMousePosition.x,
|
|
context.textureWidth);
|
|
outRequest.pixelY = ClampViewportPixelCoordinate(
|
|
context.viewportMousePosition.y,
|
|
context.textureHeight);
|
|
return true;
|
|
}
|
|
|
|
template <typename ReadPixelFn>
|
|
ViewportObjectIdPickResult PickViewportObjectIdEntity(
|
|
const ViewportObjectIdPickContext& context,
|
|
ReadPixelFn&& readPixel) {
|
|
ViewportObjectIdPickResult result = {};
|
|
|
|
ViewportObjectIdReadbackRequest request = {};
|
|
if (!BuildViewportObjectIdReadbackRequest(context, request)) {
|
|
return result;
|
|
}
|
|
|
|
std::array<uint8_t, 4> rgba = {};
|
|
if (!readPixel(request, rgba)) {
|
|
result.status = ViewportObjectIdPickStatus::ReadbackFailed;
|
|
return result;
|
|
}
|
|
|
|
result.status = ViewportObjectIdPickStatus::Success;
|
|
result.renderObjectId = Rendering::DecodeRenderObjectIdFromColor(
|
|
rgba[0],
|
|
rgba[1],
|
|
rgba[2],
|
|
rgba[3]);
|
|
result.entityId = Rendering::ConvertRenderObjectIdToRuntimeObjectId(result.renderObjectId);
|
|
return result;
|
|
}
|
|
|
|
template <typename ReadPixelFn>
|
|
bool TryPickViewportObjectIdEntity(
|
|
const ViewportObjectIdPickContext& context,
|
|
ReadPixelFn&& readPixel,
|
|
uint64_t& outEntityId) {
|
|
const ViewportObjectIdPickResult result =
|
|
PickViewportObjectIdEntity(context, std::forward<ReadPixelFn>(readPixel));
|
|
outEntityId = result.entityId;
|
|
return result.HasResolvedSample();
|
|
}
|
|
|
|
} // namespace Editor
|
|
} // namespace XCEngine
|