Собственные компоненты
Второй вид плагина вообще не открывает панель. Он прикрепляется к объекту как компонент и рисует свой интерфейс прямо в инспекторе редактора, рядом с Transform и Material.
Это правильная форма, когда ваш инструмент — про конкретный объект: заметки к объекту, особый регулятор, генератор, принадлежащий тому, что он генерирует.
Как объявить
Объявите его в components; panels может быть пустым:
{
"id": "entity-notes",
"entry": "main.tsx",
"panels": [],
"components": [{ "id": "notes", "title": "Notes", "entry": "main.tsx" }]
}
Как написать
import {
Button,
Column,
Text,
defineProps,
useEntity,
useSignals,
useSyncedState,
} from '@was/extension';
import { TransformComponent } from '@was/engine';
const useProps = defineProps({ step: { type: 'number', default: 0.5 } });
export default function Notes() {
useSignals(); // отслеживать данные сцены, прочитанные при рендере
const props = useProps(); // значения из формы в инспекторе
const entity = useEntity(); // объект, к которому это прикреплено
const [note, setNote] = useSyncedState('note', '');
return (
<Column gap={2}>
<Text muted>{note}</Text>
<Button
onClick={() =>
setNote(`y=${entity.getComponent(TransformComponent)?.get('position').y}`)
}
>
Remember
</Button>
</Column>
);
}
Всю работу делают четыре хука:
| Хук | Что даёт |
|---|---|
useEntity() | объект, к которому прикреплён ваш компонент |
useProps() | значения из формы, объявленной через defineProps |
useSignals() | перерисовку, когда меняются прочитанные при рендере данные сцены |
useSyncedState() | состояние, хранящееся на объекте и синхронизируемое как любой компонент |
defineProps использует те же типы полей, что и свойства скриптов: число, строка, логическое,
цвет, выбор, объект, ресурс — так что нормальная форма в инспекторе достаётся вам бесплатно.
Как это исполняется
Все расширения-компоненты всех плагинов работают в одном общем воркере, и React 19 внутри него.
Хуки, useEffect, контекст и Suspense работают ровно так, как вы ожидаете.
Воркер выдаёт не DOM, а его описание, которое редактор рисует своими компонентами. Именно поэтому расширение выглядит родным, а не встроенной страницей.
Из этой границы следуют две вещи:
- Набор элементов фиксирован. Вы собираете из предоставленных компонентов, а не из произвольного HTML.
- Обработчики через границу не проходят. Редактору сообщают лишь, что обработчик есть; клик
возвращается сообщением и вызывает вашу функцию в воркере.
onClickпишется как обычно — это важно, только если вы рассчитывали передавать DOM-событие дальше.
Как его добавляют
Ваше расширение появляется в + New component, в группе Extensions, — к нему относятся не более особенно, чем к встроенному компоненту.
Оно появляется и в панели инструментов под +, в разделе Plugins, чтобы было очевидно, откуда взялась незнакомая кнопка. Два входа ведут себя по-разному, и это намеренно:
| Добавлено из | Результат |
|---|---|
| + New component | прикрепляется к уже выделенному объекту |
| Панель инструментов | создаёт новый объект с вашим компонентом и выделяет его |
Локально подключённая папка тоже попадает в этот список, если у неё есть панель, — иначе добраться до неё можно было бы только через панель Plugins каждый раз. Папка, в которой нет ничего, кроме оверлея, не появляется: нажимать было бы не на что.
Доверие
Оно монтируется всякий раз, когда кто-либо открывает содержащий его проект, без всякого клика. Именно поэтому для него требуется более строгое согласие, описанное в разделе доверие и проверка.
Дальше: Горячие клавиши