// // Created by atdunbg on 2026/9/22. // // Application:程序生命周期基类。 // // 分层目标:main 不再知道 Window/Renderer 的存在—— // main 只 new 一个派生类并 Run(); // 派生类通过生命周期钩子(OnInit/OnUpdate/OnRenderOverlay/OnShutdown) // 和事件钩子(OnEvent + 类型化事件)定义程序行为; // runtime、editor 等不同程序形态只是不同的派生类。 // // 主循环固定为:PollEvents → OnUpdate(dt) → [NewFrame → OnRenderOverlay → // BuildDrawData] → 主渲染(Renderer.Render)→ 判退出。 // UI 构建与 GPU 提交分离:OnRenderOverlay 只"声明"控件,真正的 draw data // 提交发生在主渲染管线中的 ImGui pass(Forward 之后、Present 之前, // loadOp=Load 叠加)。主渲染是框架行为,派生类不可覆盖也不会丢失; // 框架自身永远不绘制任何 ImGui 控件——UI 内容全部由派生类定义。 // dt 由框架统一计时(含首帧与卡顿钳制),派生层无需自己管理。 // #ifndef HELLOVULKAN_APPLICATION_H #define HELLOVULKAN_APPLICATION_H #include #include #include #include #include "Engine/ImGui/ImGuiLayer.h" namespace Engine { class Window; class Renderer; class ImGuiLayer; namespace ECS { class Scene; } namespace Assets { class AssetManager; } class Application { public: Application(const std::string& title, u32 width, u32 height); virtual ~Application(); Application(const Application&) = delete; Application& operator=(const Application&) = delete; // 进入主循环(阻塞直到 Close() 或窗口关闭) void Run(); // 请求退出(当帧结束后生效) void Close() { m_Running = false; } // 启用 ImGui 叠加层(OnInit 内调用)。启用后每帧: // NewFrame → OnRenderOverlay(派生类画控件)→ BuildDrawData → // 主渲染(ImGui pass 把 draw data 叠加到场景上)。 void EnableImGui(); // ---- 帧率控制 ---- // vsync 开启时 present 自带节奏,手动限帧不生效; // 限帧目标最低 24fps(防止过低刷新导致交互卡死),无上限 void SetVSync(bool vsync); bool GetVSync() const { return m_VSync; } void SetTargetFps(f32 fps) { m_TargetFps = std::max(24.0f, fps); } f32 GetTargetFps() const { return m_TargetFps; } // ---- 供派生类访问的模块 ---- Window& GetWindow() const { return *m_Window; } Renderer& GetRenderer() const { return *m_Renderer; } ECS::Scene& GetScene() const { return *m_Scene; } Assets::AssetManager& GetAssets() const { return *m_Assets; } f32 GetDeltaTime() const { return m_DeltaTime; } u64 GetFrameCount() const { return m_FrameCount; } // ImGui相关 void SetImGuiEnabled(const bool enable) { if (m_ImGuiLayer) m_ImGuiLayer->SetEnabled(enable); } // 理论上ImGuiLayer不应该会空,暂时静默处理 bool GetImGuiEnabled() const { return m_ImGuiLayer ? m_ImGuiLayer->IsEnabled() : false; } protected: // ---- 生命周期钩子 ---- // 框架装配完成(Window/Renderer 可用),派生类做初始化(建场景等) virtual void OnInit() {} // 每帧逻辑更新(输入、动画、物理……) virtual void OnUpdate(f32 deltaTime) {} // 主渲染之后、当帧提交之前的叠加层钩子(ImGui/调试视图/编辑器 UI)。 // 主渲染由框架固定执行;这里只负责"额外的"渲染,不覆写则无叠加层。 virtual void OnRenderOverlay() {} // 主循环结束后、析构前(保存、清理场景等) virtual void OnShutdown() {} // ---- 事件钩子 ---- // OnEvent 收到所有事件(原始入口,适合做全局日志/拦截); // 类型化钩子按事件类型分别回调,派生类按需覆写。 virtual void OnEvent(const Event& event) {} virtual void OnWindowClose(const Event& event); virtual void OnWindowResize(const Event& event) {} virtual void OnWindowFocus(const Event& event) {} virtual void OnWindowLostFocus(const Event& event) {} virtual void OnKeyPress(const Event& event) {} virtual void OnKeyRelease(const Event& event) {} virtual void OnMouseButtonPress(const Event& event) {} virtual void OnMouseButtonRelease(const Event& event) {} virtual void OnMouseMove(const Event& event) {} virtual void OnMouseScroll(const Event& event) {} private: void DispatchEvent(const Event& event); Scope m_Window; Scope m_Scene; Scope m_Renderer; Scope m_Assets; // 注意成员序:ImGuiLayer 必须后声明(先于 Renderer/Window 析构, // 其后端销毁需要 Device 与 GLFWwindow 存活) Scope m_ImGuiLayer; bool m_Running = false; f32 m_DeltaTime = 0.0f; u64 m_FrameCount = 0; // 帧率控制 bool m_VSync = true; // 垂直同步(present 自带节奏) f32 m_TargetFps = 60.0f; // 限帧目标(≥24) std::chrono::steady_clock::time_point m_LastFrameTime; }; } // namespace Engine #endif //HELLOVULKAN_APPLICATION_H