LScript

Что это?

Это скриптовый компилятор, интегрированный в среду LightWave. В основном синтаксис заимствован из C. Поэтому программисту очень легко в нем освоиться, главное это базовый набор команд, с помощью которого и появляется возможность управления геометрией, сценой, рендерингом и т.д.

На данный момент все серъезные программные продукты трехмерной графики имеют возможность написания к ним подключаемых модулей (PlugIn’ов), способных просто расширить функциональность программы. В данном случае система скриптов, которая также встроена в программу, является альтернативой подключаемым модулям. ?спользование последнего является удобным вариантом, однако скорость выполнения значительно уступает.

Компилятор и интерпритатор в LW

В свитке Construct (конструирование) в группе Utility (утилиты) можно обнаружить раздел LScript, содержащий команды по работе со скриптами:

— LScript – это интерпритатор, при нажатии появиться диалог для выбора нужного скрипта.

— LScript/RT – команда для запуска откомпилированных скриптов

— LSCompile – компиляция скрипта.

Редактор скриптов

Для удобной работы со скриптами в LightWave на этот счет есть даже специальная утилита, которая расположена в программной директории установленного LightWave (<директория, в которую установили программу> \ Programs>). Она называется LSED.

Основы языка LScript

Структура программы

Скрипт имеет туже структуру, что и консольное приложение на языке C. Т.е. обязательно наличие главной процедуры:

main

{

}

Конечно при некоторых видах скриптов, необходимым является наличие еще нескольких процедур, но об этом поздже.

Типы переменных

number Вещественная переменная (содержащая дробную часть)
integer Переменная для хранения целых чисел
string Строка, последовательность символов
vector Тип данных для хранения трех чисел, подобно координатам вектора. Причем, числа записываются через запитую и заключены в скобки (<>)

(например, <15, 34, 5.34>)

point id Код вершины (индификационный номер)
polygon id Код полигона
boolean TRUE/true/!0 or FALSE/false/0

Присвоение значений переменным

Присвоение значения осуществляется довольно просто, с использованием знака равно (=). Причем, слева указывается та переменная, которой нужно присвоить значение того, что справа от символа равенства.

К примеру,

Num = 180 / 3.16

Если присваивается  значение литерной переменной, то текст указывается заключенным в кавычки.

S = “Это текст строки”

В отличие от C, тип переменной назначается автоматически и зависит от того, что ему нужно хранить (текст или число и т.д)

Myvar = 980.8 // сейчас переменная имеет вещественный тип

Myvar = “текст” // теперь литерный

Возможно ситуация, когда с правой части возвращается не одно значение, а массив. В этом случае указанная переменная также становиться массивом.

Например,

data = split(path) // функция split возвращает четыре параметра в массиве

Чтобы назначить нашей переменной не массив, а одно значение из него (первого элемента), заключим её в скобки

(data) = split(path) // теперь нам передается одно значение

Однако при этом три значения будут пропущены, а в ?data’ запишется только первое. Если в скобках указать две или три переменных, то в них занесётся значения последовательно из массива.

(data1, data2, file) = split(path) // пропускается только одно значение

Пользовательское задание процедур

Для написания своих процедур достаточно указать её имя. Тело процедуры (программный код) поместить между скобками { и }. Однако расположите процедуру где-нибудь в свободном месте, не в теле процедуры main.

Процедура может получать какие-то параметры, для этого после имени поставьте ?:’ и перечислите их через запятую.

Процедура может не только получать значения, но и возвращать их. Это реализуется при помощи команды ?return(<возвращаемое значения>)’. Для возвращения нескольких значений, перечислите их всех через запятую.

Пример:

        main
     {
         ...
         t = which(val1,val2,val3);
         ...
     }
     which: v1,v2,v3
     {
         if(v1)
          return(v2);
         else
          return(v3);
     }

Библиотеки

Очень часто возникает необходимость использовать одни и те же процедуры в разных скриптах. Для упрощения их повсеместного написания существует возможность создать библиотеку, т.е. написать процедуры в отдельном файле. Библиоткам не нужно наличие процедуры main.

Для подключения библиотеки вызывается команда (расположите её вызов в начале скрипта, на глобальном уровне)

library “<имя файла>”

После чего, LScript просканирует указанную библиотеку и все найденные процедуры сделает доступными для скрипта.

Возможно, что какой-то набор процедур станет действительно необходимым и стандартным при работе. Поэтому, чтобы не подключать каждый раз одни и те же библиотеки, их можно стандартизировать. Тогда всеми необходимыми процедурами появиться возможность пользоваться без всяких дополнительных загрузок библиотек. Для этого, проделайте следующие действия: в директории со скриптом создайте текстовый файл ?LWScript.CFG’, где добавьте строчки

        [LSCRIPT]
        ScriptPath=C:\LW\LSCRIPT
        DefaultLib=C:\LW\LSLIB\LIB1.LS;C:\LW\LSLIB\LIB2.LS
        ...

