Prima di iniziare a scrivere script è importante avere almeno un'idea generale di quale sia la sintassi di MEL. Chi di voi sappia programmare in C++ o in PHP potrà probabilmente passare molto velocemente questa parte del tutorial, in quanto la sintassi di MEL è molto simile a quella di questi due linguaggi.

VARIABILI

MEL supporta tre tipi principali di dati, definiti dalle keyword int, float e string

int : numeri interi (cioè senza decimali). Es. 5  7  -14
float: numeri reali. Es. 5.34   -7.2375  8.1
string: una sequenza di caratteri. Es. "ciao"  "prova"  "2fd89#$&2jd__+123-a"

Per dichiarare una variabile in MEL sarà sufficiente utilizzare una di queste tre keyword e metterla prima del nome della variabile. I nomi di variabili in MEL devono sempre iniziare con $ e possono essere costituiti da una qualsiasi serie di lettere, numeri e underscore (_); l'unica eccezione è che il nome non può iniziare con un numero.

Ad esempio sono nomi di variabili validi:

$var1  
$prova  
$nome_molto_lungo_1

Mentre non sono validi:

$5aaa (c'è un numero appena dopo il $)
$abc*d (contiene un carattere non valido)
abc (non inizia con $)

Ad esempio, per dichiarare una variabile intera e assegnarle il valore 5 possiamo scrivere:

int $var1;
$var1 = 5;

o anche, in modo più compatto:

int $var1 = 5;

Notare che la keyword int (o float o string) va messa solamente quando la variabile viene dichiarata, cioè la prima volta che la usate.

MEL tuttavia supporta anche l'implicit casting, cioè se non specifichiamo il tipo della variabile, Maya prenderà quello più ovvio, ad es:

$a = 4;
$b = 4.5;
$c = "Ciao";

$a verrà interpretata come int, $b come float e $c come string.
Ovviamente, se il tipo viene specificato esplicitamente, Maya userà quello, quindi:

float $b = 4;

tratterà $b come float, anche se gli assegnamo un valore intero (è come se avessimo scritto 4.0)
ATTENZIONE! Una volta che avete dichiarato una variabile in un certo modo, non potete usare lo stesso nome per una variabile di un altro tipo, anche se in un altro script. Quindi, se avete dichiarato $a come int, una volta eseguito lo script non potrete più dichiarare float $a (a meno di non chiudere Maya e riaprirlo).

Ovviamente con le variabili int e float possiamo fare le normali operazioni matematiche, usando + - * e /

Ad esempio:

$a = 5;
$b = 8;
print ($a+$B);

Il comando print ha come effetto quello di scrivere quello che gli viene passato come parametro, in questo caso scriverà 13 (l'output si vede nella parte superiore dello script editor).
Un operatore che spesso torna utile è l'operatore modulo, che ha come simbolo % e restituisce il resto di una divisione intera. Ad esempio

$a = 7;
print($a % 3);

Scriverà 1 (7/3 = 2 con il resto di 1)

MEL supporta anche degli operatori particolari, che sono ++  --  +=  -=  *= e /=
Questi sono delle "scorciatoie" per modificare il valore di una variabile.
In particolare:

$a++ equivale a $a = $a + 1
$a-- equivale a $a = $a – 1
$a += 5  equivale a $a = $a + 5
$a -= 5  equivale a $a = $a - 5
$a *= 5  equivale a $a = $a * 5
$a /= 5  equivale a $a = $a / 5

Per quanto riguarda le stringhe, invece, MEL supporta l'operatore + per concatenare le stringhe
Ad esempio:
$str1 = "Ciao";
$str2 = ", come stai?";
$str3 = $str1 + $str2;
print($str3);

Darà come output

Ciao, come stai?

Un'altra cosa da notare è che è possibile concatenare una stringa ad un numero, come in questo esempio:

$num = 15;
print ("Il valore di num è " + $num);

MEL è anche in grado di gestire vettori 3D (utili per direzioni, posizioni etc) oltre ad array e matrici di dati.

Per definire un vettore 3D basta scrivere:

float $vett = <<1, 2.5, 3.2>>;

Questo definirà un vettore 3D, le cui componenti sono accessibile tramite l'operatore .

print ($vett.x);
print ($vett.y);
print ($vett.z);

Se invece vogliamo definire un array di dati (cioè una lista di valori) usiamo l'operatore []:

int $arr1[50];

definirà un array di 50 elementi interi, a cui potremo accedere usando:

$arr[0]
$arr[1]

$arr[49]

(ricordarsi sempre che si inizia da 0!!!)

Se non sappiamo a priori la dimensione dell'array, possiamo sempre tralasciarla: Maya si occuperà di dimensionare correttamente l'array:

int $arr[];
arr[10] = 5;

La seconda riga assegna un valore all'11° elemento di arr (si parte da 0!) quindi in automatico Maya allocherà memoria per 11 elementi interi. State attenti all'utilizzo di questa caratteristica di Maya! Scrivere:

arr[1234567890] = 10;

farà allocare memoria per 1234567891 interi, generalmente facendo andare in crash Maya.

Possiamo inizializzare il vettore racchiudendo i valori fra parentesi graffe, ad esempio:

int $prova[3] = {1, 2, 3};

Un comando utile quando si usano gli array è size che restituisce la dimensione dell'array. Provate ad esempio questo script:

int $prova2[] = {0,1,2,3,4,5,6,7,8,9,10};
$dimprova = size($prova2);
print($dimprova);

Simili agli array sono le matrici, che possiamo considerare come array bidimensionali e si definiscono in maniera simile:

int $matr1[10][20];

definirà una matrice con 10 righe e 20 colonne di numeri interi. Le dimensioni della matrice, contrariamente a quanto avviene per gli array devono necessariamente essere specificate. Per inizializzare i valori si usa (notare che l'incolonnamento è solo una cosa "grafica" per meglio comprendere il codice, potreste scrivere anche tutto sulla stessa riga senza problemi):

int $matr2[4][3] = << 2, 5, 7;
					 10, -5, -8;
					 6, 7, 4;
					 1, 0, 1>>;

Se non si inseriscono tutti i valori (es. se nell'esempio di sopra avessi messo solo 3 delle 4 righe) Maya riempirà il resto con 0.

COMANDI

Come già detto, praticamente ogni operazione che potete fare a mano con Maya ha un corrispondente comando in MEL.
In generale i comandi hanno tutta una serie di parametri che possono essere specificati per modificarne l'output. I parametri hanno un nome lungo ed un'abbreviazione che vanno preceduti da un - e seguiti dal valore del parametro stesso.

Ad esempio:

sphere -radius 5 -axis 0 1 0 -name "sfera"

crea una sfera di raggio 5 chiamata "sfera", con l'asse parallelo all'asse y (cioè il vettore 0;1;0) ed è equivalente a

sphere -r 5 -ax 0 1 0 -n "sfera"

Per avere una lista di tutti i parametri apriamo lo script editor e dal menu help scegliamo Mel Command Reference. Per ogni comando vedremo la lista dei parametri con nomi lunghi e brevi e alcuni esempi.

Accanto ai vari parametri vedrete una colonna "Properties" con una o più delle lettere Q, E, C e M.
Queste stanno per Query, Edit, Create e More per indicare la modalità di uso del parametro.
Ci sono 3 modalità d'uso di un comando, chiamate query, edit e create appunto: se non si specifica niente (come nell'esempio sopra) si è in modalità create, per andare in modalità query si usa il flag -query (o -q), mentre -edit (o -e) ci porterà in modalità edit.
La modalità query serve per richiedere informazioni su di un oggetto. Ad esempio proviamo a usare questo script:

sphere -radius 5 -name "sfera";	  // modalità create
sphere -query -radius "sfera";		// modalità query
sphere -edit -radius 8 "sfera";	// modalità edit
sphere -query -radius "sfera";	// modalità query
// NOTA: i commenti vanno preceduti da //
/* oppure rinchiusi tra questi due simboli
se sono piu righe. */
/* MEL non considera ciò che è scritto nei commenti */

La prima riga (modalità create) crea una sfera di raggio 5 chiamata sfera.
La seconda riga richiede il raggio della sfera e darà come output

// Result: 5 //

Ci sono due cose da notare in questa riga:
1) in modalità query (e edit) è necessario specificare il nome dell'oggetto alla fine della riga.
2) in modalità query non va inserito il valore del parametro (visto che lo stiamo richiedendo)

La terza riga usa la modalità edit per modificare il raggio della sfera. Questo avrà come conseguenza il fatto che la sfera nella nostra scena diventerà più grande e che la successiva chiamata nella quarta riga restituirà 8 invece di 5.
Le successive righe direi che si spiegano da sole! biggrin

Ora, supponiamo di voler mettere il risultato di un comando query in una variabile (altrimenti sarebbe abbastanza inutile…)
Potremmo pensare di scrivere:

$raggio = sphere -q -r "sfera";

questa riga ci darà un buon numero di errori e vedremo in un attimo il perché.

Chi di voi abbia un minimo di familiarità con la programmazione saprà che generalmente le funzioni sono chiamate con:

nomefunzione(parametro1, parametro2, ..., parametroN)

MEL supporta questo tipo di "sintassi funzione" per alcuni comandi, come già visto per print e size. In generale però questo tipo di sintassi non funziona per molti comandi (es. sphere) e viene usata la "sintassi imperiale" che è essenzialmente quella che abbiamo visto sopra. Questo però comporta che il comando così scritto venga SOLO ESEGUITO senza restituire valori. Questo è il motivo per cui tentare di assegnarlo ad una variabile dà errore.
Per ottenere la restituzione di un valore basta racchiudere il comando fra backquotes  

`comando`

NOTA: questo simbolo si trova solo sulle tastiere inglesi. Sulle tastiere italiane dovrete usare ALT + 96 (sul tastierino numerico).

Quindi:

$raggio = `sphere -q -r "sfera"`;

Un'altra differenza fra le due sintassi è che con la sintassi imperiale è possibile omettere le virgolette attorno alle stringhe che non abbiano spazi.
Quindi possiamo anche scrivere:

sphere -r 10 -n sfera;

Alcuni comandi richiedono l'inserimento di più parametri; in questo caso basta inserirli separati da spazio come in questo esempio:

sphere -n sfera;
move 0 10 0 sfera;

move accetta 3 parametri (posizione su x y e z), quindi in questo caso sposteremo la sfera alla posizione (0;10; 0)

Se volessimo fare uno spostamento relativo potremmo usare –r

move -r 5 8 -7.4

sposta la sfera di 5 unità su x, di 8 su y e di -7.4 su z, relativamente alla posizione in cui si trova.

È anche possibile usare variabili all'interno di un comando come in questo esempio

$rad = 20;
sphere -r $rad;

STATEMENTS

Quando si cominciano a scrivere script un po' più complessi, sorge la necessità di poter controllare il flusso delle operazioni, ad esempio per ripetere la stessa operazione più volte. Esistono delle strutture di comandi che ci permettono di fare ciò.

if… else if… else…

Questo tipo di ciclo permette di scegliere fra due diverse "strade" a seconda di una certa condizione.
Esempio:

$a = rand(1, 10);

if ($a < 3)
   {
   sphere -r 2;
   }
else if ($a < 8)
   {
   sphere -r 1;
   cone -ax 0 1 0;
   }
else
   {
   polyCube;
   }

La prima riga assegna a $a un valore casuale (random) fra 1 e 10
La funzione rand può anche essere chiamata solo con un parametro e in quel caso restituisce un valore fra 0 e il parametro passato.

Il resto dello script controlla il valore di $a:

se è < 3 crea una sfera, poi finisce

altrimenti se $a è < 8 fa una sfera ed un cono

altrimenti fa un cubo

Quindi se $a è 1 o 2 avremo la sfera; 3,4,5,6 e 7 ci daranno sfera e cono e 8 9 e 10 il cubo.

Altre cose da sapere per quanto riguarda gli if:

1) L'unica parte indispensabile del ciclo è l'if, gli else if e l'else finale sono opzionali.

