EditorCamera (UE FEditorViewportClient semantics) owned by SceneRenderer:
own TransformComponent + reused Camera controller. BuildFrame dispatches
render source by display mode — editor form always renders from the
editor camera (usable in empty scenes), game form renders from the
scene's primary camera entity. AlignTo copies an entity pose into the
editor camera ("Align Viewport to Camera" button in Inspector). F focus
and viewport gizmo now follow the same dispatch. main.cpp stripped of
dangling sandbox camera/spinner state; onSceneLoaded hook removed.
164 lines
5.2 KiB
C++
164 lines
5.2 KiB
C++
//
|
||
// Created by atdunbg on 2026/9/20.
|
||
//
|
||
// SandboxApp:基于 Application 框架的编辑器宿主程序。
|
||
//
|
||
// main 的职责边界:
|
||
// - 定义 Application 派生类并运行它
|
||
// - 编辑器形态驱动 EditorCamera(Scene view 专用相机,非场景对象)
|
||
// - 异步环境加载、全局热键、输入归属门控
|
||
// - UI 全部委托 App/editor/ 的 docking Editor(本文件不再出现
|
||
// 任何 ImGui 控件)
|
||
//
|
||
// 场景内容(实体/组件)由编辑器 File 菜单 Save/Load 场景文件管理,
|
||
// 相机实体属于场景数据、只在游戏形态参与渲染(UE 语义)。
|
||
//
|
||
// 窗口、渲染器、事件泵、帧计时、场景容器全部由框架管理。
|
||
//
|
||
|
||
#include <Engine/Core/Application.h>
|
||
#include <Engine/Core/Time.h>
|
||
#include <Engine/Core/Window.h> // SetInputCapture(Application.h 只前置声明)
|
||
#include <Engine/Core/Log.h>
|
||
#include <Engine/Core/Stats.h>
|
||
#include <Engine/Renderer/Renderer.h>
|
||
#include <Engine/Renderer/EditorCamera.h>
|
||
|
||
#include <GLFW/glfw3.h>
|
||
|
||
#include "Editor.h"
|
||
#include "EditorContext.h" // kEnvPaths / kDefaultEnv(与 StatsPanel 共用)
|
||
|
||
using namespace Engine;
|
||
|
||
namespace
|
||
{
|
||
class SandboxApp final : public Application
|
||
{
|
||
public:
|
||
SandboxApp()
|
||
: Application("HelloVulkan", 1920, 1080)
|
||
{
|
||
}
|
||
|
||
~SandboxApp() override
|
||
{
|
||
}
|
||
|
||
protected:
|
||
// ---- 生命周期 ----
|
||
|
||
void OnInit() override
|
||
{
|
||
Renderer& renderer = GetRenderer();
|
||
renderer.SetDisplayMode(kDisplayViewport);
|
||
|
||
|
||
// ImGui 叠加层(框架只做管线桥接;UI 内容 = docking Editor)
|
||
EnableImGui();
|
||
|
||
// Editor 注入:引擎门面 + 沙盒能力回调(环境异步切换等)
|
||
InitEditor();
|
||
}
|
||
|
||
void OnUpdate(const FrameTime& frameTime) override
|
||
{
|
||
// 编辑器形态:驱动编辑器相机(RMB 飞行 / MMB 焦点环绕 /
|
||
// 滚轮推拉)。暂停(timeScale=0)时仍可飞行——unscaled dt。
|
||
// 游戏形态:相机实体由游戏逻辑驱动(本沙盒无逻辑 = 静止)
|
||
if (GetRenderer().GetDisplayMode() == kDisplayViewport)
|
||
{
|
||
GetRenderer().GetEditorCamera().Update(GetWindow(),
|
||
frameTime.UnscaledDt());
|
||
}
|
||
}
|
||
|
||
// ---- UI(全部委托 docking Editor;本文件零 ImGui 控件)----
|
||
|
||
void OnImGuiRender() override
|
||
{
|
||
m_Editor->Draw();
|
||
}
|
||
|
||
// ---- 事件 ----
|
||
|
||
void OnWindowClose(const Event& event) override
|
||
{
|
||
// 退出确认走 Editor 的模态框(ImGui 必须可见才有 UI)
|
||
SetImGuiEnabled(true);
|
||
m_Editor->RequestQuit();
|
||
}
|
||
|
||
void OnKeyPress(const Event& event) override
|
||
{
|
||
if (event.key == GLFW_KEY_GRAVE_ACCENT)
|
||
{
|
||
SetImGuiEnabled(!GetImGuiEnabled());
|
||
}
|
||
if (event.key == GLFW_KEY_F1)
|
||
{
|
||
STATS.PrintComparison();
|
||
}
|
||
}
|
||
|
||
|
||
void OnWindowResize(const Event& event) override
|
||
{
|
||
ENGINE_INFO("App: window resized to {}x{}", event.width, event.height);
|
||
}
|
||
|
||
private:
|
||
// Editor 注入:门面指针 + 反向能力回调(面板 → 沙盒)
|
||
void InitEditor()
|
||
{
|
||
EditorContext ctx;
|
||
ctx.renderer = &GetRenderer();
|
||
ctx.scene = &GetScene();
|
||
ctx.assets = &GetAssets();
|
||
ctx.app = this;
|
||
ctx.editorCamera = &GetRenderer().GetEditorCamera();
|
||
ctx.getEnvIndex = [this] { return m_EnvIndex; };
|
||
ctx.setEnvIndex = [this](int index) { m_EnvIndex = index; };
|
||
// 继承原沙盒默认:初始暂停(StatsPanel 的 Pause Simulation 开关恢复)
|
||
Time::SetTimeScale(0.0f);
|
||
m_Editor->Init(ctx);
|
||
|
||
// 输入归属:覆盖 EnableImGui 的全局 WantCapture* 谓词
|
||
//(全屏 dock host 让它恒真,输入全死)。改为 Editor 按帧
|
||
// 判定——Viewport hover/focus 拥有输入(Hazel/UE 语义);
|
||
// UI 隐藏(反引号)时 Draw 不再执行,直接全放行
|
||
GetWindow().SetInputCapture(
|
||
[this] { return GetImGuiEnabled() && m_Editor->BlockingKeyboard(); },
|
||
[this] { return GetImGuiEnabled() && m_Editor->BlockingMouse(); });
|
||
|
||
}
|
||
|
||
private:
|
||
std::unique_ptr<Editor> m_Editor = std::make_unique<Editor>();
|
||
int m_EnvIndex = kDefaultEnv;
|
||
};
|
||
}
|
||
|
||
int main()
|
||
{
|
||
Logger::Initialize();
|
||
|
||
{
|
||
SandboxApp app;
|
||
|
||
try
|
||
{
|
||
app.Run();
|
||
}
|
||
catch (const std::exception& e)
|
||
{
|
||
ENGINE_FATAL("Exception: {}", e.what());
|
||
Logger::Shutdown();
|
||
return -1;
|
||
}
|
||
} // app 析构:成员(Device/Renderer/Window…)全部销毁完毕
|
||
|
||
Logger::Shutdown();
|
||
return 0;
|
||
}
|