Заметьте, что все стандартные библиотеки назначаются как значение ?DefaultLib’ и записываются через точку с запятой.

Комментарии

Как я уже упоминал, синтаксис LScript очень схож с языком программирования C. Поэтому комментарии в скрипте записываются аналогичным способом.

Обычные комментарии указываются через двойной слеш (?//’), после которого всё написанное на данной строке расценивается как комментарии.

Есть ещё одни способ – с помощью ?/*’ и ?*/’. Всё что находится между ними будет также комментариями.

Например:

        jitter(1.5);  // make it uniformly ugly

/*

комментарии в несколько

строк

*/

Условие

Для обработки условных выражений в LScript используется команда if, которая имеет двоякий стиль написания:

1)      синтаксис в стиле «C»

        if((f.eof() == false) && (size(tokens) > 1) &&
        (tokens[1] == "Plugin"))
         info(tokens[1]," ",tokens[2]);

2)      в стиле «AREXX»

        if f.eof() == false and size(tokens) > 1 and
        tokens[1] == "Plugin" then
               info(tokens[1]," ",tokens[2]));
        Для прекращения выполнения команд в теле условия используется команда return.
        if(file == nil)

{

error(«Cannot create scene file «,sceneFile);

return;

}

или так

if file == nil then

begin

error(«Cannot create scene file «,sceneFile);

return;

end

Заметьте, что для выполнения больше чем одной команды используются либо скобки, либо лексемы «begin» и «end».

Оператор условия может обрабатывать не только результат выполнения условия (условие возвращает «истина»), но и действия в противоположном случае:

        if(lensFlare[index])
     {
         file.writeln("LensFlare 1");
         ...
     }
     else
         file.writeln("LensFlare 0");

Цикл While

Цикл «Пока», выполняет действия, заключенные в теле цикла, до тех пор, пока не выполниться данное условие.

Как и оператор if, цикл «Пока» можно задавать двумя вариантами:

1)  стиль «С»
               while ( /boolean expression/ )
                       /statement/
2)  стиль «AREXX»
               while /boolean expression/ do
               begin
                       ...
               end

Для управления работы цикла существует 2 команды: break и continue. Однако о них я расскажу чуть позже.

Цикл For

В отличие от цикла While, цикл For обрабатывает действие в теле цикла указанное количество раз (цикл While можно назвать своебразным безлимитным циклом). Опять же способов задания синтаксиса написания два:

1)  for ( /init/ ; /expr/ ; /post/ )

/statement/

2)  for /var/ = /expr/ to /expr/ [ by /expr/ ] do

begin

end

Switch/Select

Оператор switch в своём действии подобен аналогичному на «C». Он обрабатывает данное значение и в зависимости от него выполняет те или иные действия.

        switch ( /expression/ )
     {
         case /number/ :
             ...
             break;
         default:
             ...
             break;
     }

Оператор select позаимствован из «AREXX» и подобен switch

        select
         when /expression/ then do
             ...
         end
        end

Условие. inline select

Оператор inline select реализуется с помощью символов «?» и «:». Его можно назвать сокращенной формой оператора if или оператора select.

/boolean expression/ ? /true select/ : /false select/

Удобство ещё заключается в том, что применять данный оператор можно и в выражениях:

        main
     {
         j = 1;
         ...
         info("result is ",(j == 1 ? "yes" : "no"));
     }

break

Данный оператор предназначен для использования в теле цикла для немедленного выхода из него. После чего скрипт будет выполняться дальше.

        while(j)
     {
         if(j == 10)
             break;      // line 4
         ++j;
     }
     info("j == ", j);        // line 9

continue

Continue – другая команда для использования в теле цикла. При вызове которой LScript  перейдёт на следующий шаг, т.е. к вверху (при цикле for /post/ будет обработано)

        while(1)
        continue;  // uh oh! an infinite loop!

Типы переменных

Numeric

(Вещественное число с плавающей запятой)

Число может быть положительным или отрицательным и содержать дробную часть.

        main
     {
         integer = 15;
         real = 0.3;
         negative = -35.356;
         scientific = 7.5E+13;
         ...
     }

string

литерная переменная

Литерная переменная для хранения строки текста

        main
     {
         astring = "Here is a test string";
         ...
     }

Массив

LScript поддерживает вплоть до 10 размерных массивов. В массиве могут использоваться любые из типов переменных, возможно также и совместное хранение нескольких разных типов.

Массивы могут быть созданы несколькими способами:

