Skip to content

Add mesh info overlay to viewport#191

Merged
fernandotonon merged 4 commits into
masterfrom
feature/mesh-info-overlay
Mar 11, 2026
Merged

Add mesh info overlay to viewport#191
fernandotonon merged 4 commits into
masterfrom
feature/mesh-info-overlay

Conversation

@fernandotonon
Copy link
Copy Markdown
Owner

@fernandotonon fernandotonon commented Mar 11, 2026

Summary

Closes #179

  • Adds a MeshInfoOverlay that displays mesh statistics (vertices, triangles, submeshes, materials, bones, animations) on the active viewport
  • Shows stats for selected entities when a selection exists, otherwise shows aggregated scene stats
  • Toggled via Options > Show Mesh Info menu item
  • Adds MCP toggle_mesh_info tool for programmatic control
  • Bumps version to 2.12.0

Implementation details

  • Overlay is a top-level Qt::Tool frameless transparent window to avoid ghost-text artifacts from Ogre's direct-to-native rendering (WA_PaintOnScreen with null paintEngine())
  • Tracks the active viewport via OgreWidget::focusOnWidget signal
  • Repositions via event filters on both MainWindow and the active OgreWidget (handles window moves, dock splitter drags, etc.)
  • Safely iterates scene nodes checking getMovableType() == "Entity" to avoid static_cast crashes from Lights/ManualObjects
  • Reuses existing CLIPipeline::extractMeshInfo() for data extraction

Files changed

File Change
src/MeshInfoOverlay.h/cpp New overlay class
src/MeshInfoOverlay_test.cpp 6 unit tests (3 pure formatting + 3 integration)
src/MCPServer.h/cpp New toggle_mesh_info tool
src/MCPServer_test.cpp 3 new MCP tests + updated tool count
src/mainwindow.h/cpp Overlay lifecycle + viewport signal wiring
ui_files/mainwindow.ui New "Show Mesh Info" checkable action in Options menu
CMakeLists.txt Version bump 2.11.3 → 2.12.0
CLAUDE.md Document MeshInfoOverlay in Debug Overlays section

Test plan

  • Pure formatting tests pass (empty list, null entity, selection labels)
  • Integration tests with Ogre entities (single, multiple, skeleton) — skip gracefully on macOS, run in CI
  • MCP toggle_mesh_info tests (no-MainWindow error, tool recognition, on/off states)
  • Manual: Load mesh → Options > Show Mesh Info → verify overlay appears
  • Manual: Select/deselect entities → verify text updates with no ghost artifacts
  • Manual: Switch viewport layouts (1↔4) → verify no crashes
  • Manual: MCP toggle_mesh_info with --with-mcp flag

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Mesh information overlay showing live stats (verts, tris, submeshes, materials, bones, animations) for current selection or active viewport
    • Checkable "Show Mesh Info" action in View menu; overlay follows active viewport and updates with selection/scene changes
    • Remote/tool command to show/hide the overlay
    • App version bumped to 2.12.0
  • Tests

    • Added unit and integration tests for overlay formatting, lifecycle, and protocol/tool coverage

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 11, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a71e7ff8-87d0-4e08-8ef9-ae2bf4e297dd

📥 Commits

Reviewing files that changed from the base of the PR and between 1d49683 and c5c58a6.

📒 Files selected for processing (13)
  • CLAUDE.md
  • CMakeLists.txt
  • src/CMakeLists.txt
  • src/MCPServer.cpp
  • src/MCPServer.h
  • src/MCPServer_test.cpp
  • src/MeshInfoOverlay.cpp
  • src/MeshInfoOverlay.h
  • src/MeshInfoOverlay_test.cpp
  • src/mainwindow.cpp
  • src/mainwindow.h
  • tests/CMakeLists.txt
  • ui_files/mainwindow.ui

📝 Walkthrough

Walkthrough

Adds a new MeshInfoOverlay UI component and integrates it into MainWindow, the MCPServer toolset, build/test configs, and unit/integration tests; provides a toggleable overlay showing mesh statistics for active viewports or selected entities.

Changes

