Перейти к содержимому

Объекты и выделение

Создание, поиск, выделение и удаление объектов через editorAPI: параметры, история и обновление интерфейса.

editorAPI предоставляет операции над живыми объектами текущего проекта. Полученный объект остаётся частью сцены: изменение его свойств изменяет проект. Методы трансформации и их единицы приведены в справке Selectable.

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

add

await editorAPI.add(
identifier, type, parent = null, save = true,
objPos = undefined, noReply = false, options = {}
);

Асинхронно создаёт встроенный объект, загружает его модель и добавляет к родителю. Возвращает созданный объект. При отказе, отмене из-за смены проекта или ошибке результатом может быть false либо undefined; проверяйте его перед использованием.

Параметр Значение
identifier Состояние блока, идентификатор предмета или текст, в зависимости от type
type Один из типов из таблицы ниже, с указанным регистром
parent Уже существующий объект-родитель в текущем проекте; null выбирает корень проекта для дисплеев. Для StructureBlock используется группа структуры, подробнее ниже
save При true добавляет команду в Undo/Redo, если noReply = false. Это не сохранение файла
objPos Необязательный THREE.Vector3 с позицией в мировых координатах
noReply При true отключает отправку добавления участникам Share Party, запись истории и индикатор загрузки
options.skipEditorUpdate При true пропускает обновление интерфейса и сетки HeadPaint после добавления. По умолчанию false
type identifier Условия
BlockDisplay Например 'stone' или состояние из getBlockList() Обычный режим редактирования
ItemDisplay Например 'diamond_sword' Обычный режим редактирования
TextDisplay Строка текста, например 'Привет!' Может потребоваться загрузка шрифта
StructureBlock Состояние настоящего блока Только режим редактирования структуры; используется переданная группа структуры или её корень

Другие строки type, в том числе 'Collection', этим методом не создаются. В режиме структуры попытка добавить обычный дисплей возвращает false. Обычные дисплеи также нельзя добавлять внутрь группы структуры этим способом. Для StructureBlock, если parent отсутствует или не является группой структуры, редактор сам выбирает либо создаёт её корень через свою подсистему структур.

objPos преобразуется из мировых координат в локальные координаты родителя, затем прибавляется к начальной позиции объекта. Передавайте THREE.Vector3, а не обычный объект с x/y/z. У головы player_head имеется собственное начальное смещение на 0.5 по Y, поэтому objPos не всегда является окончательной позицией. Положение StructureBlock округляется до целых координат.

const block = await editorAPI.add(
'stone', 'BlockDisplay', null, true,
new THREE.Vector3(0, 1, 0)
);
if (block) {
console.log(block.uuid, block.getPosition());
}

Метод сам обновляет интерфейс при обычном вызове. Для серии добавлений можно пропускать промежуточные обновления, а затем вызвать update() один раз:

async function addTwoBlocks() {
try {
for (let x = 0; x < 2; x++) {
const block = await editorAPI.add(
'stone', 'BlockDisplay', null, true,
new THREE.Vector3(x, 0, 0), false,
{ skipEditorUpdate: true }
);
if (!block) break;
}
} finally {
editorAPI.update();
}
}

В этом примере каждый успешный add остаётся отдельной командой Undo и отдельным сообщением Share Party. skipEditorUpdate не объединяет команды в транзакцию.

addObject

const inserted = editorAPI.addObject(object, parent = null);

Синхронно вызывает parent.add(object), а при отсутствии родителя - editor.objects.add(object). Возвращает тот же object; для пустого значения возвращает null. Объект должен подходить для дерева Three.js, например быть наследником Selectable.

addObject не загружает Minecraft-модель, не добавляет команду в историю, не отправляет добавление в Share Party и не вызывает editorAPI.update(). Это другой путь, чем add.

// customObject уже создан вашим классом на базе Selectable.
editorAPI.addObject(customObject);
editorAPI.update();

См. создание собственного объекта. Сам факт добавления не обеспечивает сохранение, восстановление через Undo или экспорт произвольной геометрии в Minecraft.

find

const objects = editorAPI.find(key, val = true);

Синхронно ищет объекты в корне проекта и его потомках по прямому свойству с точным значением. Возвращает массив ссылок; при отсутствии совпадений - []. Это не поиск по всей editor.scene и не поиск по вложенному пути вроде 'position.x'.