1)      объявление массива

        main
     {
         var check[15];
         ...
     }

Для инициализации элементов в массиве достаточно присвоить им какое-то значение.

Многоразмерные массивы (не линейные, размерностью больше 1) должны быть объявлены с помощью команды var.

2)      Линейные массивы будут созданы интерпритатором LScript в случае, если тот сочтет это необходимым, при возвращение нескольких значений и т.д.

Вот к примеру функция parse() возвратит три элемента и firstItem станет массивом
               firstItem = parse(" ","Hello there, everybody!");

Номера элементов в массиве начинаются с цифры 1!

?нициализировать массив можно выполнив всего одно действие

        main
     {
         var check[15];
         ...
         check[] = -1;   // всем элементам назначается '-1'
         ...
     }

?нициализацию элементов можно выполнить через присвоение значения nil

        main
     {
         ...
         check[15] = nil;   // создание массива и инициализация элементов
         ...
     }

vector

Данный тип переменных хранит три числа, которые при записи заключены в скобки («<» и «>») и отделяются друг от друга запятой. Тип vector очень распространен и широко используется так как работать приходиться с трёхмерным пространством.

        main
     {
         apoint = <4.5,10,.03>;
         ...
     }

Объявив данную переменную доступ к данным осуществляется через символы x,y,z.

        main
     {
         apoint = <4.5,10,.03>;
         ++apoint.x;
         --apoint.y;
         if(apoint.x > 4)
         ...
     }

point/polygon id

Данный тип прямиком используется модельером для работы с геометрией. Вершинам и полигонам назначаются их собственные индификационные номера, через которые происходит их обработка.

nil

Это лексема используется часто в LScript, необходима, например для инициализации массивов или возвращается определенной функцией при неудачном выполнении операций.

Оператор File() возвращает nil в случае не удачной попытки открытия файла.

Работа с файлами

LScript объектный агент содержит класс для работы с файлами – это File(). Назначается на переменную и содержит ряд методов для удобной обработки данных:

Наименование метода Описание
isOpen
Возвращает true/false (истина/ложно) в зависимости от того, файл открыт или нет
isOpen(void)
open
Открытие файла в данном режиме
void open(<имя файла>,   <режим>)
reopen Закрывает текущий файл и открывает его в данном режиме

void reopen(<режим>)
Close Закрывает текущий файл

void close(void)
eof
Возвращает false (ложно) если файл ещё не закончился
result eof(void)
rewind Переводит позицию обработки файла на начало

void rewind(void)

name
Возвращает имя и путь текущего файла
result name(void)
write(), writeln()
Запись данных в строку файла
Команды не работают в бинарном режиме
result    write(item1[,itemN])
read Возвращает прочитанную строку. Не работает в бинарном режиме.

result read(void)
readNumber
В текстовом режиме считывает последовательность символов и конвертирует их в число. В бинарном режиме считывает одно число с файла.
result readNumber(void)
readVector
Считывает три числа и конвертирует их в вектор, который и возвращается командой.
result readVector(void)
parse
Считывает строчку и возвращает значения в соответствии с заданным «token».
Команда не работает в бинарном режиме.
result   parse(token)
nl
Записывает новую строку символов в файл. Не активно для бинарного режима.
void nl(void)
linecount
В текстовом файле возвращает количество строчек, в бинарном – размер файла в байтах.
result linecount(void)
line
Если параметр не указан, то возвращает номер текущей строки, иначе переходит на указанную.
Команда не работает в бинарном режиме.
result  line([linenumber])
readInt
Считывает целое число
result readInt(void)
readByte
Считывает целое число
result readByte(void)
writeNumber Записывается вещественное число

result writeNumber(value)

writeInt Записывается целое число

result writeInt(value)

writeByte Записывается целое число

result writeByte(value)

offset
Запущенная без параметров, команда возвращает текущую позицию в байтах. ?наче value указывает на значение отступа в байтах, а метод определяет точку отсчета и может принимать значения: FROMSTART (с начала файла), FROMEND (с конца файла), FROMHERE (с текущей позиции)
result offset([value [,method]])

Пример – запись в текстовый файл

odjdir = getdir(“Objects”)

if ((getObjFile = getFile(“Save Layer as  Object…”, “*.lwo”, objDir))==nil)

return;

if ((objFile=File(getObjFile, “w”)) == nil)

{

error(“unable to open object file.”);

return;

}

objPath = objFile.name();

objFile.close();

Пользовательские объектные агенты

LScript даёт возможность создавать свои собственные объектные классы. Аналогично с агентом работы с файлами, можно подключать свои собственные агенты. Однако для этого нужно уметь программировать на «С», т.к. для создания своих классов необходимо построить динамическую библиотеку, где поместить все необходимые функции.

        use "<filename>.dll" as class <ClassName>;