Cohort / File(s) Summary
MeshInfoOverlay Core
src/MeshInfoOverlay.h, src/MeshInfoOverlay.cpp, src/MeshInfoOverlay_test.cpp
New QObject-based overlay class that collects Ogre::Entity objects, formats locale-aware mesh statistics (verts, tris, submeshes, materials, bones, animations), manages a top-level translucent QLabel, responds to viewport/selection events, and ships extensive tests.
MainWindow Integration & UI
src/mainwindow.h, src/mainwindow.cpp, ui_files/mainwindow.ui
Adds m_meshInfoOverlay member, constructs and wires it to a new checkable actionShow_Mesh_Info, connects viewport focus events to update the overlay's active widget, and adjusts destruction order.
MCPServer and Protocol
src/MCPServer.h, src/MCPServer.cpp, src/MCPServer_test.cpp
Introduces MCP tool toggle_mesh_info with handler toolToggleMeshInfo(...), dispatch wiring and tool-list entry; tests updated/added to recognize and exercise the new tool and error paths when MainWindow is absent.
Build & Tests Configuration
CMakeLists.txt, src/CMakeLists.txt, tests/CMakeLists.txt
Project version bumped to 2.12.0; MeshInfoOverlay.{cpp,h} added to source/header lists; test build augmented to include MeshInfoOverlay and CLIPipeline sources/headers.
Test Suite Expansion
src/MCPServer_test.cpp, src/MeshInfoOverlay_test.cpp
Extensive new and updated tests covering formatStats, overlay lifecycle, event filtering, visibility toggling, and MCPServer interactions (including no-MainWindow error cases and in-memory/Ogre integration tests).

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as "MainWindow UI"
    participant MCP as "MCPServer"
    participant MW as "MainWindow"
    participant Overlay as "MeshInfoOverlay"
    participant OW as "OgreWidget"

    User->>UI: Toggle "Show Mesh Info" action
    UI->>MW: action toggled (setVisible)
    UI->>MCP: (optional) POST toggle_mesh_info(show=true)
    MCP->>MW: lookup / request overlay toggle
    MW->>Overlay: setVisible(true/false)
    MW->>Overlay: setActiveWidget(OW)
    OW->>Overlay: focus / move / resize / selection events
    Overlay->>Overlay: collectEntities() -> formatStats()
    Overlay->>Overlay: ensureLabel() / repositionLabel()
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hop through verts and count each face,

