Skip to main content

A multi-application marking menu and UI framework for Maya, 3ds Max, and Blender.

Project description

Tests License: LGPL v3 Version

Tentacle

A Qt-based marking menu (pie menu) for DCC apps, with a full toolkit for Maya.

Tentacle gives you a fast, gesture-driven launcher for tools and commands inside Autodesk Maya, 3ds Max, and Blender. Press a hotkey, flick the mouse toward a wedge, release — and the tool runs. Submenus open along the gesture path, so common multi-step actions become single muscle-memory motions.

It ships with 60+ pre-built Maya tool panels (modeling, UVs, materials, rigging, animation, rendering, …) covering most day-to-day work. The Blender and 3ds Max entry points are scaffolded but do not yet ship a slot library.

Demo


Table of contents


Why Tentacle

  • Gesture-first. Activate from anywhere, never break flow to hunt through Maya's shelf or menu bar.
  • Convention over configuration. A .ui file plus a Python class with matching method names (b005def b005(...)) is all it takes to add a tool.
  • Composable. UIs and slots are decoupled — swap the front-end without touching command logic.
  • Battery-included for Maya. Ships with curated panels for nearly every DCC discipline — see tentacle/slots/maya/.

Install

Tentacle is published to PyPI as tentacletk. Install into your DCC's bundled Python (Maya example):

"C:/Program Files/Autodesk/Maya2025/bin/mayapy.exe" -m pip install tentacletk

Or use the mayapy package manager (give your Maya version, press 1, type tentacletk).

Requirements: Python 3.9+, Qt via qtpy (PySide2 or PySide6), and the upstream toolkit packages pythontk, uitk, and mayatk (installed automatically as dependencies).

Launch

Add to your Maya userSetup.py:

from maya.utils import executeDeferred

def start_tentacle():
    from tentacle import TclMaya
    TclMaya(key_show="F12")  # Hold F12 to summon the marking menu

executeDeferred(start_tentacle)

key_show accepts either bare keys ("F12", "Space") or fully-qualified Qt names ("Key_F12").

To launch standalone for development:

python -m tentacle.tcl_maya

How it works

flowchart TD
    A["TclMaya<br/>tentacle/tcl_maya.py"] --> B["MarkingMenu<br/>uitk"]
    B --> C["Switchboard<br/>uitk — loads .ui files,<br/>binds widgets to slots"]
    C --> D["UI files<br/>tentacle/ui/*.ui"]
    C --> E["Slot classes<br/>tentacle/slots/maya/*.py"]
    B --> F["Overlay<br/>uitk — gesture path drawing"]
    A --> G["MayaUiHandler<br/>mayatk — Maya host integration"]

TclMaya is a thin Maya-flavored subclass of uitk.MarkingMenu. All the heavy lifting — input state machine, gesture overlay, dynamic UI loading, slot binding — lives in uitk. Tentacle's job is to provide:

  1. The Maya host wiring (parent window, UI handler).
  2. Default key/mouse-button → start-menu bindings.
  3. The library of .ui files and matching slot classes.

Default key bindings

With the default key_show="F12":

Gesture Opens
F12 hud#startmenu
F12 + Left Mouse cameras#startmenu
F12 + Middle Mouse editors#startmenu
F12 + Right Mouse main#startmenu
F12 + Left + Right (chord) maya#startmenu

Inside any menu, Ctrl+Shift+R repeats the last command. Override the bindings or shortcut via Customization.

Marking-menu interaction

  1. Press and hold the activation key — a radial menu appears centered on the cursor.
  2. Drag toward a wedge. A trailing path is drawn so you can see your gesture history.
  3. If the wedge has a submenu, it opens along the path — keep dragging.
  4. Release over a leaf wedge to invoke its slot.

Tap-and-release without dragging shows the menu pinned, so you can click items directly.

UI ↔ slot wiring

Tentacle relies on naming conventions, enforced by tests in test/test_ui_integrity.py and test/test_slot_integrity.py:

