### Start Quick Preview Tool
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/quickpreview/README.md
Import and start the quickpreview tool from the 3ds Max listener window.
```python
import quickpreview
quickpreview.startup()
```
--------------------------------
### Startup Command for Renameselected Tool
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/renameselected/README.md
Use this command in the 3ds Max listener to start the renameselected tool. If installed as a package, it starts automatically.
```python
import renameselected
renameselected.startup()
```
--------------------------------
### Python Startup Script for Package Initialization
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/doc/pluginpackage.md
This Python script initializes installed packages by loading entry points registered for '3dsMax' and 'startup'. It requires pip to be installed and handles potential errors during loading.
```python
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, '3ds Max', 'startup')
if not (entrypt is None):
try:
fcn = entrypt.load()
fcn()
except Exception as e:
print(f'skipped package startup for {dist} because {e}, startup not working')
```
--------------------------------
### Initialize Z-Depth Channel Module
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Call this function to start the zdepthchannel module. This is typically done from the 3ds Max listener window or automatically during 3ds Max startup if installed as a package.
```python
import zdepthchannel
zdepthchannel.startup()
```
--------------------------------
### Start Thread Progress Bar
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/threadprogressbar/README.md
Import and start the threadprogressbar module from the 3ds Max listener.
```python
import threadprogressbar
threadprogressbar.startup()
```
--------------------------------
### Import and Start Speedsheet Tool
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/speedsheet/README.md
This snippet shows how to import the speedsheet package and initiate its startup function from the 3ds Max listener window.
```python
import speedsheet
speedsheet.startup()
```
--------------------------------
### Iterating Through Installed Packages
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/pystartup/README.md
This loop iterates over all packages currently available in the Python environment, allowing the script to check each one for the startup entry point.
```python
for dist in pkg_resources.working_set:
```
--------------------------------
### Python Startup Script Logic
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/pystartup/README.md
The core Python script that iterates through installed packages and loads any that implement the '3dsMax' startup entry point. It relies on pkg_resources from setuptools.
```python
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()
de_python_startup
```
--------------------------------
### Start Worker and Connect Signal
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/threadprogressbar/README.md
Instantiate the Worker thread, start it, and connect its progress signal to the progress bar's setValue function.
```python
# start the worker
self.worker = Worker()
self.worker.progress.connect(pb.setValue)
self.worker.start()
```
--------------------------------
### MAXScript to Execute Python Startup Code
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/pystartup/README.md
This MAXScript code executes a Python script that discovers and runs '3dsMax' entry points from installed pip packages. It ensures that packages implementing the startup mechanism are loaded when 3ds Max starts.
```maxscript
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")
)
```
--------------------------------
### Install reloadmod Package
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/reloadmod/README.md
Install the reloadmod package using pip. Ensure you are in the 3ds Max Python environment directory and use the correct path to the package.
```bash
cd $maxroot/Python37
Python.exe -m pip install --user /path/to/reloadmod
```
--------------------------------
### MaxScript Example for Z-Depth Rendering
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/mxs2py/README.md
This MaxScript code demonstrates rendering a scene and extracting Z-depth information to create voxel boxes with specific positions and wire colors based on pixel data.
```maxscript
renderers.current = Default_Scanline_Renderer()
delete $VoxelBox*
rbmp = render outputsize:[32,32] channels:#(#zdepth) vfb:off
z_d = getchannelasmask rbmp #zdepth
progressstart "Rendering Voxels..."
for y = 1 to rbmp.height do
(
if not progressupdate (100.0 * y / rbmp.height) then exit
pixel_line = getpixels rbmp [0,y-1] rbmp.width
z_line = getpixels z_d [0,y-1] rbmp.width
for x = 1 to rbmp.width do
(
b = box width:10 length:10 height:(z_line[x].value/2)
b.pos = [x*10,-y*10,0]
b.wirecolor = pixel_line[x]
b.name = uniquename "VoxelBox"
)--end x loop
)--end y loop
progressend()
```
--------------------------------
### Start Progress Indicator
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Initializes a progress indicator, typically displayed in the status bar, with a custom caption to show the user the progress of a long-running operation.
```python
rt.progressStart("Rendering Voxels...")
```
--------------------------------
### Starting Socket.IO Client in a Separate Thread
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/socketioclient/README.md
This snippet shows how to initiate the Socket.IO connection process in a separate thread to prevent blocking the main 3ds Max UI thread. The `connect_socketio` function is executed in a new thread.
```python
x = threading.Thread(target=connect_socketio)
x.start()
```
--------------------------------
### npm Package Dependencies for Socket.IO App
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/socketioclient/README.md
This JSON file lists the necessary npm packages, express and socket.io, required for the Socket.IO chat application. Ensure these dependencies are installed using 'npm install'.
```json
{
"name": "socket-chat-example",
"version": "0.0.1",
"description": "my first socket.io app",
"dependencies": {
"express": "^4.17.3",
"socket.io": "^4.4.1"
}
}
```
--------------------------------
### Record Object Names at Animation Start
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/speedsheet/README.md
This code captures the names of all currently selected objects at the beginning of the animation range and writes them to the output file.
```python
with pymxs.attime(rt.animationRange.start):
objdump = ", ".join(map(lambda x: x.name, list(rt.selection)))
output_file.write(
f"Object(s): {objdump}\n")
```
--------------------------------
### Get 3ds Max Main Window
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/pyconsole/README.md
Retrieves the main 3ds Max window, which is a Qt window, to allow for docking and manipulation of other Qt widgets.
```python
main_window = GetQMaxMainWindow()
```
--------------------------------
### Iterate Through Animation Frames
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/speedsheet/README.md
This loop iterates through each frame of the animation range, from the start to the end, to calculate object speed for each frame.
```python
for t in range(int(rt.animationRange.start), int(rt.animationRange.end)):
```
--------------------------------
### Uninstall Individual HowTo Package (Manual)
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/doc/uninstall.md
Manually uninstall a specific HowTo package. The package name should follow the format 'packagename-autodesk'. Ensure your current directory is set to the Python installation folder (e.g., maxinstallationfolder/Python37) before running this command.
```bash
# current directory needs to be maxinstallationfolder/Python37:
./python.exe -m pip uninstall reloadmod-autodesk
```
--------------------------------
### End Progress Display
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Closes the progress indicator that was previously started, signaling the completion of the operation.
```python
rt.progressEnd()
```
--------------------------------
### Python Translation of MaxScript Z-Depth Rendering
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/mxs2py/README.md
This Python code is a mechanical translation of the provided MaxScript example, utilizing the pymxs library for interaction with 3ds Max. It requires the mxsshim.py module for emulation of MaxScript constructs.
```python
'''Converted from MAXScript to Python with mxs2py'''
from pymxs import runtime as rt
import mxsshim
rt.renderers.current = rt.default_scanline_renderer()
rt.delete(mxsshim.path("$VoxelBox*"))
rbmp = rt.render(outputsize=rt.point2(32, 32), channels=rt.array(rt.name("zdepth")), vfb=False)
z_d = rt.getchannelasmask(rbmp, rt.name("zdepth"))
rt.progressstart("Rendering Voxels...")
for y in range(int(1), 1 + int(rbmp.height)):
if not rt.progressupdate(100.0 * y / rbmp.height):
break
pixel_line = rt.getpixels(rbmp, rt.point2(0, y - 1), rbmp.width)
z_line = rt.getpixels(z_d, rt.point2(0, y - 1), rbmp.width)
for x in range(int(1), 1 + int(rbmp.width)):
b = rt.box(width=10, length=10, height=(z_line[x - 1].value / 2))
b.pos = rt.point3(x * 10, -y * 10, 0)
b.wirecolor = pixel_line[x - 1]
b.name = rt.uniquename("VoxelBox")
# end x loop
# end y loop
rt.progressend()
```
--------------------------------
### Uninstall Pip (Manual)
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/doc/uninstall.md
Manually uninstall pip in user mode. Ensure your current directory is set to the Python installation folder (e.g., maxinstallationfolder/Python37) before running this command.
```bash
# current directory needs to be maxinstallationfolder/Python37:
./python.exe -m pip uninstall pip
```
--------------------------------
### Get Z-Depth Channel as Grayscale Mask
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Retrieves the Z-Depth channel from a rendered bitmap as a grayscale mask. This mask can then be used to determine depth information for each pixel.
```python
z_d = rt.getChannelAsMask(rbmp, zdepth_name)
```
--------------------------------
### Get Pixel Data for a Line
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Retrieves a line of pixel data from both the main RGBA bitmap and the Z-depth mask. Note that bitmap indices are 0-based, hence the 'y-1' for the vertical position.
```python
pixel_line = rt.getPixels(rbmp, rt.Point2(0, y-1), rbmp.width)
z_line = rt.getPixels(z_d, rt.Point2(0, y-1), rbmp.width)
```
--------------------------------
### Python Entry Point in setup.py
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/pystartup/README.md
Define the 3dsMax startup entry point for a Python package. This line in setup.py allows 3ds Max to discover and load your package's startup function.
```python
entry_points={'3dsMax': 'startup=yourpackagename:startup'}
```
--------------------------------
### Loading and Executing the Entry Point Function
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/pystartup/README.md
If the startup entry point is found, this block loads the associated function and executes it. It includes error handling to report if a package's startup fails.
```python
if not (entrypt is None):
try:
fcn = entrypt.load()
fcn()
except:
print(f'skipped package startup for {dist}, startup not working')
```
--------------------------------
### Finding the 3dsMax Startup Entry Point
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/pystartup/README.md
This line attempts to retrieve the specific '3dsMax' entry point named 'startup' from the current package being inspected.
```python
entrypt = pkg_resources.get_entry_info(dist, '3dsMax', 'startup')
```
--------------------------------
### Import transformlock Module
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/transformlock/README.md
Import the transformlock module and call its startup function to initialize the tool.
```python
import transformlock
transformlock.startup()
```
--------------------------------
### Instantiate and Style Python Console
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/pyconsole/README.md
Creates a new PythonConsole instance with a predefined theme and applies a dark background stylesheet.
```python
# create and setup a console
console = PythonConsole(formats=HUGOS_THEME)
console.setStyleSheet("background-color: #333333;")
```
--------------------------------
### Clone the 3ds Max Python How-Tos Repository
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/doc/install.md
Clone the repository to your local machine to manage and update the sample projects. This is recommended for easier updates.
```bash
# from the directory where you want the sample
git clone https://github.com/ADN-DevTech/3dsMax-Python-HowTos.git
```
--------------------------------
### Create and Configure QDockWidget for Console
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/pyconsole/README.md
Sets up a QDockWidget to contain the Python console, defining its object name and window title before adding it to the main 3ds Max window's dock area.
```python
# create a dock widget for the console
dock_widget = QDockWidget(main_window)
dock_widget.setWidget(console)
dock_widget.setObjectName("pyconsole")
dock_widget.setWindowTitle("Python Console")
main_window.addDockWidget(dockingarea, dock_widget)
```
--------------------------------
### Importing pkg_resources
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/pystartup/README.md
This import statement is necessary for the Python startup script to access package information and entry points.
```python
import pkg_resources
```
--------------------------------
### Open File Dialog for Output
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/speedsheet/README.md
This code demonstrates how to prompt the user to select a file for saving the speed data using a file dialog with specified captions and file type filters.
```python
output_name = rt.getSaveFileName(
caption="SpeedSheet File",
types="SpeedSheet (*.ssh)|*.ssh|All Files (*.*)|*.*|")
```
--------------------------------
### Import webbrowser module
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/inbrowserhelp/README.md
Import the standard Python webbrowser module to open URLs.
```python
import webbrowser
```
--------------------------------
### HTML for Socket.IO Chat Client
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/socketioclient/README.md
This HTML file sets up the user interface for the chat application, including input fields, message display, and JavaScript to handle sending and receiving messages via Socket.IO.
```html
Socket.IO chat
```
--------------------------------
### Create a New Macro Script
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/menuhook/README.md
Create a new macro script with a category, action, tooltip, text, and MaxScript code.
```python
rt.macros.new(
category,
action,
tooltip,
text,
mxs)
```
--------------------------------
### Plugin Package Components Declaration
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/doc/pluginpackage.md
This XML snippet shows how to declare Python pre-start-up scripts within a 3ds Max plugin package's PackageContents.xml file. It specifies runtime requirements and the component entry point.
```xml
```
--------------------------------
### Progress Bar and Abort Button Widgets
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/threadprogressbar/README.md
Create a QProgressBar and a QPushButton within the dialog's layout.
```python
# progress bar
pb = QProgressBar()
pb.minimum = MINRANGE
pb.maximum = MAXRANGE
main_layout.addWidget(pb)
# abort button
btn = QPushButton("abort")
main_layout.addWidget(btn)
```
--------------------------------
### Enable Console Event Processing
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/pyconsole/README.md
Hooks the console into the Qt event processing mechanism, enabling it to handle events and execute code effectively within the 3ds Max environment.
```python
# make the console do stuff
console.eval_queued()
```
--------------------------------
### Define startup function for menu hook
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/removeallmaterials/README.md
Define the startup function that registers the remove_all_materials function to a menu item in 3ds Max. This function can be called manually or automatically during 3ds Max startup.
```python
def startup():
"""
Hook the function to a menu item.
"""
menuhook.register(
"removeallmaterials",
"howtos",
remove_all_materials,
menu=["&Scripting", "Python3 Development", "How To"],
text="Remove all materials from the scene",
tooltip="Remove all materials from the scene")
```
--------------------------------
### Import menuhook module
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/inbrowserhelp/README.md
Import the menuhook module for creating custom menu items in 3ds Max.
```python
import menuhook
```
--------------------------------
### Import removeallmaterials package
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/removeallmaterials/README.md
Import the removeallmaterials package to use its functions. This is typically done in the 3ds Max listener window.
```python
import removeallmaterials
removeallmaterials.startup()
```
--------------------------------
### Launch RAM Player
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/quickpreview/README.md
Opens the generated AVI animation file in the 3ds Max RAM Player.
```python
rt.ramplayer(preview_name, "")
```
--------------------------------
### Define menu topics and URLs
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/inbrowserhelp/README.md
Define a list of tuples, where each tuple contains a unique item name, a display description, and a URL for the menu items. URLs are constructed dynamically using 3ds Max version and help paths.
```python
from pymxs import runtime as rt
MAX_VERSION = rt.maxversion()[7]
MAX_HELP = f"help.autodesk.com/view/MAXDEV/{MAX_VERSION}/ENU"
TOPICS = [
("gettingstarted", "Getting Started With Python in 3ds Max",
f"{MAX_HELP}/?guid=Max_Python_API_tutorials_creating_the_dialog_html"),
("howtos", "Python HowTos Github Repo",
"github.com/ADN-DevTech/3dsMax-Python-HowTos"),
("samples", "Python samples (Github Repo)",
"github.com/ADN-DevTech/3dsMax-Python-HowTos/tree/master/src/samples"),
("pymxs", "Pymxs Online Documentation",
f"{MAX_HELP}/?guid=Max_Python_API_using_pymxs_html"),
("pyside2", "Qt for Python Documentation (PySide2)",
"doc.qt.io/qtforpython/contents.html"),
("python", "Python 3.7 Documentation",
"docs.python.org/3.7/")
]
```
--------------------------------
### Create and Show Dialog
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/threadprogressbar/README.md
Define a function to create and display the PyMaxDialog for the progress bar.
```python
def threadprogressbar():
'''Update a progress bar from a thread'''
dialog = ui.PyMaxDialog()
dialog.show()
```
--------------------------------
### Integrating Samples into 3ds Max 2025 Menu System
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/doc/pluginpackage.md
This Python code configures the new menu system in 3ds Max 2025 by registering a callback function to add howto menu items. It uses pymxs and a custom menuhook module.
```python
# configure 2025 menus
from pymxs import runtime as rt
from menuhook import register_howtos_menu_2025
def menu_func():
menumgr = rt.callbacks.notificationparam()
register_howtos_menu_2025(menumgr)
# menu system
cuiregid = rt.name("cuiRegisterMenus")
howtoid = rt.name("pyScriptHowtoMenu")
rt.callbacks.removescripts(id=cuiregid)
rt.callbacks.addscript(cuiregid, menu_func, id=howtoid)
```
--------------------------------
### Set Floating and Show Dock Widget
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/pyconsole/README.md
Configures the dock widget to be either floating or docked based on the 'floating' argument and then makes it visible.
```python
dock_widget.setFloating(floating)
dock_widget.show()
```
--------------------------------
### Open File for Writing
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/speedsheet/README.md
This snippet illustrates opening a selected file in write mode using Python's built-in open function within a 'with' block to ensure the file is automatically closed.
```python
with open(output_name, "w+") as output_file:
```
--------------------------------
### Define AVI Output Path
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/quickpreview/README.md
Constructs the full path for the AVI preview file within the 3ds Max preview directory.
```python
preview_name = path.join(rt.getDir(rt.Name("preview")), "quickpreview.avi")
```
--------------------------------
### Add Menu Item and Update Menu Bar
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/menuhook/README.md
Create a menu action item, add it to a target menu if found, and update the menu bar.
```python
if targetmenu:
newaction = rt.menuman.createActionItem(action, category)
if newaction:
targetmenu.addItem(newaction, -1)
rt.menuman.updateMenuBar()
```
--------------------------------
### Register menu items
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/inbrowserhelp/README.md
Iterate through the defined topics and register each as a menu item. When activated, the menu item will open the corresponding URL in the default web browser.
```python
for topic in TOPICS:
menuhook.register(
f"inbrowserhelp_{topic[0]}",
"howtos",
lambda topic=topic: webbrowser.open(f"https://{topic[2]}",
MENU_LOCATION,
text=topic[1],
tooltip=topic[1])
```
--------------------------------
### Transpile MaxScript to Python using mxs2py
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/mxs2py/README.md
Demonstrates how to use the `topy` function from the `mxs2py` library to convert a simple MaxScript command into its Python equivalent. The output is printed to the console.
```python
from mxs2py import topy
(output, _) = topy("rotate $ (angleaxis 90 [1,0,0])")
print(output)
```
--------------------------------
### Tabify Dock Widget
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/pyconsole/README.md
Optionally tabifies the newly created console dock widget with an existing widget if a 'tabto' name is provided. This allows multiple dockable windows to be grouped under a single tab.
```python
if (not tabto is None):
tabw = main_window.findChild(QWidget, tabto)
main_window.tabifyDockWidget(tabw, dock_widget)
```
--------------------------------
### Find a Menu by Name
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/menuhook/README.md
Find a specific menu in the 3ds Max menu manager using its name.
```python
targetmenu = rt.menuman.findmenu(menu)
```
--------------------------------
### Initialize Dialog with Unique Name
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/singleinstancedlg/README.md
Initializes the dialog and assigns a unique name using `setObjectName` to facilitate single instance management.
```python
def __init__(self, parent):
super(PyMaxDialog, self).__init__(parent)
self.setWindowTitle('Single Instance Dialog')
# keep track of being unique
self.setObjectName(PyMaxDialog.unique_name)
```
--------------------------------
### Create Bitmap for Animation
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/quickpreview/README.md
Retrieves the current viewport size and creates a bitmap object to store the animation frames.
```python
view_size = rt.getViewSize()
anim_bmp = rt.bitmap(view_size.x, view_size.y, filename=preview_name)
```
--------------------------------
### Import pymxs runtime
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/removeallmaterials/README.md
Import the pymxs runtime to access the MAXScript scripting library from Python. This allows interaction with 3ds Max functionalities.
```python
from pymxs import runtime as rt
```
--------------------------------
### Showing the Renameselected Dialog
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/renameselected/README.md
This function creates and displays the PyMaxDialog instance, passing the renameselected function as the callback for button clicks.
```python
def showdialog():
dialog = ui.PyMaxDialog(renameselected)
dialog.show()
```
--------------------------------
### Worker Thread Execution with mxthread
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/mxthread/README.md
This snippet demonstrates how to use `on_main_thread` to decorate functions and `main_thread_print` for thread-safe printing. It also shows how to execute PyMaxS commands and handle exceptions raised from the main thread.
```python
from mxthread import on_main_thread, main_thread_print, run_on_main_thread
from pymxs import runtime as rt
from qtpy.QtCore import QThread
class Worker(QThread):
"""
Worker thread doing various things with maxtrhead.
"""
def __init__(self, name="worker"):
QThread.__init__(self)
self.setObjectName(name)
def run(self):
# use a function that was already decorated with on_main_thread
main_thread_print(f"hello from thread {self.objectName()}")
# create our own function decorated with on_main_thread
@on_main_thread
def do_pymxs_stuff():
print("resetting the max file")
# reset the max file (so that the scene is empty)
rt.resetMaxFile(rt.name("noprompt"))
# we are on main thread so we can use print and it will work
print("creating 3 boxes on main thread")
# pymxs stuff can only work on the main thread. Well no problem we are on the main thread:
rt.box(width=1, height=1, depth=1, position=rt.Point3(0,0,0))
rt.box(width=1, height=1, depth=1, position=rt.Point3(0,0,2))
rt.box(width=1, height=1, depth=1, position=rt.Point3(0,0,4))
# make 3ds Max aware that the views are dirtied
rt.redrawViews()
return 3
# call our main thread function
res = do_pymxs_stuff()
main_thread_print(f"our main thread function returned {res}")
# create another function that will throw something
# (to show that exceptions are propagated)
@on_main_thread
def do_faulty_stuff():
# we are on main thread so we can use print and it will work
a = 2
b = 0
return a / b
try:
res = do_faulty_stuff()
main_thread_print(f"The function will fail, this will never be displayed")
except Exception as e:
main_thread_print(f"our main thread function raised: {e}")
# use a lambda instead
on_main_thread(lambda : print("hello from lambda"))()
# call a function on the main thread without decorating it
def some_function(a, b):
print(f"a = {a} b = {b}")
run_on_main_thread(some_function, 1, 2)
main_thread_print(f"we are done, the sample ran correctly!")
# Name the main thread
QThread.currentThread().setObjectName("main_thread")
# create a worker
worker = Worker("worker_thread")
worker.start()
# Note: we cannot wait this worker here. This will create a deadlock.
# The worker executes stuff on the main thread and we are on the main thread.
# But to convince ourselves, we can print something here and the man thread
# calls initiated by the worker will all happen after this
print("--- Worker thread calls to the main thread will run after this")
```
--------------------------------
### Open Output File in 3ds Max Editor
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/speedsheet/README.md
This command opens the generated output file in the 3ds Max text editor for review.
```python
rt.edit(output_name)
```
--------------------------------
### Worker Thread Initialization
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/threadprogressbar/README.md
Initialize a QThread subclass named Worker, defining a progress signal and an aborted flag.
```python
class Worker(QThread):
progress = Signal(int)
aborted = False
def __init__(self):
QThread.__init__(self)
```
--------------------------------
### Create Voxel Box Based on Depth and Position
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Creates a 3D box object. Its height is determined by half the Z-buffer's grayscale value, and its X and Y positions are calculated based on pixel coordinates, with a mirrored Y-axis to align with the MAX world space.
```python
box = rt.box(width=10, length=10, height=(z_line[x].value/2))
box.pos = rt.Point3(x*10, -y*10, 0)
```
--------------------------------
### Define menu location
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/inbrowserhelp/README.md
Specify the path within the 3ds Max menu system where the new submenu will be created.
```python
MENU_LOCATION = ["&Scripting", "Python3 Development", "Browse Documentation"]
```
--------------------------------
### Import necessary modules
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/singleinstancedlg/README.md
Imports required classes from PySide and the 3ds Max runtime.
```python
from qtpy.QtWidgets import QWidget, QDialog, QVBoxLayout, QPushButton
from pymxs import runtime as rt
MAIN_WINDOW = QWidget.find(rt.windows.getMAXHWND())
```
--------------------------------
### Connecting Button Click to Action
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/renameselected/README.md
Connects the push button's clicked signal to a lambda function that calls the provided click function with the text from the line edit.
```python
btn.clicked.connect(lambda : click(edit.text()))
main_layout.addWidget(btn)
self.setLayout(main_layout)
self.resize(250, 100)
```
--------------------------------
### Define New Console Function
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/pyconsole/README.md
This function creates and configures a new Python console instance within 3ds Max. It supports tabbed docking and floating behavior.
```python
def new_console(tabto = None, floating = False, dockingarea = QtCore.Qt.RightDockWidgetArea):
"""
Create a new console and float it as a max widget
tabto: name of a widget on top of which the console should be tabbed
floating: True to float the console, False to leave it docked
```
--------------------------------
### Capture and Save Animation Frames
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/quickpreview/README.md
Iterates through animation frames, captures the viewport, copies it to the animation bitmap, and saves each frame.
```python
for t in range(int(rt.animationRange.start), int(rt.animationRange.end)):
rt.sliderTime = t
dib = rt.gw.getViewportDib()
rt.copy(dib, anim_bmp)
rt.save(anim_bmp)
```
--------------------------------
### Node.js Server for Socket.IO Chat
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/socketioclient/README.md
This JavaScript code sets up an Express server and integrates Socket.IO to handle real-time chat messages. It defines routes for serving the HTML client and manages connections, disconnections, and message broadcasting.
```javascript
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const port = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
socket.on('chat message', msg => {
io.emit('chat message', msg);
});
});
http.listen(port, () => {
console.log(`Socket.IO server running at http://localhost:${port}/`);
});
```
--------------------------------
### Render Viewport with Z-Depth Channel
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Renders the active viewport at a specified resolution (32x32) and requests an additional Z-depth channel. The Virtual Frame Buffer (VFB) is disabled during this process.
```python
rbmp = rt.render(outputsize=rt.Point2(32, 32), channels=[zdepth_name], vfb=False)
```
--------------------------------
### Remove Application Plugins Directory (3ds Max 2025+)
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/doc/uninstall.md
Manually remove the Python HowTos application plugin directory for 3ds Max 2025 and later versions. This command should be run from a Git Bash terminal.
```bash
rm -fr "$ProgramData/Autodesk/ApplicationPlugins/adn-devtech-python-howtos"
```
--------------------------------
### Force Garbage Collection
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/quickpreview/README.md
Manually triggers garbage collection to free up memory used during the preview capture process.
```python
rt.gc()
```
--------------------------------
### Handling Socket.IO Events on the Main Thread
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/socketioclient/README.md
This event handler demonstrates how to process incoming Socket.IO messages on the main 3ds Max thread using `mxthread.run_on_main_thread`. It prints the received data and then disconnects.
```python
@sio.on("chat message")
def my_message(data):
mxthread.run_on_main_thread(print, f"message received {data}")
# We could emit something here
# sio.emit('my response', {'response': 'my response'})
# We could disconnect ourself (so we only handle one message)
sio.disconnect()
```
--------------------------------
### Menu Registration Function Signature
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/doc/pluginpackage.md
Defines the signature for a menu registration function, including parameters for action, category, callback function, and specific identifiers for 3ds Max 2025 menus.
```python
def register(action, category, fcn, menu=None, text=None, tooltip=None, in2025_menuid=None, id_2025=None):
```
--------------------------------
### Update Progress and Check for Cancellation
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Updates the progress indicator with a percentage value based on the current line number and total height. Exits the loop if the user cancels the operation.
```python
if not rt.progressupdate(100.0 * y / rbmp.height):
break
```
--------------------------------
### Define Custom PyMaxDialog Class
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/singleinstancedlg/README.md
Defines a custom PySide dialog class that will be attached to the 3ds Max main window. It includes a class variable for a unique name.
```python
class PyMaxDialog(QDialog):
"""
Custom dialog attached to the 3ds Max main window
"""
unique_name = __file__
```
--------------------------------
### Show Dialog Function
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/singleinstancedlg/README.md
This function ensures that only one instance of the dialog is shown. It uses `findChild` to check for an existing dialog with the unique name and creates a new one only if none is found.
```python
def show_dialog():
'''Show the dialog without duplicating it'''
dialog = MAIN_WINDOW.findChild(QDialog, PyMaxDialog.unique_name)
if dialog is None:
dialog = PyMaxDialog(MAIN_WINDOW)
dialog.show()
```
--------------------------------
### Calculate and Log Average Speed
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/speedsheet/README.md
After iterating through all frames, this code calculates the average speed over the entire animation range and writes it to the output file.
```python
average_speed /= float(rt.animationRange.end - rt.animationRange.start)
output_file.write(f"Average Speed: {average_speed}\n")
```
--------------------------------
### Dialog UI Population
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/renameselected/README.md
Populates the PySide dialog with a label, a line edit for input, and a button to trigger the renaming action.
```python
super(PyMaxDialog, self).__init__(parent)
self.setWindowTitle('Rename')
main_layout = QVBoxLayout()
label = QLabel("Enter new base name")
main_layout.addWidget(label)
edit = QLineEdit()
main_layout.addWidget(edit)
btn = QPushButton("Rename selected objects")
```
--------------------------------
### Call Function on Main Thread Directly
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/mxthread/README.md
Alternatively, call a function on the main thread using run_on_main_thread, passing the function and its arguments. This is useful when decorators are not preferred.
```python
from mxthread import run_on_main_thread
def some_function(a, b):
print(f"a = {a} b = {b}")
run_on_main_thread(some_function, 1, 2)
```
--------------------------------
### PySide Dialog Class Definition
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/renameselected/README.md
Defines a custom QDialog subclass for the renaming tool. It accepts a click function in its constructor to handle button actions.
```python
class PyMaxDialog(QDialog):
"""
Custom dialog attached to the 3ds Max main window
"""
def __init__(self, click, parent=QWidget.find(rt.windows.getMAXHWND())):
```
--------------------------------
### Storing Registered Menu Items
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/doc/pluginpackage.md
This code snippet shows how registered menu items are stored in a list, containing identifiers for the menu, category, and action. This list is used by the menu system to build the UI.
```python
registered_items.append((in2025_menuid, id_2025, category, action))
```
--------------------------------
### Connect Abort Button Signal
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/threadprogressbar/README.md
Connect the clicked signal of the abort button to the abort function of the worker thread.
```python
# connect abort button
btn.clicked.connect(self.worker.abort)
```
--------------------------------
### Register Python Function to 3ds Max Menu
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/menuhook/README.md
Use this snippet to register a Python function to a specific 3ds Max menu item. The function will be executed when the menu item is clicked. Ensure the 'menuhook' package is imported.
```python
import menuhook
def fcn():
"""
Do something. This is the function we want to attach to a menu
item.
"""
print("hello")
menuhook.register(
# the name of the action (will be listed in menu customization dialogs)
"myaction",
# the category for the action
"my category",
# the function to be executed (this is registered for a single run of 3ds Max)
fcn,
# the menu for this action. if None is provided the action
# will not be added to a menu, only created as an action.
# this can be deeply nested.
menu=["&Scripting", "Samples"],
# the menu text. if None is provided, the action name will be used
text="the text for the menu item",
# the menu tool tip. if None is provided, the action name will be used
tooltip="the tooltip")
```
--------------------------------
### Adding Menu Items to 3ds Max 2025 Menu Manager
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/doc/pluginpackage.md
This Python code iterates through registered items and adds them to the 3ds Max 2025 menu manager. It handles cases where the menu might not be found, printing an error message.
```python
# hook the registered items
for reg in registered_items:
(in2025_menuid, id_2025, category, action) = reg
scriptmenu = menumgr.getmenubyid(in2025_menuid)
if scriptmenu is not None:
try:
actionitem = scriptmenu.createaction(id_2025, 647394, f"{action}`{category}")
except Exception as e:
print(f"Could not create item {category}, {action} in menu {in2025_menuid} because {e}")
else:
print(f"Could not create item {category}, {action}, in missing menu {in2025_menuid}")
```
--------------------------------
### Filter Objects by Name Pattern
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Filters existing objects in the scene to find and delete those matching a specific name pattern (e.g., 'VoxelBox'). This is useful for cleaning up previous runs.
```python
voxelbox = re.compile("^VoxelBox")
for tbd in filter(lambda o: voxelbox.match(o.name), list(rt.objects)):
rt.delete(tbd)
```
--------------------------------
### Calculate Frame Speed
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/speedsheet/README.md
This snippet calculates the speed of the selection's center between the current frame (t) and the previous frame (t-1) by measuring the distance and multiplying by the frame rate.
```python
with pymxs.attime(t):
current_pos = rt.selection.center
with pymxs.attime(t-1):
last_pos = rt.selection.center
frame_speed = rt.distance(current_pos, last_pos) * rt.FrameRate
average_speed += frame_speed
output_file.write(f"Frame {t}: {frame_speed}\n")
```
--------------------------------
### Define remove_all_materials function
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/removeallmaterials/README.md
Define the core business logic function that iterates through all objects in the scene and sets their material property to None, effectively removing materials.
```python
def remove_all_materials():
'''Remove all materials from the scene'''
for obj in rt.objects:
obj.material = None
```
--------------------------------
### Decorate Function to Run on Main Thread
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/mxthread/README.md
Use the @on_main_thread decorator to ensure a function executes on the main thread. This allows operations like printing that are restricted in worker threads.
```python
from mxthread import on_main_thread
@on_main_thread
def do_faulty_stuff():
# we are on main thread so we can use print and it will work
a = 2
b = 0
return a / b
```
--------------------------------
### Iterate Through Bitmap Lines
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Loops through each horizontal line of a rendered bitmap. The loop variable 'y' represents the current line number.
```python
for y in range(1, rbmp.height):
print("y =", y)
```
--------------------------------
### Assign Unique Name to Box
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Assigns a unique name to the created box, using 'VoxelBox' as a base name to ensure no naming conflicts.
```python
box.name = rt.uniqueName("VoxelBox")
```
--------------------------------
### Generated Python Code for Rotation Command
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/mxs2py/README.md
This is the Python code generated by `mxs2py` for the MaxScript `rotate $ (angleaxis 90 [1,0,0])` command. It utilizes `pymxs` and `mxsshim` for execution.
```python
'''Converted from MAXScript to Python with mxs2py'''
from pymxs import runtime as rt
import mxsshim
import pymxs
rt.rotate(mxsshim.path("$"), rt.angleaxis(90, rt.point3(1, 0, 0)))
```
--------------------------------
### Iterate Through Pixels in a Line
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Loops through each pixel in the current scanline. The variable 'x' represents the horizontal pixel coordinate. It accesses the Z-buffer value for each pixel.
```python
for x in range(1, rbmp.width):
print("x =", x, z_line[x].value)
```
--------------------------------
### Assign Wireframe Color to Box
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/zdepthchannel/README.md
Sets the wireframe color of the newly created box to match the RGB color of the corresponding rendered pixel.
```python
box.wirecolor = pixel_line[x]
```
--------------------------------
### Register Transform Lock Menu Item
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/transformlock/README.md
Registers the lock_selection function as a menu item under the Scripting > Python3 Development > How To menu. This function will be executed when the menu item is clicked.
```python
def startup():
"""
Hook the transform lock function to a menu item.
"""
menuhook.register(
"transformlock",
"howtos",
lock_selection,
menu=["&Scripting", "Python3 Development", "How To"],
text="Lock transformations for the selection",
tooltip="Lock transformations for the selection")
```
--------------------------------
### Registering Renameselected Menu Item
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/renameselected/README.md
Hooks the renameselected functionality to a menu item under the 'Scripting' menu in 3ds Max. This allows users to access the tool via the UI.
```python
def startup():
"""
Hook the function to a menu item.
"""
menuhook.register(
"howtos",
"renameselected",
showdialog,
menu=[ "&Scripting", "Python3 Development", "How To"],
text="renameselected sample",
tooltip="renameselected sample")
```
--------------------------------
### Lock Selection Transforms
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/transformlock/README.md
Defines the core function to lock all transformations (position, rotation, scale) on the currently selected objects in 3ds Max.
```python
def lock_selection():
'''Lock all transforms on the selection'''
rt.setTransformLockFlags(rt.selection, rt.Name("all"))
```
--------------------------------
### Worker Thread Run Loop
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/threadprogressbar/README.md
The run function of the Worker thread iterates, emits progress, sleeps, and checks for abortion.
```python
for i in range(MINRANGE, MAXRANGE):
self.progress.emit(i)
time.sleep(0.5)
if self.aborted:
return
self.progress.emit(MAXRANGE)
```
--------------------------------
### Close Animation Bitmap
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/quickpreview/README.md
Closes the bitmap file after all animation frames have been saved.
```python
rt.close(anim_bmp)
```
--------------------------------
### Core Renaming Functionality
Source: https://github.com/adn-devtech/3dsmax-python-howtos/blob/master/src/packages/renameselected/README.md
This Python function renames all selected objects in 3ds Max using a provided base name. It ensures unique names for each object.
```python
def renameselected(text):
'''Rename all elements in selection'''
if text != "":
for i in rt.selection:
i.name = rt.uniquename(text)
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.