Navigating MeshInspector’s UI Tree Programmatically

Find tabs and tools from Python, open them by name and check which buttons are available, just as if you clicked them

6 min read

Overview

The MeshInspector interface is available to Python as a tree of named entries: tabs, tools, tool windows and their buttons and fields. A script can list the entries, open a tab, start a tool and press buttons, so any sequence of clicks can be repeated by a script.

Run the scripts of this article in the Python window (Home › Python). If you have not used it yet, start with How to Control MeshInspector’s UI with Python.

Understanding the UI Tree

Every entry is reached by a path, a list of names from the top of the tree. Three functions of mrviewerpy do the work:

  • uiListEntries() lists the entries directly under a path;
  • uiListAllEntries() lists the whole subtree under a path in one call;
  • uiPressButton() presses the button at a path.

Hierarchy Structure

Level What it is Where to find it
Tab A Ribbon tab, for example Home, View or Mesh Repair. Buttons inside the RibbonTabs group.
Tool A tool of the open tab, for example Mesh Healer or Fill Holes. Buttons inside the Ribbon group (only the tools of the tab that is open now).
Parameter A button, check box, number or text field of an open tool window. Inside the entry named after the window, for example Mesh Healer.

The paths of the three levels look like this:

['RibbonTabs', 'Mesh Repair']        # a tab
['Ribbon', 'Mesh Healer']            # a tool of the open tab
['Mesh Healer', 'Repair Resolution'] # a field of the open Mesh Healer window

What an entry tells you

Each entry returned by uiListEntries() has three fields:

  • name: the name to use in a path;
  • type: button, group (an entry with entries inside), valueInt, valueUint, valueReal or valueString (fields; check boxes are valueUint with the values 0 and 1);
  • status: available, or the reason why the entry cannot be used now.

To see the top of the tree, pass an empty path:

from meshlib import mrviewerpy as mv

for entry in mv.uiListEntries([]):
    print(entry.name, entry.type, entry.status)

The list contains the groups RibbonTabs, Ribbon, QuickAccess, Toolbar and RibbonSearch. Open tool windows (such as Mesh Healer) and the panels of the selected object appear next to them.

Listing Available Tabs

from meshlib import mrviewerpy as mv

tabs = mv.uiListEntries(['RibbonTabs'])
print("Available tabs:", [t.name for t in tabs])

Example output in MeshInspector 2.5.9:

Available tabs: ['CT', 'Distance Maps', 'Home', 'Inspect', 'Lines', 'Mesh Edit', 'Mesh Repair', 'Nesting', 'Points', 'Select', 'Toolpath', 'Transform', 'View']

Opening a Tab

To open a tab, press its button in RibbonTabs:

from meshlib import mrviewerpy as mv

mv.uiPressButton(['RibbonTabs', 'Mesh Repair'])
mv.Viewer().skipFrames(1)
print("Opened the 'Mesh Repair' tab.")

uiPressButton() waits a few frames by itself; the extra skipFrames(1) makes sure the interface has been redrawn before the next command reads it.

Listing Tools in the Active Tab

After the tab is open, its tools are inside Ribbon:

from meshlib import mrviewerpy as mv

mv.uiPressButton(['RibbonTabs', 'Mesh Repair'])
mv.Viewer().skipFrames(1)
tools = mv.uiListEntries(['Ribbon'])
print("Tools in Mesh Repair:", [t.name for t in tools])

Example output in MeshInspector 2.5.9:

Tools in Mesh Repair: ['##DropDownFill Holes', '##DropDownReduce Noise', '##DropDownSeparate Components', '##DropDownStraighten Boundary', 'Decimate Mesh', 'Fill Holes', 'Fix Tunnels', 'Flip Normals', 'Make Delone', 'Mesh Healer', 'Position Vertices Smoothly', 'Re-mesh', 'Rebuild Mesh', 'Reduce Noise', 'Reorient Mesh', 'Rewrap', 'Separate Components', 'Stitch two Holes', 'Straighten Boundary', 'Subdivide Mesh', 'Unite Close Vertices', 'Unite Many Meshes']

Finding Where a Tool Lives

Ribbon shows only the tools of the open tab, so to find the tab of a tool, open the tabs one by one:

