Zum Hauptinhalt springen

Eigene Komponenten

Die zweite Art Plugin öffnet gar kein Panel. Sie hängt sich als Komponente an ein Objekt und zeichnet ihre Oberfläche im Inspektor des Editors, neben Transform und Material.

Das ist die richtige Form, wenn Ihr Werkzeug von einem bestimmten Objekt handelt: Notizen zu einem Objekt, ein eigenes Bedienelement, ein Generator, der zu dem gehört, was er erzeugt.

Deklarieren

Deklarieren Sie sie in components; panels darf leer bleiben:

{
"id": "entity-notes",
"entry": "main.tsx",
"panels": [],
"components": [{ "id": "notes", "title": "Notes", "entry": "main.tsx" }]
}

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(); // beim Rendern gelesene Szenendaten verfolgen
const props = useProps(); // Werte aus dem Inspektor-Formular
const entity = useEntity(); // das Objekt, an dem das 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>
);
}

Vier Hooks erledigen die Arbeit:

HookLiefert Ihnen
useEntity()das Objekt, an dem Ihre Komponente hängt
useProps()die Werte aus dem mit defineProps deklarierten Formular
useSignals()ein Neurendern, wenn sich beim Rendern gelesene Szenendaten ändern
useSyncedState()Zustand, der am Objekt liegt und wie jede Komponente synchronisiert wird

defineProps benutzt dieselben Feldtypen wie Skript-Eigenschaften — Zahl, Zeichenkette, Boolean, Farbe, Auswahl, Objekt, Ressource — Ihre Komponente bekommt also ein ordentliches Inspektor-Formular geschenkt.

Wie es läuft

Das ist echtes React, keine vereinfachte Nachbildung

Jede Komponenten-Erweiterung jedes Plugins läuft in einem gemeinsamen Worker, mit React 19 darin. Hooks, useEffect, Context und Suspense funktionieren genau so, wie Sie es erwarten.

Was der Worker erzeugt, ist kein DOM, sondern eine Beschreibung davon, die der Editor mit seinen eigenen Komponenten zeichnet. Genau das lässt eine Erweiterung nativ wirken statt wie eine eingebettete Seite.

Zwei Folgen dieser Grenze:

  • Die Menge der Elemente ist eine feste Liste. Sie bauen aus den bereitgestellten Komponenten, nicht aus beliebigem HTML.
  • Handler überqueren die Grenze nicht. Dem Editor wird nur gesagt, dass ein Handler existiert; ein Klick kommt als Nachricht zurück und ruft Ihre Funktion im Worker auf. Sie schreiben onClick ganz normal — das zählt nur, wenn Sie ein DOM-Event weiterreichen wollten.

Wie man sie hinzufügt

Ihre Erweiterung erscheint in + New component, in einer Gruppe Extensions — sie wird nicht besonderer behandelt als eine eingebaute Komponente.

Sie erscheint außerdem in der Werkzeugleiste unter +, gruppiert unter der Überschrift Plugins, damit klar ist, woher ein unbekannter Button kommt. Die beiden Einstiege verhalten sich bewusst unterschiedlich:

Hinzugefügt überErgebnis
+ New componenthängt sich an das bereits ausgewählte Objekt
Die Werkzeugleisteerzeugt ein neues Objekt mit Ihrer Komponente und wählt es aus

Ein lokal verbundener Ordner taucht in dieser Liste ebenfalls auf, wenn er ein Panel hat — sonst wäre der einzige Weg dorthin, jedes Mal das Plugins-Panel zu öffnen. Ein Ordner, der nichts als ein Overlay enthält, erscheint nicht: Es gäbe nichts zu drücken.

Vertrauen

Eine Komponenten-Erweiterung läuft, ohne geöffnet zu werden

Sie hängt sich ein, sobald irgendwer ein Projekt öffnet, das sie enthält — ganz ohne Klick. Genau das stellt sie hinter die stärkere Zustimmung, beschrieben unter Vertrauen und Prüfung.


Weiter: Tastenkürzel