Maya MEL Modellazione procedurale per artisti - UI

Questo tutorial è un'introduzione alla costruzione di interfacce utente grafiche (GUI) in MEL per Maya 2010 e versioni successive. Maya 2011 introduce una nuova metodologia per la creazione di GUI che non saranno trattate qui. Discuteremo la corretta codifica per le interfacce utente, la gestione degli errori e creeremo uno script molto utile che ti offre un controllo considerevole sul punto di rotazione di un oggetto.

Interfacce utente

Se hai intenzione di dare i tuoi script ad un altro artista, allora può essere incredibilmente utile mettere insieme una GUI user-friendly che rende il tuo codice accessibile ai non programmatori. In questi giorni, utilizzo raramente i tasti di scelta rapida personalizzati, affidandosi invece a una manciata di interfacce utente che ho creato in MEL per automatizzare i processi di Maya. Posso portarli con me e non devo modificare alcuna preferenza per lavorare comodamente su più postazioni di lavoro. La possibilità di creare e gestire interfacce utente è uno strumento potente ma a volte frustrante nel toolkit MEL.


Passo 1

Diamo un'occhiata a ciò che creeremo oggi. Inizia salvando il file "EdW_PivotControl.mel" incluso con questo tutorial nella directory degli script. Quindi apri Maya. Userò Maya 2010 per la durata di questo tutorial, ma lo stesso codice dovrebbe funzionare per la maggior parte delle versioni di Maya. Digitare quanto segue nella riga di comando e premere Invio:

fonte EdW_PivotControl; EdW_PivotControl;

Passo 2

Dovremmo avere una finestra aperta con alcuni pulsanti su di essa. Prova a creare geometrie e sperimenta con lo script. L'obiettivo è creare uno script che ti dia il controllo immediato sui punti di pivot degli oggetti.


Passaggio 3

Definire le procedure di cui avremo bisogno per realizzare questo script:

  • EdW_PivotControl - avvia la procedura principale dello script
  • epc_pivotControl - crea l'interfaccia utente
  • epc_getBounds: utilizza il comando xform per ottenere il riquadro di delimitazione dell'oggetto selezionato
  • epc_movePivotLocal - sposta il pivot dell'oggetto su una posizione locale (y min, x min, ecc.)
  • epc_movePivotToObject: sposta il pivot nella posizione di un altro oggetto

Sto usando epc_ come prefisso. Come nei tutorial precedenti, si desidera assicurarsi che le procedure abbiano nomi univoci, in modo da non interferire con altri script.


Passaggio 4

Inizieremo il nostro script aprendo il vecchio standby, Microsoft Notepad. La prima procedura è semplice:


Passaggio 5

Salva il tuo file. Quando si salva un documento MEL, assicurarsi di selezionare "Tutti i file" sotto "salva come tipo". Salva il documento come file .mel nella directory degli script Maya. Userò EdW_PivotControl.mel come nome del mio file, ma mi sento libero di scegliere quello che ti piace.


Passaggio 6

Ora arriviamo alla parte difficile. La creazione di interfacce utente in MEL non è mai stata un processo particolarmente elegante, quindi farò del mio meglio per rendere il processo il più semplice possibile. A volte, è meglio disegnare qualcosa su carta prima di iniziare a scrivere il codice, in modo da delineare un layout di base per ciò che si desidera che l'interfaccia utente finale assomigli. Questo script è piuttosto semplice, ma quando inizi a trattare tab, menu, barre di scorrimento, ecc., Devi assicurarti di avere in mente un piano di gioco.


Passaggio 7

Stiamo andando a guardare tre diversi tipi di comandi dell'interfaccia utente:

  • Windows: oggetti di livello superiore con i pulsanti standard di qualsiasi finestra del sistema operativo, ad esempio Riduci a icona, Ingrandisci e Chiudi.
  • Layout: diversi modi di organizzare gli oggetti all'interno di una finestra.
  • Controlli: pulsanti, cursori, campi di testo, ecc. Questi sono gli elementi interattivi dell'interfaccia utente.

Ecco una ripartizione del nostro schizzo in base ai comandi MEL utilizzati per crearli:


Passaggio 8

Il primo passo per creare l'interfaccia utente è stabilire la finestra. Poiché il nostro oggetto Window avrà un nome univoco, Maya non può avere due della stessa finestra aperta in una volta. La prima parte della nostra procedura controlla se la finestra è già aperta e la chiude se lo è.

 // Crea UI global proc pivotControl () 