2) Gli operatori usati per definire la condizione sono

==   per confrontare due numeri. Questo all'inizio può dare un po' di confusione:

$a = 1;		  // un solo uguale serve per assegnare un valore

if ($b == 2)   // due uguali servono per confrontare un valore

if ($b = 2)	 // questa istruzione non dà errore, ma non controllerà il valore di $b
					// anzi, lo cambierà in 2 !!!

<    minore
<=   minore o uguale
> maggiore
>= maggiore o uguale

Per combinare più operatori si usano i booleani

&& AND
|| OR
! NOT

Ad esempio

if ($a<5 && $b<8)  // Se $a è minore di 5 E $b è minore di 8

if ($a<5 || $b<8)   // Se $a è minore di 5 OPPURE $b è minore di 8

if (!($a < 5))		 //  Se $a NON è minore di 5

Un operatore speciale è l'operatore != (diverso)

if ($a != 11)		// Se $a è diverso da 11

3) Se dopo l'if c'è una sola operazione si possono omettere le parentesi graffe (questo è vero anche per gli altri tipi di statements), ma è buona abitudine metterle comunque, magari indentate, per migliorare la leggibilità del codice.

Ciclo for

Questo tipo di struttura serve per ripetere la stessa operazione un certo numero di volte, fino a che una determinata condizione resti soddisfatta. La struttura generale è:

