feat(installer): Maya drag-and-drop installer - #12
Merged
Conversation
Companion to Slice 13 — lets end users install/uninstall the rbfmax plugin by dragging a Python file into the Maya viewport. Files added ----------- - installer/drag_drop_install.py — onMayaDroppedPythonFile hook + install / uninstall via Maya Module System (.mod descriptor written into the user's ~/Documents/maya/modules). Single- version install covers Maya 2022 and 2025 via per-version MAYAVERSION blocks in the .mod file. - installer/package.py — copies built .mll from build-maya-<ver>/bin/Release/ into installer/plug-ins/<ver>/. Strict fail-fast build-missing preflight: exits 1 with a full cmake recipe if either version's .mll is absent. - installer/README.md — Chinese user guide covering both the end- user and developer flows, plus a troubleshooting section. - docs/install.md — repository-level user entry pointing at the installer (so GitHub viewers see the Maya install path without having to download the zip first). Files updated ------------- - README.md — adds a blockquote under Quick Start pointing Maya end users at docs/install.md. - .gitignore — excludes installer/plug-ins/2022/*.mll and installer/plug-ins/2025/*.mll (large build artifacts; users populate them via package.py). Validation ---------- mayapy install + uninstall smoke cycle on Maya 2022 and 2025: - package.py copies .mll : Maya 2022 505.5 KiB / 2025 506.0 KiB - install copies payload + .mod : both versions OK - uninstall deletes .mod + dir : both versions OK - post-uninstall residue check : zero bytes on both versions - build-missing guard : exit 1 with full cmake recipe Design rationale ---------------- - Maya Module System (rather than dropping .mll into the user's plug-ins dir) gives a clean uninstall surface — one .mod file + one directory, both in a user-owned, non-system path. - onMayaDroppedPythonFile is Autodesk's standard drag-drop hook; stable across Maya 2022 / 2024 / 2025 / 2026. - Per-version plug-in subdirectories are selected at Maya runtime via MAYAVERSION blocks in the .mod file — one install script covers all supported versions, no user choice needed. - Scene node purge (deletes mRBFNode + mRBFShape) precedes unloadPlugin during uninstall; Maya refuses unload otherwise. Stacked on top of Slice 13 — must merge after PR #11. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On Windows machines with HOME env var set (Git Bash / MSYS / Cygwin /
WSL commonly set it to Documents), os.path.expanduser('~') returns
C:/Users/<user>/Documents instead of C:/Users/<user>, causing the
installer to write .mod file and module tree to
C:/Users/<user>/Documents/Documents/maya/modules/ — a path Maya never
scans. Installer reported success but plugin never loaded; createNode
fell back to unknown placeholder nodes.
Fix: use cmds.internalVar(userAppDir=True) when inside Maya (Maya uses
SHGetFolderPath independent of HOME env), and USERPROFILE as fallback
outside Maya on Windows (USERPROFILE is the Windows-standard variable
and never modified by Unix tools).
Discovered during Slice 13 GUI verification — user's HOME was set to
Documents by a prior Git Bash install; mayapy automated smokes did not
catch this because mayapy in CI-style setups typically runs with a
cleaner env.
On Windows, even after cmds.unloadPlugin('rbfmax_maya'), the .mll file
is held by Maya's DLL loader (FreeLibrary may defer). shutil.rmtree
fails with [WinError 5] Permission Denied. Prior to this fix,
reinstall flow threw a PermissionError that aborted _install, and
uninstall reported 'completed with warnings' while silently leaving
the .mll behind (misleading because autoload would still fire next
launch if .mod was recreated).
Changes:
- Add _safe_rmtree with retry+sleep (Windows DLL handle release lag)
- Add _force_overwrite_tree as file-level fallback when rmtree fails
- After unloadPlugin, gc.collect() + time.sleep(0.5) to encourage
FreeLibrary completion
- _copy_payload falls back to file-level overwrite instead of aborting
- _uninstall dialog now distinguishes clean uninstall vs partial
(with explicit 'restart Maya to finish cleanup' instruction)
Fundamental Windows limitation remains: fully hot reinstall (same
session, new .mll replacing locked .mll) is not achievable and not
attempted. Hot uninstall + cold reinstall (after Maya restart) is
the supported path.
Discovered during Slice 13 GUI verification when user reinstalled
in same session.
8 tasks
891458249
added a commit
that referenced
this pull request
Apr 23, 2026
* build(cmake): bump VERSION 1.1.0 -> 1.2.0 (Phase 2B close-out) Phase 2B delivered Viewport 2.0 visualization (Slice 13 Path B), HM-1 per-center viridis coloring (Slice 14), HM-2 prediction-field grid + X-Ray (Slice 15), and a drag-drop installer (PR #12 with two follow-ups). No Phase 1 or Slice 10A/11/12 touches; Phase 2A invariants preserved throughout. Top-level CMakeLists.txt project VERSION bumps to 1.2.0. maya_node/CMakeLists.txt RBFMAX_MAYA_PLUGIN_VERSION follows; this value is injected into plugin_info.hpp via configure_file and bound into the .mll via MFnPlugin::registerNode's 4th-arg version string. Verified via mayapy: cmds.pluginInfo('rbfmax_maya', q=True, version=True) returns '1.2.0' on both Maya 2022 and 2025 builds. * docs(changelog): add [1.2.0] entry — HM-1 + HM-2 + X-Ray + installer * docs(devlog): record Slice 16 — Phase 2B retrospective + v1.2.0 ~145 LOC Slice 16 entry covering Phase 2B scope summary (5 PRs merged), quantitative summary (LOC / tests / F-stops), invariant tracking (Phase 1 / mRBFNode compute / mRBFShape R-44 / Slice 13 override config / Slice 14 viridis LUT — all zero-touch across the phase), tech-debt status table (T-17/R-45 resolved within Phase 2B; T-10/T-16/T-18/T-19/T-20 + dev_unload.py rolled to Phase 2C), Phase 2B reviewer-discipline summary (Rules 3/4 exercised + Rule 5 formalization from Slice 13), Phase 2C entry conditions (4 specific deliverables), Slice 16-specific validation (139/180/8 smokes/version injection assertion), post-merge tag plan (v1.1.0 retro on d624c79 + v1.2.0 on the merge commit). Also bumps README.md version badge to 1.2.0 (release link reference). --------- Co-authored-by: 891458249 <d891458249@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Companion to Slice 13 (PR #11, now merged) — a drag-and-drop installer so Maya artists can install / uninstall the
rbfmax_mayaplugin by dragging a single Python file into the Maya viewport.This PR was originally planned to stack on the Slice 13 branch, but Slice 13 merged to
mainduring preparation, so it is now a standard PR againstmain. Diff shows exactly 6 files / +769 lines — no Slice 13 content duplicated.Design
.modfile + standalone directory under~/Documents/maya/modules/) rather than dropping.mlldirectly into the user's plug-ins dir. Benefits:.mod+ one directory, both in user-owned paths (no admin privileges required)MAYAVERSIONblocks in the.modfileonMayaDroppedPythonFile— Autodesk's standard drag-drop hook; stable across Maya 2022 / 2024 / 2025 / 2026installer/plug-ins/2022/andinstaller/plug-ins/2025/(the.mllbinaries themselves are gitignored;installer/package.pycopies them frombuild-maya-<ver>/bin/Release/)mRBFNode+mRBFShapenodes first; Maya refusesunloadPluginotherwiseFiles
installer/drag_drop_install.pyinstaller/package.py.mllfrombuild-maya-<ver>/with strict fail-fast guardinstaller/README.mddocs/install.mdREADME.mddocs/install.md.gitignoreinstaller/plug-ins/*.mll(build artifacts)Validation — mayapy install + uninstall cycle
package.pycopies.mll.mod(dual-version blocks).modpackage.pybuild-missing guardManual verification (pending, before merge)
python installer/package.pyon a dev machine with both builds freshinstaller/drag_drop_install.pyinto Maya 2022 GUI viewport → click "安装" → verify plugin loads andcreateNode mRBFNode+createNode mRBFShapesucceed~/Documents/maya/modules/Test plan
package.pystrict guard — exit 1 when build missing, exit 0 + copies on all-presentMaya 2022 install via mayapy (writes
.mod+ payload)Maya 2022 uninstall via mayapy (zero residue)
Maya 2025 install via mayapy (writes
.mod+ payload)Maya 2025 uninstall via mayapy (zero residue)
GUI drag-drop install on Maya 2022 (user-side, before merge)
GUI drag-drop install on Maya 2025 (user-side, before merge)
Verified on Windows machine with HOME=Documents env var (reproduced double-Documents bug, confirmed fix produces single-Documents path via cmds.internalVar)