Triangles hum and submeshes find their place.
A translucent label floats on view,
Whispering bone and animation clues.
Hooray — the mesh tale shows in grace!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add mesh info overlay to viewport' is a clear and specific summary that accurately describes the primary change in this pull request.
Description check ✅ Passed The description provides a comprehensive summary, technical details, files changed, and test plan, aligning well with the repository's template structure and requirements.
Linked Issues check ✅ Passed The PR fully implements the objective from #179: provides an on-screen overlay displaying mesh statistics (vertices, triangles, animations), shows per-entity stats when selected or aggregated scene stats when nothing is selected.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the mesh info overlay feature and its integration. The version bump and documentation update are appropriate supporting changes for a feature release.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/mesh-info-overlay

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 12ce55f789

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/MeshInfoOverlay.cpp
Comment on lines +36 to +39
if (type == QEvent::Move || type == QEvent::Resize) {
if (mVisible && mLabel && mActiveWidget)
repositionLabel();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Hide mesh info overlay when active viewport is destroyed

Handle viewport-destroy events in addition to move/resize here: when the active OgreWidget is closed, mActiveWidget is nulled by QPointer but refresh() is never triggered, so the floating QLabel can remain visible with stale stats (especially when closing the last viewport) until some unrelated selection/entity signal happens. This leaves an orphaned overlay window on screen and breaks the expected toggle behavior.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
ui_files/mainwindow.ui (1)

83-83: Avoid extending the legacy Widgets menu for new UI surface area.

This adds a brand-new control to ui_files/mainwindow.ui, but the repo guidance says new UI should go through QML instead of extending the existing Widgets-based surface. If this toggle needs to stay here for now, I’d at least document it as an exception and move it into the QML settings/debug UI in a follow-up.

As per coding guidelines "UI: QML over Widgets. New UI should be built in QML (Qt Quick), not Qt Widgets. Existing Widget-based UI (ui_files/) remains but should not be extended."

Also applies to: 229-239

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui_files/mainwindow.ui` at line 83, The new Widgets action
actionShow_Mesh_Info added to ui_files/mainwindow.ui violates the "UI: QML over
Widgets" guideline; either remove this addaction and implement the toggle in QML
(e.g., add it to the QML settings/debug UI), or if you must keep it temporarily,
document it as an explicit exception in the commit message/PR and create a
follow-up ticket to migrate actionShow_Mesh_Info (and the related controls
around lines 229-239) into QML; update the UI change to match one of these two
paths and avoid adding new Widget-based controls in ui_files.
src/MCPServer_test.cpp (1)

2518-2532: Replace one of these error-path checks with a real success-path toggle test.

These assertions only prove that toggle_mesh_info is recognized and that the no-MainWindow path returns some error text. They will not catch regressions in the actual behavior—e.g. findChild<MeshInfoOverlay*>() failing or the show argument being ignored. A small fixture with a real MainWindow + MeshInfoOverlay would cover the feature much better.

As per coding guidelines, "Add Google Test unit tests for new functionality."

Also applies to: 2706-2723

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/MCPServer_test.cpp` around lines 2518 - 2532, Replace one of the
error-path checks with a real success-path test that constructs a MainWindow
containing a MeshInfoOverlay, then calls server->callTool("toggle_mesh_info",
args) to toggle visibility and asserts the overlay was found and its visibility
changed; specifically, in the TEST_F named ToggleMeshInfoIsRecognizedTool (or a
new TEST_F), create a MainWindow instance, ensure findChild<MeshInfoOverlay*>()
returns a valid pointer, call server->callTool("toggle_mesh_info",
QJsonObject{{"show", true}}) and verify the returned result is not an error and
the MeshInfoOverlay is visible, then call with {"show", false} and verify it
becomes hidden, using server->callTool, MeshInfoOverlay, MainWindow,
getResultText and isError to validate outcomes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/mainwindow.cpp`:
- Around line 352-357: The menu QAction currently drives MeshInfoOverlay but not
vice versa, so make the QAction the single source of truth by additionally
connecting overlay visibility changes back to the action: after creating
m_meshInfoOverlay, connect its visibility/visibilityChanged signal (or add a
signal like void visibilityChanged(bool) to MeshInfoOverlay that is emitted
whenever setVisible is called or the widget visibility changes) to
ui->actionShow_Mesh_Info->setChecked, e.g. connect(m_meshInfoOverlay,
&MeshInfoOverlay::visibilityChanged, ui->actionShow_Mesh_Info,
&QAction::setChecked); keep the existing connect(ui->actionShow_Mesh_Info,
&QAction::toggled, m_meshInfoOverlay, &MeshInfoOverlay::setVisible) and the
focusOnWidget connections unchanged so programmatic toggles (from MCPServer)
update the QAction state as well.

In `@src/MCPServer.cpp`:
- Around line 1907-1919: The MCP toggle is directly calling
MeshInfoOverlay::setVisible which bypasses the MainWindow path that keeps the
menu action and overlay in sync; change MCPServer::toolToggleMeshInfo to call
the same MainWindow helper/slot used by the Options > Show Mesh Info action
(e.g. the slot method connected to the QAction or a helper like
MainWindow::setMeshInfoVisible / MainWindow::on_actionShowMeshInfo_triggered)
instead of touching MeshInfoOverlay directly so the menu checkable action is
updated; locate the MainWindow slot that the menu action uses and invoke that
with the desired show boolean rather than calling overlay->setVisible.

In `@src/MeshInfoOverlay.cpp`:
- Around line 85-123: In MeshInfoOverlay::formatStats, build a filtered list of
valid entities (e.g., validEntities) by skipping null pointers before computing
totals and use that list for the empty check and header logic instead of the raw
entities parameter; update the loop to iterate over validEntities, compute
totals (vertices, triangles, submeshes, bones, animations, materials) from it,
and then derive the header (single-mesh name, "Selected (N meshes)", "Scene (N
meshes)" or "No meshes") from validEntities.size() so null-only or mixed lists
report correct counts and "No meshes" when appropriate.
- Around line 33-40: The overlay can be left visible when the active viewport
goes away; update MeshInfoOverlay::eventFilter to also handle QEvent::Hide,
QEvent::Close and QEvent::Destroy (or QEvent::HideToParent as appropriate) and
when such an event is received for the current mActiveWidget, call
mLabel->hide(), set mVisible = false and clear mActiveWidget (mActiveWidget =
nullptr) so the floating label is removed immediately; alternatively (or
additionally) in setActiveWidget() connect the widget's destroyed(QObject*)
signal to a small slot/lambda that hides the label, clears mActiveWidget and
prevents repositionLabel() from being called on a dead QPointer.

---

Nitpick comments:
In `@src/MCPServer_test.cpp`:
- Around line 2518-2532: Replace one of the error-path checks with a real
success-path test that constructs a MainWindow containing a MeshInfoOverlay,
then calls server->callTool("toggle_mesh_info", args) to toggle visibility and
asserts the overlay was found and its visibility changed; specifically, in the
TEST_F named ToggleMeshInfoIsRecognizedTool (or a new TEST_F), create a
MainWindow instance, ensure findChild<MeshInfoOverlay*>() returns a valid
pointer, call server->callTool("toggle_mesh_info", QJsonObject{{"show", true}})
and verify the returned result is not an error and the MeshInfoOverlay is
visible, then call with {"show", false} and verify it becomes hidden, using
server->callTool, MeshInfoOverlay, MainWindow, getResultText and isError to
validate outcomes.

In `@ui_files/mainwindow.ui`:
- Line 83: The new Widgets action actionShow_Mesh_Info added to
ui_files/mainwindow.ui violates the "UI: QML over Widgets" guideline; either
remove this addaction and implement the toggle in QML (e.g., add it to the QML
settings/debug UI), or if you must keep it temporarily, document it as an
explicit exception in the commit message/PR and create a follow-up ticket to
migrate actionShow_Mesh_Info (and the related controls around lines 229-239)
into QML; update the UI change to match one of these two paths and avoid adding
new Widget-based controls in ui_files.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fe7478e6-631b-42a6-8626-a2f0c79c9f72

📥 Commits

Reviewing files that changed from the base of the PR and between 99cdc04 and 12ce55f.

📒 Files selected for processing (12)
  • CLAUDE.md
  • CMakeLists.txt
  • src/CMakeLists.txt
  • src/MCPServer.cpp
  • src/MCPServer.h
  • src/MCPServer_test.cpp
  • src/MeshInfoOverlay.cpp
  • src/MeshInfoOverlay.h
  • src/MeshInfoOverlay_test.cpp
  • src/mainwindow.cpp
  • src/mainwindow.h
  • ui_files/mainwindow.ui

Comment thread src/mainwindow.cpp
Comment thread src/MCPServer.cpp
Comment on lines +1907 to +1919
QJsonObject MCPServer::toolToggleMeshInfo(const QJsonObject &args)
{
if (!m_mainWindow)
return makeErrorResult("Error: MainWindow not available. Run with --with-mcp flag.");

MeshInfoOverlay* overlay = m_mainWindow->findChild<MeshInfoOverlay*>();
if (!overlay)
return makeErrorResult("Error: MeshInfoOverlay not found");

bool show = args.contains("show") ? args["show"].toBool() : !overlay->isVisible();
overlay->setVisible(show);

return makeSuccessResult(QString("Mesh info overlay %1").arg(show ? "shown" : "hidden"));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Route this through the same MainWindow path as the menu action.

This flips MeshInfoOverlay directly, but the PR also adds a checkable Options > Show Mesh Info action. Since src/MeshInfoOverlay.h only exposes isVisible() / setVisible() and no visibility-change signal, that action never learns about this state change. After an MCP toggle, the overlay state and the menu checkmark can drift apart. Use the same MainWindow helper/slot that updates both pieces of UI.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/MCPServer.cpp` around lines 1907 - 1919, The MCP toggle is directly
calling MeshInfoOverlay::setVisible which bypasses the MainWindow path that
keeps the menu action and overlay in sync; change MCPServer::toolToggleMeshInfo
to call the same MainWindow helper/slot used by the Options > Show Mesh Info
action (e.g. the slot method connected to the QAction or a helper like
MainWindow::setMeshInfoVisible / MainWindow::on_actionShowMeshInfo_triggered)
instead of touching MeshInfoOverlay directly so the menu checkable action is
updated; locate the MainWindow slot that the menu action uses and invoke that
with the desired show boolean rather than calling overlay->setVisible.

Comment thread src/MeshInfoOverlay.cpp
Comment thread src/MeshInfoOverlay.cpp
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
tests/CMakeLists.txt (1)

58-59: Duplicate source file entry.

QMLMaterialHighlighter.cpp appears twice in TEST_SRC_FILES (line 47 and line 59). While CMake typically handles duplicates gracefully, this should be cleaned up to avoid confusion.

Remove duplicate entry
         ${CMAKE_CURRENT_SOURCE_DIR}/../src/MCPSettingsDialog.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/../src/MeshInfoOverlay.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/../src/QMLMaterialHighlighter.cpp
     )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/CMakeLists.txt` around lines 58 - 59, The TEST_SRC_FILES list contains
a duplicate entry for QMLMaterialHighlighter.cpp; open the CMakeLists.txt where
TEST_SRC_FILES is defined and remove the redundant occurrence of
QMLMaterialHighlighter.cpp so it appears only once in TEST_SRC_FILES (ensure
other source filenames such as MeshInfoOverlay.cpp remain unchanged).
src/MeshInfoOverlay.cpp (1)

108-112: Consider using unsigned int for totalBones for consistency.

totalBones is declared as unsigned short while other counters (totalVerts, totalTris, totalSubmeshes) use unsigned int. With multiple skeletal meshes, the sum could theoretically overflow unsigned short (max 65535). While unlikely in practice, using unsigned int would be consistent with the other counters.

Suggested change
     unsigned int totalVerts = 0;
     unsigned int totalTris = 0;
     unsigned int totalSubmeshes = 0;
-    unsigned short totalBones = 0;
+    unsigned int totalBones = 0;
     int totalAnims = 0;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/MeshInfoOverlay.cpp` around lines 108 - 112, Change the type of the
