A partir de 3ds Max 2022, la biblioteca MaxPlus está en desuso. Este blog tiene la intención de ayudar a aquellos que utilizan MaxPlus a hacer la transición a pymxs para 3ds Max. En este artículo se mostrará un ejemplo de cómo migrar el sistema xref de MaxPlus a pymxs.

Desde 3ds Max 2021, MaxPlus no es compatible con Python 3. A partir de 3ds Max 2022, se dejó de enviar MaxPlus ya que pymxs se convirtió en el lenguaje de scripting Python admitido en 3ds Max.

Scripting en 3ds Max

El scripting en 3ds Max es una herramienta poderosa para automatizar tareas y crear complementos personalizados que amplían la funcionalidad ofrecida por 3ds Max o introducen nuevas características no presentes en el software. Esto es especialmente importante en la Automatización de diseño, donde las actividades se ejecutan dentro de los servicios de la plataforma de Autodesk (anteriormente conocidos como Forge).


Para aprovechar al máximo el poder del scripting

3ds Max ofrece dos opciones principales: MAXScript, el lenguaje de scripting nativo de 3ds Max, y Python, que es una capa de abstracción sobre MAXScript. Al utilizar estos lenguajes de scripting, los usuarios pueden lograr una gran flexibilidad y control sobre 3ds Max. Además, 3ds Max ofrece SDKs para C++ y C# para aquellos que prefieren el desarrollo de complementos, lo que permite crear y ampliar las capacidades del software.

Dentro de 3ds Max, MAXScript está integrado de forma predeterminada y se puede acceder a él desde la ventana inferior izquierda de la interfaz de usuario o a través de la opción Scripting en el menú de 3ds Max.

Para abrir la ventana de scripting, simplemente selecciona la opción Scripting Listener en el menú desplegable superior. Esto mostrará la ventana del "Scripting listener" con dos opciones: MAXScript y Python. Puedes ingresar y ejecutar tus scripts en la ventana del editor, moviéndote a una nueva línea cada vez, tal como se muestra a continuación.


Scripting en Python

El scripting en Python ha sido una opción desde hace bastante tiempo. Inicialmente, 3ds Max exponía sus APIs a través de una biblioteca llamada MaxPlus, la cual quedó obsoleta en 3ds Max 2019 y fue reemplazada por pymxs. Ambas bibliotecas funcionan de manera diferente y tienen diferencias en las funcionalidades que se exponen a Python.

Para comparar la diferencia, el código a continuación muestra cómo se ve la estructura del código para crear un objeto en la escena y modificar sus parámetros.

Código:
import MaxPlus

obj = MaxPlus.Factory.CreateGeomObject(MaxPlus.ClassIds.Box)
obj.ParameterBlock.Width.Value = 10.0
obj.ParameterBlock.Length.Value = 10.0
obj.ParameterBlock.Height.Value = 10.0
Código:
import pymxs

obj = pymxs.runtime.box(width=10.0, length=10.0, height=10.0)
¿Por qué hay esa diferencia?

Si estás familiarizado con el SDK de 3ds Max, el código de MaxPlus tiene un enfoque similar al crear objetos. Se genera a partir del SDK de C++, por lo que su sistema de código sigue cómo se hace en C++ o en .NET.

Por otro lado, pymxs sigue un enfoque diferente. Observa el primer código que hicimos para MAXScript para agregar una caja a la escena, ¿es similar, verdad? Pymxs está construido como un envoltorio alrededor de MAXScript en lugar del SDK de C++. Como resultado, el código parece más fácil de entender si conoces un poco de scripting en MAXScript.

Migrando MaxPlus a pymxs

Supongamos que tienes algunos scripts antiguos que creaste en MaxPlus y quieres migrarlos a la versión más reciente de 3ds Max, pero ahora las últimas versiones de 3ds Max ya no incluyen las bibliotecas de MaxPlus. La opción es migrar la base de código a C++/.NET, MAXScript o Python. Veamos algunos ejemplos:

1. XREFS

xrefs es un término que se refiere a la referencia externa de otros archivos o escenas en la escena actual. Esto evita cargar proyectos externos completos en el proyecto actual, en su lugar, solo se hace referencia a ellos. MaxPlus proporciona una manipulación directa de los archivos xref de la siguiente manera:

Contando archivos

Código:
import MaxPlus

num_xrefs = MaxPlus.XRefs.GetXRefFileCount()
print(num_xrefs)
A continuación se muestra un código equivalente en pymxs para una funcionalidad similar.

Código:
import pymxs
num_xrefs = pymxs.runtime.xrefs.getXRefFileCount()
print(num_xrefs)
Obteniendo archivos xref

Una vez que se crean xrefs dentro de una escena, se puede recuperar archivos xref específicos para cualquier propósito de la siguiente manera tanto en MaxPlus como en pymxs.

Código:
import MaxPlus

index = 0 # index of the xref file
xref_file = MaxPlus.XRefs.GetXRefFile(index)
print(xref_file)

# IN PYMXS

import pymxs

index = 0 # index of the xref file
xref_file = pymxs.runtime.xrefs.getXRefFile(index)
print(xref_file)
Ten en cuenta que ambos requieren un parámetro que especifique el índice del archivo XRef del cual obtener información.

