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..
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..
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;
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..
Determine qué procedimientos necesitaremos para hacer este script:
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..
Comenzaremos nuestro script abriendo ese antiguo modo de espera, el Bloc de notas de Microsoft. El primer procedimiento es fácil:
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.
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..
Vamos a ver tres tipos diferentes de comandos UI:
Aquí hay un desglose de nuestro boceto de acuerdo con los comandos de MEL utilizados para crearlos:
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;
; //…;
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;
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;
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; ;
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;
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;
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:";
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;
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";
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;
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; ;
Al igual que el gridLayout, el columnLayout debe cerrarse estableciendo su principal.
setParent…;
Fuente en el script y ver lo que obtienes:
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; ;
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:
Coloque el pseudo-código para epc_getBounds:
cree el esqueleto para el procedimiento, complete con un tipo de retorno y un argumento pasado.
global proc float [] epc_getBounds (string $ objSel) ;
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'; ;
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.
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
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
Agregue los promedios recién calculados y devuelva la matriz final.
$ getBoundArray [6] = $ bbXAv; $ getBoundArray [7] = $ bbYAv; $ getBoundArray [8] = $ bbZAv; devuelve $ getBoundArray;
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; ;
Ahora podemos poner este código a trabajar dentro de nuestro procedimiento epc_movePivotLocal. Escribe el pseudocódigo:
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í; ;
Utilice el procedimiento de retorno-valor de epc_getBounds para escribir una matriz flotante:
float $ pos [] = 'epc_getBounds $ thisObj';
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; ;
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; ; ; ;
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:
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";
Y hemos terminado!