totalBones variable in MeshInfoOverlay.cpp from unsigned short to unsigned int
to match the other counters (totalVerts, totalTris, totalSubmeshes) and avoid
potential overflow when summing bones across multiple meshes; update any related
uses of totalBones in functions or calculations in the same file (e.g., places
referencing totalBones) to work with unsigned int.
src/MeshInfoOverlay_test.cpp (1)

94-96: Test assertions for vertex/triangle counts are somewhat fragile.

Checking result.contains("3") and result.contains("1") could match other numbers in the output (e.g., locale-formatted numbers or other stats). Consider using a more specific pattern or regex to match "Verts: 3" and "Tris: 1" directly.

More specific assertions
-    // 3 vertices, 1 triangle
-    EXPECT_TRUE(result.contains("3")) << "Result: " << result.toStdString();
-    EXPECT_TRUE(result.contains("1")) << "Result: " << result.toStdString();
+    // 3 vertices, 1 triangle - use more specific patterns
+    EXPECT_TRUE(result.contains("Verts: 3")) << "Result: " << result.toStdString();
+    EXPECT_TRUE(result.contains("Tris: 1")) << "Result: " << result.toStdString();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/MeshInfoOverlay_test.cpp` around lines 94 - 96, The assertions using
result.contains("3") and result.contains("1") are too broad; update the test to
assert against more specific text patterns like "Verts: 3" and "Tris: 1" (or use
a QRegularExpression) instead of plain digit checks. Locate the EXPECT_TRUE
lines that reference result and replace them with checks such as
result.contains("Verts: 3") and result.contains("Tris: 1") or use
QRegularExpression/QString::contains with explicit patterns (e.g.,
QRegularExpression(R"(Verts:\s*3)")) to avoid accidental matches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/MeshInfoOverlay_test.cpp`:
- Around line 94-96: The assertions using result.contains("3") and
result.contains("1") are too broad; update the test to assert against more
specific text patterns like "Verts: 3" and "Tris: 1" (or use a
QRegularExpression) instead of plain digit checks. Locate the EXPECT_TRUE lines
that reference result and replace them with checks such as
result.contains("Verts: 3") and result.contains("Tris: 1") or use
QRegularExpression/QString::contains with explicit patterns (e.g.,
QRegularExpression(R"(Verts:\s*3)")) to avoid accidental matches.