for (inizializzazione; condizione; operazione di fine ciclo)
{
istruzioni da ripetere
}

Facciamo un esempio pratico

for ($i=1; $i<=10; $i++)
	{
	sphere -ax 0 1 0 -r 2 -n ("Sfera" + $i);
	move $i 0 0 ("Sfera" + $i);
	}

Questo script ci darà come risultato qualcosa simile ad un "bruco"

bruco

La prima riga va letta in questo modo:

- Inizializza $i a 1
- Continua a ripetere tutto ciò che c'è fra parentesi graffe fino a che $i è minore o uguale a 10
- Ogni volta che fai le operazioni tra graffe incrementa $i

Quindi in pratica è come dire "ripeti queste due istruzioni 10 volte".
Le altre due righe creano una sfera e la muovono.
Notare che per assegnare un nome "dinamico" alle sfere (cioè "Sfera1", "Sfera2" etc.) ho usato

–n ("Sfera" + $i)

Le parentesi sono necessarie perché altrimenti il comando prenderebbe solo "Sfera" come nome e darebbe errore per il + $i. In questo modo, invece, tutto quello che sta tra parentesi viene considerato come una cosa unica.

Qualche altra considerazioni a proposito dei cicli for:

1) La condizione non deve necessariamente implicare la variabile che inizializziamo, ad esempio potrei scrivere:

for ($i=0; $j<15; $a++)

Questo sarebbe validissimo, anche se non è proprio il massimo della comprensibilità e potrebbe portare a cicli infiniti se ad esempio ci dimentichiamo di modificare il valore di $j all'interno del blocco definito dalle graffe.

2) È possibile omettere alcune delle parti tra parentesi tonde:

for ($i=0; $i<10; )

Questo inizializza $i a 0 e va avanti fino a che $i è minore di 10, ma non incrementa $i alla fine del ciclo. Attenzione a fare cose del genere perché se non cambiate il valore di $i all'interno del ciclo avrete un ciclo infinito (leggi: Maya non risponde più)

3) Si possono mettere più istruzioni nei vari blocchi, separate da virgola:

for ($i=0, $j=0; $i<10; $i++, $j+=3)

In questo caso alla fine del ciclo $i è aumentato di 1 e $j di 3.

Come esercizio adesso potreste provate a riprodurre questo con un ciclo for (suggerimento: le funzioni sin e cos possono tornare molto utili!)

cubi

while e do… while

Due cicli simili al for sono il ciclo while e do… while, che hanno questa struttura:

while (condizione)
{
Istruzioni da ripetere
}

do
{
Istruzioni da ripetere
}
while (condizione)

Ad esempio:

$i=0;
while ($i<10)
	{
	cone -ax 1 0 0 -n ("Cono" + $i);
		  rotate 0 ($i*36) 0 ("Cono" + $i);
		 $i++;
}

Creerà 10 coni e li ruoterà attorno all'asse y, generando qualcosa di questo tipo:

star

La differenza fra while e do… while è semplicemente che la condizione viene controllata all'inizio del ciclo con while e alla fine con do… while.
In altre parole, le istruzioni di do… while sono sempre eseguite almeno una volta.

for … in …

Questo tipo di ciclo è utile quando si usano degli array

La sintassi è:

for (variabile in array)
{
istruzioni da ripetere;
}

Ad esempio, questo script scrive i nomi degli oggetti selezionati nella scena (ovviamente dovrete creare degli oggetti e selezionarli prima di farlo andare!)

string $selection[] = `ls -selection`;
string $obj;

print ("Hai selezionato:\n");

for ($obj in $selection)
	{
	print ($obj+"\n");
	}

Il comando ls dà come output un array di stringhe contenenti i nomi degli oggetti nella scena. Usando il parametro –selection, restringiamo l'output ai soli oggetti selezionati.
Il nostro loop prende gli elementi di questo array uno alla volta e li assegna ad $obj.

break e continue

Questi due comandi possono essere usati in qualunque ciclo e servono rispettivamente per forzare l'uscita dal ciclo (break) o per andare al successivo passaggio (continue).

Ad esempio:

for ($i=0; $i<10; $i++)
	{
	if ($i==8)
		break;
	if ($i==6)
		continue;
	print($i + "\n");
	}

In questo caso verranno scritti i numeri da 0 a 7, escluso il 6. Questo perché se $i è uguale a 6 verrà eseguito un continue, che fa andare alla fine del ciclo (quindi aumenta i di 1) senza eseguire tutto ciò che segue. Quando $i è 8, invece, eseguiamo un break, quindi usciamo dal ciclo dunque non scriviamo 8, 9 e 10.

E questo è tutto per questa seconda parte! Con queste conoscenze dovreste essere in grado di scrivere qualche script piuttosto semplice… oppure leggete la prossima parte in cui finalmente vedremo qualche script un po' più utile!

---
Questo articolo è stato importato automaticamente dal forum il 31/lug/2014
Per vedere il post originale e/o i commenti sul forum prima di quella data clicca qui