Вызовом команды use, происходит загрузка библиотеки и подключение соответствующего класса.

Активация доступа к агенту

Для загрузки агента  программе потребуется знать путь нахождения данной библиотеки. За это отвечает глобальная переменная «LibraryPath». Нахождение этого значения зависит от конкретной операционной системы, однако существуют команды для работы с глобальными переменными – globalstore() и globalrecall().

Глобальные переменные в среде Windows

Все глобальные настройки храняться в регистре Windows:

        HKEY_CURRENT_USER\Software\NewTek\LScript

Создайте новые переменные и поместите вплоть до 10 путей

        Name                Data
        (Default)           (value not set)
        LibraryPath         "f:\lw\dev\lscript\dll;f:\oa;c:\temp"

Расширение «lwscript.h»

Появляется новая функция для работы с динамической библиотекой.

        typedef struct _lsdll
         {
             const char *ClassName;
             const char *InstanceName;
             LS_VAR  *instance[MAXINSTANCE];
             LSFunc  *func;
         } LSDLL;

где      ClassName – имя класса

InstanceName – имя переменной, т.е. объектного агента

Для создания общего класса объектного агента существует специальная функция, прототип которой описан

typedef LS_VAR * (*ObjectAgentMethod)(int *,LS_VAR *,LSDLL *);

Дополнительные возможности

Под дополнительными возможностями я подразумеваю набор констант, процедур и функций, необходимых для работы с переменными, математикой и просто без которых не обойтись.

Заданные величины

Следующие, перечисленные ниже величины являются стандартом в LScript и доступны только для чтения (изменять их нельзя):

        PI             E              GAMMA
        DEG            PHI            READ
        WRITE          APPEND         VERTICAL
        HORIZONTAL     FROMSTART      FROMEND
        FROMHERE       INTEL          ALPHA
        SGI            MIPS           MACINTOSH
        AMIGA          CREATE         ATTACH
        AUTOCLEAR      LAYOUT         MODELER
        SCREAMERNET    nil            true/TRUE
        false/FALSE    X              Y
        Z

А вот перечень дополнительных заданных величин для модельера:

        GAUSSIAN       UNIFORM        NORMAL
        SHARP          BUFFERED       KNOTS
        SUBTRACT       INTERSECT      ADD
        LENGTHS        CORE           TUNNEL
        STENCIL        SLICE          FLAT
        SMOOTH         METAFORM       SET
        CLEAR          VOLUME         CONNECT
        NPEQ           NPLT           NPGT
        VOLEXCL        VOLINCL        SURFACE
        NVEQ           NVLT           NVGT
        CURVE          NONPLANAR      SELECTED
        FACE           UNSELECTED     ABORT
        START          END            DETAIL
        GLOBAL         USER           RADIAL
        UNION          POLYNDX        POLYID
        POINTNDX       POINTID

? наконец, список для Layout:

        SCENEMODE      OBJECTMODE     MESH
        LIGHT          CAMERA         BONE
        SCENE          POSITION       RIGHT
        UP             FORWARD        ROTATION
        SCALING        PIVOT          WPOSITION

В зависимости от типа вашего скрипта появляется ещё небольшой перечень дополнительных специализированных величин:

Image Filter

     SPECIAL        LUMINOUS       DIFFUSE
     SPECULAR       MIRROR         TRANS
     RAWRED         RAWGREEN       RAWBLUE
     SHADING        SHADOW         GEOMETRY
     DEPTH          RED            GREEN
     BLUE           ALPHA

Procedural Texture

     NORMAL         COLOR          LUMINOUS
     DIFFUSE        SPECULAR       MIRROR
     TRANSPARENT    ETA            ROUGHNESS
     RAYTRACE

Displacement Map

     WORLD          LOCAL

Object Replacement

     NONE           PREVIEW        RENDER

Внутренние команды

Основные команды для работы со скриптами как под модельер (Modeler), так и под редактор сцены (Layout).

Название команды Описание
angle Функция возвращает угол, в градусах, между двумя точками в заданной плоскости (XY, XZ, YZ). Команда принимает три параметра, первые два из которых – координаты двух точек, а третий – ось, перпендикуляр к плоскости, на которой будет рассчитываться угол.

...
     editbegin();
       pnt1 = pointinfo(points[1]);
       pnt2 = pointinfo(points[2]);
     editend();
     info(angle(pnt1,pnt2,X),    // return angle in the YZ plane
          " degrees");
     ...
sqrt Функция возвращает корень квадратный данного числа

...
     angle = 180;    // 180 degrees
     varSquare = sqrt(angle);  // calc square root of angle
     ...
