Maya MEL Modelado de Procedimientos para Artistas - UIs

Este tutorial es una introducción a la creación de interfaces gráficas de usuario (GUI) en MEL para Maya 2010 y versiones posteriores. Maya 2011 presenta una nueva metodología para crear GUI que no se tratará aquí. Revisaremos la codificación adecuada para las IU, el control de errores y armaremos un script muy útil que le brinda un control considerable sobre el punto de pivote de un objeto..

Interfaces de usuario

Si planea entregar sus scripts a otro artista, entonces puede ser increíblemente útil armar una GUI fácil de usar que haga que su código sea accesible para los no programadores. En estos días, rara vez utilizo teclas de acceso rápido personalizadas, en lugar de eso confío en un puñado de interfaces de usuario que he construido en MEL para automatizar los procesos de Maya. Puedo llevarlos conmigo, y no tengo que cambiar ninguna preferencia para trabajar cómodamente en múltiples estaciones de trabajo. La capacidad de crear y mantener interfaces de usuario es una herramienta poderosa pero a veces frustrante en el kit de herramientas MEL..


Paso 1

Echemos un vistazo a lo que vamos a crear hoy. Comience por guardar el archivo "EdW_PivotControl.mel" incluido con este tutorial en su directorio de scripts. Entonces, abre Maya. Usaré Maya 2010 mientras dure este tutorial, pero el mismo código debería funcionar para la mayoría de las versiones mayas. Escribe lo siguiente en la línea de comandos y presiona enter:

fuente EdW_PivotControl; EdW_PivotControl;

Paso 2

Deberíamos tener una ventana abierta con algunos botones en ella. Intenta crear algo de geometría y experimenta con el script. El objetivo es crear un script que le brinde control sobre los puntos de pivote del objeto sobre la marcha..


Paso 3

Determine qué procedimientos necesitaremos para hacer este script:

  • EdW_PivotControl: inicia el procedimiento principal del script
  • epc_pivotControl - crea la interfaz de usuario
  • epc_getBounds: use el comando xform para obtener el cuadro delimitador del objeto seleccionado
  • epc_movePivotLocal: mueve el pivote del objeto a una posición local (y min, x min, etc.)
  • epc_movePivotToObject: mueve el pivote a la ubicación de otro objeto

Estoy usando epc_ como mi prefijo. Al igual que en los tutoriales anteriores, desea asegurarse de que sus procedimientos tengan nombres únicos, para no interferir con ningún otro script..


Etapa 4

Comenzaremos nuestro script abriendo ese antiguo modo de espera, el Bloc de notas de Microsoft. El primer procedimiento es fácil:


Paso 5

Guarde su archivo. Al guardar un documento MEL, asegúrese de elegir "Todos los archivos" en "guardar como tipo". Guarde su documento como un archivo .mel en su directorio de scripts de Maya. Usaré EdW_PivotControl.mel como mi nombre de archivo, pero siéntase libre de elegir lo que quiera.


Paso 6

Ahora llegamos a la parte difícil. Crear UI en MEL nunca ha sido un proceso especialmente elegante, por lo que haré todo lo posible para que el proceso sea lo menos doloroso posible. A veces, es mejor simplemente dibujar algo en el papel antes de comenzar a escribir el código, así que haga un bosquejo de un diseño básico para que se vea la interfaz de usuario final. Este script es bastante simple, pero cuando empiezas a manejar pestañas, menús, barras de desplazamiento, etc., debes asegurarte de tener un plan de juego en mente..


Paso 7

Vamos a ver tres tipos diferentes de comandos UI:

  • Windows: objetos de nivel superior que tienen los botones estándar de cualquier ventana del sistema operativo, como minimizar, maximizar y cerrar.
  • Diseños - diferentes formas de organizar los objetos dentro de una ventana.
  • Controles: botones, controles deslizantes, campos de texto, etc. Estos son los elementos interactivos de la interfaz de usuario.

Aquí hay un desglose de nuestro boceto de acuerdo con los comandos de MEL utilizados para crearlos:


Paso 8

El primer paso para crear la interfaz de usuario es establecer la ventana. Debido a que nuestro objeto Window tendrá un nombre único, Maya no puede tener dos de la misma ventana abiertas al mismo tiempo. La primera parte de nuestro procedimiento verifica si la ventana ya está abierta y la cierra si está.

 // Crear UI global proc pivotControl () 
if ('window -xist PivotControlMain')
deleteUI PivotControlMain;
; //…;

Paso 9