from meshlib import mrviewerpy as mv

TARGET_TOOL = 'Mesh Healer'
found = None

for tab in [t.name for t in mv.uiListEntries(['RibbonTabs'])]:
    mv.uiPressButton(['RibbonTabs', tab])
    mv.Viewer().skipFrames(1)
    if TARGET_TOOL in [e.name for e in mv.uiListEntries(['Ribbon'])]:
        found = tab
        break

if found:
    print(f"Tool '{TARGET_TOOL}' is in tab: {found}")
    print("Path:", ['RibbonTabs', found], "->", ['Ribbon', TARGET_TOOL])
else:
    print(f"Tool '{TARGET_TOOL}' not found.")

Example output:

Tool 'Mesh Healer' is in tab: Mesh Repair
Path: ['RibbonTabs', 'Mesh Repair'] -> ['Ribbon', 'Mesh Healer']

The script leaves the found tab open. A tool can be on several tabs; the script stops at the first one.

Opening a Tool Programmatically

Open the tab first, then press the tool. Most tools need a selected object, so select a mesh in the scene before you run the script.

from meshlib import mrviewerpy as mv

# Step 1: open the tab
mv.uiPressButton(['RibbonTabs', 'Mesh Repair'])
mv.Viewer().skipFrames(1)

# Step 2: start the tool
mv.uiPressButton(['Ribbon', 'Mesh Healer'])
mv.Viewer().skipFrames(1)

print("Tool 'Mesh Healer' launched.")

The Mesh Healer window opens on the right, just as if you clicked the button. Pressing the same tool button again closes the window.

Understanding Path Naming

The names in the tree are not always the captions you see on the Ribbon:

  • Tools are listed by their internal names. The button with the caption Simplify is Decimate Mesh in Ribbon, Remesh is Re-mesh, Auto Repair Mesh is Rebuild Mesh, and Section on the Inspect tab is Object Section.
  • Windows use the title shown on the window. Pressing ['Ribbon', 'Decimate Mesh'] opens a window named Simplify, and ['Ribbon', 'Object Section'] opens a window named Section. Use these names for the parameters, for example ['Section', '<parameter>'].
  • Entries that start with ## are hidden helper names, such as ##DropDownFill Holes for the arrow that opens the drop-down list next to Fill Holes.
  • Names are exact. Case, spaces and hyphens must match.

So always list the entries with uiListEntries() before you press a button or read a value.

Checking Whether a Button Is Available

A button that is unavailable (for example, a tool that needs a selected mesh while nothing is selected) has a status that explains why. Pressing such a button does nothing: the script continues, and only a warning is written to the MeshInspector log. Check the status first:

from meshlib import mrviewerpy as mv

for entry in mv.uiListEntries(['Ribbon']):
    if entry.type == mv.UiEntryType.button and entry.status != 'available':
        print(entry.name, '->', entry.status)

Example output on the Mesh Repair tab with nothing selected:

Decimate Mesh -> disabled: Select exactly one Mesh
Fill Holes -> disabled: Select exactly one Mesh
Flip Normals -> disabled: Select at least one Mesh
Mesh Healer -> disabled: Select exactly one Mesh

Listing a Whole Window at Once

uiListAllEntries() returns every entry of a subtree with its full path, which is handy to explore a tool window:

from meshlib import mrviewerpy as mv

for path, entry in mv.uiListAllEntries(['Mesh Healer']):
    print(path, entry.type, entry.status)

The first lines of the output with the Mesh Healer window open:

['Mesh Healer', '##Auto Repair'] UiEntryType.button available
['Mesh Healer', '##Local Repair'] UiEntryType.button available
['Mesh Healer', 'Disconnected Parts'] UiEntryType.valueUint available
['Mesh Healer', 'Flipped Normals'] UiEntryType.valueUint available
['Mesh Healer', 'Holes'] UiEntryType.valueUint available
['Mesh Healer', 'Repair Resolution'] UiEntryType.valueReal available
['Mesh Healer', 'Repair Selected'] UiEntryType.button available

Customize Consent Preferences

We use cookies and similar technologies, such as local storage. You will find detailed information about all of them under each consent category below.

To learn more about how Google processes personal information, visit: Google privacy policy

Always Active