AXE Proxy builds invisible clickable outlines over your rig controls directly in VP2. Animators hover to reveal them, click to select — the underlying rig control gets selected transparently. No rig modifications, no extra transforms, no scene clutter that survives the session.
For each selected control, AXE Proxy reads the NURBS curve shapes under that transform. If the control has multiple curves, the one with the largest bounding box is selected as the primary shape. The curve's CVs are sampled in local space into a point array.
The control's viewport draw color is read from Maya's override system. The color is mildly boosted (factor 1.1) to ensure the proxy outline reads clearly over the curve it mirrors. Controls with no color override fall back to white.
A custom axeProxyShape C++ node (MPxLocatorNode with a DrawOverride) is created as a sibling shape under the control's transform — not a child transform. This is the same DAG parent, so the proxy inherits the control's world matrix automatically with zero rig overhead. The point data, color, line width, and target control path are stored as attributes directly on the node.
All proxy shapes are added to the AXE_ProxyLayer display layer (created automatically, type Normal). This lets you show/hide all proxies in a single click from the Layer Editor, and keeps them isolated from the rest of the scene's display logic.
A Qt event filter (hover_tracker) watches MouseMove events on the VP2 viewport widget and writes the cursor position (X, Y in screen pixels) to optionVars at ~30fps. The C++ draw override reads these optionVars each frame to compute whether the cursor is within the proximity radius of each proxy, and adjusts draw opacity accordingly.
A Maya scriptJob fires on every SelectionChanged event. If the newly-selected nodes contain any axeProxyShape parents, the job transparently replaces them with their target rig controls. The animator never sees the proxy selected — they always end up with the real control. The redirect only fires for viewport interactions, not Graph Editor or Outliner selections.
AXE_ProxyLayer display layer and the axeProxy_* object sets, both of which are cleaned up on Remove All.| Control | What it does |
|---|---|
| ▶ Build Selected | Builds proxy shapes for the current Maya selection. Only transforms with NURBS curve shapes are processed — mesh controls, joints, and non-curve shapes are silently skipped. Already-proxied controls are also skipped (use Rebuild for those). Reports Built / Skipped / Failed counts via Maya's viewport toast. |
| ↺ Rebuild Selected | Removes existing proxies from the selected controls then rebuilds them fresh. Use after editing the rig's curve shapes or after a scale/position change that has made the proxy shape stale. |
| ✕ Remove All Proxies | Deletes all axeProxyShape nodes from the scene, restores NURBS curve visibility, removes the axeProxy_Master set, and cleans up the AXE_ProxyLayer display layer if empty. The rig is left untouched. Fully undoable. |
| Sets panel | See the Sets section below. |
| Nurbs Curves — Show / Hide | Toggles visibility on the NURBS curve shapes of every proxied control only — it does not touch controls without proxies. Use Hide after building to get a clean viewport showing only the proxy outlines. |
| Line Width slider | Sets the pixel width of all proxy shape outlines globally. Range 0.5–8.0px. The label updates live while dragging; the Maya call and undo chunk are written only on mouse release to keep the undo queue clean. Persists via optionVar so new proxies built after the change will inherit the last-used value. |
| X-Ray toggle | When ON, proxy outlines draw through geometry (depth test disabled) — useful for controls that are buried inside a mesh, like spine or hip controls on a skinned character. When OFF, outlines are depth-tested and will be occluded by geometry in front of them. Persists via optionVar. |
| Proximity slider | The screen-space radius (in pixels) within which the cursor must be for a proxy to become visible. At 0 the proxies are always visible (proximity off). When Interaction is enabled, the default snaps to 150px on activation. Drag to taste — smaller values require more precise hovering, larger values make larger click targets. Persists via optionVar. |
| Enable / Disable (Interaction) | Toggles the selection redirect scriptJob and the hover event filter on and off. When Disabled: proxies are still visible but clicking them selects the proxy transform, not the control. Proximity is reset to 0 (always visible) so you can inspect the proxies. When Enabled: clicking a proxy transparently selects the underlying rig control, and proximity is restored to the last-used value. |
The three display controls — Line Width, X-Ray, and Proximity — all work the same way architecturally: they write to a Maya optionVar and then iterate over every axeProxyShape in the scene to apply the value. New proxies built after a change inherit the stored optionVar value automatically, so you don't need to re-apply settings after adding controls.
| Setting | OptionVar key | Default | Notes |
|---|---|---|---|
| Line Width | axeProxyLineWidth |
2.0 px | Clamped to 0.5–8.0. Controls edge thickness in both normal and X-Ray modes. |
| X-Ray Mode | axeProxyXrayMode |
Off | Boolean. Best used on buried controls — spine, pelvis, COG, etc. |
| Proximity Radius | axeProxyProximityRadius |
0 (off) | Pixel radius in screen space. 0 = always visible. Set to 150 on Interaction Enable. |
AXE_ProxyLayer is set to Normal display type, not Reference or Template. Fix with: cmds.setAttr("AXE_ProxyLayer.displayType", 0)Named sets let you group controls for quick recall and targeted rebuilds. They're stored as Maya objectSet nodes tagged with an axeProxySet attribute — so they survive save/open cycles and work correctly with referenced rigs.
| Action | What it does |
|---|---|
| Create (with name) | Type a name in the text field and click Create with controls selected. Creates a Maya objectSet named axeProxy_YourName. If the set already exists, new controls are added without duplicating existing ones. |
| Master set | Created automatically after every Build. Contains every control that was built successfully in that operation. If the Master set already exists, new controls are merged in (deduplicated). Useful for rebuilding the entire rig's proxies in one click. |
| Select from dropdown | Selects all controls in the chosen set. Resolves referenced nodes gracefully — if a control was renamed or its namespace changed, the tool attempts short-name and wildcard matching before giving up. |
| Build from set | Selects the set's controls then calls Build Selected. Efficient for per-region rebuilds (e.g. rebuild just the Face set after tweaking face curves). |
Body, Face, Hand_L, Hand_R, Fingers_L. Spaces are converted to underscores internally. Sets are sorted alphabetically in the dropdown.Two lightweight components handle the interactive behaviour. Both are intentionally narrow in scope — they do the minimum necessary and get out of the way.
A Qt application-level event filter installed on Maya's viewport widget classes (QmayaGLWidget, QOpenGLWidget, etc). On every MouseMove event inside a viewport, it writes the cursor X/Y to optionVars axeProxyCursorX / axeProxyCursorY and requests a viewport refresh — throttled to 30fps to avoid hammering VP2. The C++ draw override reads these vars each draw call to compute hover state. The filter is stored on __main__ so it survives Python module reloads without leaking duplicate instances.
A single scriptJob on the SelectionChanged event. When fired, it checks if the focused panel is a model panel — if not (e.g. Graph Editor, Outliner, Channel Box), it exits immediately without touching selection. For viewport selections, it walks the selected transforms, checks each for an axeProxyShape sibling, reads the stored targetControl attribute, resolves the path (handling namespace changes and renames), and re-selects the final control list. A _redirecting guard flag prevents the re-select from triggering a recursive callback loop.
Two common causes:
No NURBS curve shapes. Only controls with NURBS curve shapes are buildable. If your rig uses mesh controls, joint-only pickers, or locators, those will always be skipped. Check via Outliner — expand the control's transform and look for a nurbsCurve shape node.
Already proxied. Controls that already have an axeProxyShape node are skipped on Build. If you want to refresh them, use Rebuild Selected instead.
A third case: the curve is degenerate — all CVs coincide at a single point (e.g. a collapsed curve used as an annotation or tag). The tool checks for this and skips it. Fix the curve in the rig file if you need that control proxied.
The proxy shape is a sibling shape under the control's transform. It inherits the control's world matrix automatically — so ordinarily it sits exactly on the curve. Misalignment usually means one of:
The curve has a shape-level transform offset. If a curve shape has a non-identity intermediateObject upstream, or if the CV positions are in a different space than expected, the sampled points will be wrong. This is rare on clean mGear rigs but can happen with imported or converted curves.
The rig root has been moved after proxies were built. The proxy's point data is in the control's local space, so moving the rig root doesn't misalign it — they move together. But if the control itself was repositioned after building (e.g. a guide reposition), rebuild to pick up the new CV positions.
Interaction is not enabled, or the selection redirect scriptJob has died. Check the Interaction section of the UI — the status badge should read ON. If it shows OFF, click Enable.
If the badge shows ON but selection is still wrong, the scriptJob may have been killed by a Maya error or a forced scene change. Disable then re-enable Interaction to restart it.
Also confirm the panel in focus is a 3D model panel. The redirect intentionally ignores non-viewport selections — so clicking in the Outliner or Graph Editor will select the proxy node directly. This is correct behaviour.
Proximity of 0 means always visible — the hover fade is disabled. If you want hover-to-reveal behaviour, make sure the Proximity slider is set above 0 (default 150px when Interaction is enabled). If you moved it to 0 manually, drag it back up.
If proximity is above 0 but proxies are still always visible, the hover tracker may not be receiving cursor events from the viewport. This can happen if another application event filter is intercepting mouse events before they reach the viewport widget. Try disabling and re-enabling Interaction.
The Hide Nurbs Curves button hides curve shapes by setting visibility = False on each shape individually — not via display layer. The axeProxyShape nodes are a different shape type and are unaffected by this operation.
If your proxies are also disappearing, the most likely cause is that the display layer AXE_ProxyLayer is set to Template or Reference. In that case the layer overrides each member's visibility regardless of shape type. Fix: in the Layer Editor, right-click AXE_ProxyLayer → Attributes → set Display Type to Normal. Or via script: cmds.setAttr("AXE_ProxyLayer.displayType", 0)
The C++ plugin axeProxyPlugin.mll is not loaded in the current Maya session. The Python side of the tool can open the UI but cannot build or display any proxies without it.
Check that the axeProxy.mod file is in a directory Maya scans for modules (usually Documents/maya/modules/ on Windows). The mod file tells Maya where to find the .mll. After ensuring the mod is in place, either restart Maya or manually load the plugin via Plug-in Manager (Windows → Settings/Preferences → Plug-in Manager → find axeProxyPlugin.mll → tick Loaded).
Yes — with one important rule: build proxies in the referencing scene, not inside the rig file itself. Open your shot or asset scene where the rig is referenced in, select the controls normally, and build.
The tool stores control paths including namespace prefixes (e.g. char_rig_RN:spine_C0_ctl). On scene open, the selection redirect resolves these paths with a short-name fallback and a wildcard namespace search, so renamed namespaces are handled gracefully.
If controls go missing after a namespace change, the set members will still point to the old paths. Remove and re-add them to the set with the new namespace. The proxy shapes themselves can be rebuilt from the updated paths via Rebuild Selected.
Build and Remove are both wrapped in undo chunks (axeProxy_build and axeProxy_remove) and are fully undoable with Ctrl+Z. If undo seems to not work, check the Script Editor for errors during the operation — a failed step can leave the undo chunk open, which prevents the queue from registering correctly.
The curves visibility change (Show/Hide) is also undoable as a separate chunk. If you hid curves and then removed proxies, you may need to undo twice to restore both.
Check in order:
VP2 must be active. The draw override only fires under Viewport 2.0. If you're running Legacy Viewport or High Quality Rendering, switch to Renderer → Viewport 2.0.
AXE_ProxyLayer visibility. The layer may be hidden. In the Layer Editor, make sure the V column is checked for AXE_ProxyLayer.
Proximity is 0 and proxies are transparent. At proximity 0, proxies are always visible at full opacity. If they're still invisible, check the line width — at 0.5px on a high-DPI display they can be nearly invisible. Bump line width up to 3–4px to confirm the shapes are actually there.
Plugin not loaded. Without the C++ plugin, the draw override doesn't run. Check for the banner at the top of the UI.
The hover tracker forces a viewport refresh at up to 30fps whenever the cursor is inside a VP2 panel. This is necessary for the proximity fade to feel responsive, but it does mean VP2 is redrawing constantly while you hover — even if nothing in the scene has changed.
On complex scenes with expensive shaders or many lights this can be noticeable. Options:
Disable Interaction when not picking. The hover tracker only runs when Interaction is enabled. Toggle it off during playback review or heavy scrubbing, then back on when you need to pick controls.
Set proximity to 0. Without proximity, the draw override is a cheap static draw and no hover-driven refreshes are needed.
Use a dedicated picker viewport. Some animators open a small, isolated panel at a low resolution specifically for control picking, keeping the main viewport free for playback. Proxies only refresh the panel the cursor is in.
Not currently. The curve sampler specifically looks for nurbsCurve shape nodes under the control transform. Mesh controls and locators are silently skipped.
The reason is practical: NURBS curve CVs give a clean, lightweight point array that directly represents the intended control shape. Mesh controls would require edge extraction or bounding-box approximation, which is more complex and produces inferior results. This is on the roadmap but not in v0.2.
Workaround for mesh controls: parent a NURBS curve (matched to the mesh's outline) under the control transform. AXE Proxy will then build from that curve while leaving the mesh visible normally.
Settings are stored as Maya optionVars and persist across sessions in the Maya preferences. If they're resetting, the most likely cause is that your Maya preferences directory is being wiped or reset on launch (e.g. by a studio pipeline tool that resets prefs to a clean baseline). Check with your pipeline TD if you're in a managed environment.
You can also set defaults at the start of a session via the Python API — add the following to your userSetup.py after the tool loads:
import axe_proxy; axe_proxy.set_line_width(3.0); axe_proxy.set_proximity_radius(150)
All UI actions are thin wrappers over a clean Python API. You can use these directly from the Script Editor, shelf buttons, or pipeline scripts.
built, skipped, failed lists.True = show, False = hide.True = depth test disabled. Persists via optionVar.0 = always visible. Persists via optionVar.["Body", "Face", "Hand_L"]).import axe_proxy; axe_proxy.build()