Configurando un archivo xref

Esto se utiliza para establecer un archivo como xref.

Código:
import MaxPlus

# get the XRef object that you want to set the file path for
xref_object = MaxPlus.Core.GetINodeByName("MyXRefObject")

# set the file path for the XRef object
file_path = "C:/path/to/my/xref/file.max"
MaxPlus.Core.SetXRefFile(xref_object, file_path)
Ten en cuenta que este código representa una solución alternativa para actualizar el archivo XRef, ya que no hay una forma directa de actualizar el archivo en pymxs.

Código:
import pymxs

index = 1
# Get the XRef object for index 1
xref_obj = pymxs.runtime.xrefs.getXRefFile(index)

new_file = "path\to\file\something.max"

# Using MAXScript in pymxs
maxscript_code = f'''
axref = xrefs.getXRefFile {index}
axref.filename = "{new_file}"
flagChanged axref
'''

_axref = pymxs.runtime.execute(maxscript_code)

print(_axref)
Marcando el archivo xref como modificado

Se utiliza para indicar que el xref ha sido modificado.

Código:
import MaxPlus

# get the XRef object that you want to flag as changed
xref_object = MaxPlus.Core.GetINodeByName("MyXRefObject")

# flag the XRef object as changed
MaxPlus.Core.FlagXrefChanged(xref_object)
Para marcar un archivo específico como modificado, pymxs no proporciona una forma directa de hacerlo. Como alternativa, podemos invocar MAXScript para marcar los archivos como modificados, como se muestra a continuación:

Código:
import pymxs

index = 1 # Index for the xref you want to flag as updated

maxscript_code = f'''
axref = xrefs.getXRefFile {index}
flagChanged axref
axref
'''

_axref = pymxs.runtime.execute(maxscript_code)

print(_axref)
Actualizando los xrefs modificados

Actualiza los XRefs que se han marcado como modificados. Esta función carga las nuevas versiones de los archivos referenciados y actualiza los XRefs en la escena en consecuencia.

Código:
# In MAXPLUS
import MaxPlus

# update all XRef objects that have been flagged as changed
MaxPlus.Core.UpdateChangedXRefs()

# In PYMXS
import pymxs

# Updates the changed XRefs and resets their changed flags
pymxs.runtime.xrefs.updateChangedXRefs()
3. Animación

Obteniendo el rango de animación

Obtener el rango de animación se utiliza para recuperar el rango de animación de la escena actual.

Código:
import MaxPlus

# get the animation range of the current scene
start_time, end_time = MaxPlus.Animation.GetAnimRange()

# print the start and end times of the animation range
print("Animation Range:")
print("Start Time:", start_time)
print("End Time:", end_time)
La función correspondiente en pymxs de MaxPlus devuelve un par de objetos de tiempo: el primer elemento de la tupla es el tiempo de inicio del rango de animación, y el segundo elemento es el tiempo de finalización del rango de animación.

Código:
import pymxs

# Get the animation range in 3ds Max
anim_range = pymxs.runtime.animationRange

# Print the start and end times of the animation range
print("Start Time:", anim_range.start)
print("End Time:", anim_range.end)
Obteniendo el tiempo actual

Devuelve el tiempo actual en la animación.

Código:
import MaxPlus

# get the current time in the animation
current_time = MaxPlus.Animation.GetTime()

# print the current time to the console
print("Current Time:", current_time)
Los siguientes ejemplos de código se utilizan para obtener el tiempo actual al animar en pymxs.

Código:
import pymxs

# get current time 
current_time = pymxs.runtime.currentTime

# Log the values
print(current_time)
print(current_time.frame)
print(current_time.ticks)
Conclusión

Las muestras no cubren todos los aspectos de la migración de código de MaxPlus a pymxs. Sin embargo, la guía completa se puede encontrar en la documentación en https://help.autodesk.com/view/MAXDE..._to_pymxs_html. La guía tiene como objetivo brindar ideas sobre cómo migrar los códigos actuales a pymxs.

Hemos examinado tanto las funciones nativas de pymxs similares a las funciones de MaxPlus como la incorporación de MAXScript en pymxs para lograr funcionalidades que actualmente no están expuestas en pymxs.

Preguntas frecuentes

¿MaxPlus y pymxs son equivalentes uno a uno?

No. Debido a la arquitectura, estos dos tienen una exposición diferente a las funcionalidades subyacentes. Por lo tanto, algunas funciones y módulos en MaxPlus no están disponibles en pymxs y viceversa.

¿Puedo convertir completamente mi código de MaxPlus a pymxs?

Sí. El código de MaxPlus se puede migrar a pymxs, pero no existe una conversión uno a uno. Ten en cuenta que deberás combinar pymxs y MAXScript para algunas funcionalidades para lograrlo. Se trata de obtener una funcionalidad similar.

Entonces, ¿qué hay de pymxs y MAXScript?

pymxs es un envoltorio de MAXScript, pero no todas las funcionalidades y propiedades de MAXScript se generan directamente en los módulos/funciones/propiedades de pymxs. Hay soluciones alternativas, pero no hay funciones/módulos directos como los de MAXScript.