Ahora, vamos a intentar crear una ventana en el código y ver qué pasa:

 ventana -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 450 -h 300 PivotControlMain;
  • -ResizeToFitChildren (-rtf) si es verdadero, la ventana se redimensionará automáticamente para adaptarse a todos los diseños y controles que cree
  • -título (-t) el texto que se muestra en la barra de título en la parte superior de la ventana
  • -minimizarButton (-mnb) habilita o inhabilita el botón de minimizar
  • -Maximizar botón (-mxb) activa o desactiva el botón maximizar
  • -ancho (-w) ancho de la ventana en píxeles
  • -altura (-h) altura de la ventana en píxeles

Paso 10

En este momento, la ventana se ha creado dentro de la secuencia de comandos, pero se necesita otro comando para mostrarla. Este comando siempre vendrá después de todos los comandos de IU para la ventana.

 showWindow PivotControlMain;

Paso 11

Nuestro código completo debería verse así:

 // Función principal global proc EdW_PivotControl () pivotControl; ; // Crear el proc pivotControl () if ('(window -exists PivotControlMain') global de la UI) deleteUI PivotControlMain; ; ventana -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 200 -h 350 PivotControlMain; showWindow PivotControlMain; ;

Paso 12

Fuente en el nuevo código y ejecútelo desde la línea de comando Maya. Esto es lo que debes conseguir:

 fuente EdW_PivotControl; EdW_PivotControl; 

Paso 13

La ventana es el objeto más alto en nuestra jerarquía de interfaz de usuario. Todos los diseños y controles son hijos de este objeto. El primer diseño que usaremos es un diseño de columna, para mantener presionados los botones:

 columnLayout -adjustableColumn 1 -rowSpacing 0 EPC_MainColumnLayout;
  • -Columna ajustable (-ac) la columna se redimensionará automáticamente de acuerdo con el ancho de la ventana
  • -rowSpacing (-rs) la distancia en píxeles entre cada fila en la columna

Paso 14

Descubrí que incluir algunas instrucciones o aclaraciones en la interfaz de usuario puede hacer que el script sea más útil. Agregue un control de texto al script:

 text -l "Mover el pivote a:";
  • -etiqueta (-l) el texto real del control


Paso 15

A continuación, queremos agregar un diseño para mantener los botones en la parte superior de la ventana, para mover los pivotes. Un diseño que podemos usar es gridLayout, que crea un conjunto de celdas espaciadas uniformemente que contienen un objeto cada una.

 gridLayout -cwh 60 24 -nrc 2 5;
  • -cellWidthHeight (-cwh) establece el ancho y el alto de cada celda individual.
  • -numberOfRowsColumns (-nrc) establece el número de filas horizontales y columnas verticales en la cuadrícula


Paso 16

Cada celda de la cuadrícula puede contener un solo control. Estos se rellenan automáticamente cuando crea los objetos debajo del diseño. En nuestro caso, queremos crear nueve botones. Usaremos la marca de comando más adelante para indicar a los botones a qué procedimiento llamar:

 botón -l "Centro"; botón -l "Y Min"; botón -l "Y Max"; botón -l "Origen"; botón -l "Seleccionado"; botón -l "X min"; botón -l "X Max"; botón -l "Z min"; botón -l "Z Max";
  • -etiqueta (-l) el texto mostrado en el botón


Paso 17

Ahora, necesitamos una forma de decirle a Maya que hemos terminado con el gridLayout, y queremos agregar más elementos al columnLayout. Para hacerlo, usaremos un comando MEL para establecer el padre del gridLayout.

 setParent…;

Los… ; indica que desea ser padre del diseño un paso más arriba de la cadena de jerarquía. También podríamos usar el nombre del diseño, pero esto solo es útil si todos los diseños tienen nombres explícitos:

 setParent EPC_MainColumnLayout;

Paso 18

Nuestro script pivotControl ahora debería verse así:

 global proc pivotControl () if ('window -exists PivotControlMain') deleteUI PivotControlMain; ; ventana -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 200 -h 350 PivotControlMain; columnLayout -adjustableColumn 1 -rowSpacing 0 EPC_MainColumnLayout; text -l "Mover el pivote a:"; gridLayout -cwh 60 24 -nrc 2 5 -ag 1; botón -l "Centro"; botón -l "Y Min"; botón -l "Y Max"; botón -l "Origen"; botón -l "Seleccionado"; botón -l "X min"; botón -l "X Max"; botón -l "Z min"; botón -l "Z Max"; setParent…; showWindow PivotControlMain; ;

Paso 19

Al igual que el gridLayout, el columnLayout debe cerrarse estableciendo su principal.

setParent…;

Paso 20