exp Функция возвращает значение экспоненты данного числа

...
     v1 = exp(27.5);
     ...
log Функция возвращает логарифмическое значение данного числа

...
     v1 = log(347.495);
     ...
sin asin cos acos tan atan cosh sinh tanh sec cot csc Функции рассчитывают тригонометрические значения данного угла. Возвращаемое значение в радианах.

...
     sin1 = sin(45);
     ...
     asin1 = asin(276);
     ...
abs Функция возвращает модуль числа

...
     if(abs(decline) > 30)
     ...
ceil floor
Ceil возвращает наименьшее целое значение, а floor наибольшее
...
     c = ceil(45.6);
     f = floor(13.3);
     ...
random Функция возвращает случайное целое значение в промежутке, заданное в качестве аргумента. Значения могут быть как положительные, так и отрицитальные.

...
     triggerFrame = random(20,50);
     ...
randu Возвращает случайное значение в промежутке от 0 до 1

...
     rad = 0.05 * maxlen * (1 + randu())
     ...
min, max Возращение минимального/максимального значение из двух данных чисел

...
     t = min(top,7);
     ...
mod Возвращает остаток при делении одного числа на другое. Может быть вычислено через знак % в LScript.

t = mod(34.5,6);  // returns 4.5

или так

t = 34.5 % 6;

pow Возводит первое данное число в степень второго числа

...
     t = pow(5,3);  // возвратит 125
     ...
hypot() Функция рассчитывает гипотенузу в правильном треугольник, где два данных числа – стороны трегольника

...
     t = hypot(3,5);
     ...
rad, deg Перевод из градусов в радианы – функция rad. Обратные перевод выполняется через deg.

...
     t = rad(degrees); // equivalent to: degrees * (PI / 180)
     ...
range()
Функция проверяет первое данное число на нахождения в промежутке, заданное двумя данными числами. Возвращает истинно/ложно.
...
     if(range(top,3,8))
     ...
select()
Сравнивает первые два числа и возвращает третье данное число если первое меньше второго. Возвращает четвёртое данное число если первое меньше или равно второму.
...
     t = select(4,7,15,3); // returns 15
     ...
     t = select(15,7,7,10); // returns 10
     ...
step()
Сравнивает первые два данных числа и возвращает 0 если первое из них больше второго, иначе, если второе больше или равно первому, возвращает третье данное число.
...
     t += step(y,10,.25); // step by .25
     ...
round()
Функция округляет первое данное число. Если второе данное число 0, то результат округления – целое число, иначе второе данное число – количество знаков после запятой при округлении.
...
     t = round(37.7,0);  // returns 38
     t = round(4.4394,2);  // returns 4.44
     ...
frac()
Функция возвращает фрактал данного числа
...
     t = frac(46.75);  // returns 0.75
     ...
fac()
Возвращает факториал данного числа
...
     t = fac(5);  // returns 120
     ...
vmag()
Рассчитывает натяжение вектора
...
     t = vmag(x,y,z); // calculate magnitude of my location
     ...
info, warn, error
Функции по выводу информации пользователю
...
     error("Value ",val," exceeds max limit of ",
               10 * items," items");
     ...
File()
Функция возвращает файловый объектный агент для работы с файлом данного пути

sceneFile = File(«/temp.lws»,»w»);

Режимы открытия схожи с «C»:

r    чтение (ascii)

w    запись (ascii)

a    добавление (ascii)

b    бинарный (т.е., «rb» будет чтение бинарного)

+    с обновлением (т.е., файловый указатель может быть перемещен)

fileexists
Возвращает истина/ложно относительно существования файла с заданным именем и путем
index = 9;
     ...
     if(fileexist("/temp" + index + ".lwo"))   // filename becomes "/temp9.lwo"
     ...
