#pragma once #include "IViewportHostService.h" #include "ViewportHostRenderTargets.h" #include #include #include #include #include namespace XCEngine { namespace Editor { struct ViewportRenderFallbackPolicy { const char* statusText = nullptr; Math::Color clearColor = Math::Color::Black(); bool shouldClear = false; bool setStatusIfEmpty = false; bool invalidateObjectIdFrame = true; }; enum class SceneViewportRenderFailure { MissingSceneViewCamera, NoActiveScene, SceneRendererFailed }; enum class GameViewportRenderFailure { NoActiveScene, NoCameraInScene, SceneRendererFailed }; inline void SetViewportStatusIfEmpty(std::string& statusText, const char* message) { if (statusText.empty()) { statusText = message; } } inline void ApplyViewportFailureStatus( std::string& statusText, const ViewportRenderFallbackPolicy& policy) { if (policy.statusText == nullptr) { return; } if (policy.setStatusIfEmpty) { SetViewportStatusIfEmpty(statusText, policy.statusText); return; } statusText = policy.statusText; } inline void InvalidateViewportObjectIdFrame(ViewportRenderTargets& targets) { targets.hasValidObjectIdFrame = false; } inline ViewportRenderFallbackPolicy BuildViewportRenderTargetUnavailablePolicy() { ViewportRenderFallbackPolicy policy = {}; policy.statusText = "Viewport render target is unavailable"; return policy; } inline ViewportRenderFallbackPolicy BuildSceneViewportRenderFailurePolicy( SceneViewportRenderFailure failure) { ViewportRenderFallbackPolicy policy = {}; policy.shouldClear = true; switch (failure) { case SceneViewportRenderFailure::MissingSceneViewCamera: policy.statusText = "Scene view camera is unavailable"; policy.clearColor = Math::Color(0.18f, 0.07f, 0.07f, 1.0f); break; case SceneViewportRenderFailure::NoActiveScene: policy.statusText = "No active scene"; policy.clearColor = Math::Color(0.07f, 0.08f, 0.10f, 1.0f); break; case SceneViewportRenderFailure::SceneRendererFailed: policy.statusText = "Scene renderer failed"; policy.clearColor = Math::Color(0.18f, 0.07f, 0.07f, 1.0f); policy.setStatusIfEmpty = true; break; default: break; } return policy; } inline ViewportRenderFallbackPolicy BuildGameViewportRenderFailurePolicy( GameViewportRenderFailure failure) { ViewportRenderFallbackPolicy policy = {}; policy.shouldClear = true; switch (failure) { case GameViewportRenderFailure::NoActiveScene: policy.statusText = "No active scene"; policy.clearColor = Math::Color(0.07f, 0.08f, 0.10f, 1.0f); break; case GameViewportRenderFailure::NoCameraInScene: policy.statusText = "No camera in scene"; policy.clearColor = Math::Color(0.10f, 0.09f, 0.08f, 1.0f); break; case GameViewportRenderFailure::SceneRendererFailed: policy.statusText = "Scene renderer failed"; policy.clearColor = Math::Color(0.18f, 0.07f, 0.07f, 1.0f); break; default: break; } return policy; } inline Rendering::Passes::InfiniteGridPassData BuildSceneViewportGridPassData( const SceneViewportOverlayData& overlay) { Rendering::Passes::InfiniteGridPassData data = {}; data.valid = overlay.valid; data.cameraPosition = overlay.cameraPosition; data.cameraForward = overlay.cameraForward; data.cameraRight = overlay.cameraRight; data.cameraUp = overlay.cameraUp; data.verticalFovDegrees = overlay.verticalFovDegrees; data.nearClipPlane = overlay.nearClipPlane; data.farClipPlane = overlay.farClipPlane; data.orbitDistance = overlay.orbitDistance; return data; } inline Rendering::Passes::ObjectIdOutlineStyle BuildSceneViewportSelectionOutlineStyle( bool debugSelectionMask = false) { Rendering::Passes::ObjectIdOutlineStyle style = {}; style.outlineColor = Math::Color(1.0f, 0.4f, 0.0f, 1.0f); style.outlineWidthPixels = 2.0f; style.debugSelectionMask = debugSelectionMask; return style; } inline void ApplySceneViewportRenderRequestSetup( const ViewportRenderTargets& targets, Rendering::RenderPassSequence* postPasses, Rendering::CameraRenderRequest& request) { request.preScenePasses = nullptr; request.postScenePasses = nullptr; request.overlayPasses = nullptr; request.objectId = {}; if (postPasses != nullptr && postPasses->GetPassCount() > 0) { request.postScenePasses = postPasses; } if (targets.objectIdView == nullptr) { return; } request.objectId.surface = BuildViewportObjectIdSurface(targets); request.objectId.surface.SetRenderArea(request.surface.GetRenderArea()); } inline void MarkSceneViewportRenderSuccess( ViewportRenderTargets& targets, const Rendering::CameraRenderRequest& request) { targets.colorState = RHI::ResourceStates::PixelShaderResource; targets.objectIdState = RHI::ResourceStates::PixelShaderResource; targets.hasValidObjectIdFrame = request.objectId.IsRequested(); } inline void MarkGameViewportRenderSuccess(ViewportRenderTargets& targets) { targets.colorState = RHI::ResourceStates::PixelShaderResource; targets.hasValidObjectIdFrame = false; } } // namespace Editor } // namespace XCEngine