メインコンテンツまでスキップ

共有パッケージ

これらのパッケージは、自分のコードからインポートできます。ここでは、どこで何が使えるかと、各パッケージでできることを説明します。

エンティティはオブジェクトのことです

コードでは、エディターに表示されるオブジェクトをエンティティと呼びます。どちらも同じものです。

インポートできるパッケージは、コードが動く場所によって決まります。

パッケージできることスクリプトプラグインコンポーネント拡張
@was/ecsエンティティ、コンポーネント、ワールド✓✓✓
@was/engineコンポーネントのクラス✓✓✓
@was/signalsリアクティブな値—✓✓
@was/svdtスキーマと検証✓✓—
@was/utils小さなヘルパー✓✓—
@was/uiエディター自身のコンポーネントライブラリ—✓✓
@was/iconsエディターのアイコンセット—✓✓
reactReact 19—✓✓
スクリプトでは ctx.effect を使います

スクリプトから @was/signals を直接インポートすることはできません。代わりに ctx.effect を使ってください。使い方は同じで、オブジェクトがなくなると止まるので、動き続けるものが残りません。

@was/signals:リアクティブな値​

シグナルは、誰に読まれているかを知っている値です。値が変わると、それに依存しているものだけが更新されます。

import { signal, computed, effect, batch, untracked } from '@was/signals';

const score = signal(0);
const doubled = computed(() => score.value * 2);

const stop = effect(() => {
render(score.value); // score が変わったときだけ再実行される
});

batch(() => {
score.value += 1;
score.value += 1; // effect の実行は 2 回ではなく 1 回
});

stop();
関数役割
signal(v)監視できる値。.value で読み書きします
computed(fn)派生した値。読んでいるものが変わったときだけ再計算されます
effect(fn)すぐに実行され、読んだものが変わるたびに再実行されます。停止用の関数を返します
batch(fn)書き込みをまとめ、監視側の実行を最後の 1 回にします
untracked(fn)依存関係をつくらずに値を読みます
ref(obj)オブジェクト全体を、入れ子の値の奥までリアクティブにします
snapshot(obj)リアクティブではない、ただのコピー
raw(obj)追跡なしの元のオブジェクト
readonly(obj)書き込みできないビュー

React のパネル向けには、useSignal、useComputed、useSignalEffect、useLiveSignal を提供する関連パッケージがあります。これを使うと、余計な配線なしに、シグナルの変化でコンポーネントが再レンダリングされます。

@was/ui:エディターのコンポーネント​

プラグインのパネルやコンポーネント拡張は、エディターと同じコンポーネントでつくりましょう。そうすれば、パネルが埋め込まれたウェブページではなく、エディターの一部のように見えます。ライブラリには次のコンポーネントがあります。

Accordion · Avatar · Button · Card · Checkbox · Chip · CloseButton
DimensionInput · Draggable · Dropdown · Flag · Icon · IconButton · Input
Menu · Modal · Outside · Panel · Popover · Portal · Render · Scroll
Search · Section · Segmented · Select · Skeleton · Switcher · Tabs
Toast · Toolbar · Tooltip

アイコンには @was/icons を使います。

スタイルシートはビルド済みです

パネルで使えるのは、ライブラリに含まれているユーティリティクラスだけです。text-[13px] のような任意の値は含まれていません。スケールにないサイズには、インラインの style を使ってください。

@was/ecs:エンティティとコンポーネント​

このパッケージには Entity、Component、Space があります。プラグインは、機能を絞った別の API ではなく、完全な API でシーンを読み書きできます。

Space:ワールド​

呼び出し返すもの
getEntity(id)1 つのエンティティ。なければ何も返しません
hasEntity(id)存在するかどうか
getEntities()すべてのエンティティ
queryEntities(A, B, …)指定したコンポーネントをすべて持つエンティティ全部
makeQueryEntities(A, B, …)同じクエリを、繰り返し使えるよう一度だけつくったもの
createEntity(id?, components?)ワールドに追加された新しいエンティティ
addEntity(…e) · removeEntity(…e)エンティティをワールドに追加する、または取り除く
getSystem(S) · hasSystem(S)システム、またはそれが存在するかどうか
execute()1 フレームを実行します
エンティティを探すには queryEntities を使いましょう

