自作の component
もう 1 つの形のプラグインは、パネルをまったく開きません。component としてオブジェクトに付き、 エディターのインスペクターの中、Transform や Material の隣に自分の UI を描きます。
道具が特定のオブジェクトについてのものであるときは、これが正しい形です。オブジェクトへのメモ、 専用のコントロール、生成対象に属するジェネレーターなどです。
宣言する
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>
);
}
仕事をするのは 4 つのフックです。
| フック | 得られるもの |
|---|---|
useEntity() | この component が付いているオブジェクト |
useProps() | defineProps で宣言したフォームの値 |
useSignals() | 描画中に読んだシーンデータが変わったときの再描画 |
useSyncedState() | オブジェクトに保存され、ほかの component と同じように同期される状態 |
defineProps が使うフィールドの型は script のプロパティと同じです。数値・文字列・真偽値・色・
選択・オブジェクト・リソース。おかげで、ちゃんとしたインスペクターのフォームが無償で付いてきます。
どのように動くか
すべてのプラグインの component 拡張は、React 19 を内蔵した 1 つの共有ワーカーの中で動きます。
フック、useEffect、コンテキスト、Suspense はどれも期待どおりに働きます。
ワーカーが出力するのは DOM ではなく、その記述です。エディターはそれを自前の component で描きます。 拡張が埋め込みページではなくネイティブに見えるのは、このためです。
この境界から 2 つの帰結があります。
- 使える要素は決まった一覧です。 任意の HTML ではなく、提供された component から組み立てます
- ハンドラーは境界を越えません。 エディターにはハンドラーが存在することだけが伝わります。
クリックはメッセージとして返り、ワーカー内のあなたの関数を呼びます。
onClickはふつうに 書けます。これが問題になるのは、DOM イベントそのものを持ち回るつもりだった場合だけです
追加のされかた
あなたの拡張は + New component の Extensions グループに現れます。組み込みの component より 特別扱いされることはありません。
ツールバーの + にも、Plugins という見出しの下に現れます。見慣れないボタンがどこから来たか 分かるようにするためです。この 2 つの入口は、意図的に異なるふるまいをします。
| 追加した場所 | 結果 |
|---|---|
| + New component | すでに選択しているオブジェクトに付く |
| ツールバー | あなたの component を持つ新しいオブジェクトを作り、選択する |
ローカルに接続したフォルダーも、パネルを持っていればこの一覧に出ます。そうでないと、毎回 Plugins パネルを開くしか到達手段がなくなるからです。オーバーレイしか持たないフォルダーは 現れません。押すものがないからです。
信頼
それを含むプロジェクトを誰かが開いた時点で、クリックなしでマウントされます。これが、 信頼と検証で説明したより強い同意を必要とする理由です。
次へ: キーボードショートカット