Formalize scene viewport overlay sprite resource lifecycle

This commit is contained in:
2026-04-04 17:10:15 +08:00
parent 98b307bc6d
commit c6b835a390
10 changed files with 434 additions and 184 deletions

View File

@@ -18,6 +18,7 @@ set(EDITOR_TEST_SOURCES
test_scene_viewport_chrome.cpp
test_scene_viewport_transform_gizmo_coordinator.cpp
test_scene_viewport_shader_paths.cpp
test_scene_viewport_overlay_sprite_resources.cpp
test_scene_viewport_overlay_renderer.cpp
test_scene_viewport_overlay_providers.cpp
test_script_component_editor_utils.cpp
@@ -49,6 +50,7 @@ set(EDITOR_TEST_SOURCES
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportTransformGizmoCoordinator.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOrientationGizmo.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOverlayBuilder.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOverlaySpriteResources.cpp
${CMAKE_SOURCE_DIR}/editor/src/Viewport/SceneViewportOverlayProviders.cpp
)

View File

@@ -0,0 +1,54 @@
#include <gtest/gtest.h>
#include "Viewport/SceneViewportOverlaySpriteResources.h"
#include <filesystem>
#include <string>
namespace {
using XCEngine::Editor::GetSceneViewportOverlaySpriteAssetSpec;
using XCEngine::Editor::GetSceneViewportOverlaySpriteResourceIndex;
using XCEngine::Editor::GetSceneViewportOverlaySpriteTextureKindByIndex;
using XCEngine::Editor::LoadSceneViewportOverlaySpritePixels;
using XCEngine::Editor::SceneViewportOverlaySpritePixels;
using XCEngine::Editor::SceneViewportOverlaySpriteTextureKind;
using XCEngine::Editor::kSceneViewportOverlaySpriteResourceCount;
using XCEngine::Editor::kSceneViewportOverlaySpriteTextureKinds;
TEST(SceneViewportOverlaySpriteResourcesTest, TextureKindIndexMappingIsStable) {
EXPECT_EQ(kSceneViewportOverlaySpriteResourceCount, 2u);
EXPECT_EQ(GetSceneViewportOverlaySpriteResourceIndex(SceneViewportOverlaySpriteTextureKind::Camera), 0u);
EXPECT_EQ(GetSceneViewportOverlaySpriteResourceIndex(SceneViewportOverlaySpriteTextureKind::Light), 1u);
EXPECT_EQ(GetSceneViewportOverlaySpriteTextureKindByIndex(0u), SceneViewportOverlaySpriteTextureKind::Camera);
EXPECT_EQ(GetSceneViewportOverlaySpriteTextureKindByIndex(1u), SceneViewportOverlaySpriteTextureKind::Light);
}
TEST(SceneViewportOverlaySpriteResourcesTest, AssetSpecsResolveKnownEditorIcons) {
for (SceneViewportOverlaySpriteTextureKind textureKind : kSceneViewportOverlaySpriteTextureKinds) {
const auto spec = GetSceneViewportOverlaySpriteAssetSpec(textureKind);
EXPECT_EQ(spec.kind, textureKind);
EXPECT_FALSE(spec.resourcePath.Empty());
const std::filesystem::path path(spec.resourcePath.CStr());
EXPECT_TRUE(path.is_absolute());
EXPECT_TRUE(std::filesystem::exists(path));
EXPECT_NE(path.generic_string().find("editor/resources/Icons"), std::string::npos);
}
}
TEST(SceneViewportOverlaySpriteResourcesTest, LoadsOverlaySpritePixelsFromEditorResources) {
for (SceneViewportOverlaySpriteTextureKind textureKind : kSceneViewportOverlaySpriteTextureKinds) {
SceneViewportOverlaySpritePixels pixels = {};
EXPECT_TRUE(LoadSceneViewportOverlaySpritePixels(textureKind, pixels));
EXPECT_TRUE(pixels.IsValid());
EXPECT_GT(pixels.width, 0u);
EXPECT_GT(pixels.height, 0u);
EXPECT_FALSE(pixels.rgbaPixels.empty());
EXPECT_EQ(
pixels.rgbaPixels.size(),
static_cast<size_t>(pixels.width) * static_cast<size_t>(pixels.height) * 4u);
}
}
} // namespace

View File

@@ -1,5 +1,6 @@
#include <gtest/gtest.h>
#include "Viewport/SceneViewportResourcePaths.h"
#include "Viewport/SceneViewportShaderPaths.h"
#include <XCEngine/Core/Asset/ResourceManager.h>
@@ -10,7 +11,9 @@
namespace {
using XCEngine::Editor::GetSceneViewportCameraGizmoIconPath;
using XCEngine::Editor::GetSceneViewportInfiniteGridShaderPath;
using XCEngine::Editor::GetSceneViewportMainLightGizmoIconPath;
using XCEngine::Editor::GetSceneViewportObjectIdOutlineShaderPath;
using XCEngine::Resources::LoadResult;
using XCEngine::Resources::ResourceHandle;
@@ -25,13 +28,21 @@ using XCEngine::Resources::ShaderType;
TEST(SceneViewportShaderPathsTest, ResolvePathsUnderEditorResources) {
const std::filesystem::path gridPath(GetSceneViewportInfiniteGridShaderPath().CStr());
const std::filesystem::path outlinePath(GetSceneViewportObjectIdOutlineShaderPath().CStr());
const std::filesystem::path cameraIconPath(GetSceneViewportCameraGizmoIconPath().CStr());
const std::filesystem::path lightIconPath(GetSceneViewportMainLightGizmoIconPath().CStr());
EXPECT_TRUE(gridPath.is_absolute());
EXPECT_TRUE(outlinePath.is_absolute());
EXPECT_TRUE(cameraIconPath.is_absolute());
EXPECT_TRUE(lightIconPath.is_absolute());
EXPECT_TRUE(std::filesystem::exists(gridPath));
EXPECT_TRUE(std::filesystem::exists(outlinePath));
EXPECT_TRUE(std::filesystem::exists(cameraIconPath));
EXPECT_TRUE(std::filesystem::exists(lightIconPath));
EXPECT_NE(gridPath.generic_string().find("editor/resources/shaders/scene-viewport"), std::string::npos);
EXPECT_NE(outlinePath.generic_string().find("editor/resources/shaders/scene-viewport"), std::string::npos);
EXPECT_NE(cameraIconPath.generic_string().find("editor/resources/Icons"), std::string::npos);
EXPECT_NE(lightIconPath.generic_string().find("editor/resources/Icons"), std::string::npos);
}
TEST(SceneViewportShaderPathsTest, ShaderLoaderLoadsSceneViewportInfiniteGridShader) {

View File

@@ -13,6 +13,7 @@ using XCEngine::Editor::ApplySceneViewportRenderRequestSetup;
using XCEngine::Editor::ApplySceneViewportRenderPlan;
using XCEngine::Editor::ApplyViewportFailureStatus;
using XCEngine::Editor::BuildGameViewportRenderFailurePolicy;
using XCEngine::Editor::BuildSceneViewportGridPassData;
using XCEngine::Editor::BuildSceneViewportRenderPlan;
using XCEngine::Editor::BuildSceneViewportRenderFailurePolicy;
using XCEngine::Editor::BuildSceneViewportSelectionOutlineStyle;
@@ -24,7 +25,9 @@ using XCEngine::Editor::SceneViewportOverlayFrameData;
using XCEngine::Editor::SceneViewportOverlayLinePrimitive;
using XCEngine::Editor::SceneViewportRenderFailure;
using XCEngine::Editor::SceneViewportOverlayData;
using XCEngine::Editor::SceneViewportGridPassData;
using XCEngine::Editor::SceneViewportRenderPlan;
using XCEngine::Editor::SceneViewportSelectionOutlineStyle;
using XCEngine::Editor::ViewportRenderTargets;
using XCEngine::RHI::Format;
using XCEngine::RHI::RHIResourceView;
@@ -163,7 +166,7 @@ TEST(ViewportRenderFlowUtilsTest, ApplyViewportFailureStatusRespectsSetIfEmptyBe
TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportGridPassDataCopiesSceneCameraState) {
const SceneViewportOverlayData overlay = CreateValidOverlay();
const auto gridPassData = XCEngine::Editor::BuildSceneViewportGridPassData(overlay);
const auto gridPassData = BuildSceneViewportGridPassData(overlay);
EXPECT_TRUE(gridPassData.valid);
EXPECT_FLOAT_EQ(gridPassData.cameraPosition.x, overlay.cameraPosition.x);
@@ -265,7 +268,7 @@ TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanCollectsPostSceneA
overlay,
{ 7u, 11u },
editorOverlayFrameData,
[&gridPassFactoryCallCount](const XCEngine::Rendering::Passes::InfiniteGridPassData& data) {
[&gridPassFactoryCallCount](const SceneViewportGridPassData& data) {
++gridPassFactoryCallCount;
EXPECT_TRUE(data.valid);
return std::make_unique<NoopRenderPass>();
@@ -273,7 +276,7 @@ TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanCollectsPostSceneA
[&selectionOutlinePassFactoryCallCount](
RHIResourceView* objectIdTextureView,
const std::vector<uint64_t>& selectedObjectIds,
const XCEngine::Rendering::Passes::ObjectIdOutlineStyle& style) {
const SceneViewportSelectionOutlineStyle& style) {
++selectionOutlinePassFactoryCallCount;
EXPECT_NE(objectIdTextureView, nullptr);
EXPECT_EQ(selectedObjectIds.size(), 2u);
@@ -304,13 +307,13 @@ TEST(ViewportRenderFlowUtilsTest, BuildSceneViewportRenderPlanWarnsWhenSelection
overlay,
{ 42u },
{},
[](const XCEngine::Rendering::Passes::InfiniteGridPassData&) {
[](const SceneViewportGridPassData&) {
return std::make_unique<NoopRenderPass>();
},
[](
RHIResourceView*,
const std::vector<uint64_t>&,
const XCEngine::Rendering::Passes::ObjectIdOutlineStyle&) {
const SceneViewportSelectionOutlineStyle&) {
return std::make_unique<NoopRenderPass>();
},
[](const SceneViewportOverlayFrameData&) {