In `@src/MeshInfoOverlay.cpp`:
- Around line 108-112: Change the type of the totalBones variable in
MeshInfoOverlay.cpp from unsigned short to unsigned int to match the other
counters (totalVerts, totalTris, totalSubmeshes) and avoid potential overflow
when summing bones across multiple meshes; update any related uses of totalBones
in functions or calculations in the same file (e.g., places referencing
totalBones) to work with unsigned int.

In `@tests/CMakeLists.txt`:
- Around line 58-59: The TEST_SRC_FILES list contains a duplicate entry for
QMLMaterialHighlighter.cpp; open the CMakeLists.txt where TEST_SRC_FILES is
defined and remove the redundant occurrence of QMLMaterialHighlighter.cpp so it
appears only once in TEST_SRC_FILES (ensure other source filenames such as
MeshInfoOverlay.cpp remain unchanged).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 42d48508-1c07-4c90-a820-664e34c252d0

📥 Commits

Reviewing files that changed from the base of the PR and between 12ce55f and 65b862d.

📒 Files selected for processing (5)
  • src/MeshInfoOverlay.cpp
  • src/MeshInfoOverlay.h
  • src/MeshInfoOverlay_test.cpp
  • src/mainwindow.cpp
  • tests/CMakeLists.txt
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/mainwindow.cpp
  • src/MeshInfoOverlay.h

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/MCPServer_test.cpp (1)