if ('window -exists PivotControlMain')
deleteUI PivotControlMain;
; // ...;

Passaggio 9

Ora proviamo a creare una finestra nel codice e vediamo cosa succede:

 window -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 450 -h 300 PivotControlMain;
  • -resizeToFitChildren (-rtf) se true, la finestra verrà ridimensionata automaticamente per adattarsi a tutti i layout e ai controlli creati
  • -title (-t) il testo visualizzato nella barra del titolo nella parte superiore della finestra
  • -minimizza pulsante (-mnb) attiva o disattiva il pulsante di riduzione a icona
  • -maximButton (-mxb) abilita o disabilita il pulsante di ingrandimento
  • -larghezza (-w) larghezza della finestra in pixel
  • -altezza (-h) altezza della finestra in pixel

Passaggio 10

In questo momento, la finestra è stata creata all'interno dello script, ma è necessario un altro comando per mostrarlo. Questo comando verrà sempre dopo tutti i comandi dell'interfaccia utente per la finestra.

 showWindow PivotControlMain;

Passaggio 11

Il nostro codice completo dovrebbe assomigliare a questo:

 // Main Function global proc EdW_PivotControl () pivotControl; ; // Crea l'UI globale proc pivotControl () if ('window -exists PivotControlMain') deleteUI PivotControlMain; ; window -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 200 -h 350 PivotControlMain; showWindow PivotControlMain; ;

Passaggio 12

Fonte nel nuovo codice ed eseguilo dalla riga di comando di Maya. Questo è ciò che dovresti ottenere:

 fonte EdW_PivotControl; EdW_PivotControl; 

Passaggio 13

La finestra è l'oggetto più in alto nella nostra gerarchia dell'interfaccia utente. Tutti i layout e i controlli sono figli di questo oggetto. Il primo layout che useremo è un layout di colonna, per contenere i pulsanti:

 columnLayout -adjustableColumn 1 -rowSpacing 0 EPC_MainColumnLayout;
  • -adjustableColumn (-ac) la colonna verrà ridimensionata automaticamente in base alla larghezza della finestra
  • -rowSpacing (-rs) la distanza in pixel tra ogni riga nella colonna

Passaggio 14

Ho scoperto che includere alcune istruzioni o chiarimenti all'interno dell'interfaccia utente può rendere lo script più utilizzabile. Aggiungi un controllo di testo allo script:

 text -l "Move Pivot To:";
  • -etichetta (-l) il testo effettivo del controllo


Passaggio 15

Successivamente, vogliamo aggiungere un layout per contenere i pulsanti nella parte superiore della finestra, per spostare i perni. Un layout che possiamo usare è gridLayout, che crea un insieme di celle equidistanti che contengono un oggetto ciascuna.

 gridLayout -cwh 60 24 -nrc 2 5;
  • -cellWidthHeight (-cwh) imposta la larghezza e l'altezza di ogni singola cella.
  • -numberOfRowsColumns (-nrc) imposta il numero di righe orizzontali e colonne verticali nella griglia


Passaggio 16

Ogni cella nella griglia può contenere un singolo controllo. Questi vengono riempiti automaticamente quando si creano gli oggetti sotto il layout. Nel nostro caso, vogliamo creare nove pulsanti. Utilizzeremo la flag -command in un secondo momento per indicare ai pulsanti quale procedura chiamare:

 pulsante -l "Centro"; pulsante -l "Y Min"; pulsante -l "Y Max"; pulsante -l "Origine"; pulsante -l "Selezionato"; pulsante -l "X Min"; pulsante -l "X Max"; pulsante -l "Z Min"; pulsante -l "Z Max";
  • -etichetta (-l) il testo visualizzato sul pulsante


Passaggio 17

Ora, abbiamo bisogno di un modo per dire a Maya che abbiamo finito con gridLayout, e vogliamo aggiungere più elementi alla colonnaLayout. Per fare ciò, useremo un comando MEL per impostare il genitore del gridLayout.

 setParent ...;

Il… ; indica che si desidera eseguire il padre del layout con un gradino verso l'alto della catena gerarchica. Potremmo anche usare il nome del layout, ma questo è utile solo se tutti i layout hanno nomi espliciti:

 setParent EPC_MainColumnLayout;

Passaggio 18