filedelete
Удаление заданного файла. Возвращает 0 в случае успешного завершения операции.
index = 1;
     ...
     if(filedelete("\\temp",index,".lwo"))
         error("Cannot remove file \\temp",index,".lwo!);
     ...
center()
Возвращает середину между двумя заданными векторами. Данные можно задать в виде двух векторов, в виде шести чисел.
// boundingbox() возвращает два вектора
     objectCntr = center(boundingbox());
extend()
Функция рассчитывает расстояние между двумя точками
objectSize = extent(boundingbox());
parse()
Функция разбивает первый аргумент-строку на множество строчек данным символом
str = "23,45,69.6,100";
     tokens = parse(",",str);  // returns "23", "45", "69.9"
                                   // and "100"
     ...
size()
Предназначения для вычисления размера данной переменной или данного типа
str = "23,45,69.6,100";
     tokens[10] = nil;
     t = size(tokens);  // returns 0
     tokens = parse(",",str);  // returns four elements
     t = size(tokens);  // returns 4
     tokens[8] = 1.0;
     t = size(tokens);  // returns 5
     ...
number/integer
Функции для перевода текста в вещественное/целое число
str = "69.6";
     t = number(str);                        // returns 69.9
     t = integer(str);                       // returns 69
     t = integer(round(number("69.9")));     // returns 70
     t = number("The answer is: .1593");     // returns .1593
     ...
vector()
Конвертирование строки в вектор
str = "4 6.5 8";
     t = vector(str);  // returns <4,6.5,8>
     ...
string()
Конвертирует список аргументов в одни текст
t = string("Value ",val," exceeds max limit of ",
                    10 * items," items");
split
Функция предназначается для работы с именем файла и путем. Возвращает массив в 4 элемента: имя диска, путь, имя файла и расширение файла.
file = getfile("Select A Scene...","*.lws");
     if(file == nil)
          return;
     if(fileexists(file))
     {
         base = split(file);  // get the components (base becomes an array)
         ...
append
Функция предназначена как для литерной переменной, так и для массива. Добавляет либо текст, либо новый элемент в конец
spawn
Запускает данный процесс
// launch ScreamerNet II in parallel
     snID = spawn("lwsn -2 ",
               getenv("TMP"),"\\snii.job ",
               getenv("TMP"),"\\snii.rpl");
     if(snID == nil)
     {
         error("Cannot create ScreamerNet process");
         ...
getdir()
Возвращает стандартные LightWave пути

«Fonts»/FONTSDIR              Modeler

«Macros»/MACROSDIR            Modeler

«Install»/INSTALLDIR          Layout/Modeler

«Objects»/OBJECTSDIR          Layout/Modeler

«Images»/IMAGESDIR            Layout/Modeler

«Motions»/MOTIONSDIR          Layout/Modeler

«Temp»/TEMPDIR                Layout/Modeler

«Plugins»/PLUGINSDIR          Layout/Modeler

«Settings»/SETTINSDIR         Layout/Modeler

«Content»/CONTENTDIR          Layout

«Scenes»/SCENESDIR            Layout

«Hierarchies»/HIERARCHIESDIR  Layout

«Surfaces»/SURFACESDIR        Layout

«Output»/OUTPUTDIR            Layout

«Animations»/ANIMATIONSDIR    Layout

«Envelopes»/ENVELOPESDIR      Layout

«Previews»/PREVIEWSDIR        Layout

«Command»/COMMANDDIR          Layout

Получить сами пути можно следующим образом:

install = getdir(«Install»);

plugins = getdir(PLUGINSDIR);

sleep
Выполнение прекращается на заданное количество миллисекунд
1000 миллисекунд равняется 1 секунде
sleep(1000);   // спим 1 секунду
dump
Отладочная функция, которая позволяет записывать в файл значения переменных скрипта
dump("/myscript.var");
strleft, strright, strsub, strupper, strlower
Функции для работы со строкой
Strleft(), strright() возвращают данное количество символов от строки в данном направлении
// the following prints 'My first name is "Ted"'
     info("My first name is \"",
          strleft("Ted Philmore",3"),"\");
strsub позволяет вырезать из строки подстроку
t = strsub("Ted Philmore",3,3);    // returns "d P"
strupper, strlower переводит данную строку в верхний/нижний регистр

Команды LightWave для Modeler’а

Функциональность модельера слишком огромна, поэтому я представлю здесь только самое необходимое и основное.

Работа со слоями

Слои являются, на мой взгляд, одним из главнейших преимуществ данного модельера. Естественно, что их управление в LScript может обязательно пригодиться.

1)      lyrfg, lyrbg

Данные команды возвращают номера тех слоев, которые выделены на данный момент. Причем, lyrfg – передние слои, а lyrbg – задние слои. Возвращаемое значение может быть как одним числом, так и целым массивом. Одно значение лежит в диапазоне от 1 до 10, т.к. именно такое максимальное количество активных слоёв может быть одновременным.

2)      lyrdata, lyrempty

Команды возвращают информацию о наличие геометрии. lyrdata – возвращает одно значение или массив номеров слоёв, содержащих геометрию (не зависит от того, передний слой или задний), а lyrempty – наоборот, возвращает номера пустых слоёв.

3)      lyrswap()

Процедура меняет местами состояние слоя. Если он был передним, то станет задним и наоборот.

4)      lyrsetfg(<список номеров>), lyrsetbg(<список номеров>)

Команды предназначены для выставления активных передних и задних слоёв. Аргумент может содержать как одно значение, так и массив, однако слоёв всего 10.

Выделение

Для работы с выделением в LScript присутствуют следующие команды:

1)      selmode(<режим>)

