Maya MEL Procedural Modelling voor Artists - UIs

Deze zelfstudie is een inleiding tot het bouwen van grafische gebruikersinterfaces (GUI) in MEL voor Maya 2010 en lager. Maya 2011 introduceert een nieuwe methode voor het maken van GUI's die hier niet worden behandeld. We gaan over correcte codering voor gebruikersinterfaces, foutafhandeling en we zullen een zeer bruikbaar script samenstellen dat u aanzienlijke controle geeft over het draaipunt van een object..

Gebruikersinterfaces

Als je van plan bent je scripts aan een andere artiest te geven, dan kan het ongelooflijk handig zijn om een ​​gebruikersvriendelijke GUI samen te stellen die je code toegankelijk maakt voor niet-programmeurs. Tegenwoordig gebruik ik meestal geen aangepaste sneltoetsen, maar vertrouw ik op een handjevol UI's die ik in MEL heb gebouwd om Maya-processen te automatiseren. Ik kan ze bij me dragen en hoef geen voorkeuren aan te passen om comfortabel te kunnen werken op meerdere werkstations. De mogelijkheid om gebruikersinterfaces te maken en te onderhouden is een krachtige maar soms frustrerende tool in de MEL-toolkit.


Stap 1

Laten we eens kijken naar wat we vandaag gaan creëren. Begin met het opslaan van het bestand "EdW_PivotControl.mel" dat bij deze zelfstudie is toegevoegd aan uw scriptdirectory. Open Maya dan. Ik gebruik Maya 2010 voor de duur van deze tutorial, maar dezelfde code zou moeten werken voor de meeste Maya-versies. Typ het volgende in de opdrachtregel en druk op Enter:

bron EdW_PivotControl; EdW_PivotControl;

Stap 2

We zouden een venster moeten openen met een paar knoppen erop. Probeer wat geometrie te maken en experimenteer met het script. Het doel is om een ​​script te maken waarmee u on-the-fly controle hebt over draaipunten van objecten.


Stap 3

Geef aan welke procedures we nodig hebben om dit script te maken:

  • EdW_PivotControl - start de hoofdprocedure van het script
  • epc_pivotControl - maakt de gebruikersinterface
  • epc_getBounds - gebruik de opdracht xform om het selectiekader van het geselecteerde object te krijgen
  • epc_movePivotLocal - verplaatst het draaipunt van het object naar een lokale positie (y min, x min, etc.)
  • epc_movePivotToObject - verplaatst het draaipunt naar de locatie van een ander object

Ik gebruik epc_ als mijn voorvoegsel. Net als in eerdere zelfstudies wilt u ervoor zorgen dat uw procedures unieke namen hebben, zodat u zich niet met andere scripts bemoeit.


Stap 4

We beginnen ons script met het openen van die oude stand-by, Microsoft Notepad. De eerste procedure is eenvoudig:


Stap 5

Sla uw bestand op. Zorg er bij het opslaan van een MEL-document voor dat u "Alle bestanden" kiest onder "opslaan als type". Sla uw document op als een .mel-bestand in uw Maya-scripts-map. Ik gebruik EdW_PivotControl.mel als mijn bestandsnaam, maar voel je vrij om te kiezen wat je wilt.


Stap 6

Nu komen we bij het moeilijke gedeelte. Het creëren van gebruikersinterfaces in MEL is nog nooit een bijzonder elegant proces geweest, dus ik zal mijn best doen om het proces zo pijnvrij mogelijk te maken. Soms is het het beste om gewoon iets op papier te tekenen voordat we beginnen met het schrijven van code, dus schets een basislayout voor hoe je de uiteindelijke gebruikersinterface eruit wilt laten zien. Dit script is vrij eenvoudig, maar als je begint om te gaan met tabbladen, menu's, schuifbalken, enz., Wil je zeker weten dat je een plan voor een game hebt.


Stap 7