Fuente en el script y ver lo que obtienes:


Paso 22

El procedimiento de interfaz de usuario se realiza!

 // Función principal global proc EdW_PivotControl () pivotControl; ; // Crear el proc pivotControl () if ('(window -exists PivotControlMain') global de la UI) deleteUI PivotControlMain; ; ventana -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 200 -h 350 PivotControlMain; columnLayout -adjustableColumn 1 -rowSpacing 0 EPC_MainColumnLayout; text -l "Mover el pivote a:"; gridLayout -cwh 60 24 -nrc 2 5 -ag 1; botón -l "Centro"; botón -l "Y Min"; botón -l "Y Max"; botón -l "Origen"; botón -l "Seleccionado"; botón -l "X min"; botón -l "X Max"; botón -l "Z min"; botón -l "Z Max"; setParent…; setParent…; showWindow PivotControlMain; ;

Paso 23

Ahora necesitamos crear el código para mover realmente el punto de pivote de un objeto. Para hacerlo, vamos a crear dos procedimientos que trabajarán juntos:

  • epc_getBounds usará un comando xform y un poco de aritmética para devolver los mínimos, máximos y promedios del cuadro delimitador.
  • epc_movePivotLocal recuperará la información del cuadro delimitador utilizando epc_getBounds para mover las ubicaciones dinámicas.

Paso 24

Coloque el pseudo-código para epc_getBounds:

  • seleccione el objeto pasado de epc_movePivotLocal
  • escribe el resultado de un comando xform consultado en una matriz
  • obtenga los promedios de los mínimos y máximos de x, y y z devueltos desde xform
  • añadir los promedios en la matriz de retorno
  • devuelve la matriz del cuadro delimitador junto con los promedios

Paso 25

cree el esqueleto para el procedimiento, complete con un tipo de retorno y un argumento pasado.

 global proc float [] epc_getBounds (string $ objSel) ;

Paso 26

seleccione el objeto pasado como argumento y obtenga la información del cuadro delimitador.

 global proc float [] epc_getBounds (string $ objSel) select -r $ objSel; float $ getBoundArray [] = 'xform -q -ws -bb'; ;
  • -consulta (-q) consulta el comando, en lugar de realmente transformar nada
  • -worldSpace (-ws) asegúrese de que
  • -boundingBox (-bb) devuelve las posiciones mínima y máxima del cuadro delimitador

El indicador -boundingBox devuelve seis valores en una matriz: x mínimo, x máximo, mínimo y, máximo z, y máximo z.


Paso 27

Calcula los promedios entre los mínimos y los máximos. Recuerde que las matrices siempre comienzan con un índice de cero..

 float $ bbXAv = (($ getBoundArray [3] + $ getBoundArray [0]) / 2); // xmax más xmin dividido por dos float $ bbYAv = (($ getBoundArray [4] + $ getBoundArray [1]) / 2); // ymax más ymin dividido por dos float $ bbZAv = (($ getBoundArray [5] + $ getBoundArray [2]) / 2); // zmax más zmin dividido por dos

Paso 28

Calcula los promedios entre los mínimos y los máximos. Recuerde que las matrices siempre comienzan con un índice de cero..

 float $ bbXAv = (($ getBoundArray [3] + $ getBoundArray [0]) / 2); // xmax más xmin dividido por dos float $ bbYAv = (($ getBoundArray [4] + $ getBoundArray [1]) / 2); // ymax más ymin dividido por dos float $ bbZAv = (($ getBoundArray [5] + $ getBoundArray [2]) / 2); // zmax más zmin dividido por dos

Paso 28

Agregue los promedios recién calculados y devuelva la matriz final.

 $ getBoundArray [6] = $ bbXAv; $ getBoundArray [7] = $ bbYAv; $ getBoundArray [8] = $ bbZAv; devuelve $ getBoundArray;

Paso 29

El procedimiento final debería verse así:

 global proc float [] epc_getBounds (string $ objSel) select -r $ objSel; float $ getBoundArray [] = 'xform -q -ws -bb'; float $ bbXAv = (($ getBoundArray [3] + $ getBoundArray [0]) / 2); float $ bbYAv = (($ getBoundArray [4] + $ getBoundArray [1]) / 2); float $ bbZAv = (($ getBoundArray [5] + $ getBoundArray [2]) / 2); $ getBoundArray [6] = $ bbXAv; $ getBoundArray [7] = $ bbYAv; $ getBoundArray [8] = $ bbZAv; devuelve $ getBoundArray; ;

Paso 30