Convention Example
UI file name → menu identity materials.ui, main#startmenu.ui
Widget objectName → slot method b005def b005(self)
Optional setup hook def b005_init(self, widget)
Header section initializer def header_init(self, widget)
Info button (i###) accessibleName → submenu UI name i000.accessibleName = "polygons"

Widget prefixes carry semantic meaning, recognized by Switchboard:

Prefix Widget kind
b### QPushButton
tb### Tool button (with option box)
cmb### QComboBox / dropdown
list### Expandable list
chk### Checkbox
lbl### Label (clickable)
i### Info / submenu router

Project layout

tentacle/
├── tcl_maya.py            # Maya entry point — TclMaya class
├── tcl_max.py             # 3ds Max wrapper (TclMax)
├── tcl_blender.py         # Blender wrapper (TclBlender)
├── slots/
│   ├── _slots.py          # Base Slots class — repeat-last-command shortcut
│   └── maya/
│       ├── _slots_maya.py # SlotsMaya base for all Maya slot classes
│       ├── materials.py   # MaterialsSlots — example slot module
│       ├── animation.py
│       └── ... (~55 modules covering all DCC disciplines)
└── ui/
    ├── *.ui               # Top-level menu definitions
    ├── *#startmenu.ui     # Wedges for the radial start menus
    ├── *#submenu.ui       # Submenu panels reached via i### routers
    └── maya_menus/        # Maya-specific submenus

Each slot module pairs with one or more .ui files of the same basename. The Switchboard resolves the pair at load time.

Adding your own menu

Minimal recipe to add a new tool panel:

  1. Create the UI in Qt Designer and save as tentacle/ui/my_tools.ui. Add buttons and set their objectName to follow the prefix convention (b000, b001, …).

  2. Create the slot class at tentacle/slots/maya/my_tools.py:

    from tentacle.slots.maya._slots_maya import SlotsMaya
    
    class MyToolsSlots(SlotsMaya):
        def __init__(self, switchboard):
            super().__init__(switchboard)
            self.ui = self.sb.loaded_ui.my_tools
    
        def b000_init(self, widget):  # optional setup hook
            widget.setToolTip("Run the thing.")
    
        def b000(self):
            print("Hello from my_tools b000")
    
  3. Wire it into a start menu by adding an info-button (i###) to e.g. main#startmenu.ui whose accessibleName equals "my_tools". Or bind it directly to a key via the bindings argument to TclMaya.

The package's tests will fail if a UI/slot pair is mismatched, so structural mistakes are caught early.

Customization

TclMaya accepts overrides for activation key, bindings, slot directory, and log level:

from tentacle import TclMaya

TclMaya(
    key_show="F11",                   # change activation key
    slot_source="my_studio/slots",    # use a custom slot library
    log_level="DEBUG",                # uitk MarkingMenu log verbosity
    bindings={                        # fully replace the default bindings
        "Key_F11": "main#startmenu",
        "Key_F11|RightButton": "cameras#startmenu",
    },
)

User-facing preferences (shortcut for Repeat Last Command, theming, etc.) can be edited in-app via the Preferences panel — see slots/maya/preferences.py.

Platform support

DCC Status
Maya 2025+ Full — entry point, ~55 slot modules, all default menus wired.
Blender Wrapper class only (TclBlender). No bundled slot library.
3ds Max Wrapper class only (TclMax). No bundled slot library.

Contributions of Blender / Max slot suites are welcome.

Development

Clone and install in editable mode:

git clone https://github.com/m3trik/tentacle
pip install -e ./tentacle

Run the structural test suite:

cd tentacle
python -m pytest test/

The CI workflow (.github/workflows/tests.yml) runs:

  • test_package.py — package metadata sanity
  • test_slot_integrity.py — widget-name ↔ slot-method binding coverage
  • test_ui_integrity.py — UI/slot file pairing
  • Module-specific suites (e.g. test_rendering.py)

For ad-hoc reproductions, drop scripts into test/temp_tests/ (gitignored from the regular run).

Further reading

  • API_REGISTRY.md — auto-generated, exhaustive list of every public class/method with file:line links.
  • API_CHANGES.md — diff vs. previous registry refresh.
  • CHANGELOG.md — notable behavioral and feature changes.
  • CLAUDE.md — engineering conventions for contributors / agents.
  • Upstream packagespythontk (utilities), uitk (Switchboard + MarkingMenu engine), mayatk (Maya helpers).

License

Tentacle is released under the LGPL v3.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tentacletk-0.10.80-py3-none-any.whl (243.1 kB view details)

Uploaded Python 3

File details

Details for the file tentacletk-0.10.80-py3-none-any.whl.

File metadata

  • Download URL: tentacletk-0.10.80-py3-none-any.whl
  • Upload date:
  • Size: 243.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for tentacletk-0.10.80-py3-none-any.whl
Algorithm Hash digest
SHA256 cf8b1b47cf058adc5da05beaae8fafbd134a10303bde0258443f98a59d824cd3
MD5 b984cfa2f9bf5300e52fc109be3e540e
BLAKE2b-256 12d75cbeaeb80132d061228c13bad47f6af359c95fb58b97ebce10321a91c33e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page