We gaan kijken naar drie verschillende soorten UI-opdrachten:

  • Windows - objecten op het hoogste niveau met de standaardknoppen van een OS-venster, zoals minimaliseren, maximaliseren en sluiten.
  • Lay-outs - verschillende manieren om de objecten in een venster te ordenen.
  • Besturing - knoppen, schuifregelaars, tekstvelden, etc. Dit zijn de interactieve elementen van de gebruikersinterface.

Hier is een overzicht van onze schets volgens de MEL-opdrachten die zijn gebruikt om ze te maken:


Stap 8

De eerste stap bij het maken van de gebruikersinterface is om het venster te maken. Omdat ons Window-object een unieke naam heeft, kan Maya niet tegelijkertijd twee vensters van hetzelfde venster openen. Het eerste deel van onze procedure controleert of het venster al open is en sluit het als het is.

 // Maak UI global proc pivotControl () 
if ('window-existeert PivotControlMain')
deleteUI PivotControlMain;
; // ...;

Stap 9

Laten we nu proberen een venster in de code te maken en te kijken wat er gebeurt:

 window -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 450 -h 300 PivotControlHain;
  • -resizeToFitChildren (-rtf) als true, wordt het formaat van het venster automatisch aangepast aan alle lay-outs en besturingselementen die u maakt
  • -titel (-t) de tekst die wordt weergegeven in de titelbalk boven aan het venster
  • -minimalButton (-mnb) schakelt de minimalisatieknop in of uit
  • -OptimizeButton (-mxb) schakelt de knop Maximaliseren in of uit
  • -breedte (-w) breedte van het venster in pixels
  • -hoogte (-h) hoogte van het venster in pixels

Stap 10

Op dit moment is het venster binnen het script gemaakt, maar een ander commando is nodig om het te tonen. Deze opdracht komt altijd na alle UI-opdrachten voor het venster.

 showWindow PivotControlMain;

Stap 11

Onze volledige code zou er als volgt uit moeten zien:

 // Hoofdfunctie global proc EdW_PivotControl () pivotControl; ; // Maak de UI global proc pivotControl () if ('window-existing PivotControlMain') deleteUI PivotControlMain; ; window -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 200 -h 350 PivotControlHain; showWindow PivotControlMain; ;

Stap 12

Bron in de nieuwe code en voer deze uit vanaf de Maya-opdrachtregel. Dit is wat je zou moeten krijgen:

 bron EdW_PivotControl; EdW_PivotControl; 

Stap 13

Het venster is het bovenste object in onze UI-hiërarchie. Alle lay-outs en besturingselementen zijn kinderen van dit object. De eerste lay-out die we zullen gebruiken is een kolomlay-out, om de knoppen vast te houden:

 columnLayout -justableColumn 1 -rowSpacing 0 EPC_MainColumnLayout;
  • -adjustableColumn (-ac) de kolom wordt automatisch aangepast aan de breedte van het venster
  • -rowSpacing (-rs) de afstand in pixels tussen elke rij in de kolom

Stap 14

Ik heb gemerkt dat het toevoegen van enkele instructies of verduidelijkingen in de gebruikersinterface het script bruikbaarder kan maken. Voeg een tekstcontrole toe aan het script:

 text -l "Move Pivot To:";
  • -label (-l) de feitelijke tekst van het besturingselement


Stap 15

Vervolgens willen we een lay-out toevoegen om de knoppen bovenaan het venster te houden, voor het verplaatsen van de draaipunten. Een lay-out die we kunnen gebruiken is gridLayout, waarmee een set cellen met gelijkmatige tussenruimten wordt gemaakt die elk één object bevatten.

 gridLayout -cwh 60 24 -nrc 2 5;
  • -celWidthHeight (-cwh) stelt de breedte en hoogte in van elke afzonderlijke cel.
  • -numberOfRowsColumns (-nrc) stelt het aantal horizontale rijen en verticale kolommen in het raster in


Stap 16

