Дим,
Со всем постом согласен от "А" до "Я", аж приятно.
Не совсем понял как глобальную переменную передать в процедуру.
Вот смотри.
У тебя любая переменная может быть
либо локальной, либо глобальной. Т.е., она существует либо только в пределах той процедуры, где она объявлена, либо вообще везде. Если ты создал переменную прямо в скрипт эдиторе - то она по определению является глобальной. Потому что ты создал её не в какой-то процедуре, а прямо в Майе.
Чтобы явно создать глобальную переменную - надо пользоваться ключевым словом global:
Тут надо отметить 3 вещи:
- Глобальную переменную нельзя сразу и создать, и добавить ей значение. Это надо делать по очереди, в 2 строчки.
- В Майе стандартная практика - это добавлять всем глобальным переменным префикс "g". Т.е., я все мои глобальные переменные называю как-то так:
Код:
global int $gDRL_myInteger;
- Только что неожиданно для себя обнаружил, что иметь как можно меньше глобальных переменных - это официальная рекомендация из доков (ссылка выше). Так что, я бы сказал, создавать что-то глобальное надо только тогда, когда это действительно необходимо. У меня вот сейчас в общей сложности порядка 30 скриптов (да, немного - ведь я обычно в Майе работаю с тем, что есть, а скриптую только в самую последнюю очередь). Ну плюс ещё пачка мелких хаков стандартных майских процедур.
Так вот, за всё это время мне потребовалось создать всего три глобальных переменных. Одна из них - счётчик timerX, две другие уже не помню. С ними просто ну никак иначе из одной процедуры в другую значение не передашь.
Помимо глобальных/локальных переменных есть ещё глобальные/локальные процедуры. Аналогично, при создании процедуры прямо в скрипт эдиторе, она является глобальной. Но если она описана в скрипте - то вызвать её можно только из этого же скрипта. Либо тоже создавать её как глобальную, тем же ключевым словом:
Код:
global proc my_superPuper_Procedure() {
print "Super-Puper!!!";
}
Соответственно, когда ты весь свой код сохранишь как скрипт, тебе придётся хотя бы одну процедуру в нём сделать глобальной, иначе ты просто не сможешь к ним обратиться. Тут тоже действует такое же правило: чем меньше глобальных процедур - тем лучше. Если ты
точно знаешь, что к какой-то процедуре в скрипте ты будешь обращаться только из этого скрипта - оставь её локальной (не дописывай ей
global).
Но, по правде говоря, с локальными процедурами сложнее, чем с локальными переменными. Дело в том, что с процедурами не всегда очевидно, захочет ли левая пятка Майи, чтоб та или иная процедура была глобальной.
Ярче всего это видно как раз на примере с гуём.
Любое окошко, которое ты своими скриптами создал, почему-то всегда считается глобальным. И любая процедура, которую оно вызывает, соответственно, тоже должна быть глобальной.
Скажу иначе. Вот у тебя есть скрипт. Вот ты написал в нём процедуру, которая создаёт окно. Вот ты в Майе этот скрипт за'source'ил и вызвал эту процедуру. Вот окошко создалось. Так вот, теперь у тебя любая процедура, которая указана в качестве команды для любого элемента (будь то кнопка или чекбокс или ещё что) - должна быть глобальной. Потому что Майя вдруг взяла и забыла, что это окошко создалось из твоего скрипта. И поэтому ей совершенно по барабану, что процедуры, вызывающиеся по нажатию на кнопку, описаны
в том же скрипте. Она требует, чтобы эти процедуры были глобальными - и всё тут.
Правда, справедливости ради, такое наблюдается только с процедурами, которые надо вызывать из элементов гуя. Во всех остальных случаях можно совершенно спокойно делать процедуру локальной, если ты уверен, что она будет использоваться только в этом скрипте.
И ещё, раз уж тему процедур задели...
Помимо всего прочего, процедура может возвращать значение.
Код:
global proc string my_superPuper_Procedure() {
string $superPuper = "Super-Puper!!!";
print $superPuper;
return $superPuper;
}
Данный конкретный пример совершенно бессмысленен. Но я взял за практику вообще всегда возвращать что-то полезное. Например, сколько раз она отработала, или какие файлы были созданы, или какие ноды, или какой код ошибки, или целый массив всяких нужных результатов.
Когда ты вызываешь процедуру - тебе ничто не мешает просто заставить её отработать. Но если понадобится - ты всегда можешь запомнить результаты её работы, чтобы в дальнейшем с ними работать как-то ещё. Как-то так:
Код:
string $procedureResult = my_superPuper_Procedure;
Ну и напоследок:
обрати внимание, все переменные, которые ты передаёшь процедуре в качестве аргументов, изменяются не только внутри неё. Как бы сказать иначе? Если ты в коде процедуры как-то изменял значение переданной переменной, то её значение поменяется не только внутри процедуры. Оно поменяется и там, где ты к этой процедуре обращался. Например:
Код:
proc SimpleProc (int $int) {
$int += 1;
}
int $my_superPuper_int = 6;
SimpleProc ($my_superPuper_int);
После того, как этот код отработает, в $my_superPuper_int будет 7. Хотя, казалось бы, мы сами тут его значение не меняли. Но его поменяла процедура.
Это надо иметь в виду.
С одной стороны, чтобы предотвратить изменение переменных, которые были переданы в процедуру, надо первым делом создавать их копии. И уже с копиями работать в процедуре.
С другой стороны - это отличный способ вернуть несколько значений, если нам это требуется. Т.е., что-то самое фундаментальное возвращает сама процедура, а ещё какие-нибудь полезные результаты записываются в некоторые переменные, которые мы передали в качестве аргументов. Думаю, будет проще с примером:
Код:
proc int DRL_useless (string $str, float $resPart, string $resChar)
/* Совершенно бесполезная процедура, которая сама по себе возвращает число символов в строке,
а в 2 последних аргумента записывает всякую хрень: какую часть от длины строки занимает 1 символ и какой символ - первый */
{
int $res = `size $str`;
$resChar = `substring $str 1 1`;
$resPart = 1 / $res;
return $res;
}
string $myString = "Super";
int $myLength;
float $myPart;
string $myChar;
$myLength = DRL_useless($myString, $myPart, $myChar);
// После этого в $myLength - 5, в $myPart - 0.2, в $myChar - "S".
Извиняюсь за такой длинный пост. Я старался охватить все нюансы по теме вопроса, чтобы у тебя сразу в голове всё уложилось структурировано, и не пришлось искать обрывочную информацию тут и там.