Il nostro script pivotControl dovrebbe ora assomigliare a questo:

 global proc pivotControl () if ('window -exists PivotControlMain') deleteUI PivotControlMain; ; window -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 200 -h 350 PivotControlMain; columnLayout -adjustableColumn 1 -rowSpacing 0 EPC_MainColumnLayout; text -l "Move Pivot To:"; gridLayout -cwh 60 24 -nrc 2 5 -ag 1; pulsante -l "Centro"; pulsante -l "Y Min"; pulsante -l "Y Max"; pulsante -l "Origine"; pulsante -l "Selezionato"; pulsante -l "X Min"; pulsante -l "X Max"; pulsante -l "Z Min"; pulsante -l "Z Max"; setParent ...; showWindow PivotControlMain; ;

Passaggio 19

Proprio come il gridLayout, il columnLayout deve essere chiuso impostando il suo parent.

setParent ...;

Passaggio 20

Fonte nella sceneggiatura e vedi cosa ottieni:


Passaggio 22

La procedura dell'interfaccia utente è stata completata!

 // Main Function global proc EdW_PivotControl () pivotControl; ; // Crea l'UI globale proc pivotControl () if ('window -exists PivotControlMain') deleteUI PivotControlMain; ; window -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 200 -h 350 PivotControlMain; columnLayout -adjustableColumn 1 -rowSpacing 0 EPC_MainColumnLayout; text -l "Move Pivot To:"; gridLayout -cwh 60 24 -nrc 2 5 -ag 1; pulsante -l "Centro"; pulsante -l "Y Min"; pulsante -l "Y Max"; pulsante -l "Origine"; pulsante -l "Selezionato"; pulsante -l "X Min"; pulsante -l "X Max"; pulsante -l "Z Min"; pulsante -l "Z Max"; setParent ...; setParent ...; showWindow PivotControlMain; ;

Passaggio 23

Ora dobbiamo creare il codice per spostare effettivamente il punto di rotazione di un oggetto. Per fare ciò, creeremo due procedure che funzioneranno insieme:

  • epc_getBounds utilizzerà un comando xform e un po 'di aritmetica per restituire i limiti minimi, i massimi e le medie del riquadro di delimitazione.
  • epc_movePivotLocal recupererà le informazioni del riquadro di delimitazione utilizzando epc_getBounds per spostare le posizioni dei pivot.

Passaggio 24

Disporre lo pseudo-codice per epc_getBounds:

  • seleziona l'oggetto passato da epc_movePivotLocal
  • scrivere il risultato di un comando xform interrogato su un array
  • ottenere le medie dei minimi x, ye z raggiunti da xform
  • aggiungere le medie sull'array di restituzione
  • restituisce l'array del riquadro di delimitazione insieme alle medie

Passaggio 25

creare lo scheletro per la procedura, completo di un tipo restituito e un argomento passato.

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

Passaggio 26

seleziona l'oggetto passato come argomento e ottieni le informazioni sul riquadro di delimitazione.

 global proc float [] epc_getBounds (string $ objSel) select -r $ objSel; float $ getBoundArray [] = 'xform -q -ws -bb'; ;
  • -query (-q) richiede il comando, invece di trasformare effettivamente qualcosa
  • -worldSpace (-ws) assicurarsi che il
  • -boundingBox (-bb) restituisce le posizioni min e max del riquadro di delimitazione

Il flag -boundingBox restituisce sei valori in un array: x minimo, x massimo, y minimo, y massimo, z minimo e z massimo.


Passo 27

calcolare le medie tra il minimo e il massimo. Ricorda che gli array iniziano sempre con un indice pari a zero.

 float $ bbXAv = (($ getBoundArray [3] + $ getBoundArray [0]) / 2); // xmax plus xmin diviso per due float $ bbYAv = (($ getBoundArray [4] + $ getBoundArray [1]) / 2); // ymax plus ymin diviso per due float $ bbZAv = (($ getBoundArray [5] + $ getBoundArray [2]) / 2); // zmax plus zmin diviso per due

Passaggio 28

calcolare le medie tra il minimo e il massimo. Ricorda che gli array iniziano sempre con un indice pari a zero.

 float $ bbXAv = (($ getBoundArray [3] + $ getBoundArray [0]) / 2); // xmax plus xmin diviso per due float $ bbYAv = (($ getBoundArray [4] + $ getBoundArray [1]) / 2); // ymax plus ymin diviso per due float $ bbZAv = (($ getBoundArray [5] + $ getBoundArray [2]) / 2); // zmax plus zmin diviso per due

