Files
HelloVulkan/App/main.cpp
T
atdunbg cc837bc605 Add animation controller system, material assets and skeleton visualization
- .animctrl state machine asset (params/transitions/blend trees, 1D+2D
  directional blending) with Unity Animator-style editor panel: state
  list, transitions, params, directional pad preview driving live
  CrossFade on the selected entity
- Split animation evaluation out of SceneRenderer into
  AnimationSystem/AnimationEvaluator; skin palettes with rest-pose
  fallback and blend-weight epsilon filtering
- MaterialAsset (.material) with reload-safe preview tile pool
  (DropMaterial clears dirty refs before instance destruction)
- EditorGizmoPass skeleton wires + viewport joint overlay; camera
  projection rework (baked Vulkan Y-flip, ortho support)
- Editor/game build split via HELLOVULKAN_EDITOR option
2026-10-07 01:50:04 +08:00

187 lines
5.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// 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 <Engine/Core/Input.h>
// editor/game 编译期分离(HELLOVULKAN_EDITOR CMake option):editor 形态
// 挂接 docking Editor;game 形态 = Direct 直渲 + primary 相机,零编辑器代码
#ifdef HELLO_EDITOR
#include "Editor.h"
#include "EditorContext.h"
#endif
using namespace Engine;
namespace
{
class SandboxApp final : public Application
{
public:
SandboxApp()
: Application("HelloVulkan", 1920, 1080)
{
}
~SandboxApp() override
{
}
protected:
// ---- 生命周期 ----
void OnInit() override
{
Renderer& renderer = GetRenderer();
#ifdef HELLO_EDITOR
renderer.SetDisplayMode(kDisplayViewport);
// ImGui 叠加层(框架只做管线桥接;UI 内容 = docking Editor)
EnableImGui();
// Editor 注入:引擎门面 + 沙盒能力回调(环境异步切换等)
InitEditor();
#else
// game 形态:全窗口 Direct 直渲(Renderer 默认即 kDisplayDirect),
// 相机由场景 primary camera 提供,无 UI
#endif
}
void OnUpdate(const FrameTime& frameTime) override
{
#ifdef HELLO_EDITOR
// 编辑器形态:驱动编辑器相机(RMB 飞行 / MMB 焦点环绕 /
// 滚轮推拉)。暂停(timeScale=0)时仍可飞行——unscaled dt。
// PIE 内嵌播放:渲染源已切 primary 相机,编辑器相机停驱
//(否则与游戏脚本抢 WASD,Stop 后视角也被偷跑)。
// 游戏形态:相机实体由游戏逻辑驱动(本沙盒无逻辑 = 静止)
if (GetRenderer().GetDisplayMode() == kDisplayViewport &&
!m_Editor->IsPlaying())
{
GetRenderer().GetEditorCamera().Update(frameTime.UnscaledDt());
}
#else
(void)frameTime; // game 形态:本沙盒无游戏逻辑
#endif
}
// ---- UI(全部委托 docking Editor;本文件零 ImGui 控件)----
void OnImGuiRender() override
{
#ifdef HELLO_EDITOR
m_Editor->Draw();
#endif
}
// ---- 事件 ----
void OnWindowClose(const Event& event) override
{
#ifdef HELLO_EDITOR
// 退出确认走 Editor 的模态框(ImGui 必须可见才有 UI)
SetImGuiEnabled(true);
m_Editor->RequestQuit();
#else
(void)event;
#endif
}
void OnKeyPress(const Event& event) override
{
// 键码统一走 Input::Key(App 层零 GLFW 依赖)
#ifdef HELLO_EDITOR
if (event.key == static_cast<int>(Input::Key::GraveAccent))
{
SetImGuiEnabled(!GetImGuiEnabled());
}
#endif
if (event.key == static_cast<int>(Input::Key::F1))
{
STATS.PrintComparison();
}
}
void OnWindowResize(const Event& event) override
{
ENGINE_INFO("App: window resized to {}x{}", event.width, event.height);
}
private:
#ifdef HELLO_EDITOR
// Editor 注入:门面指针 + 反向能力回调(面板 → 沙盒)
void InitEditor()
{
EditorContext ctx;
ctx.renderer = &GetRenderer();
ctx.scene = &GetScene();
ctx.assets = &GetAssets();
ctx.app = this;
ctx.editorCamera = &GetRenderer().GetEditorCamera();
// 继承原沙盒默认:初始暂停(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>();
#endif
};
}
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;
}