Elke cel in het raster kan één besturingselement bevatten. Deze worden automatisch ingevuld wanneer u de objecten onder de lay-out maakt. In ons geval willen we negen knoppen maken. We zullen de -command-vlag later gebruiken om aan de knoppen te vertellen welke procedure moet worden aangeroepen:

 knop -l "Center"; knop - l "Y Min"; knop - l "Y Max"; knop -l "Oorsprong"; knop -l "Geselecteerd"; knop - l "X Min"; knop - l "X Max"; knop - l "Z Min"; knop -l "Z Max";
  • -label (-l) de tekst die op de knop wordt weergegeven


Stap 17

Nu hebben we een manier nodig om Maya te vertellen dat we klaar zijn met de gridLayout, en we willen meer elementen toevoegen aan de columnLayout. Om dit te doen, zullen we een MEL-opdracht gebruiken om de ouder van de gridLayout in te stellen.

 setParent ...;

De… ; geeft aan dat u een bovenliggend element wilt van de lay-out één stap hoger in de hiërarchieketen. We kunnen ook de naam van de lay-out gebruiken, maar dit is alleen nuttig als alle lay-outs expliciete namen hebben:

 setParent EPC_MainColumnLayout;

Stap 18

Ons pivotControl-script zou er nu als volgt uit moeten zien:

 global proc pivotControl () if ('window-existeert PivotControlMain') deleteUI PivotControlMain; ; window -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 200 -h 350 PivotControlHain; columnLayout -justableColumn 1 -rowSpacing 0 EPC_MainColumnLayout; text -l "Move Pivot To:"; gridLayout -cwh 60 24 -nrc 2 5 -ag 1; knop -l "Center"; knop - l "Y Min"; knop - l "Y Max"; knop -l "Oorsprong"; knop -l "Geselecteerd"; knop - l "X Min"; knop - l "X Max"; knop - l "Z Min"; knop -l "Z Max"; setParent ...; showWindow PivotControlMain; ;

Stap 19

Net als de gridLayout moet de columnLayout worden gesloten door het bovenliggende element in te stellen.

setParent ...;

Stap 20

Bron in het script en zie wat je krijgt:


Stap 22

De UI-procedure is voltooid!

 // Hoofdfunctie global proc EdW_PivotControl () pivotControl; ; // Maak de UI global proc pivotControl () if ('window-existing PivotControlMain') deleteUI PivotControlMain; ; window -rtf 1 -t "EdW Pivot Control" -mnb 1 -mxb 1 -w 200 -h 350 PivotControlHain; columnLayout -justableColumn 1 -rowSpacing 0 EPC_MainColumnLayout; text -l "Move Pivot To:"; gridLayout -cwh 60 24 -nrc 2 5 -ag 1; knop -l "Center"; knop - l "Y Min"; knop - l "Y Max"; knop -l "Oorsprong"; knop -l "Geselecteerd"; knop - l "X Min"; knop - l "X Max"; knop - l "Z Min"; knop -l "Z Max"; setParent ...; setParent ...; showWindow PivotControlMain; ;

Stap 23

Nu moeten we de code maken om het draaipunt van een object daadwerkelijk te verplaatsen. Om dit te doen, gaan we twee procedures maken die samenwerken:

  • epc_getBounds gebruikt een xform-commando en een beetje rekenkundig om de minimumlimieten, maxima en gemiddelden van het selectiekader terug te geven.
  • epc_movePivotLocal haalt de bounding box-informatie op met behulp van epc_getBounds om de spillocaties te verplaatsen.

Stap 24

Lay-out van de pseudo-code voor epc_getBounds:

  • selecteer het object doorgegeven vanuit epc_movePivotLocal
  • schrijf het resultaat van een opgevraagd xform-commando naar een array
  • krijg de gemiddelden van de x, y, en z-minima en maxima terug van de xform
  • voeg de gemiddelden toe aan de return-array
  • retourneer de matrix van de bounding box samen met de gemiddelden

Stap 25

maak het skelet voor de procedure, compleet met een retourneringstype en een geslaagd argument.

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

Stap 26

selecteer het object dat als een argument is doorgegeven en ontvang de informatie over het selectiekader.

 global proc float [] epc_getBounds (string $ objSel) select -r $ objSel; float $ getBoundArray [] = 'xform -q -ws -bb'; ;
  • -query (-q) query op de opdracht, in plaats van daadwerkelijk iets te transformeren
  • -worldSpace (-ws) zorg ervoor dat de
  • -boundingBox (-bb) retourneert de min- en max-posities van het selectiekader

De vlag - boundingBox retourneert zes waarden in een array: x minimum, x maximum, y minimum, y maximum, z minimum en z maximum.


Stap 27

bereken de gemiddelden tussen de minima en maxima. Vergeet niet dat arrays altijd beginnen met een index van nul.

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

Stap 28

bereken de gemiddelden tussen de minima en maxima. Vergeet niet dat arrays altijd beginnen met een index van nul.

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

Stap 28

Voeg de nieuw berekende gemiddelden toe en retourneer de laatste array.

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

Stap 29

De laatste procedure zou er als volgt uit moeten zien:

 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; ;

Stap 30

Nu kunnen we deze code gebruiken in onze epc_movePivotLocal-procedure. Schrijf de pseudo-code op:

  • schrijf een lijst met geselecteerde objecten naar een array
  • ontvang de begrenzingsvakinformatie voor elk geselecteerd object, met behulp van de epc_getBounds-procedure
  • maak een switch-case statement om te bepalen waar het draaipunt naartoe moet gaan

Stap 31

maak het skelet voor de procedure. Stel een for-in-lus in zodat de code eenmaal wordt uitgevoerd voor elk object dat in de scène is geselecteerd.

 global proc epc_movePivotLocal (string $ mode) string $ sel [] = 'ls -sl'; voor ($ thisObj in $ sel) // code gaat hier; ;

Stap 32

Gebruik de retour-waarde van de procedure van epc_getBounds om een ​​float-array te schrijven:

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

Stap 32

Nu gebruiken we een switch-case statement om het draaipunt echt te verplaatsen. De basisstructuur van een schakelkast is deze:

 switch ($ variable) // de variabele kan van elk type zijn, inclusief strings en floats case variableValue: // als de variabele overeenkomt met variableValue // voer deze code-einde uit; case otherValue: // code here break; ;

De switch-case-instructie is een trapsgewijs systeem, wat betekent dat als u na elke case het commando "break" niet opneemt, de rest van de cases ook wordt uitgevoerd. Voor onze procedure willen we een switch-case toevoegen waarmee we dezelfde procedure kunnen gebruiken om een ​​spil naar veel verschillende posities te verplaatsen. Onze switch-case ziet er als volgt uit:

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

Stap 33

Ga door met het toevoegen van cases aan het script, zodat elk van onze UI-knoppen een overeenkomstige case heeft. De volledige procedure zou er als volgt uit moeten zien:

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

Stap 33

Onze laatste procedure volgt vrijwel hetzelfde idee.

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

Er zijn slechts twee nieuwe vlaggen in deze procedure:

  • -tail (-tl) schrijft alleen het laatste object dat in de array is geselecteerd (ls-opdracht)
  • -pivot (-piv) zoekt naar de huidige locatie van het draaipunt op een object (xform-opdracht)

Stap 35

Nu rest ons alleen nog maar dat onze knoppen in de gebruikersinterface de procedures bellen die we hebben geschreven.

 knop -l "Center" -c "epc_movePivotLocal center"; knop -l "Y Min" -c "epc_movePivotLocal ymin"; knop -l "Y Max" -c "epc_movePivotLocal ymax"; knop -l "Oorsprong" -c "epc_movePivotLocal origin"; knop -l "Selected" -c "epc_movePivotToObject"; knop -l "X Min" -c "epc_movePivotLocal xmin"; knop -l "X Max" -c "epc_movePivotLocal xmax"; knop -l "Z Min" -c "epc_movePivotLocal zmin"; knop -l "Z Max" -c "epc_movePivotLocal zmax";
  • -command (-c) roept een commando of lijst met opdrachten aan telkens wanneer op de knop wordt gedrukt

Stap 35

En we zijn klaar!