Passaggio 28

Aggiungere le medie calcolate di recente e restituire l'array finale.

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

Passaggio 29

La procedura finale dovrebbe assomigliare a questa:

 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; return $ getBoundArray; ;

Passaggio 30

Ora possiamo far funzionare questo codice all'interno della nostra procedura epc_movePivotLocal. Scrivi lo pseudo-codice:

  • scrivere una lista di oggetti selezionati in una matrice
  • ottenere le informazioni sul riquadro di delimitazione per ciascun oggetto selezionato, utilizzando la procedura epc_getBounds
  • creare un'istruzione switch-case per controllare dove deve passare il pivot

Passaggio 31

crea lo scheletro per la procedura. Imposta un ciclo for-in in modo che il codice venga eseguito una volta per ogni oggetto selezionato nella scena.

 global proc epc_movePivotLocal (stringa $ mode) string $ sel [] = 'ls -sl'; for ($ thisObj in $ sel) // code goes here; ;

Passo 32

Utilizzare la procedura valore di ritorno da epc_getBounds per scrivere un array float:

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

Passo 32

Ora, useremo un'istruzione switch-case per spostare effettivamente il pivot. La struttura di base di un caso di commutazione è questa:

 switch ($ variable) // la variabile può essere di qualsiasi tipo, inclusi stringhe e float caso variabileValore: // se la variabile corrisponde a variabileValore // esegue questa interruzione di codice; caso altroValore: // codice qui break; ;

L'istruzione switch-case è un sistema a cascata, il che significa che se non si include il comando "break" dopo ogni caso, verrà eseguito anche il resto dei casi. Per la nostra procedura, vogliamo aggiungere un interruttore che consentirà di utilizzare la stessa procedura per spostare un pivot in molte posizioni diverse. La nostra centralina sarà simile a questa:

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

Passaggio 33

Continua ad aggiungere casi allo script, in modo che ciascuno dei nostri pulsanti dell'interfaccia utente abbia un caso corrispondente. La procedura completa dovrebbe assomigliare a questa:

 global proc epc_movePivotLocal (stringa $ mode) string $ sel [] = 'ls -sl'; for ($ thisObj in $ sel) float $ pos [] = 'epc_getBounds $ thisObj'; switch ($ mode) case "center": CenterPivot $ thisObj; rompere; case "ymin": move -a -rpr $ pos [6] $ pos [1] $ pos [8] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); rompere; case "ymax": move -a -rpr $ pos [6] $ pos [4] $ pos [8] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); rompere; caso "origine": move -a -rpr 0 0 0 ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); rompere; case "xmin": move -a -rpr $ pos [0] $ pos [7] $ pos [8] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); rompere; case "xmax": move -a -rpr $ pos [3] $ pos [7] $ pos [8] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); rompere; caso "zmin": move -a -rpr $ pos [6] $ pos [7] $ pos [2] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); rompere; caso "zmax": move -a -rpr $ pos [6] $ pos [7] $ pos [5] ($ thisObj + ".rotatePivot") ($ thisObj + ".scalePivot"); rompere; ; ; ;

Passaggio 33

La nostra ultima procedura segue praticamente la stessa idea.

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

Ci sono solo due nuovi flag in questa procedura:

  • -tail (-tl) scrive solo l'ultimo oggetto selezionato nell'array (comando ls)
  • -pivot (-piv) interroga la posizione corrente del pivot su un oggetto (comando xform)

Passaggio 35

Ora non resta che rendere i nostri pulsanti nell'interfaccia utente effettivamente chiamate le procedure che abbiamo scritto.

 pulsante -l "Centro" -c "epc_movePivotCentro locale"; pulsante -l "Y Min" -c "epc_movePivotLocal ymin"; pulsante -l "Y Max" -c "epc_movePivotLocal ymax"; button -l "Origin" -c "epc_movePivotLocal origin"; button -l "Selected" -c "epc_movePivotToObject"; button -l "X Min" -c "epc_movePivotLocal xmin"; button -l "X Max" -c "epc_movePivotLocal xmax"; pulsante -l "Z Min" -c "epc_movePivotLocal zmin"; pulsante -l "Z Max" -c "epc_movePivotLocal zmax";
  • -comando (-c) chiama un comando o un elenco di comandi ogni volta che si preme il pulsante

Passaggio 35

E abbiamo finito!