Formalize editor skybox wiring and debug presets
This commit is contained in:
35
CMakePresets.json
Normal file
35
CMakePresets.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"version": 3,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 21,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "vs2022-x64",
|
||||
"displayName": "Visual Studio 2022 x64",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"binaryDir": "${sourceDir}/build"
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "debug",
|
||||
"displayName": "Build Debug",
|
||||
"configurePreset": "vs2022-x64",
|
||||
"configuration": "Debug"
|
||||
}
|
||||
],
|
||||
"testPresets": [
|
||||
{
|
||||
"name": "debug",
|
||||
"displayName": "Test Debug",
|
||||
"configurePreset": "vs2022-x64",
|
||||
"configuration": "Debug",
|
||||
"output": {
|
||||
"outputOnFailure": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "AssetReferenceEditorUtils.h"
|
||||
#include "IComponentEditor.h"
|
||||
#include "Core/IUndoManager.h"
|
||||
#include "UI/UI.h"
|
||||
|
||||
#include <XCEngine/Components/CameraComponent.h>
|
||||
#include <XCEngine/Core/Math/Color.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
@@ -95,6 +99,87 @@ public:
|
||||
camera->SetPrimary(primary);
|
||||
});
|
||||
|
||||
bool skyboxEnabled = camera->IsSkyboxEnabled();
|
||||
changed |= UI::ApplyPropertyChange(
|
||||
UI::DrawPropertyBool("Skybox", skyboxEnabled),
|
||||
undoManager,
|
||||
kUndoLabel,
|
||||
[&]() {
|
||||
camera->SetSkyboxEnabled(skyboxEnabled);
|
||||
});
|
||||
|
||||
if (skyboxEnabled) {
|
||||
const ComponentEditorAssetUI::AssetReferenceInteraction skyboxMaterialInteraction =
|
||||
ComponentEditorAssetUI::DrawAssetReferenceProperty(
|
||||
"Skybox Material",
|
||||
camera->GetSkyboxMaterialPath(),
|
||||
"Drop Skybox Material",
|
||||
{ ".mat" });
|
||||
|
||||
changed |= UI::ApplyPropertyChange(
|
||||
skyboxMaterialInteraction.clearRequested && !camera->GetSkyboxMaterialPath().empty(),
|
||||
undoManager,
|
||||
kUndoLabel,
|
||||
[camera]() {
|
||||
camera->SetSkyboxMaterialPath(std::string());
|
||||
});
|
||||
changed |= UI::ApplyPropertyChange(
|
||||
!skyboxMaterialInteraction.assignedPath.empty() &&
|
||||
skyboxMaterialInteraction.assignedPath != camera->GetSkyboxMaterialPath(),
|
||||
undoManager,
|
||||
kUndoLabel,
|
||||
[camera, assignedPath = skyboxMaterialInteraction.assignedPath]() {
|
||||
camera->SetSkyboxMaterialPath(assignedPath);
|
||||
});
|
||||
|
||||
if (camera->GetSkyboxMaterialPath().empty()) {
|
||||
float topColor[4] = {
|
||||
camera->GetSkyboxTopColor().r,
|
||||
camera->GetSkyboxTopColor().g,
|
||||
camera->GetSkyboxTopColor().b,
|
||||
camera->GetSkyboxTopColor().a
|
||||
};
|
||||
changed |= UI::ApplyPropertyChange(
|
||||
UI::DrawPropertyColor4("Skybox Top", topColor),
|
||||
undoManager,
|
||||
kUndoLabel,
|
||||
[&]() {
|
||||
camera->SetSkyboxTopColor(::XCEngine::Math::Color(
|
||||
topColor[0], topColor[1], topColor[2], topColor[3]));
|
||||
});
|
||||
|
||||
float horizonColor[4] = {
|
||||
camera->GetSkyboxHorizonColor().r,
|
||||
camera->GetSkyboxHorizonColor().g,
|
||||
camera->GetSkyboxHorizonColor().b,
|
||||
camera->GetSkyboxHorizonColor().a
|
||||
};
|
||||
changed |= UI::ApplyPropertyChange(
|
||||
UI::DrawPropertyColor4("Skybox Horizon", horizonColor),
|
||||
undoManager,
|
||||
kUndoLabel,
|
||||
[&]() {
|
||||
camera->SetSkyboxHorizonColor(::XCEngine::Math::Color(
|
||||
horizonColor[0], horizonColor[1], horizonColor[2], horizonColor[3]));
|
||||
});
|
||||
|
||||
float bottomColor[4] = {
|
||||
camera->GetSkyboxBottomColor().r,
|
||||
camera->GetSkyboxBottomColor().g,
|
||||
camera->GetSkyboxBottomColor().b,
|
||||
camera->GetSkyboxBottomColor().a
|
||||
};
|
||||
changed |= UI::ApplyPropertyChange(
|
||||
UI::DrawPropertyColor4("Skybox Bottom", bottomColor),
|
||||
undoManager,
|
||||
kUndoLabel,
|
||||
[&]() {
|
||||
camera->SetSkyboxBottomColor(::XCEngine::Math::Color(
|
||||
bottomColor[0], bottomColor[1], bottomColor[2], bottomColor[3]));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
float clearColor[4] = {
|
||||
camera->GetClearColor().r,
|
||||
camera->GetClearColor().g,
|
||||
|
||||
@@ -471,7 +471,9 @@ void SceneManager::CreateDemoScene() {
|
||||
ClearSceneLoadProgress();
|
||||
|
||||
::XCEngine::Components::GameObject* camera = CreateEntity("Main Camera", nullptr);
|
||||
camera->AddComponent<::XCEngine::Components::CameraComponent>();
|
||||
if (auto* cameraComponent = camera->AddComponent<::XCEngine::Components::CameraComponent>()) {
|
||||
cameraComponent->SetSkyboxEnabled(true);
|
||||
}
|
||||
|
||||
::XCEngine::Components::GameObject* light = CreateEntity("Directional Light", nullptr);
|
||||
light->AddComponent<::XCEngine::Components::LightComponent>();
|
||||
|
||||
@@ -98,6 +98,8 @@ struct BuiltInIconState {
|
||||
BuiltInTexture folder;
|
||||
BuiltInTexture gameObject;
|
||||
BuiltInTexture scene;
|
||||
BuiltInTexture cameraGizmo;
|
||||
BuiltInTexture mainLightGizmo;
|
||||
struct CachedAssetPreview {
|
||||
BuiltInTexture texture;
|
||||
std::unique_ptr<LoadedTexturePixels> decodedPixels;
|
||||
@@ -150,6 +152,16 @@ std::filesystem::path ResolveSceneIconPath() {
|
||||
return (exeDir / ".." / ".." / "resources" / "Icons" / "scene_icon.png").lexically_normal();
|
||||
}
|
||||
|
||||
std::filesystem::path ResolveCameraGizmoIconPath() {
|
||||
const std::filesystem::path exeDir(Platform::GetExecutableDirectoryUtf8());
|
||||
return (exeDir / ".." / ".." / "resources" / "Icons" / "camera_gizmo.png").lexically_normal();
|
||||
}
|
||||
|
||||
std::filesystem::path ResolveMainLightGizmoIconPath() {
|
||||
const std::filesystem::path exeDir(Platform::GetExecutableDirectoryUtf8());
|
||||
return (exeDir / ".." / ".." / "resources" / "Icons" / "main_light_gizmo.png").lexically_normal();
|
||||
}
|
||||
|
||||
std::string NormalizePathKey(const std::filesystem::path& path) {
|
||||
std::wstring key = path.lexically_normal().generic_wstring();
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::towlower);
|
||||
@@ -959,6 +971,17 @@ void PruneAssetPreviewCache() {
|
||||
}
|
||||
}
|
||||
|
||||
BuiltInTexture* ResolveEditorTexture(EditorTextureIconKind kind) {
|
||||
switch (kind) {
|
||||
case EditorTextureIconKind::CameraGizmo:
|
||||
return &g_icons.cameraGizmo;
|
||||
case EditorTextureIconKind::MainLightGizmo:
|
||||
return &g_icons.mainLightGizmo;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void InitializeBuiltInIcons(
|
||||
@@ -985,6 +1008,28 @@ void InitializeBuiltInIcons(
|
||||
if (LoadTextureFromFile(backend, device, commandQueue, ResolveSceneIconPath(), g_icons.scene, pendingUpload)) {
|
||||
g_icons.pendingIconUploads.push_back(std::move(pendingUpload));
|
||||
}
|
||||
|
||||
pendingUpload.reset();
|
||||
if (LoadTextureFromFile(
|
||||
backend,
|
||||
device,
|
||||
commandQueue,
|
||||
ResolveCameraGizmoIconPath(),
|
||||
g_icons.cameraGizmo,
|
||||
pendingUpload)) {
|
||||
g_icons.pendingIconUploads.push_back(std::move(pendingUpload));
|
||||
}
|
||||
|
||||
pendingUpload.reset();
|
||||
if (LoadTextureFromFile(
|
||||
backend,
|
||||
device,
|
||||
commandQueue,
|
||||
ResolveMainLightGizmoIconPath(),
|
||||
g_icons.mainLightGizmo,
|
||||
pendingUpload)) {
|
||||
g_icons.pendingIconUploads.push_back(std::move(pendingUpload));
|
||||
}
|
||||
}
|
||||
|
||||
void ShutdownBuiltInIcons() {
|
||||
@@ -997,6 +1042,8 @@ void ShutdownBuiltInIcons() {
|
||||
ResetTexture(g_icons.folder);
|
||||
ResetTexture(g_icons.gameObject);
|
||||
ResetTexture(g_icons.scene);
|
||||
ResetTexture(g_icons.cameraGizmo);
|
||||
ResetTexture(g_icons.mainLightGizmo);
|
||||
g_icons.backend = nullptr;
|
||||
g_icons.device = nullptr;
|
||||
g_icons.commandQueue = nullptr;
|
||||
@@ -1041,6 +1088,22 @@ void DrawAssetIcon(ImDrawList* drawList, const ImVec2& min, const ImVec2& max, A
|
||||
DrawBuiltInFileIcon(drawList, min, max);
|
||||
}
|
||||
|
||||
bool DrawEditorTextureIcon(
|
||||
ImDrawList* drawList,
|
||||
const ImVec2& min,
|
||||
const ImVec2& max,
|
||||
EditorTextureIconKind kind) {
|
||||
MaintainIconRuntimeState();
|
||||
|
||||
const BuiltInTexture* texture = ResolveEditorTexture(kind);
|
||||
if (texture == nullptr || !texture->IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DrawTextureIcon(drawList, *texture, min, max);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DrawTextureAssetPreview(
|
||||
ImDrawList* drawList,
|
||||
const ImVec2& min,
|
||||
|
||||
@@ -19,6 +19,11 @@ enum class AssetIconKind {
|
||||
Scene
|
||||
};
|
||||
|
||||
enum class EditorTextureIconKind {
|
||||
CameraGizmo,
|
||||
MainLightGizmo
|
||||
};
|
||||
|
||||
void InitializeBuiltInIcons(
|
||||
ImGuiBackendBridge& backend,
|
||||
ID3D12Device* device,
|
||||
@@ -27,6 +32,11 @@ void InitializeBuiltInIcons(
|
||||
void ShutdownBuiltInIcons();
|
||||
|
||||
void DrawAssetIcon(ImDrawList* drawList, const ImVec2& min, const ImVec2& max, AssetIconKind kind);
|
||||
bool DrawEditorTextureIcon(
|
||||
ImDrawList* drawList,
|
||||
const ImVec2& min,
|
||||
const ImVec2& max,
|
||||
EditorTextureIconKind kind);
|
||||
bool DrawTextureAssetPreview(
|
||||
ImDrawList* drawList,
|
||||
const ImVec2& min,
|
||||
|
||||
@@ -378,7 +378,7 @@ bool SceneViewportEditorOverlayPassRenderer::Render(
|
||||
const Rendering::RenderContext& renderContext,
|
||||
const Rendering::RenderSurface& surface,
|
||||
const SceneViewportOverlayFrameData& frameData) {
|
||||
if (!frameData.HasOverlayPrimitives() || !renderContext.IsValid() || renderContext.commandList == nullptr) {
|
||||
if (!frameData.HasRenderPassPrimitives() || !renderContext.IsValid() || renderContext.commandList == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -411,33 +411,10 @@ bool SceneViewportEditorOverlayPassRenderer::Render(
|
||||
AppendScreenTriangleVertices(targetVertices, triangle);
|
||||
}
|
||||
|
||||
std::vector<const SceneViewportOverlaySpritePrimitive*> depthTestedSprites = {};
|
||||
std::vector<const SceneViewportOverlaySpritePrimitive*> alwaysOnTopSprites = {};
|
||||
depthTestedSprites.reserve(frameData.worldSprites.size());
|
||||
alwaysOnTopSprites.reserve(frameData.worldSprites.size());
|
||||
for (const SceneViewportOverlaySpritePrimitive& sprite : frameData.worldSprites) {
|
||||
if (sprite.sizePixels.x <= Math::EPSILON || sprite.sizePixels.y <= Math::EPSILON) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sprite.depthMode == SceneViewportOverlayDepthMode::DepthTested) {
|
||||
depthTestedSprites.push_back(&sprite);
|
||||
} else {
|
||||
alwaysOnTopSprites.push_back(&sprite);
|
||||
}
|
||||
}
|
||||
|
||||
const auto sortBackToFront =
|
||||
[](const SceneViewportOverlaySpritePrimitive* lhs, const SceneViewportOverlaySpritePrimitive* rhs) {
|
||||
return lhs->sortDepth > rhs->sortDepth;
|
||||
};
|
||||
std::sort(depthTestedSprites.begin(), depthTestedSprites.end(), sortBackToFront);
|
||||
std::sort(alwaysOnTopSprites.begin(), alwaysOnTopSprites.end(), sortBackToFront);
|
||||
|
||||
const size_t lineVertexCount = depthTestedLineVertices.size() + alwaysOnTopLineVertices.size();
|
||||
const size_t screenTriangleVertexCount =
|
||||
depthTestedScreenTriangleVertices.size() + alwaysOnTopScreenTriangleVertices.size();
|
||||
const size_t spriteVertexCount = (depthTestedSprites.size() + alwaysOnTopSprites.size()) * 6u;
|
||||
const size_t spriteVertexCount = 0u;
|
||||
if (lineVertexCount == 0u && screenTriangleVertexCount == 0u && spriteVertexCount == 0u) {
|
||||
return true;
|
||||
}
|
||||
@@ -471,35 +448,6 @@ bool SceneViewportEditorOverlayPassRenderer::Render(
|
||||
screenTriangleVertices.size() * sizeof(OverlayScreenTriangleVertex));
|
||||
}
|
||||
|
||||
std::vector<OverlaySpriteVertex> spriteVertices = {};
|
||||
std::array<OverlaySpriteBatchRange, kSceneViewportOverlaySpriteResourceCount> depthTestedSpriteBatches = {};
|
||||
std::array<OverlaySpriteBatchRange, kSceneViewportOverlaySpriteResourceCount> alwaysOnTopSpriteBatches = {};
|
||||
if (spriteVertexCount > 0u) {
|
||||
spriteVertices.reserve(spriteVertexCount);
|
||||
const auto appendSpriteBatches =
|
||||
[&spriteVertices](
|
||||
const std::vector<const SceneViewportOverlaySpritePrimitive*>& sprites,
|
||||
std::array<OverlaySpriteBatchRange, kSceneViewportOverlaySpriteResourceCount>& outBatches) {
|
||||
for (size_t textureIndex = 0; textureIndex < kSceneViewportOverlaySpriteResourceCount; ++textureIndex) {
|
||||
OverlaySpriteBatchRange range = {};
|
||||
range.firstVertex = static_cast<uint32_t>(spriteVertices.size());
|
||||
for (const SceneViewportOverlaySpritePrimitive* sprite : sprites) {
|
||||
if (sprite == nullptr ||
|
||||
GetSceneViewportOverlaySpriteResourceIndex(sprite->textureKind) != textureIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AppendSpriteVertices(spriteVertices, *sprite);
|
||||
}
|
||||
range.vertexCount = static_cast<uint32_t>(spriteVertices.size()) - range.firstVertex;
|
||||
outBatches[textureIndex] = range;
|
||||
}
|
||||
};
|
||||
appendSpriteBatches(depthTestedSprites, depthTestedSpriteBatches);
|
||||
appendSpriteBatches(alwaysOnTopSprites, alwaysOnTopSpriteBatches);
|
||||
m_spriteVertexBuffer->SetData(spriteVertices.data(), spriteVertices.size() * sizeof(OverlaySpriteVertex));
|
||||
}
|
||||
|
||||
OverlayConstants constants = {};
|
||||
constants.viewProjection = BuildSceneViewportViewProjectionMatrix(
|
||||
frameData.overlay,
|
||||
@@ -564,49 +512,6 @@ bool SceneViewportEditorOverlayPassRenderer::Render(
|
||||
}
|
||||
}
|
||||
|
||||
if (spriteVertexCount > 0u) {
|
||||
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
||||
RHI::RHIResourceView* vertexBuffers[] = { m_spriteVertexBufferView };
|
||||
const uint64_t offsets[] = { 0u };
|
||||
const uint32_t strides[] = { static_cast<uint32_t>(sizeof(OverlaySpriteVertex)) };
|
||||
commandList->SetVertexBuffers(0, 1, vertexBuffers, offsets, strides);
|
||||
|
||||
const auto drawSpriteBatchGroup =
|
||||
[this, commandList](
|
||||
RHI::RHIPipelineState* pipelineState,
|
||||
const std::array<OverlaySpriteBatchRange, kSceneViewportOverlaySpriteResourceCount>& batches) {
|
||||
if (pipelineState == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
commandList->SetPipelineState(pipelineState);
|
||||
for (size_t textureIndex = 0; textureIndex < kSceneViewportOverlaySpriteResourceCount; ++textureIndex) {
|
||||
const OverlaySpriteBatchRange& batch = batches[textureIndex];
|
||||
if (!batch.HasVertices()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RHI::RHIDescriptorSet* const textureSet =
|
||||
m_overlaySpriteResources.GetTextureSet(
|
||||
GetSceneViewportOverlaySpriteTextureKindByIndex(textureIndex));
|
||||
if (textureSet == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RHI::RHIDescriptorSet* descriptorSets[] = {
|
||||
m_constantSet,
|
||||
textureSet,
|
||||
m_samplerSet
|
||||
};
|
||||
commandList->SetGraphicsDescriptorSets(0, 3, descriptorSets, m_spritePipelineLayout);
|
||||
commandList->Draw(batch.vertexCount, 1, batch.firstVertex, 0);
|
||||
}
|
||||
};
|
||||
|
||||
drawSpriteBatchGroup(m_depthTestedSpritePipelineState, depthTestedSpriteBatches);
|
||||
drawSpriteBatchGroup(m_alwaysOnTopSpritePipelineState, alwaysOnTopSpriteBatches);
|
||||
}
|
||||
|
||||
if (screenTriangleVertexCount > 0u) {
|
||||
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
||||
RHI::RHIResourceView* vertexBuffers[] = { m_screenTriangleVertexBufferView };
|
||||
|
||||
@@ -110,6 +110,10 @@ struct SceneViewportOverlayFrameData {
|
||||
return overlay.valid && (!worldLines.empty() || !worldSprites.empty() || !screenTriangles.empty());
|
||||
}
|
||||
|
||||
bool HasRenderPassPrimitives() const {
|
||||
return overlay.valid && (!worldLines.empty() || !screenTriangles.empty());
|
||||
}
|
||||
|
||||
bool HasWorldOverlay() const {
|
||||
return HasOverlayPrimitives();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
#include "SceneViewportHudOverlay.h"
|
||||
|
||||
#include "SceneViewportOrientationGizmo.h"
|
||||
#include "SceneViewportMath.h"
|
||||
|
||||
#include "UI/BuiltInIcons.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
@@ -11,6 +17,97 @@ bool IsViewportRectValid(const ImVec2& viewportMin, const ImVec2& viewportMax) {
|
||||
viewportMax.y - viewportMin.y > 1.0f;
|
||||
}
|
||||
|
||||
bool DrawSceneViewportSpriteIcon(
|
||||
ImDrawList* drawList,
|
||||
const ImVec2& min,
|
||||
const ImVec2& max,
|
||||
SceneViewportOverlaySpriteTextureKind textureKind) {
|
||||
switch (textureKind) {
|
||||
case SceneViewportOverlaySpriteTextureKind::Camera:
|
||||
return UI::DrawEditorTextureIcon(
|
||||
drawList,
|
||||
min,
|
||||
max,
|
||||
UI::EditorTextureIconKind::CameraGizmo);
|
||||
case SceneViewportOverlaySpriteTextureKind::Light:
|
||||
return UI::DrawEditorTextureIcon(
|
||||
drawList,
|
||||
min,
|
||||
max,
|
||||
UI::EditorTextureIconKind::MainLightGizmo);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSceneViewportSceneIcons(
|
||||
ImDrawList* drawList,
|
||||
const SceneViewportHudOverlayData& overlay,
|
||||
const ImVec2& viewportMin,
|
||||
const ImVec2& viewportMax) {
|
||||
if (drawList == nullptr ||
|
||||
!overlay.showSceneIcons ||
|
||||
overlay.overlayFrameData == nullptr ||
|
||||
overlay.overlayFrameData->worldSprites.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float viewportWidth = viewportMax.x - viewportMin.x;
|
||||
const float viewportHeight = viewportMax.y - viewportMin.y;
|
||||
if (viewportWidth <= 1.0f || viewportHeight <= 1.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<const SceneViewportOverlaySpritePrimitive*> sortedSprites = {};
|
||||
sortedSprites.reserve(overlay.overlayFrameData->worldSprites.size());
|
||||
for (const SceneViewportOverlaySpritePrimitive& sprite : overlay.overlayFrameData->worldSprites) {
|
||||
sortedSprites.push_back(&sprite);
|
||||
}
|
||||
|
||||
std::sort(
|
||||
sortedSprites.begin(),
|
||||
sortedSprites.end(),
|
||||
[](const SceneViewportOverlaySpritePrimitive* lhs, const SceneViewportOverlaySpritePrimitive* rhs) {
|
||||
if (lhs == rhs) {
|
||||
return false;
|
||||
}
|
||||
if (lhs == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (rhs == nullptr) {
|
||||
return true;
|
||||
}
|
||||
return lhs->sortDepth > rhs->sortDepth;
|
||||
});
|
||||
|
||||
for (const SceneViewportOverlaySpritePrimitive* sprite : sortedSprites) {
|
||||
if (sprite == nullptr ||
|
||||
sprite->sizePixels.x <= Math::EPSILON ||
|
||||
sprite->sizePixels.y <= Math::EPSILON) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const SceneViewportProjectedPoint projectedPoint = ProjectSceneViewportWorldPoint(
|
||||
overlay.sceneOverlay,
|
||||
viewportWidth,
|
||||
viewportHeight,
|
||||
sprite->worldPosition);
|
||||
if (!projectedPoint.visible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ImVec2 halfSize(sprite->sizePixels.x * 0.5f, sprite->sizePixels.y * 0.5f);
|
||||
const ImVec2 center(
|
||||
viewportMin.x + projectedPoint.screenPosition.x,
|
||||
viewportMin.y + projectedPoint.screenPosition.y);
|
||||
DrawSceneViewportSpriteIcon(
|
||||
drawList,
|
||||
ImVec2(center.x - halfSize.x, center.y - halfSize.y),
|
||||
ImVec2(center.x + halfSize.x, center.y + halfSize.y),
|
||||
sprite->textureKind);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void DrawSceneViewportHudOverlay(
|
||||
@@ -25,6 +122,11 @@ void DrawSceneViewportHudOverlay(
|
||||
}
|
||||
|
||||
drawList->PushClipRect(viewportMin, viewportMax, true);
|
||||
DrawSceneViewportSceneIcons(
|
||||
drawList,
|
||||
overlay,
|
||||
viewportMin,
|
||||
viewportMax);
|
||||
if (overlay.showOrientationGizmo) {
|
||||
DrawSceneViewportOrientationGizmo(
|
||||
drawList,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IViewportHostService.h"
|
||||
#include "SceneViewportEditorOverlayData.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
@@ -26,18 +26,28 @@ struct SceneViewportHudOverlayHitResult {
|
||||
struct SceneViewportHudOverlayData {
|
||||
SceneViewportOverlayData sceneOverlay = {};
|
||||
bool showOrientationGizmo = true;
|
||||
bool showSceneIcons = true;
|
||||
const SceneViewportOverlayFrameData* overlayFrameData = nullptr;
|
||||
|
||||
bool HasVisibleElements() const {
|
||||
return sceneOverlay.valid && showOrientationGizmo;
|
||||
return sceneOverlay.valid &&
|
||||
(showOrientationGizmo ||
|
||||
(showSceneIcons &&
|
||||
overlayFrameData != nullptr &&
|
||||
!overlayFrameData->worldSprites.empty()));
|
||||
}
|
||||
};
|
||||
|
||||
inline SceneViewportHudOverlayData BuildSceneViewportHudOverlayData(
|
||||
const SceneViewportOverlayData& sceneOverlay,
|
||||
bool showOrientationGizmo = true) {
|
||||
bool showOrientationGizmo = true,
|
||||
const SceneViewportOverlayFrameData* overlayFrameData = nullptr,
|
||||
bool showSceneIcons = true) {
|
||||
SceneViewportHudOverlayData data = {};
|
||||
data.sceneOverlay = sceneOverlay;
|
||||
data.showOrientationGizmo = showOrientationGizmo;
|
||||
data.showSceneIcons = showSceneIcons;
|
||||
data.overlayFrameData = overlayFrameData;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ inline bool ShouldFocusSceneViewportAfterInteraction(
|
||||
struct SceneViewportPresentationRequest {
|
||||
IEditorContext* context = nullptr;
|
||||
IViewportHostService* viewportHostService = nullptr;
|
||||
const SceneViewportOverlayFrameData* overlayFrameData = nullptr;
|
||||
bool hasInteractiveViewport = false;
|
||||
SceneViewportFrameGeometry geometry = {};
|
||||
SceneViewportTransformGizmoFrameOptions gizmoFrameOptions = {};
|
||||
@@ -182,7 +183,10 @@ inline void RefreshAndDrawSceneViewportPresentation(const SceneViewportPresentat
|
||||
|
||||
DrawSceneViewportHudOverlay(
|
||||
request.drawList,
|
||||
BuildSceneViewportHudOverlayData(overlay),
|
||||
BuildSceneViewportHudOverlayData(
|
||||
overlay,
|
||||
true,
|
||||
request.overlayFrameData),
|
||||
request.viewportMin,
|
||||
request.viewportMax);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ inline SceneViewportRenderPlanBuildResult BuildSceneViewportRenderPlan(
|
||||
}
|
||||
}
|
||||
|
||||
if (editorOverlayFrameData.HasOverlayPrimitives() &&
|
||||
if (editorOverlayFrameData.HasRenderPassPrimitives() &&
|
||||
overlayPassFactory != nullptr) {
|
||||
std::unique_ptr<Rendering::RenderPass> overlayPass = overlayPassFactory(editorOverlayFrameData);
|
||||
if (overlayPass != nullptr) {
|
||||
|
||||
@@ -194,6 +194,7 @@ void SceneViewPanel::Render() {
|
||||
SceneViewportPresentationRequest presentationRequest = {};
|
||||
presentationRequest.context = m_context;
|
||||
presentationRequest.viewportHostService = viewportHostService;
|
||||
presentationRequest.overlayFrameData = interactionFrameState.overlayFrameData;
|
||||
presentationRequest.hasInteractiveViewport = hasInteractiveViewport;
|
||||
presentationRequest.geometry = frameGeometry;
|
||||
presentationRequest.gizmoFrameOptions = toolState.gizmoFrameOptions;
|
||||
|
||||
Reference in New Issue
Block a user