Eigene Komponenten
Ein Plugin kann Objekten eine eigene Komponente hinzufügen. Ihre Oberfläche erscheint im Inspektor, neben Transformation und Material.
Das ist sinnvoll, wenn Ihr Werkzeug zu einem einzelnen Objekt gehört: Notizen zu einem Objekt, ein eigenes Bedienelement oder ein Generator, der bei dem bleibt, was er erzeugt. Ein solches Plugin braucht kein Panel.
Komponente deklarieren
Führen Sie sie im Manifest unter components auf. panels darf leer sein:
{
"id": "entity-notes",
"entry": "main.tsx",
"panels": [],
"components": [{ "id": "notes", "title": "Notes", "entry": "main.tsx" }]
}
Komponente schreiben
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(); // neu rendern, wenn sich hier gelesene Szenendaten ändern
const props = useProps(); // Werte aus dem Formular im Inspektor
const entity = useEntity(); // das Objekt, an dem die Komponente hängt
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>
);
}
Diese Hooks erledigen die Arbeit:
| Hook | Was Sie bekommen |
|---|---|
useEntity() | das Objekt, an dem Ihre Komponente hängt |
useWorld() | die Szene, in der dieses Objekt liegt |
useProps() | die Werte aus dem Formular, das Sie mit defineProps deklariert haben |
useSignals() | ein neues Rendern, wenn sich Szenendaten ändern, die Sie beim Rendern gelesen haben |
useSyncedState() | Zustand, der am Objekt gespeichert und wie jede andere Komponente synchronisiert wird |
useSelected() | ob das Objekt im Editor ausgewählt ist |
useViewportPointer() | Mausereignisse im Viewport, mit dem Objekt und dem Punkt unter dem Zeiger |
defineProps verwendet dieselben Feldtypen wie Skripteigenschaften: Zahl, Text, Boolean, Farbe,
Auswahl, Objekt, Szene, Raum, Ressource, Datensatz, Liste und Gruppe. So bekommt Ihre Komponente
ohne zusätzlichen Aufwand ein richtiges Formular im Inspektor.
Werte aus der Komponente ändern
props.$set(patch) ändert die eigenen Felder Ihrer Komponente, so wie es der Inspektor tut: Die
Änderung wird mit allen synchronisiert und lässt sich rückgängig machen. Sie wird gegen
defineProps geprüft: Zahlen bleiben zwischen ihrem min und max, und ein Feld, das Sie nicht
deklariert haben, löst einen Fehler aus. So können Sie einen Wert im Viewport ziehen:
<Handle axis={[0, 1, 0]} onDrag={(p) => props.$set({ height: p[1] })} />
Feldnamen, die mit $ beginnen, sind dafür reserviert, deshalb lehnt defineProps sie ab.
Zustand deklarieren
defineState deklariert den Zustand der Komponente mit Standardwerten, so wie defineProps das
Formular deklariert:
const useScore = defineState({ points: { type: 'number', default: 0 } });
const [score, setScore] = useScore(); // innerhalb der Komponente
Skripte lesen diesen Zustand dann typisiert, mit denselben Standardwerten.
Übersetzen
i18n() oder useEditorLocale() aus @was/extension geben Ihnen t(key, vars) für die
Sprachdateien Ihres Plugins, in der Sprache des
Editors.
So läuft sie
Ihre Komponente ist echtes React 19. Hooks, useEffect, Context und Suspense funktionieren wie
gewohnt.
Der Editor zeichnet Ihre Komponente mit seinen eigenen Elementen. Deshalb sieht sie aus wie ein Teil des Editors.
Daraus folgen zwei Dinge:
- Sie bauen nur aus den bereitgestellten Elementen. Beliebiges HTML ist nicht verfügbar. Im
Inspektor:
Column,Row,Text,Button,Divider,InputText,InputNumber,InputColor,Slider,CheckboxundSelect. Im Viewport:Overlay,Gizmo,Group,Box,Sphere,Line,HandleundControl. Geben Sie einemGizmooder einemOverlaywhen="selected", damit es nur am ausgewählten Objekt erscheint. - Event-Handler schreiben Sie wie gewohnt.
onClickfunktioniert ganz normal. Nur ein DOM-Event können Sie nicht weiterreichen.
So wird sie hinzugefügt
Ihre Komponente lässt sich auf zwei Wegen hinzufügen:
| Hinzugefügt über | Ergebnis |
|---|---|
| + neue Komponente, in der Gruppe Erweiterungen | sie wird dem bereits ausgewählten Objekt hinzugefügt |
| die Werkzeugleiste, unter +, in der Gruppe Plugins | ein neues Objekt mit Ihrer Komponente wird erstellt und ausgewählt |
Die Überschrift Plugins in der Werkzeugleiste zeigt, woher eine unbekannte Schaltfläche kommt.
Ein Plugin-Ordner, den Sie von Ihrem Computer verbunden haben, erscheint ebenfalls in dieser Liste der Werkzeugleiste, wenn er ein Panel hat. So öffnen Sie ihn, ohne jedes Mal über das Panel Plugins zu gehen. Ein Ordner, der nur ein Overlay enthält, erscheint dort nicht, weil es nichts zu öffnen gibt.
In Skripten und im veröffentlichten Projekt nutzen
Die Oberfläche der Komponente funktioniert nur im Editor. Ihre Werte werden am Objekt gespeichert, sodass das Projekt sie nutzen kann, wenn es läuft:
- Skripte lesen und ändern die Komponente mit
ctx.plugin('<plugin id>/<component id>')→ Die ctx-API; - der eigene Code Ihres Plugins für das veröffentlichte Projekt macht dasselbe → Laufzeitcode.
Vertrauen
Eine eigene Komponente startet, sobald jemand ein Projekt öffnet, das sie enthält. Deshalb durchläuft sie die strengere Prüfung, die unter Vertrauen und Prüfung beschrieben ist.
Weiter: Laufzeitcode – damit Ihr Plugin auch im veröffentlichten Projekt funktioniert.