これを使うと、「ライトとトランスフォームを持つものすべて」のような問い合わせも速く返ります。getEntities() はワールド全体を返すので、自分で絞り込む必要があります。

Entity:ワールド内の 1 つのオブジェクト​

呼び出し役割
getComponent(Type)コンポーネントを 1 つ返します。なければ null
getComponents(A, B)複数のコンポーネントを、指定した順にまとめて返します
hasComponent(A, B)すべてを持っているかどうかを確認します
addComponent(…c)コンポーネントを追加します。すでにある種類は無視されます
removeComponent(…c)クラスかインスタンスを指定して、コンポーネントを外します
component(fn)今ある、そしてこれから追加されるすべてのコンポーネントに fn を実行します
clone() · clean()エンティティをコピーする、またはコンポーネントをすべて外す
.id · .componentsID と、種類ごとのコンポーネント

Component:データ​

呼び出し役割
.x または get('x')フィールドを読みます。effect の中では、そのフィールドを購読もします
$dataコンポーネント全体を、ただのオブジェクトとして返します
$rawData購読せずに、保存されているオブジェクトを返します。読み取り専用です
update({ … })データを書き込みます。書き込む方法はこれだけです。
updateAt(path, value)大きなコンポーネントの奥深くに、全体を検証し直さずに書き込みます
version(field?)何かが変わると増えるカウンターです。フィールドを読まずに依存できます
reset(data?)初期値に戻します
clone()コピーをつくります
大きなリストには version() を使いましょう

大きな値を読むと、その中のすべての要素を購読することになります。代わりにバージョンのカウンターに依存すれば、すべての要素を監視しなくても、変わったことがわかります。2 万件のリストを持つパネルでも速さを保てるのは、このしくみのおかげです。

@was/engine:コンポーネントのクラス​

コンポーネントの種類はそれぞれクラスになっています。TransformComponent、MaterialComponent、RigidBodyComponent などです。クラスをインポートして、getComponent、hasComponent、query に渡します。

すべてのフィールドを含む一覧は、コンポーネントリファレンスを参照してください。

@was/svdt:スキーマ​

このパッケージで、データの形を記述し、データを確認できます。

import { s, compile } from '@was/svdt';

const schema = s.object({ speed: s.f64(1), name: s.string('') });
const codec = compile(schema); // コンパイルは宣言する場所で一度だけ。呼び出しのたびには行わない
const value = codec.parse(input);

形を記述する​

  • 数値:s.f32 s.f64 s.i8 s.u8 s.i16 s.u16 s.i32 s.u32。それぞれ初期値を指定します。
  • スカラー:s.bool、s.string、s.color、s.literal、s.enum、s.unknown、s.ref。
  • ベクトル:s.vec2、s.vec3、s.mat4。
  • 複合型:s.object、s.variant、s.array、s.record、s.union、s.preprocess、s.lazy。

どれにも、.default(v)、.optional()、.nullable()、.min(n)、.max(n)、.int() をつなげて使えます。

コンパイルしたコーデックを使う​

呼び出し役割
parse(input)検証して正規化します。入力が不正なら例外を投げます
safeParse(input)同じ処理ですが、例外を投げずに成功かエラーを返します
parseAt(path, v)ほかには触れずに、1 つのフィールドだけを検証します
equals(a, b)深い比較
diff(a, b)変わった部分を返します
apply(target, p)差分を適用します
invert(p)差分を逆にします
pack · unpackコンパクトなバイナリ形式との相互変換

データではなくスキーマそのものを調べるには、introspect、keys、requiredKeys を使います。

@was/utils​

小さなヘルパーです。pick、omit、assign、keys、values、entries、capitalize、basename、extname、dispose(後片付けの関数を 1 つにまとめます)、ファイルの種類を確認する MIME タイプのヘルパーがあります。


次へ: 用語集 — このドキュメント全体で使う用語。