2727-2761: Success path test covers visibility toggling and automatic flip behavior.

The test validates:

  • Initial hidden state
  • Toggle on with show=true → "shown" message, overlay visible
  • Toggle off with show=false → "hidden" message, overlay hidden
  • Toggle without show arg → flips to visible

The cleanup correctly resets the server's mainWindow and deletes the overlay. However, if an assertion fails mid-test, the overlay won't be deleted. This is acceptable for tests, but consider using a unique_ptr or RAII wrapper for cleaner exception safety.

🛡️ Optional: Use RAII for exception-safe cleanup
 TEST_F(MCPServerTest, ToggleMeshInfo_SuccessPath)
 {
     // Create a fake MainWindow with a MeshInfoOverlay child so findChild works
     QMainWindow fakeWindow;
-    auto* overlay = new MeshInfoOverlay(reinterpret_cast<MainWindow*>(&fakeWindow));
+    std::unique_ptr<MeshInfoOverlay> overlay(
+        new MeshInfoOverlay(reinterpret_cast<MainWindow*>(&fakeWindow)));
     server->setMainWindow(reinterpret_cast<MainWindow*>(&fakeWindow));

-    EXPECT_FALSE(overlay->isVisible());
+    EXPECT_FALSE(overlay->isVisible());

     // Toggle on
     QJsonObject argsOn;
     argsOn["show"] = true;
     QJsonObject resultOn = server->callTool("toggle_mesh_info", argsOn);
     EXPECT_FALSE(isError(resultOn)) << getResultText(resultOn).toStdString();
     EXPECT_TRUE(getResultText(resultOn).contains("shown"));
     EXPECT_TRUE(overlay->isVisible());

     // ... rest of test ...

     // Clean up
     server->setMainWindow(nullptr);
-    delete overlay;
+    // overlay automatically deleted by unique_ptr
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/MCPServer_test.cpp` around lines 2727 - 2761, The test creates a raw
MeshInfoOverlay* (overlay) attached to fakeWindow and manually deletes it at the
end, which leaks if an assertion aborts mid-test; change the allocation to use
RAII (e.g., std::unique_ptr<MeshInfoOverlay> or a scoped guard) and ensure
server->setMainWindow is reset in a destructor or scope guard so that overlay is
automatically deleted even on test failures; update references to overlay to use
the smart pointer (overlay.get()) and keep server->setMainWindow(nullptr) in the
RAII cleanup.
src/MeshInfoOverlay_test.cpp (1)

54-60: Consider documenting the reinterpret_cast usage more explicitly.

The fakeMainWindow helper uses reinterpret_cast to avoid constructing the heavyweight real MainWindow. The comment explains the rationale, but this is a somewhat fragile pattern.

This approach works because MeshInfoOverlay only uses QObject/QWidget methods on the MainWindow*, but if MainWindow ever adds virtual methods or non-standard memory layout, this could cause subtle issues.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/MeshInfoOverlay_test.cpp` around lines 54 - 60, Document the
reinterpret_cast in fakeMainWindow more explicitly: expand the comment in the
fakeMainWindow function to state that we deliberately cast a QMainWindow* to
MainWindow* because MeshInfoOverlay only calls QObject/QWidget methods
(installEventFilter, findChildren, QLabel parent) and therefore no
MainWindow-specific state or virtual dispatch is required, and add a clear
TODO/FIXME warning that this is fragile — if MainWindow acquires virtual
methods, non-trivial data, or changes inheritance, this cast becomes unsafe and
callers should construct a real MainWindow instead; also mention MeshInfoOverlay
by name so future editors see the dependency.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/MCPServer_test.cpp`:
- Around line 2727-2761: The test creates a raw MeshInfoOverlay* (overlay)
attached to fakeWindow and manually deletes it at the end, which leaks if an
assertion aborts mid-test; change the allocation to use RAII (e.g.,
std::unique_ptr<MeshInfoOverlay> or a scoped guard) and ensure
server->setMainWindow is reset in a destructor or scope guard so that overlay is
automatically deleted even on test failures; update references to overlay to use
the smart pointer (overlay.get()) and keep server->setMainWindow(nullptr) in the
RAII cleanup.

In `@src/MeshInfoOverlay_test.cpp`:
- Around line 54-60: Document the reinterpret_cast in fakeMainWindow more
explicitly: expand the comment in the fakeMainWindow function to state that we
deliberately cast a QMainWindow* to MainWindow* because MeshInfoOverlay only
calls QObject/QWidget methods (installEventFilter, findChildren, QLabel parent)
and therefore no MainWindow-specific state or virtual dispatch is required, and
add a clear TODO/FIXME warning that this is fragile — if MainWindow acquires
virtual methods, non-trivial data, or changes inheritance, this cast becomes
unsafe and callers should construct a real MainWindow instead; also mention
MeshInfoOverlay by name so future editors see the dependency.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fb8247ef-62e1-4739-a010-eeba30127ee0

📥 Commits

Reviewing files that changed from the base of the PR and between 66e51f5 and 1d49683.

📒 Files selected for processing (2)
  • src/MCPServer_test.cpp
  • src/MeshInfoOverlay_test.cpp

fernandotonon and others added 4 commits March 11, 2026 15:47
Displays mesh statistics (vertices, triangles, submeshes, materials,
bones, animations) on the active viewport. Shows stats for selected
entities when a selection exists, otherwise shows aggregated scene stats.
Toggled via Options > Show Mesh Info menu or MCP toggle_mesh_info tool.

Implemented as a top-level Qt::Tool window to avoid ghost-text artifacts
from Ogre's direct-to-native rendering (WA_PaintOnScreen). The overlay
tracks the active viewport via OgreWidget::focusOnWidget and repositions
via event filters on both MainWindow and the active OgreWidget.

Bumps version to 2.12.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix CI: add MeshInfoOverlay.cpp/h to tests/CMakeLists.txt so
  MaterialEditorQML test targets can link MCPServer's toggle_mesh_info
- Sync QAction with MCP toggles: add visibilityChanged signal to
  MeshInfoOverlay and connect it back to actionShow_Mesh_Info so
  programmatic toggles keep the menu checkmark in sync
- Hide overlay on viewport destroy: handle Hide/Close/Destroy events
  in eventFilter to prevent orphaned floating label when active
  viewport is removed
- Fix null entity counting: filter nulls before computing header
  and stats so null-only lists correctly report "No meshes"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MeshInfoOverlay calls CLIPipeline::extractMeshInfo(), so the
MaterialEditorQML test targets need CLIPipeline.cpp linked in.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 24 new MeshInfoOverlay tests covering lifecycle, event handling,
visibility toggling, widget management, and entity collection. Add
MCPServer toggle_mesh_info success-path test with fake MainWindow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fernandotonon fernandotonon force-pushed the feature/mesh-info-overlay branch from 1d49683 to c5c58a6 Compare March 11, 2026 19:47
@fernandotonon fernandotonon merged commit 73b0313 into master Mar 11, 2026
5 of 6 checks passed
@fernandotonon fernandotonon deleted the feature/mesh-info-overlay branch March 11, 2026 19:48
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add an info overlay to the viewport

1 participant