const blocks = editorAPI.find('isBlockDisplay');
const named = editorAPI.find('name', 'Мой объект');
const selected = editorAPI.find('selected');

Значение по умолчанию - boolean true, а не проверка на любое непустое значение. Например, find('name') не означает «объекты с именем». Для свойств-объектов сравнивается ссылка. Поиск может возвращать разные типы объектов; перед вызовом специфичных методов проверяйте тип или наличие метода.

getSelectedObjects

const objects = editorAPI.getSelectedObjects();

Синхронно возвращает результат find('selected', true): массив выбранных объектов, либо []. В одном выделении могут быть группы, дисплеи и служебные объекты. Массив можно фильтровать, но его элементы не являются копиями сцены.

const blocks = editorAPI.getSelectedObjects()
.filter(object => object.isBlockDisplay);
console.log('Выделено блоковых дисплеев:', blocks.length);

Это снимок состава выделения на момент вызова. Для повторного нажатия кнопки получайте выделение заново: пользователь мог сменить проект или удалить объекты.

delete

editorAPI.delete(objects);

Принимает массив живых объектов и запускает штатное удаление: нормализует цели, создаёт команду Undo/Redo, отправляет удаления в Share Party и обновляет контроллер выделения. Повторяющиеся объекты и потомки уже удаляемого родителя не удаляются второй раз; устаревшие ссылки отбрасываются. Возвращает undefined, Promise от публичного метода нет.

Пустой массив не означает «ничего не делать». Если аргумент не является непустым массивом, редактор использует текущее выделение. Проверяйте результат фильтрации до удаления:

const blocks = editorAPI.getSelectedObjects()
.filter(object => object.isBlockDisplay);
if (blocks.length > 0) {
editorAPI.delete(blocks);
}

Ограничения режима структуры сохраняются: вне него её части не удаляются, а внутри нельзя удалить сам корень структуры или посторонние объекты. Для произвольного собственного класса возможность восстановления зависит от поддержки его сериализации редактором.

deleteSelected

editorAPI.deleteSelected();

Удаляет текущее выделение тем же путём, что delete. Если выделение пустое, ничего не делает. Возвращает undefined. Отдельного подтверждения перед удалением этот метод не показывает.

removeObject

editorAPI.removeObject(object);

Для существующего аргумента вызывает штатное удаление массива [object]. Для null или undefined ничего не делает. Синхронно возвращает undefined.

Название метода не означает «тихо убрать из Three.js-сцены»: здесь используются те же история, ограничения и сетевой путь, что у delete. Он не вызывает автоматическую очистку всех ресурсов, созданных сторонним плагином.

update

editorAPI.update(withControl = false);

Обновляет панели, список объектов, свойства и отображение сцены. Если withControl = true, дополнительно пересобирает временное выделение контроллера по текущим выбранным объектам. Возвращает undefined.

const object = editorAPI.getSelectedObjects()
.find(item => typeof item.setPosition === 'function');
if (object) {
const position = object.getPosition();
object.setPosition({ y: position.y + 1 });
editorAPI.update(true);
}

update не сохраняет файл, не создаёт Undo-команду и не рассылает произвольные изменения в Share Party. Сеттер в этом примере меняет объект напрямую; история трансформации отдельно не добавляется.

Родитель, история и повтор

Операция История Share Party Обновление
add(...) с обычными параметрами Команда добавления Отправка добавленного объекта Да
add(..., save = false) Нет Да, пока noReply = false Да, пока не задан skipEditorUpdate
add(..., noReply = true) Нет, даже при save = true Нет Да, пока не задан skipEditorUpdate
addObject Нет Нет Вызовите update
delete, deleteSelected, removeObject Штатная команда удаления Отправка удаления Обновляется контроллер
Сеттеры позиции, поворота, масштаба Автоматически не создаётся Автоматически не отправляется Вызовите update(true), если меняли выделение
update Нет Нет Да

Родитель для add должен находиться в текущем проекте. Если во время загрузки сменился проект, история или родитель, добавление завершается отказом. Не держите ссылки на объекты прежнего проекта для будущих операций.

Для собственной логики группировки, истории и сетевого взаимодействия можно использовать editor. Это доступный внутренний интерфейс с меняющимся устройством; такую зависимость документируйте и проверяйте при обновлении редактора. Различие со стабильным API описано в editorAPI и внутреннем editor.

Применить на практике