Ahora podemos poner este código a trabajar dentro de nuestro procedimiento epc_movePivotLocal. Escribe el pseudocódigo:

  • escribir una lista de objetos seleccionados en una matriz
  • obtenga la información del cuadro delimitador para cada objeto seleccionado, utilizando el procedimiento epc_getBounds
  • crear una declaración de cambio de caso para controlar dónde se debe mover el pivote

Paso 31

Crea el esqueleto para el procedimiento. Configure un bucle for-in para que el código se ejecute una vez por cada objeto seleccionado en la escena.

 global proc epc_movePivotLocal (string $ mode) string $ sel [] = 'ls -sl'; para ($ thisObj en $ sel) // el código va aquí; ;

Paso 32

Utilice el procedimiento de retorno-valor de epc_getBounds para escribir una matriz flotante:

 float $ pos [] = 'epc_getBounds $ thisObj';

Paso 32

Ahora, usaremos una declaración de cambio de caso para mover el pivote. La estructura básica de un conmutador es la siguiente:

 switch ($ variable) // la variable puede ser de cualquier tipo, incluidas cadenas y flotantes caso variableValue: // si la variable coincide con variableValue // ejecuta este salto de código; case otherValue: // code here break; ;

La sentencia switch-case es un sistema en cascada, lo que significa que si no incluye el comando "break" después de cada caso, el resto de los casos también se ejecutarán. Para nuestro procedimiento, deseamos agregar un conmutador que nos permita usar el mismo procedimiento para mover un pivote a muchas posiciones diferentes. Nuestro conmutador se verá así:

 switch ($ mode) case "center": CenterPivot $ thisObj; descanso; caso "ymin": mueve -a -rpr $ pos [6] $ pos [1] $ pos [8] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); descanso; ;

Paso 33

Continúe agregando casos al script, para que cada uno de nuestros botones de UI tenga un caso correspondiente. El procedimiento completo debería verse así:

 global proc epc_movePivotLocal (string $ mode) string $ sel [] = 'ls -sl'; para ($ thisObj en $ sel) float $ pos [] = 'epc_getBounds $ thisObj'; switch ($ mode) case "center": CenterPivot $ thisObj; descanso; caso "ymin": mueve -a -rpr $ pos [6] $ pos [1] $ pos [8] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); descanso; caso "ymax": mover -a -rpr $ pos [6] $ pos [4] $ pos [8] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); descanso; caso "origen": mueva -a -rpr 0 0 0 ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); descanso; caso "xmin": mover -a -rpr $ pos [0] $ pos [7] $ pos [8] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); descanso; caso "xmax": mover -a -rpr $ pos [3] $ pos [7] $ pos [8] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); descanso; caso "zmin": mover -a -rpr $ pos [6] $ pos [7] $ pos [2] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); descanso; caso "zmax": mover -a -rpr $ pos [6] $ pos [7] $ pos [5] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); descanso; ; ; ;

Paso 33

Nuestro último procedimiento sigue prácticamente la misma idea..

 global proc epc_movePivotToObject () string $ selLast [] = 'ls -sl -tail 1'; string $ copyToObj = $ selLast [0]; seleccione -deseleccione $ copyToObj; string $ selSet [] = 'ls -sl'; float $ pivotSel [] = 'xform -q -piv -ws $ copyToObj'; imprimir $ pivotSel; para ($ each in $ selSet) move -a $ pivotSel [0] $ pivotSel [1] $ pivotSel [2] ($ each + ".rotatePivot") ($ each + ".scalePivot"); ; ;

Solo hay dos nuevas banderas en este procedimiento:

  • -cola (-tl) solo escribe el último objeto seleccionado en la matriz (comando ls)
  • -pivote (-piv) consulta la ubicación actual del pivote en un objeto (comando xform)

Paso 35

Ahora todo lo que queda es hacer que nuestros botones en la interfaz de usuario realmente llamen a los procedimientos que hemos escrito.

 botón -l "Centro" -c "epc_movePivotLocal center"; botón -l "Y Min" -c "epc_movePivotLocal ymin"; botón -l "Y Max" -c "epc_movePivotLocal ymax"; botón -l "Origen" -c "origen epc_movePivotLocal"; botón -l "Seleccionado" -c "epc_movePivotToObject"; botón -l "X Min" -c "epc_movePivotLocal xmin"; botón -l "X Max" -c "epc_movePivotLocal xmax"; botón -l "Z Min" -c "epc_movePivotLocal zmin"; botón -l "Z Max" -c "epc_movePivotLocal zmax";
  • -el comando (-c) llama a un comando o lista de comandos cada vez que se presiona el botón

Paso 35

Y hemos terminado!