Задание режима выделения. Возможно два значения: USER или GLOBAL (по умолчанию). При последнем для обработки будут доступны все вершины и полигоны, при первом режиме – доступны только выделенные.

Команды selpoint() и selpolygon() будут не доступны пока selmode не будет установлен в USER. 

2)      selpoint(<режим1>, <режим2>, <параметры>)

Команде в качестве параметров нужно задать два значения для определения режима выделения и последний в качестве параметров выделения точек.

Первый параметр может принимать значения SET и CLEAR. В первом случае выделение задаваемое вызовом этой команды будет вносить изменения в текущее выделение, т.е. если вершина была уже выделена, то выделение для неё сброситься и т.д. В случае режима CLEAR выделение будет установлено точно в соответствии с заданным значениями.

Второй параметр определяет различные варианты выделения:

Режим Аргументы Описание

VOLUME

Два вектора, определяющие диапазон выделения Выделение точек, находящихся в заданном пределе

CONNECT

нет Выделение точек, соединенных с уже выделенными. Работает только в режиме SET.

NPEQ

Количество точек в полигоне Выделение всех точек в полигоне, если их количество соответствует заданному.

NPLT

Количество точек в полигоне Выделение всех точек в полигоне, если их количество меньше заданному.

NPGT

Количество точек в полигоне Выделение всех точек в полигоне, если их количество больше заданному.

POINTNDX

Номер, определяющий линейный индекс точки; массив, задающий линейные индексы   точек Выделение/сброс выделения заданной точки или массива точек в соответствии с данным индексом или массивом линейных индексов.

POINTID

Одно или массив значений, определяющих точки через point id Выделение/сброс выделения по заданным значениям

Таблица сверху определяет тип и количество возможных параметров, подаваемых в качестве третьего аргумента в команду selpoint().

Для работы этой команды режим самого выделения должен быть USER.

3)      selpolygon(<режим1>, <режим2>, <параметры>)

Команда selpolygon по своей структуре очень схожа с командой selpoint.

selmode(USER);

selpolgon(SET, POLYNDX, @1,3,5@);

Редактирование

1) editbegin()

Команда для перехода в режим редактирования каркаса. При вызове появляются два массива points[] и polygons[], содержащие данные о сцене.

Команда возвращает количество выделенных точек.

2) editend([status])

Команда вызывается для завершения операций по редактированию геометрии. Если status задать как ABORT, то все произведенные изменения будут отменены.

3) pointcount()

Команда возвращает количество выделенных точек.

ttlPnts = pointcount();

if(!ttlPnts)

{

return;

}

4) polygoncount()

функция возвращает массив в шесть элементов с данными о состояние выделения на уровне полигонов.

[1] Общее количество выделенных полигонов
[2] Общее количество выделенных полигонов,

содержащих только 1 точку.

[3] Общее количество выделенных полигонов,

содержащих только 2 точки.

[4] Общее количество выделенных полигонов,

содержащих только 3 точки.

[5] Общее количество выделенных полигонов,

содержащих только 4 точки.

[6] Общее количество выделенных полигонов,

содержащих больше 4 точек.

Например, многие операции для своей работы требуют наличие только треугольников или четырехугольников, поэтому если есть полигоны с большим числом точек, то переведем все в треугольники.

        var totalpoints[6];
        totalpoints = polycount();
        if(totalpoints[5] || totalpoints[6])
         triple();
        subdivide(METAFORM);

5) polyinfo(<polygon id>)

Команда возвращает массив значений, первый элемент из которого – название материала, присвоенного данному полигону. Остальные элементы – массив id точек, составляющих этот полигон.

6) polypointcount(<polygon id>)

Команда возвращает количество точек данного полигона.

        ...
        var pcount = polypointcount(polygons[x]);
        var ppoints[pcount + 1];  // первый элемент – имя материала
        ppoints = polyinfo(polygons[x]);
        ...

7) pointinfo(<point id>)

Команда возвращает положение в пространстве данной точки.

8) polynormal (<polygon id>)

Возвращает нормаль данного полигона.

9) rempoint(<point id>), rempoly(<polygon id>)

Удаление указанной точки/полигона.

10) pointmove(<point id>, <новая позиция>)

Устанавливает точку в новую позицию

11) polypoints(<polygon id>, <массив с новыми id точек для полигона>)

Назначает указанные точки для данного полигона. Старые не удаляются автоматически, их нужно удалять в ручную.

12) freezecurves()

Конвертировать все выделенные кривые в полигоны.

13) addpoint(<позиция в пространстве>)

Добавление новой точки с заданными координатами. Функция возвращает id новой точки.

14) addpolygon(<массив id точек>, [имя материала])

Добавление полигона с данными точками. Функция возвращает id нового полигона.

