Собственные объекты и глобальные зависимости
THREE, Selectable, методы трансформации и границы сохранения и экспорта собственных объектов плагина.
Плагин может создавать собственную геометрию и изучать устройство редактора.
Для встроенных действий используйте стабильный editorAPI. Глобальный
editor и классы редактора дают более глубокий доступ, но их устройство
может меняться между версиями.
Видимый объект Three.js, редактируемый объект BDEngine и сущность Minecraft имеют разные контракты. Добавление меша в сцену решает только первую часть.
THREE и GLTFExporter
При инициализации системы плагинов доступны:
| Глобальное значение | Назначение |
|---|---|
window.editorAPI |
Публичный API плагинов |
window.editor |
Текущий экземпляр редактора и его внутренние подсистемы |
window.THREE |
Three.js из сборки редактора |
window.THREE.GLTFExporter |
Класс экспортёра glTF, добавленный к THREE |
window.Selectable |
Базовый класс объектов редактора, наследник THREE.Group |
window.libs.JSZip |
Подключённый редактором JSZip |
gT |
Получение переведённого текста по ключу |
GLTFExporter здесь находится именно в THREE.GLTFExporter; отдельный
глобальный GLTFExporter не создаётся. Используйте экземпляр Three.js
редактора, чтобы объекты, материалы и экспортёр работали с одной версией.
console.log('Three.js revision:', THREE.REVISION);const exporter = new THREE.GLTFExporter();const zip = new window.libs.JSZip();Версии библиотек связаны со сборкой BDEngine. Не переносите гарантии стабильности
editorAPI на любой внутренний класс или метод зависимости. Доступность
глобальных объектов ещё не означает готовность интерфейса:
порядок запуска плагина.
Регистрация словарей и gT описаны в
справке переводов.
Selectable и собственный класс
Конструктор new Selectable(editor) создаёт группу с методами трансформации,
состоянием выделения и связью с редактором. Он не создаёт Minecraft-дисплей,
не загружает модель и не назначает сериализатор собственному типу.
Ниже пример временного визуального маркера. Это собственная Three.js-геометрия для текущей сессии. Она не является экспортируемым блоком Minecraft.
class PreviewMarker extends Selectable { constructor(editor) { super(editor); this.name = 'Маркер плагина'; this.markerMesh = new THREE.Mesh( new THREE.BoxGeometry(0.25, 0.25, 0.25), new THREE.MeshBasicMaterial({ color: 0xffaa00 }) ); this.add(this.markerMesh); }
disposePreview() { if (this.parent) this.delete(); this.markerMesh.geometry.dispose(); this.markerMesh.material.dispose(); }}Selectable предоставляет базовое выделение, но не включает все возможности
встроенного типа: собственная группа не получает автоматически строку в панели
объектов, Minecraft-экспорт или поддержку каждого инструмента. Для такой
интеграции изучайте соответствующую подсистему editor и проверяйте её контракт.
Методы трансформации и selected
Описанные ниже сеттеры и геттеры синхронны. Позиция, вращение и масштаб локальны относительно родителя. Сеттеры по умолчанию помечают изменившуюся геометрию, рамки и данные пересечения для обновления, но сами не создают Undo-команду, не рассылают трансформацию в Share Party и не обновляют все панели.
У сеттеров есть skipDirty = false. В обычном плагине оставьте значение
по умолчанию. true пропускает служебную отметку изменения и требует
самостоятельного управления обновлениями.
Для setPosition, setRotation и setScale можно передать часть осей:
отсутствующая или равная undefined ось остаётся без изменения. Переданные
значения должны быть конечными числами. Строки, NaN и бесконечности вызывают
ProjectValidationError; при ошибке набор значений не применяется частично.
setPosition
object.setPosition({ x, y, z }, skipDirty = false) меняет локальную позицию.
Единицы - единицы сцены BDEngine, для обычных дисплеев одна единица соответствует
одному блоку Minecraft. Значения округляются по object.stepPosition
(по умолчанию 0.000625). Возвращает undefined.
object.setPosition({ x: 2, z: -1 }); // Y сохраняется.getPosition
object.getPosition() возвращает новый обычный объект { x, y, z } с
округлёнными локальными координатами. Изменение этого результата не меняет
исходную позицию. Сам геттер позицию не переписывает.
const position = object.getPosition();object.setPosition({ y: position.y + 1 });setRotation
object.setRotation({ x, y, z }, skipDirty = false) принимает градусы,
округляет по object.stepRotation (по умолчанию 0.01) и обновляет
соответствующие углы Three.js. Возвращает undefined.
object.setRotation({ y: 90 });В отличие от этого метода, обычное свойство Three.js object.rotation
содержит радианы. Не передавайте градусы напрямую в object.rotation.y.
getRotation
object.getRotation() возвращает { x, y, z } в градусах.
Если внутреннее представление ещё не создано, оно вычисляется из вращения.
В отличие от getPosition(), здесь возвращается ссылка на внутренний
customRotation. Для снимка скопируйте её. Изменение этой ссылки вручную
не запускает пересчёт Three.js-вращения и уведомления об изменении:
const rotation = { ...object.getRotation() };object.setRotation({ y: rotation.y + 15 });Углы могут сохранять накопленные обороты. Не ожидайте обязательной нормализации
в диапазон от -180 до 180.
setQuaternionRotation
object.setQuaternionRotation(quaternion, skipDirty = false) копирует
кватернион и обновляет представление поворота в градусах с учётом изменения
относительно предыдущего кватерниона. Возвращает undefined; пустой аргумент
ничего не меняет.
Передавайте нормализованный THREE.Quaternion. Проверка требует конечные
компоненты x/y/z/w и ненулевую длину, но метод не нормализует присваиваемый
кватернион автоматически. Невалидный кватернион вызывает ProjectValidationError.
const quaternion = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3(0, 1, 0), Math.PI / 2);object.setQuaternionRotation(quaternion);Угол в setFromAxisAngle - радианы, а getRotation() по-прежнему возвращает
градусы. Кватернион описывает ориентацию, но сам по себе не хранит число полных
оборотов, поэтому не используйте его как замену многовитковым ключам анимации.
setScale
object.setScale({ x, y, z }, skipDirty = false) задаёт множители масштаба.
Значения округляются по stepScale (по умолчанию 0.0001) и ограничиваются
снизу minScale (по умолчанию 0.0011). Возвращает undefined.
У частицы дополнительно обновляет масштаб её gizmo.
object.setScale({ x: 2, y: 2, z: 2 });Нулевой или отрицательный масштаб не создаёт нулевой размер или отражение:
он поднимается до минимального положительного значения. Для поддерживаемых
объектов отражение задаётся отдельно через setMirrorX.
getScale
object.getScale() возвращает новый объект { x, y, z }.
Геттер может изменить исходный объект: если текущий масштаб не соответствует
округлению или минимуму, он вызывает setScale и обновляет локальную и мировую
матрицы. Поэтому это не всегда чтение без побочных эффектов.
selected
object.selected - свойство состояния выделения. Присваивайте boolean.
При включении создаётся визуальная рамка, при выключении она удаляется;
редактор также обновляет ревизию выделения.
object.selected = true;editorAPI.update(true);Присваивание не снимает выделение с других объектов, не создаёт историю
выделения и само по себе не выполняет полный workflow контроллера. После
пакетного изменения состояния используйте editorAPI.update(true).
Скос, отражение и матрицы
Аффинная трансформация включается для объектов, у которых isDisplay или
isCollection истинно. У обычного собственного наследника Selectable
это не включено. Не назначайте эти флаги только ради эффекта: другие системы
редактора ожидают соответствующий встроенный тип.
| Метод | Контракт |
|---|---|
supportsAffineTransform() |
Возвращает boolean, включена ли поддержка скоса и отражения |
getShear() |
Возвращает копию { xy, xz, yz }, углы в радианах |
setShear({ xy, xz, yz }, skipDirty = false, updateMatrix = true) |
Обновляет указанные компоненты. Для каждой нужен конечный угол строго между -Math.PI / 2 и Math.PI / 2; неверный угол возвращает false без изменения, успех - true |
getMirrorX() |
Возвращает boolean отражения по локальной X |
setMirrorX(value, skipDirty = false, updateMatrix = true) |
Приводит значение к boolean, обновляет матрицу и служебные данные по флагам. Возвращает undefined |
setFromAffineMatrix(matrix, options = {}) |
Разбирает THREE.Matrix4 в компоненты и возвращает сам объект |
applyMatrix4(matrix) |
Применяет матрицу слева к локальной матрице, возвращает сам объект |
updateMatrix() |
Пересобирает локальную матрицу с учётом поддерживаемых скоса и отражения; возвращает undefined |
setShear допускает частичный набор осей. Значения очень близко к границе
дополнительно ограничиваются до Math.PI / 2 - 0.000001 по модулю.
У setFromAffineMatrix доступны referenceRotation = null (опорный
THREE.Euler), skipDirty = false и updateWorld = true.
Для объекта без аффинной поддержки матрица раскладывается в обычные позицию,
кватернион и масштаб.
if (object.supportsAffineTransform()) { object.setShear({ xy: THREE.MathUtils.degToRad(10) }); object.setMirrorX(true); editorAPI.update(true);}Добавить объект в сцену
Созданный экземпляр подключается через
editorAPI.addObject.
В примере используется класс PreviewMarker выше:
const marker = new PreviewMarker(editor);marker.setPosition({ x: 0, y: 1, z: 0 });editorAPI.addObject(marker);marker.selected = true;editorAPI.update(true);
// Когда предпросмотр больше не нужен:// marker.disposePreview();// editorAPI.update(true);У самого Selectable есть add(...objects) и remove(...objects),
унаследованные от группы и дополненные обновлением служебных индексов редактора.
Они меняют дерево и возвращают объект-родитель, но не создают историю.
object.delete() снимает выделение у потомков и отсоединяет объект от родителя;
он возвращает undefined и требует, чтобы родитель существовал.
Прямое удаление в примере подходит временному предпросмотру. Для штатных объектов проекта используйте операции удаления editorAPI.
Сохранение, экспорт и ресурсы
Проект сохраняет известные редактору типы через их собственное представление.
Наследования от Selectable недостаточно, чтобы сериализовать произвольный
класс, загрузить его обратно или восстановить после Undo. В частности,
addObject не регистрирует формат и не добавляет команду истории.
Геометрия THREE.Mesh также не превращается автоматически в Minecraft-дисплей.
Для своего формата экспорта можно взять
снимок мешей и обработать
его собственной логикой. Для полноценной интеграции типа с проектом потребуются
дополнительные механизмы editor и отдельная проверка сохранения и восстановления.
Ресурсы, созданные плагином, освобождает плагин: геометрии, материалы, собственные текстуры, обработчики и таймеры. Удаление DOM-окна или отсоединение Three.js-объекта не вызывает их полную очистку. Освобождайте только то, чем владеете; общие текстуры и материалы редактора могут использоваться другими объектами.
Когда лучше встроенный объект
Если результат должен остаться редактируемым дисплеем и экспортироваться в
Minecraft, начните с editorAPI.add для BlockDisplay, ItemDisplay или
TextDisplay. Их загрузка и штатная сериализация уже реализованы редактором.
Собственная геометрия полезна для предпросмотра, визуальных инструментов и других возможностей плагина, где сохранение и игровой экспорт определяются отдельно. Практический путь: создать генератор встроенных объектов.