Управление Объектами
Boxshot позволяет создавать, обходить, редактировать и удалять элементы сцены (объекты) с помощью JavaScript. Нажмите на ссылки ниже, чтобы перейти к нужной теме.
Создание
Создание объектов
Boxshot создает объекты внутри иерархии сцены. Нельзя просто создать объект сам по себе — нужно создать его как чей-то дочерний элемент. Обычно ваши объекты будут дочерними элементами корневого узла сцены. Чтобы создать объект “сфера” в корневом узле, выполните такой код:
scene.root.addMesh("sphere", "generator.simple.sphere");
У объекта scene есть переменная root, которой вы будете пользоваться очень часто. Метод addMesh() принимает два параметра: имя объекта и его идентификатор (тип). Имя вы задаете сами, а вот идентификатор должен быть корректным, так как Boxshot использует его, чтобы понять, какой именно объект вы собираетесь создать.
Идентификаторы всех объектов вы можете посмотреть в учебнике по созданию объектов.
Создание источников света
Источники света создаются похожим образом, но другим методом:
var l = scene.root.addLight("a light");
Обратите внимание: вы можете присвоить созданный объект переменной, чтобы использовать его позже. Например, можно задать позицию и интенсивность источника света так:
l.translation = vec3(10, 20, 30);
l.intensity = 5;
Больше информации о настройке света в скриптах есть в учебнике по специальным объектам.
Создание групп
Группы — это узлы, которые содержат другие узлы. Они очень полезны, если вам нужно сделать анимацию сразу для нескольких узлов. Например, вы можете вращать несколько объектов вокруг точки или масштабировать их вместе. Скрипт снова выглядит похоже:
scene.root.addGroup("a group");
Вы можете присвоить новый объект переменной, чтобы использовать его позже. Ниже вы увидите несколько примеров.
Обход сцены
Когда вы успешно создали несколько объектов, имеет смысл научиться находить их в сцене, чтобы управлять их параметрами, переименовывать и т.д.
Корневой узел
В каждой сцене есть невидимый корневой узел, который содержит все узлы верхнего уровня. Вот как его получить:
var r = scene.root;
print(r.name);
В окне вывода Редактора скриптов вы увидите Root. Используйте корневой узел
как стартовую точку для обхода сцены.
Поиск дочерних элементов
Создайте несколько объектов в сцене, затем выполните такой код:
var top = scene.root.children;
for (var i in top)
{
var ch = top[i];
print("%1: %2", i, ch.name);
}
Здесь top — это массив дочерних узлов. Количество дочерних узлов можно получить так:
var num = scene.root.children.length;
При этом у каждого дочернего узла могут быть свои дочерние узлы, так что при желании вы можете обойти всю сцену:
function traverse(node, spaces)
{
var items = node.children;
for (var i in items)
{
var n = items[i];
print("%1%2", spaces, n.name);
traverse(n, spaces + " ");
}
}
traverse(scene.root, "");
Родительский узел
У каждого узла есть родитель. Получить его можно так:
var n = scene.root.addMesh("sphere", "generator.simple.sphere");
print("node: %1", n.name);
print("parent: %1", n.parent.name);
Если запустить скрипт, вы получите:
node: sphere
parent: Root
Все верно: сфера была создана в корневом узле, поэтому ее родитель — Root.
А что если попробовать получить родителя корневого узла?
var p = scene.root.parent;
print(p);
Вы получите null, потому что корневой узел — самый верхний и родителей не
имеет. Все остальные — имеют.
Поиск соседних узлов
Теперь вы легко можете находить соседние узлы. Для этого нет отдельной функции, потому что все необходимое у вас уже есть. Давайте создадим сферу и получим ее “соседей”:
var n = scene.root.addMesh("sphere", "generator.simple.sphere");
var siblings = n.parent.children;
print("our sphere has %1 siblings", siblings.length - 1); // мы не считаем нашу сферу, поэтому -1
Редактирование объектов
Теперь, когда вы легко обходите сцену, вам может понадобиться получать или изменять параметры узлов. Вы уже заметили, что во время обхода сцены мы выводили имена узлов. Точно так же можно делать и многое другое.
Имя
Снова создадим сферу, получим ее имя и попробуем изменить его:
var n = scene.root.addMesh("sphere", "generator.simple.sphere");
print("current name is %1", n.name);
n.name = "new name";
print("the new name is %1", n.name);
Если запустить это, вы увидите:
current name is: sphere
the new name is: new name
Видимость
Сделаем задачу чуть сложнее: найдем и скроем все объекты-сферы верхнего уровня. У нас уже есть базовый код, который находит все узлы верхнего уровня — модифицируем его так, чтобы он фильтровал сферы и скрывал их. Нужно всего три строки:
var top = scene.root.children;
for (var i in top)
{
var ch = top[i];
if (ch.type != 1) continue; // 1*
if (ch.generator.toString().search("Sphere") == -1) continue; // 2*
ch.visible = false; // 3*
}
К этому коду нужны комментарии. В строке (1) мы получаем тип узла и проверяем, равен ли он 1. Boxshot поддерживает три типа узлов:
- 0 - узел группы
- 1 - узел объекта (коробка, книга, итп)
- 2 - узел источника света
Если узел не является узлом объекта, мы просто пропускаем его. В строке (2) –
самая сложная часть. У каждого узла объекта есть объект generator, который
генерирует геометрию по заданным параметрам. Поэтому мы берем generator
каждого объекта и проверяем, содержит ли его имя слово Sphere. Если нет –
пропускаем.
Наконец, строка (3) скрывает узел, устанавливая свойство visible в false. Чтобы показать узлы, запустите тот же скрипт, но с true вместо false.
Трансформации
Вот как можно менять смещение, вращение и масштаб узла:
var node = ...; // scene.root.children[0];
node.translation = vec3(10, 20, 30);
node.rotation = vec3(0, 0, 90);
node.scale = vec3(1.2, 1.2, 1.2);
Используйте ровно те же значения, которые вы вводите на странице трансформаций в интерфейсе.
Выбор узлов
Текущее выделение контролируется сценой, поэтому подход здесь немного другой. Сначала нужно собрать список узлов, которые вы хотите выделить. Можно использовать и один узел.
Выделим самый первый узел верхнего уровня в сцене (предполагая, что сцена не пустая):
scene.selection = scene.root.children[0];
Просто? Тогда выделим все элементы верхнего уровня в сцене:
scene.selection = scene.root.children;
Видите разницу? Мы передали массив. А как снять выделение? Передайте null или
пустой массив — оба варианта работают:
scene.selection = null;
scene.selection = [];
Это легко. А если нужно добавить к текущему выделению? Тут все решается манипуляцией массивом. Добавим самый первый узел верхнего уровня к текущему выделению:
var sel = scene.selection;
sel.push(scene.root.children[0]);
scene.selection = sel;
Вторая строка — это JavaScript-способ добавить элемент в массив.
Перестановка узлов
Это легко делается мышью, но можно сделать и скриптом. Boxshot позволяет взять список узлов и сделать их дочерними по отношению к другому узлу, в конкретной позиции. Это включает смену родителя, что удобно для группировки и разгруппировки узлов.
Ниже — код, который берет текущее выделение и “перетаскивает” его внутрь самого первого узла верхнего уровня. Убедитесь, что вы не выделили этот узел, иначе получите сообщение об ошибке.
var sel = scene.selection;
var target = scene.root.children[0];
scene.drag(target, target.children.length, sel);
Скрипт довольно прямолинейный, основная работа делается в последней строке. Первый параметр метода drag() — целевой узел, второй — позиция (мы передаем количество дочерних элементов целевого узла, чтобы добавить в конец), и последний — список узлов, которые нужно перетащить.
Клонирование узлов
Это полезно, когда вы создали сложный объект с настроенными параметрами и материалами и хотите сделать похожий, чтобы поставить рядом. Boxshot позволяет клонировать только узел или узел вместе с его дочерними элементами. Код простой:
var n = scene.root.addMesh("sphere", "generator.simple.sphere");
n.generator.radius = 1;
n.translation = vec3(0, 0, 1);
var n1 = scene.clone(n, false);
n1.translation = vec3(0, 0, 10);
Обратите внимание: вы не можете клонировать корневой узел, и следующий код вернет ошибку:
scene.clone(scene.root);
Это потому, что у корневого узла нет родителя, а значит, нет места, куда прикрепить клон. Если вам нужно клонировать все элементы верхнего уровня, подумайте о том, чтобы сначала переместить их внутрь группы, а затем клонировать уже группу:
var top = scene.root.children;
var g = scene.root.addGroup("group");
scene.drag(g, 0, top);
var g1 = scene.clone(g, true);
g1.name = "cloned group";
Удаление объектов
После всех этих обходов и редактирования удалять узлы очень просто. Просто составьте список узлов (или укажите один узел) и передайте его в соответствующий метод объекта scene. Скрипт ниже удаляет все выделенные узлы:
scene.del(scene.selection);
А этот скрипт удаляет первый узел верхнего уровня в сцене:
scene.del(scene.root.children[0]);
Удалить корневой узел нельзя, поэтому вы получите ошибку, если попробуете выполнить такой код:
scene.del(scene.root);
Это все, что вам нужно знать про удаление.
Больше Информации о Скриптах
- Обзор — общая информация об использовании скриптов в Boxshot.
- Управление объектами — обход сцены и работа с ее элементами;
- Специальные объекты — камера, материалы, освещение итп;
- Объекты сцены — настройка встроенных объектов;
- Инструменты — использование инструментов из скриптов;
- Командная строка — запуск скриптов Boxshot из командной строки.