Панель прогресса

При выполнении каких-то сложных продолжительных операций желательно использовать панель прогресса, чтобы пользователь был спокоен.

Команда moninit (<количество шагов>, [название — текст]). Вызовом мы инициализируем саму панель прогресса.

Для прохождения шага monstep([шаг]), которая в основном возвращает ложно (false), однако если пользователь нажал кнопку отмены, то функция возвратит истину (true).

Для закрытия панели прогресса команда monend().

teeth = 15

moninit(teeth, “Generation gear…”);

for(i=0; i<teeth; i++)

{

if(monstep())

{

editend(ABORT);

}

}

monend();

Пользовательский интерфейс

Модельер предоставляет механизмы, необходимые для организации пользовательского интерфейса. Отправной точкой здесь можно считать команду regbegin().

Вызовом этой команды появляется диалог, где можно поместить какие-то сообщения, а чаще всего он будет нужен для ввода параметров.

Для закрытия диалога команда regend().

regbegin(<заголовок>), где заголовок представляет собой обычный текст.

regpost() команда выполняется после того как работа с диалогом была закончена и возвращает булевское значение. Если результат истинно (true), то пользователь вышел из диалога нажатием кнопки «Ok», иначе можно подумать и выходе из выполнения дальнейших действий, т.к. пользователь нажал «Отмену».

В качестве компонентов пользовательского интерфейса в LScript есть следующий набор: ctlstring, ctlinteger, ctlnumber, ctlvector, ctldistance, ctlchoice, ctltext, ctlcolor, ctlsurface, ctlfont. При вызове той или иной функции для соответствующего компонента, возвращаемое значение есть ни что иное как личный номер этого компонента, по которому к нему осуществляется впоследствии доступ.  Теперь рассмотрим поподробнее.

Название компонента Описание
ctlstring, ctlinteger, ctlnumber, ctlvector
компоненты предоставляющие работу с стандартными типами данных: с текстом и числами.
...
     name = "BillyBob";
     age = 18;
     c1 = ctlstring("Your name?",name);
     c2 = ctlinteger("Your age?",age);
     ...
ctldistance
Работа с числами через «пользунок». В качестве второго параметра выставляется возможная длина.
...
     length = .25;
     c1 = ctldistance("Length",length);
     ...
ctlchoice
этот компонент предназначен для создания группы элементов, из которых выбранным может быть только один.
booleans[1] = "Yes";
     booleans[2] = "No";
     choice = 2;        // set "No" as initial selection
c1 = ctlchoice("Use random                height?",choice,booleans);

четвертый параметр задаёт ориентацию компонента: вертикальную или горизонтальную (по умолчанию). Причем ложно (false) указывает на последнее.

choice = 1;
     // create a vertical selection list
     c1 = ctlchoice("Quadrant?",choice,@"90","180","270"@,true);
ctltext
компонент для вывода какого-то текстового сообщения на диалог.
ctltext("WARNING",  // <-- first arg is control title
             "This operation could take a long time,",
             "and create very many points if Level is high");
ctlcolor подобно ctlvector, компонент для выбора цвета состоит из трех полей.
ctlsurface, ctlfont эти компоненты предназначены для отрисовки данного материала или шрифта. Причем, первый аргумент отвечает за заголовок, а второй либо за название материала, либо за название шрифта.

Для того, чтобы получить значение, введенное пользователем, используйте команду getValue(<личный номер компонента>). Данная функция возвращает данные, относительно данного компонента.

Назначение данных компонентам осуществляется при помощи команды setValue(<личный номер компонента>,<данные>).

В комплект вместе с программой LightWave поставляется утилита LSID (дизайнер пользовательского интерфейса для LScript), который позволяет довольно удобно и наглядно всё расположить и настроить. Затем экспортировать в виде скрипта и получить тем самым уже написанный код красивого интерфейса.

Отладка скриптов

Lscript отладчик наделен всеми необходимыми инструментами для управления данным ему процессом. С помощью которого появляется возможность производить отладку в реалтайме, а также в пошаговом режиме, осуществлять контроль за значения тех или иных переменных.

Отладчик берет свои полномочия только после вызова команды debug(). Это новая команда, располагать её желательно в важном стратегическом месте, т.к. после неё уже идет режим отладки.

Клавиатурные комбинации для выполнения тех или иных операций:

Сочетание клавиш Последующее действие
F10 шаг через одну строчку
F11 шаг к выполнению следующей строки
F9 установить точку остановки
F5 последующие выполнение скрипта до точки остановки
F6 дисконект. произойдет прекращение выполнения скрипта
F8 диалог просмотра значений указанных переменных скрипта.
Документация по LScript (перевод)
Метки:        

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *