From 611dcd0d46d948a31e457f7981de70549263423b Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Tue, 14 Apr 2026 13:55:39 +0300 Subject: [PATCH] FPS/batch counter works --- src/features/editScene/EditorApp.cpp | 24 +++++-- src/features/editScene/EditorApp.hpp | 12 +++- .../editScene/systems/EditorUISystem.cpp | 67 ++++++++++++++++++- .../editScene/systems/EditorUISystem.hpp | 21 +++++- 4 files changed, 117 insertions(+), 7 deletions(-) diff --git a/src/features/editScene/EditorApp.cpp b/src/features/editScene/EditorApp.cpp index f7ec8ef..911d87d 100644 --- a/src/features/editScene/EditorApp.cpp +++ b/src/features/editScene/EditorApp.cpp @@ -38,22 +38,31 @@ //============================================================================= ImGuiRenderListener::ImGuiRenderListener(Ogre::ImGuiOverlay *imguiOverlay, - EditorUISystem *uiSystem) + EditorUISystem *uiSystem, + Ogre::RenderWindow* renderWindow) : m_imguiOverlay(imguiOverlay) , m_uiSystem(uiSystem) + , m_renderWindow(renderWindow) { + m_lastTime = m_timer.getMilliseconds(); } void ImGuiRenderListener::preViewportUpdate( const Ogre::RenderTargetViewportEvent &evt) { (void)evt; + + // Calculate delta time + unsigned long currentTime = m_timer.getMilliseconds(); + m_deltaTime = (currentTime - m_lastTime) / 1000.0f; + m_lastTime = currentTime; + // Start ImGui frame before viewport renders Ogre::ImGuiOverlay::NewFrame(); - // Render editor UI + // Render editor UI with delta time if (m_uiSystem) { - m_uiSystem->update(); + m_uiSystem->update(m_deltaTime); } } @@ -61,6 +70,13 @@ void ImGuiRenderListener::postViewportUpdate( const Ogre::RenderTargetViewportEvent &evt) { (void)evt; + + // Capture stats after rendering (they're updated at end of frame) + if (m_renderWindow && m_uiSystem) { + Ogre::RenderTarget::FrameStats stats = m_renderWindow->getStatistics(); + m_uiSystem->setLastBatchCount(static_cast(stats.batchCount)); + } + // End ImGui frame after viewport renders ImGui::EndFrame(); } @@ -207,7 +223,7 @@ void EditorApp::setup() // Create and register ImGui render listener m_imguiListener = std::make_unique( - m_imguiOverlay, m_uiSystem.get()); + m_imguiOverlay, m_uiSystem.get(), getRenderWindow()); getRenderWindow()->addListener(m_imguiListener.get()); // Register input listeners diff --git a/src/features/editScene/EditorApp.hpp b/src/features/editScene/EditorApp.hpp index e78087b..8ad9c25 100644 --- a/src/features/editScene/EditorApp.hpp +++ b/src/features/editScene/EditorApp.hpp @@ -31,7 +31,8 @@ class RoomLayoutSystem; class ImGuiRenderListener : public Ogre::RenderTargetListener { public: ImGuiRenderListener(Ogre::ImGuiOverlay *imguiOverlay, - EditorUISystem *uiSystem); + EditorUISystem *uiSystem, + Ogre::RenderWindow* renderWindow); void preViewportUpdate(const Ogre::RenderTargetViewportEvent &evt) override; void postViewportUpdate(const Ogre::RenderTargetViewportEvent &evt) override; @@ -39,6 +40,15 @@ public: private: Ogre::ImGuiOverlay *m_imguiOverlay; EditorUISystem *m_uiSystem; + Ogre::RenderWindow* m_renderWindow; + + // Timer for delta time calculation + Ogre::Timer m_timer; + unsigned long m_lastTime = 0; + float m_deltaTime = 0.0f; + + // Frame stats (updated in postViewportUpdate) + int m_lastBatchCount = 0; }; /** diff --git a/src/features/editScene/systems/EditorUISystem.cpp b/src/features/editScene/systems/EditorUISystem.cpp index c45cb9b..1b37daa 100644 --- a/src/features/editScene/systems/EditorUISystem.cpp +++ b/src/features/editScene/systems/EditorUISystem.cpp @@ -176,7 +176,7 @@ void EditorUISystem::registerModularComponents() ComponentRegistration::registerAll(m_componentRegistry, m_sceneMgr, m_physicsSystem, m_renderWindow); } -void EditorUISystem::update() +void EditorUISystem::update(float deltaTime) { // Render UI windows // Note: NewFrame() is called by ImGuiRenderListener::preViewportUpdate @@ -192,6 +192,9 @@ void EditorUISystem::update() if (m_showFileDialog) { renderFileDialog(); } + + // Render FPS overlay + renderFPSOverlay(deltaTime); } void EditorUISystem::setSelectedEntity(flecs::entity entity) @@ -1131,3 +1134,65 @@ void EditorUISystem::renderFileDialog() ImGui::End(); } + + +void EditorUISystem::renderFPSOverlay(float deltaTime) +{ + // Toggle FPS overlay with F12 key + if (ImGui::IsKeyPressed(ImGuiKey_F12)) { + m_showFPSOverlay = !m_showFPSOverlay; + } + + if (!m_showFPSOverlay) { + return; + } + + // Update FPS calculation + m_fpsTimeAccumulator += deltaTime; + m_fpsFrameCount++; + + // Note: Batch count is set by ImGuiRenderListener::postViewportUpdate + // after each frame render (stats are updated at end of frame) + + // Update FPS every 0.5 seconds for smoother display + if (m_fpsTimeAccumulator >= 0.5f) { + m_currentFPS = m_fpsFrameCount / m_fpsTimeAccumulator; + m_fpsTimeAccumulator = 0.0f; + m_fpsFrameCount = 0; + } + + // Set up transparent window style + ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration | + ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_NoFocusOnAppearing | + ImGuiWindowFlags_NoNav; + + // Position in top-right corner with padding + ImVec2 windowPos = ImVec2(ImGui::GetIO().DisplaySize.x - 10.0f, 10.0f); + ImVec2 windowPivot = ImVec2(1.0f, 0.0f); // Top-right pivot + + ImGui::SetNextWindowPos(windowPos, ImGuiCond_Always, windowPivot); + ImGui::SetNextWindowBgAlpha(0.35f); // Semi-transparent background + + if (ImGui::Begin("FPS Overlay", nullptr, windowFlags)) { + // FPS text color based on performance + ImVec4 fpsColor; + if (m_currentFPS >= 60.0f) { + fpsColor = ImVec4(0.0f, 1.0f, 0.0f, 1.0f); // Green for 60+ FPS + } else if (m_currentFPS >= 30.0f) { + fpsColor = ImVec4(1.0f, 1.0f, 0.0f, 1.0f); // Yellow for 30-60 FPS + } else { + fpsColor = ImVec4(1.0f, 0.0f, 0.0f, 1.0f); // Red for <30 FPS + } + + ImGui::TextColored(fpsColor, "%.1f FPS", m_currentFPS); + ImGui::Text("Batches: %d", m_lastBatchCount); + + ImGui::Separator(); + + ImVec4 hintColor = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); + ImGui::TextColored(hintColor, "F12 to toggle"); + } + ImGui::End(); +} diff --git a/src/features/editScene/systems/EditorUISystem.hpp b/src/features/editScene/systems/EditorUISystem.hpp index 98439ed..310bc1d 100644 --- a/src/features/editScene/systems/EditorUISystem.hpp +++ b/src/features/editScene/systems/EditorUISystem.hpp @@ -35,7 +35,12 @@ public: * Update and render all UI windows * Call this once per frame */ - void update(); + void update(float deltaTime); + + /** + * Render FPS and batch count overlay + */ + void renderFPSOverlay(float deltaTime); /** * Set the currently selected entity @@ -83,6 +88,11 @@ public: * Set physics system for debug toggle */ void setPhysicsSystem(EditorPhysicsSystem* physics) { m_physicsSystem = physics; } + + /** + * Set last frame batch count (called from render listener) + */ + void setLastBatchCount(int count) { m_lastBatchCount = count; } @@ -144,6 +154,15 @@ private: // Settings bool m_parentSceneNodes = true; // Whether child entities inherit parent's SceneNode + + // FPS overlay settings + bool m_showFPSOverlay = true; // Show FPS counter by default + + // FPS tracking + float m_fpsTimeAccumulator = 0.0f; + int m_fpsFrameCount = 0; + float m_currentFPS = 0.0f; + int m_lastBatchCount = 0; // Physics system reference (for debug toggle) EditorPhysicsSystem* m_physicsSystem = nullptr;