pystartup.ms
is a MAXScript file that adds to 3ds Max the ability to startup
pip packages when they are present in the Python environment.
The pystartup.ms file must be copied to the 3dsMax startup directory.
To be automatically loaded by this mechanism, a pip package must implement the 3dsMax startup entry point.
This is done by adding a line like this in the setup.py file of a pip package:
entry_points={'3dsMax': 'startup=yourpackagename:startup'},
where yourpackagename
is the name of the package (i.e. import
yourpackagename works) and startup is an exported function of
yourpackagename that will be called during startup.
Most if not all Python samples in this repo implement this entry point. transformlock's setup script can be taken as en example as well as transformlock's __init__.py.
The pystartup.ms code consists in a call to python.execute that runs a small Python program.
if isProperty python "execute" then (
python.execute ("def _python_startup():\n" +
" try:\n" +
" import pkg_resources\n" +
" except ImportError:\n" +
" print('startup Python modules require pip to be installed.')\n" +
" return\n" +
" for dist in pkg_resources.working_set: \n" +
" entrypt = pkg_resources.get_entry_info(dist, '3dsMax', 'startup')\n" +
" if not (entrypt is None):\n" +
" try:\n" +
" fcn = entrypt.load()\n" +
" fcn()\n" +
" except:\n" +
" print('skipped package startup for {}, startup not working'.format(dist))\n" +
"_python_startup()\n" +
"del _python_startup")
)
Here is the Python code used for the entry points:
def _python_startup():
try:
import pkg_resources
except ImportError:
print('startup Python modules require pip to be installed.')
return
for dist in pkg_resources.working_set:
entrypt = pkg_resources.get_entry_info(dist, '3dsMax', 'startup')
if not (entrypt is None):
try:
fcn = entrypt.load()
fcn()
except:
print(f'skipped package startup for {dist}, startup not working')
_python_startup()
del _python_startup
pkg\_resources
is part of setuptools
and comes installed with pip. It allows this script to discover packages present
in the environment.
The script first imports pkg_resources.
import pkg_resources
it then iterates all packages in the environment:
for dist in pkg_resources.working_set:
It then tries to find the 3dsMax startup entry point in the package:
entrypt = pkg_resources.get_entry_info(dist, '3dsMax', 'startup')
And if this works, loads and executes the entry point:
if not (entrypt is None):
try:
fcn = entrypt.load()
fcn()
except:
print(f'skipped package startup for {dist}, startup not working')