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..
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.
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;
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.
Geef aan welke procedures we nodig hebben om dit script te maken:
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.
We beginnen ons script met het openen van die oude stand-by, Microsoft Notepad. De eerste procedure is eenvoudig:
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.
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.
We gaan kijken naar drie verschillende soorten UI-opdrachten:
Hier is een overzicht van onze schets volgens de MEL-opdrachten die zijn gebruikt om ze te maken:
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;
; // ...;
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;
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;
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; ;
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;
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;
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:";
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;
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";
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;
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; ;
Net als de gridLayout moet de columnLayout worden gesloten door het bovenliggende element in te stellen.
setParent ...;
Bron in het script en zie wat je krijgt:
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; ;
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:
Lay-out van de pseudo-code voor epc_getBounds:
maak het skelet voor de procedure, compleet met een retourneringstype en een geslaagd argument.
global proc float [] epc_getBounds (string $ objSel) ;
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'; ;
De vlag - boundingBox retourneert zes waarden in een array: x minimum, x maximum, y minimum, y maximum, z minimum en z maximum.
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
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
Voeg de nieuw berekende gemiddelden toe en retourneer de laatste array.
$ getBoundArray [6] = $ bbXAv; $ getBoundArray [7] = $ bbYAv; $ getBoundArray [8] = $ bbZAv; return $ getBoundArray;
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; ;
Nu kunnen we deze code gebruiken in onze epc_movePivotLocal-procedure. Schrijf de pseudo-code op:
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; ;
Gebruik de retour-waarde van de procedure van epc_getBounds om een float-array te schrijven:
float $ pos [] = 'epc_getBounds $ thisObj';
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; ;
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; ; ; ;
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:
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";
En we zijn klaar!