refactor(editor): isolate engine service boundaries
This commit is contained in:
187
editor/app/Services/Engine/EngineSceneViewportBridge.cpp
Normal file
187
editor/app/Services/Engine/EngineSceneViewportBridge.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
#include "Engine/EngineSceneViewportBridge.h"
|
||||
|
||||
#include <XCEngine/Components/CameraComponent.h>
|
||||
#include <XCEngine/Components/GameObject.h>
|
||||
#include <XCEngine/Components/TransformComponent.h>
|
||||
#include <XCEngine/Rendering/Execution/SceneRenderer.h>
|
||||
#include <XCEngine/Rendering/Picking/RenderObjectIdRegistry.h>
|
||||
#include <XCEngine/Scene/Scene.h>
|
||||
#include <XCEngine/Scene/SceneManager.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine::UI::Editor::App {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::XCEngine::Components::GameObject;
|
||||
using ::XCEngine::Components::Scene;
|
||||
using ::XCEngine::Components::SceneManager;
|
||||
using ::XCEngine::Components::TransformComponent;
|
||||
using ::XCEngine::Math::Quaternion;
|
||||
using ::XCEngine::Math::Vector3;
|
||||
using ::XCEngine::Rendering::RenderObjectId;
|
||||
using ::XCEngine::Rendering::RenderObjectIdRegistry;
|
||||
|
||||
Scene* ResolvePrimaryScene(SceneManager& sceneManager) {
|
||||
if (Scene* activeScene = sceneManager.GetActiveScene();
|
||||
activeScene != nullptr) {
|
||||
return activeScene;
|
||||
}
|
||||
|
||||
const std::vector<Scene*> scenes = sceneManager.GetAllScenes();
|
||||
if (!scenes.empty() && scenes.front() != nullptr) {
|
||||
sceneManager.SetActiveScene(scenes.front());
|
||||
return scenes.front();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
EngineSceneViewportBridge::~EngineSceneViewportBridge() = default;
|
||||
|
||||
void EngineSceneViewportBridge::Shutdown() {
|
||||
m_sceneViewportCamera = nullptr;
|
||||
m_sceneViewportCameraObject.reset();
|
||||
}
|
||||
|
||||
SceneViewportFramePlanBuildStatus EngineSceneViewportBridge::BuildFramePlan(
|
||||
const SceneViewportRenderRequest& request,
|
||||
const ::XCEngine::Rendering::RenderContext& renderContext,
|
||||
const ::XCEngine::Rendering::RenderSurface& surface,
|
||||
::XCEngine::Rendering::CameraFramePlan& outFramePlan) {
|
||||
outFramePlan = {};
|
||||
if (!request.IsValid()) {
|
||||
return SceneViewportFramePlanBuildStatus::InvalidRequest;
|
||||
}
|
||||
|
||||
Scene* scene = ResolvePrimaryScene(SceneManager::Get());
|
||||
if (scene == nullptr) {
|
||||
return SceneViewportFramePlanBuildStatus::NoActiveScene;
|
||||
}
|
||||
|
||||
if (!EnsureSceneViewportCamera()) {
|
||||
return SceneViewportFramePlanBuildStatus::Failed;
|
||||
}
|
||||
|
||||
ConfigureSceneViewportCamera(request.camera);
|
||||
const std::vector<::XCEngine::Rendering::CameraFramePlan> framePlans =
|
||||
m_sceneViewportRenderer.BuildFramePlans(
|
||||
*scene,
|
||||
m_sceneViewportCamera,
|
||||
renderContext,
|
||||
surface);
|
||||
if (framePlans.empty() || !framePlans.front().IsValid()) {
|
||||
return SceneViewportFramePlanBuildStatus::Failed;
|
||||
}
|
||||
|
||||
outFramePlan = framePlans.front();
|
||||
return SceneViewportFramePlanBuildStatus::Success;
|
||||
}
|
||||
|
||||
bool EngineSceneViewportBridge::RenderFramePlan(
|
||||
const ::XCEngine::Rendering::CameraFramePlan& framePlan) {
|
||||
return framePlan.IsValid() &&
|
||||
m_sceneViewportRenderer.Render(framePlan);
|
||||
}
|
||||
|
||||
bool EngineSceneViewportBridge::TryResolveActiveSceneRenderObjectId(
|
||||
RenderObjectId renderObjectId,
|
||||
EditorSceneObjectId& outRuntimeObjectId) const {
|
||||
outRuntimeObjectId = kInvalidEditorSceneObjectId;
|
||||
|
||||
std::uint64_t runtimeObjectId = kInvalidEditorSceneObjectId;
|
||||
if (!RenderObjectIdRegistry::Get().TryResolveRuntimeObjectId(
|
||||
renderObjectId,
|
||||
runtimeObjectId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Scene* scene = ResolvePrimaryScene(SceneManager::Get());
|
||||
GameObject* gameObject =
|
||||
scene != nullptr
|
||||
? scene->FindByID(static_cast<EditorSceneObjectId>(runtimeObjectId))
|
||||
: nullptr;
|
||||
if (gameObject == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
outRuntimeObjectId = gameObject->GetID();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EngineSceneViewportBridge::EnsureSceneViewportCamera() {
|
||||
if (m_sceneViewportCameraObject != nullptr &&
|
||||
m_sceneViewportCamera != nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
m_sceneViewportCamera = nullptr;
|
||||
m_sceneViewportCameraObject =
|
||||
std::make_unique<GameObject>("EditorSceneViewportCamera");
|
||||
m_sceneViewportCamera =
|
||||
m_sceneViewportCameraObject->AddComponent<
|
||||
::XCEngine::Components::CameraComponent>();
|
||||
if (m_sceneViewportCamera == nullptr) {
|
||||
m_sceneViewportCameraObject.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_sceneViewportCamera->SetPrimary(false);
|
||||
m_sceneViewportCamera->SetProjectionType(
|
||||
::XCEngine::Components::CameraProjectionType::Perspective);
|
||||
m_sceneViewportCamera->SetFieldOfView(60.0f);
|
||||
m_sceneViewportCamera->SetNearClipPlane(0.03f);
|
||||
m_sceneViewportCamera->SetFarClipPlane(2000.0f);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EngineSceneViewportBridge::ConfigureSceneViewportCamera(
|
||||
const EditorSceneCameraSnapshot& snapshot) {
|
||||
if (!EnsureSceneViewportCamera() ||
|
||||
m_sceneViewportCameraObject == nullptr ||
|
||||
m_sceneViewportCamera == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
TransformComponent* transform =
|
||||
m_sceneViewportCameraObject->GetTransform();
|
||||
if (transform == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 forward = snapshot.forward.SqrMagnitude() >
|
||||
::XCEngine::Math::EPSILON
|
||||
? snapshot.forward.Normalized()
|
||||
: Vector3::Forward();
|
||||
Vector3 up = snapshot.up.SqrMagnitude() >
|
||||
::XCEngine::Math::EPSILON
|
||||
? snapshot.up.Normalized()
|
||||
: Vector3::Up();
|
||||
if (Vector3::Cross(forward, up).SqrMagnitude() <=
|
||||
::XCEngine::Math::EPSILON) {
|
||||
up = std::abs(Vector3::Dot(forward, Vector3::Up())) < 0.999f
|
||||
? Vector3::Up()
|
||||
: Vector3::Right();
|
||||
}
|
||||
|
||||
transform->SetPosition(snapshot.position);
|
||||
transform->SetRotation(Quaternion::LookRotation(forward, up));
|
||||
|
||||
const float nearClipPlane = (std::max)(snapshot.nearClipPlane, 0.001f);
|
||||
const float farClipPlane =
|
||||
(std::max)(snapshot.farClipPlane, nearClipPlane + 0.001f);
|
||||
m_sceneViewportCamera->SetPrimary(false);
|
||||
m_sceneViewportCamera->SetProjectionType(
|
||||
::XCEngine::Components::CameraProjectionType::Perspective);
|
||||
m_sceneViewportCamera->SetFieldOfView(
|
||||
std::clamp(snapshot.verticalFovDegrees, 1.0f, 179.0f));
|
||||
m_sceneViewportCamera->SetNearClipPlane(nearClipPlane);
|
||||
m_sceneViewportCamera->SetFarClipPlane(farClipPlane);
|
||||
}
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
Reference in New Issue
Block a user